IEEE P1619/XTS, inconsistent reference implementation and test vectors I'm testing IEEE's P1619, which is XTS mode. IEEE documents from 2007 provided both test vectors and a reference implementation. Documents from 2008 only provided the reference implementation. Here is the 2007 document with both.

The reference implementation stayed the same from 2007 and 2008. The problem is, the reference implementation does not arrive at the test vector result. I've got it tracked down to the handling of the 64-bit S parameter in XTS_EncryptSector. The test vectors call out, for example, S=0x9a78563412; but I believe it should be S=0x123456789a, which allows the reference implementation to arrive at the test vector result.

I believe one of three things is wrong but I am not sure which one:


The S parameter is incorrect and should be byte-reversed
XTS_EncryptSector, which parses S into the tweak, is incorrect
The test vector result is incorrect


Based on Section 5, p. 4, I believe the test vector or S parameter is incorrect because of this sentence, which seems to apply to the S parameter:


  When encrypting tweak value using AES, the tweak is first converted into a little-endian 4 byte array. For example, tweak value 123456789A16 corresponds to byte array 9a16,7816,5616,3416,1216.


For anyone who wishes to try the code, see test2.cxx on GitHub. It is a copy/paste of the algorithm "C.2 Encryption of a data unit with a size that is not a multiple of 16 bytes" with OpenSSL providing AES code.

My question is, where does the problem lie?



Here's the relevant code for the handling of S:

void XTS_EncryptSector
(
    const AES_Key k2,               // key used for tweaking
    const AES_Key k1,               // key used for "ECB" encryption
    u64b  S,                        // sector number (64 bits)
    uint  N,                        // sector size, in bytes
    const u08b *pt,                 //  plaintext sector  input data
    u08b *ct                        // ciphertext sector output data
)
{
    ...

    for (j=0;j&lt;AES_BLK_BYTES;j++)
    {                               // convert sector number to tweak plaintext
        T[j] = (u08b) (S &amp; 0xFF);
        S    = S &gt;&gt; 8;              // also note that T[] is padded with zeroes
    }
    ...
}


It takes a value like S=0x9a78563412, and converts it into a tweak 12 34 56 78 9a 00 00 00 00 00 00 00 00 00 00 00 00.
From §5.1 ‘Data units and tweaks’, p. 4:


  Each data unit is assigned a tweak value which is a non-negative integer. The tweak values are assigned consecutively, starting from an arbitrary non-negative integer.  When encrypting tweak value using AES, the tweak is first converted into a little-endian byte array.  For example, tweak value 123456789A16 corresponds to byte array 9a16, 7816, 5616, 3416, 1216.


The test vectors appear to be written as byte arrays, not as integers (which in English are written big-endian), so where it says


  Data unit sequence number 9a78563412


on p. 23, that presumably means the integer 0x123456789a, i.e. 78187493530 in decimal.