<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>