[openssl-users] Block Ciphers in XTS mode (AES-XTS) [SOLVED - almost ?]

Dr. Pala director at openca.org
Wed Apr 6 20:58:05 UTC 2016


Hi all,

well.. I did dig a little bit into the implementation code.. I wish who 
wrote the code would have put some comments to understand how to use the 
cipher properly.. I hope I did get it right. If anybody is interested in 
the code-tracking, here's some details:

    // Tracking down XTS code in OSSL
    //
    // crypto/evp/e_evp.c:
    //  EVP_AES_XTS_CTX (@line 85)
    //   aes_xts_ctrl (supports EVP_CTRL_COPY & EVP_CTRL_INIT only)
    (@line 1000)
    //   aes_xts_init_key (@line 1026)
    //   aes_xts_cipher (@line 1088) -> CRYPTO_xts128_encrypt
    //   define: BLOCK_CIPHER_custom (@line 1119)
    //
    // crypto/modes/modes.h: [TODO: check tweak, scratch]
    //  XTS128_CONTEXT (@line 144) -> struct xts128_context
    //  CRYPTO_xts128_encrypt (@line 146)
    //
    // crypto/modes/xts128.c:
    //   CRYPTO_xts128_encrypt (@line 61)
    //
    // crypto/modes/modes_lcl.h:
    //   struct xts128_context (@line 120)
    //

Now, for the interesting part, checking the code I noticed the use of a 
flag that checks for the size of the data to be encrypted that, for FIPS 
implementation, should not exceed 2^20 * block-size (in disk encryption 
that would be the size of the block, I suppose). Anyhow, that inspired 
me to try to see if, since there is no CRTL to set the size of the 
block, the implementation assumes that the size of the block is actually 
passed as the size of the data for each EVP_EncryptUpdate (or 
EVP_DecryptUpdate)... that seems to be the case. The test code that I 
generated is capable of decrypting the data at "block" boundaries (code 
follows).

Although I hoped for a more sophisticated and less error-prone 
interface, I guess I can work with this (but I hope someone would take 
charge of adding a little more of complexity to help with the details - 
maybe that work can also help CTR mode as well to be easier to use for 
random-access decryption).

Here's an initial (very simple) test implementation:

    // Init the CTX
    ctx = EVP_CIPHER_CTX_new();

    // Set cipher type and mode
    if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_xts(), NULL, key, iv)

    // Total bytes to encrypt
    n_ops = 0;
    next_op_size = 0;
    remains = clear_len;

    enc_buf_curr = enc_buf;
    clear_buf_curr = clear_buf;

    // Encrypt plaintext
    while (remains > 0) {

       // Gets the size of the next chunk to be encrypted
       next_op_size = (block_size < remains ? block_size : remains);

       // Performs the encryption
       EVP_EncryptUpdate(ctx, enc_buf_curr, &tmp_len, clear_buf_curr,
    next_op_size);

       // Updates the number of ops
       n_ops++;

       // Updates the remaining data size to encrypt
       remains -= block_size;

       // Updates the pointer to the next enc buffer space
       enc_buf_curr += tmp_len;

       // Updates the pointer to the next clear buffer space
       clear_buf_curr += block_size;
    }

    // Finalize the Encryption
    EVP_EncryptFinal_ex(ctx, &enc_buf[ret_len], &tmp_len);

    // Now we can output the cyphertext (encrypted message)
    printf("Ciphertext %d:\n", ret_len);
    BIO_dump_fp(stdout, (char *)enc_buf, ret_len);
    printf("\n");

    // Let's free the OpenSSL CTX structure
    EVP_CIPHER_CTX_free(ctx);

Although this works, I noticed that the same data in different blocks 
result in the same ciphertext (really bad!). For example, with a block 
size of 64bytes (I know it is very small, but bear with me) and the 
following clear text input:

      char * text =
         // 128bits per row
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF"
         "0123456789ABCDEF";

The output is as follows:

    Encrypted Data:
    0000 - bb 56 4d ed dc 56 7c 3d-f8 c5 9d 58 34 d6 68 94 .VM..V|=...X4.h.
    0010 - f8 10 03 59 f0 a7 bb 79-e0 9c a3 33 bf b9 48 2d ...Y...y...3..H-
    0020 - 0f 23 c7 56 a8 b0 9c bf-aa a1 0e 4f 11 8b 18 14 .#.V.......O....
    0030 - 93 aa ca 02 ea 33 2f 92-b1 40 a2 01 c2 87 3f cc .....3/.. at ....?.
    0040 - bb 56 4d ed dc 56 7c 3d-f8 c5 9d 58 34 d6 68 94 .VM..V|=...X4.h.
    0050 - f8 10 03 59 f0 a7 bb 79-e0 9c a3 33 bf b9 48 2d ...Y...y...3..H-
    0060 - 0f 23 c7 56 a8 b0 9c bf-aa a1 0e 4f 11 8b 18 14 .#.V.......O....
    0070 - 93 aa ca 02 ea 33 2f 92-b1 40 a2 01 c2 87 3f cc .....3/.. at ....?.
    0080 - bb 56 4d ed dc 56 7c 3d-f8 c5 9d 58 34 d6 68 94 .VM..V|=...X4.h.
    0090 - f8 10 03 59 f0 a7 bb 79-e0 9c a3 33 bf b9 48 2d ...Y...y...3..H-
    00a0 - 0f 23 c7 56 a8 b0 9c bf-aa a1 0e 4f 11 8b 18 14 .#.V.......O....
    00b0 - 93 aa ca 02 ea 33 2f 92-b1 40 a2 01 c2 87 3f cc .....3/.. at ....?.
    00c0 - bb 56 4d ed dc 56 7c 3d-f8 c5 9d 58 34 d6 68 94 .VM..V|=...X4.h.
    00d0 - f8 10 03 59 f0 a7 bb 79-e0 9c a3 33 bf b9 48 2d ...Y...y...3..H-
    00e0 - 0f 23 c7 56 a8 b0 9c bf-aa a1 0e 4f 11 8b 18 14 .#.V.......O....
    00f0 - 93 aa ca 02 ea 33 2f 92-b1 40 a2 01 c2 87 3f cc .....3/.. at ....?.

Which, for what I know if XTS (that is very little, I admit), this 
should not be the case.. am I correct ? I was under the impression that 
the encryption should be tied to the position in the file (or Disk) - 
i.e., the block number. If so, does anybody know what I am actually 
missing here ? Am I supposed to, somehow, modify the plaintext before 
encrypting it (e.g., XOR with the block number ?).

Thanks,
Max

P.S.: I am cross-posting the message also to dev as this might have 
better chances to get an answer there... ?


On 4/6/16 10:54 AM, Dr. Pala wrote:
> Hi all,
>
> I am trying to solve a particular problem related to provide random 
> access to encrypted files. AFAIK, I have two options. The first is to 
> use CRT mode (read only) and the second is to use XTS (read and write).
>
> Since I have never used the XTS mode before, does anybody have 
> experience in using the XTS support in OpenSSL ? Do you have any 
> particular recommendations for key re-usage in this case (i.e., shall 
> I use one key per file or can I re-use the same key for different 
> files) ?
>
> Any examples that can guide me through the implementation effort ?
>
> Thanks,
> Max
>
>
> -- 
> Massimiliano Pala, PhD
> Director at OpenCA Labs
> twitter: @openca
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mta.openssl.org/pipermail/openssl-users/attachments/20160406/39b4b75c/attachment-0001.html>


More information about the openssl-users mailing list