<div dir="ltr">Thanks for the feedback Matt.<div><br></div><div>I definitely missed this difference between XTS and GCM and didnt realize one supports "streaming" and one doesnt.</div><div><br></div><div>For our application we only ever call EncryptUpdate once so XTS works well but its great to understand the limitations and make sure future changes dont screw something up.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jan 25, 2019 at 4:18 PM Matt Caswell <<a href="mailto:matt@openssl.org">matt@openssl.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
<br>
On 25/01/2019 20:16, Andrew Tucker wrote:<br>
> I was doing some comparisons of XTS and GCM mode using the EVP APIs and found a<br>
> discrepancy that seems to be an issue with XTS.<br>
> <br>
> In GCM mode if the buffer is encrypted in one call to EVP_EncryptUpdate or with<br>
> several calls with smaller buffers the resulting ciphertext is the same, as I<br>
> would expect.   With XTS mode, calling EVP_EncryptUpdate results in the same<br>
> ciphertext for the same plaintext and does not match the results when the buffer<br>
> is encrypted with one call to EVP_EncryptUpdate.<br>
> <br>
> I would expect that the counter is incremented in both XTS and GCM mode in the<br>
> same way and that in both cases the output would match regardless of the<br>
> encryption block size.<br>
> <br>
> A simple repro test is attached.    If you run it you can see that the output<br>
> "GCM in one block" matches the output for "GCM in 16 byte blocks" and the<br>
> outputs do not match for XTS.<br>
> <br>
> I am using OpenSSL v1.02p but I have tried with other versions and got the same<br>
> results.<br>
> <br>
> Am I misunderstanding the use of XTS mode or is this an issue with OpenSSL?<br>
<br>
The documentation for XTS mode seems to be particularly dreadful (i.e.<br>
practically non-existent).<br>
<br>
XTS mode was designed for disk encryption and works quite differently to modes<br>
like GCM. XTS encrypts blocks at a time where each block has a separate "tweak"<br>
value (and by "block" here I'm talking about disk blocks not encryption blocks).<br>
There is no "streaming" concept - there is not necessarily any relationship with<br>
the tweak from one block to be encrypted to the next one. AFAICT from code<br>
inspection you are expected to set the tweak in the IV field and then encrypt an<br>
entire (disk) block in one go with EVP_EncryptUpdate().<br>
<br>
This seems to be supported by this post from Steve Henson where he describes the<br>
XTS implementation as not being able to stream and as a "one shot" version:<br>
<br>
<a href="http://openssl.6102.n7.nabble.com/patch-AES-XTS-supporting-custom-iv-from-openssl-enc-command-tt51949.html#a52009" rel="noreferrer" target="_blank">http://openssl.6102.n7.nabble.com/patch-AES-XTS-supporting-custom-iv-from-openssl-enc-command-tt51949.html#a52009</a><br>
<br>
In this later post in the same thread Steve talks about calling<br>
EVP_EncryptInit_ex again with all the params set to NULL except the ctx and iv<br>
(i.e. tweak) in order to set a new tweak and then call EVP_EncryptUpdate again.<br>
<br>
<a href="http://openssl.6102.n7.nabble.com/patch-AES-XTS-supporting-custom-iv-from-openssl-enc-command-tp51949p52006.html" rel="noreferrer" target="_blank">http://openssl.6102.n7.nabble.com/patch-AES-XTS-supporting-custom-iv-from-openssl-enc-command-tp51949p52006.html</a><br>
<br>
In other words I think you are supposed to use it something like this (error<br>
handling omitted for brevity):<br>
<br>
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();<br>
<br>
EVP_EncryptInit_ex(ctx, EVP_aes_256_xts(), NULL, aes_key, NULL);<br>
<br>
EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, tweak1);<br>
EVP_EncryptUpdate(ctx, out, &outl, block1, blocklen1);<br>
EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, tweak2);<br>
EVP_EncryptUpdate(ctx, out, &outl, block2, blocklen2);<br>
EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, tweak3);<br>
EVP_EncryptUpdate(ctx, out, &outl, block3, blocklen3);<br>
<br>
That really needs to go in the man pages.<br>
<br>
Matt<br>
<br>
<br>
<br>
<br>
<br>
-- <br>
openssl-users mailing list<br>
To unsubscribe: <a href="https://mta.openssl.org/mailman/listinfo/openssl-users" rel="noreferrer" target="_blank">https://mta.openssl.org/mailman/listinfo/openssl-users</a><br>
</blockquote></div>