Search code examples
cheaderfreepascalecryptfs

How does this unique file header 'special marker' tell eCryptfs that it's an eCryptfs file?


I am writing a program (using Free Pascal, not C) that parses the header of eCryptfs files.

One of the values in the header starts at byte 7 and ends at 15 (an 8 byte value). It is of use to me because it's a value that uniquely identifies the files as eCryptfs files. So I am trying to code my app to recognise it when it finds such values in files.

However, the marker itself is generated by XOR'ing a randomly generated 4 byte value (X) with another 4 byte static hex value of 0x3c81b7f5 (Y). The generated value is 4 bytes, Z. X + Z together form the 8 byte special marker. Y itself is not stored in the files header. So, seeing as the value 0x3c81b7f5 (Y) is never stored in the header, I can't code my application to look for it and seeing as the other 4 bytes are the XOR'd result of one static value with a another random one, I can't work out how it's recognised.

Having asked how the eCryptfs program recognises this value as "an eCryptfs file" at the eCryptfs Launchpad site (https://answers.launchpad.net/ecryptfs/+question/152821, one of the community referred me to the relevant C source code which I have linked to below. However, I don't understand C well enough to work out how it is recognising the special markers. Can anyone help me so I can code the same kind of recognition process into my own app? I don't want source code but I just want someone to explain how the C code is working out "Ah yes, that's an eCryptfs file right there!" so I know what I need to code my app to do.

http://fxr.watson.org/fxr/source/fs/ecryptfs/crypto.c?v=linux-2.6;im=excerpts#L1029


Solution

  • What you're really interested in is this part here:

    m_1 = get_unaligned_be32(data);
    m_2 = get_unaligned_be32(data + 4);
    if ((m_1 ^ MAGIC_ECRYPTFS_MARKER) == m_2)
        return 1;
    

    The get_unaligned_be32 function just converts four bytes from data to an unsigned four byte integer with possible byte order adjustments. The data + 4 in the second call to get_unaligned_be32 moves the address passed to get_unaligned_be32 up by four bytes:

    [0][3][2][4][4][5][6][7]   
    ^           ^
    data        data + 4
    m_1         m_2          /* After adjusting byte order */
    

    So, the first two lines just pull two unsigned integers out of the first eight bytes of data (possibly with byte order fixes).

    Then we have this expression:

    (m_1 ^ MAGIC_ECRYPTFS_MARKER) == m_2
    

    The ^ is just the XOR operator and MAGIC_ECRYPTFS_MARKER is 0x3c81b7f5 so this test is just XORing m_1 and 0x3c81b7f5 and seeing if it is equal to m_2; if this comparison is true then you have the right type of file.