<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Hi all,<br>
    <br>
    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:<br>
    <blockquote><tt>// Tracking down XTS code in OSSL<br>
        //<br>
        // crypto/evp/e_evp.c:<br>
        //  EVP_AES_XTS_CTX (@line 85)<br>
        //   aes_xts_ctrl (supports EVP_CTRL_COPY & EVP_CTRL_INIT
        only) (@line 1000)<br>
        //   aes_xts_init_key (@line 1026)<br>
        //   aes_xts_cipher (@line 1088) -> CRYPTO_xts128_encrypt<br>
        //   define: BLOCK_CIPHER_custom (@line 1119)<br>
        //<br>
        // crypto/modes/modes.h: [TODO: check tweak, scratch]<br>
        //  XTS128_CONTEXT (@line 144) -> struct xts128_context<br>
        //  CRYPTO_xts128_encrypt (@line 146)<br>
        //<br>
        // crypto/modes/xts128.c:<br>
        //   CRYPTO_xts128_encrypt (@line 61)<br>
        //<br>
        // crypto/modes/modes_lcl.h:<br>
        //   struct xts128_context (@line 120)<br>
        //<br>
      </tt></blockquote>
    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).<br>
    <br>
    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). <br>
    <br>
    Here's an initial (very simple) test implementation:<br>
    <blockquote><tt>// Init the CTX</tt><tt><br>
      </tt><tt>ctx = EVP_CIPHER_CTX_new();</tt><tt><br>
      </tt><tt><br>
      </tt><tt>// Set cipher type and mode</tt><tt><br>
      </tt><tt>if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_xts(), NULL,
        key, iv)</tt><tt><br>
      </tt><tt><br>
      </tt><tt>// Total bytes to encrypt</tt><tt><br>
      </tt><tt>n_ops = 0;</tt><tt><br>
      </tt><tt>next_op_size = 0;</tt><tt><br>
      </tt><tt>remains = clear_len;</tt><tt><br>
      </tt><tt><br>
      </tt><tt>enc_buf_curr = enc_buf;</tt><tt><br>
      </tt><tt>clear_buf_curr = clear_buf;</tt><tt><br>
      </tt><tt><br>
      </tt><tt>// Encrypt plaintext</tt><tt><br>
      </tt><tt>while (remains > 0) {</tt><tt><br>
      </tt><tt><br>
      </tt><tt>  // Gets the size of the next chunk to be encrypted</tt><tt><br>
      </tt><tt>  next_op_size = (block_size < remains ? block_size :
        remains);</tt><tt><br>
      </tt><tt><br>
      </tt><tt>  // Performs the encryption</tt><tt><br>
      </tt><tt>  EVP_EncryptUpdate(ctx, enc_buf_curr, &tmp_len,
        clear_buf_curr, next_op_size);</tt><tt><br>
      </tt><tt><br>
          // Updates the number of ops</tt><tt><br>
      </tt><tt>  n_ops++;</tt><tt><br>
      </tt><tt><br>
      </tt><tt>  // Updates the remaining data size to encrypt</tt><tt><br>
      </tt><tt>  remains -= block_size;</tt><tt><br>
      </tt><tt><br>
      </tt><tt>  // Updates the pointer to the next enc buffer space</tt><tt><br>
      </tt><tt>  enc_buf_curr += tmp_len;</tt><tt><br>
      </tt><tt><br>
      </tt><tt>  // Updates the pointer to the next clear buffer space</tt><tt><br>
      </tt><tt>  clear_buf_curr += block_size;</tt><tt><br>
      </tt><tt>}</tt><tt><br>
      </tt><tt><br>
      </tt><tt>// Finalize the Encryption</tt><tt><br>
      </tt><tt>EVP_EncryptFinal_ex(ctx, &enc_buf[ret_len],
        &tmp_len);</tt><tt><br>
      </tt><tt><br>
      </tt><tt>// Now we can output the cyphertext (encrypted message)</tt><tt><br>
      </tt><tt>printf("Ciphertext %d:\n", ret_len);</tt><tt><br>
      </tt><tt>BIO_dump_fp(stdout, (char *)enc_buf, ret_len);</tt><tt><br>
      </tt><tt>printf("\n");</tt><tt><br>
      </tt><tt><br>
      </tt><tt>// Let's free the OpenSSL CTX structure</tt><tt><br>
      </tt><tt>EVP_CIPHER_CTX_free(ctx);</tt><br>
    </blockquote>
    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:<br>
    <blockquote><tt> char * text = </tt><br>
      <tt>    // 128bits per row</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF"</tt><br>
      <tt>    "0123456789ABCDEF";</tt><br>
    </blockquote>
    The output is as follows:<br>
    <blockquote><tt>Encrypted Data:</tt><br>
      <tt>0000 - bb 56 4d ed dc 56 7c 3d-f8 c5 9d 58 34 d6 68 94  
        .VM..V|=...X4.h.</tt><br>
      <tt>0010 - f8 10 03 59 f0 a7 bb 79-e0 9c a3 33 bf b9 48 2d  
        ...Y...y...3..H-</tt><br>
      <tt>0020 - 0f 23 c7 56 a8 b0 9c bf-aa a1 0e 4f 11 8b 18 14  
        .#.V.......O....</tt><br>
      <tt>0030 - 93 aa ca 02 ea 33 2f 92-b1 40 a2 01 c2 87 3f cc  
        .....3/..@....?.</tt><br>
      <tt>0040 - bb 56 4d ed dc 56 7c 3d-f8 c5 9d 58 34 d6 68 94  
        .VM..V|=...X4.h.</tt><br>
      <tt>0050 - f8 10 03 59 f0 a7 bb 79-e0 9c a3 33 bf b9 48 2d  
        ...Y...y...3..H-</tt><br>
      <tt>0060 - 0f 23 c7 56 a8 b0 9c bf-aa a1 0e 4f 11 8b 18 14  
        .#.V.......O....</tt><br>
      <tt>0070 - 93 aa ca 02 ea 33 2f 92-b1 40 a2 01 c2 87 3f cc  
        .....3/..@....?.</tt><br>
      <tt>0080 - bb 56 4d ed dc 56 7c 3d-f8 c5 9d 58 34 d6 68 94  
        .VM..V|=...X4.h.</tt><br>
      <tt>0090 - f8 10 03 59 f0 a7 bb 79-e0 9c a3 33 bf b9 48 2d  
        ...Y...y...3..H-</tt><br>
      <tt>00a0 - 0f 23 c7 56 a8 b0 9c bf-aa a1 0e 4f 11 8b 18 14  
        .#.V.......O....</tt><br>
      <tt>00b0 - 93 aa ca 02 ea 33 2f 92-b1 40 a2 01 c2 87 3f cc  
        .....3/..@....?.</tt><br>
      <tt>00c0 - bb 56 4d ed dc 56 7c 3d-f8 c5 9d 58 34 d6 68 94  
        .VM..V|=...X4.h.</tt><br>
      <tt>00d0 - f8 10 03 59 f0 a7 bb 79-e0 9c a3 33 bf b9 48 2d  
        ...Y...y...3..H-</tt><br>
      <tt>00e0 - 0f 23 c7 56 a8 b0 9c bf-aa a1 0e 4f 11 8b 18 14  
        .#.V.......O....</tt><br>
      <tt>00f0 - 93 aa ca 02 ea 33 2f 92-b1 40 a2 01 c2 87 3f cc  
        .....3/..@....?.</tt><br>
    </blockquote>
    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 ?).<br>
    <br>
    Thanks,<br>
    Max<br>
    <br>
    P.S.: I am cross-posting the message also to dev as this might have
    better chances to get an answer there... ?<br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 4/6/16 10:54 AM, Dr. Pala wrote:<br>
    </div>
    <blockquote cite="mid:5705150D.6060200@openca.org" type="cite">Hi
      all,
      <br>
      <br>
      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).
      <br>
      <br>
      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) ?
      <br>
      <br>
      Any examples that can guide me through the implementation effort ?
      <br>
      <br>
      Thanks,
      <br>
      Max
      <br>
      <br>
      <br>
      <pre class="moz-signature" cols="72">-- 
Massimiliano Pala, PhD
Director at OpenCA Labs
twitter: @openca</pre>
    </blockquote>
  </body>
</html>