Commit d74d1674 authored by Simo Sorce's avatar Simo Sorce Committed by Niels Möller

Add support for XTS encryption mode

XEX encryption mode with tweak and ciphertext stealing (XTS) is
standardized in IEEE 1619 and generally used for storage devices.
Signed-off-by: default avatarSimo Sorce <simo@redhat.com>
parent d85e39b5
......@@ -135,7 +135,8 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
umac32.c umac64.c umac96.c umac128.c \
version.c \
write-be32.c write-le32.c write-le64.c \
yarrow256.c yarrow_key_event.c
yarrow256.c yarrow_key_event.c \
xts.c xts-aes128.c xts-aes256.c
hogweed_SOURCES = sexp.c sexp-format.c \
sexp-transport.c sexp-transport-format.c \
......@@ -206,7 +207,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
pgp.h pkcs1.h pss.h pss-mgf1.h realloc.h ripemd160.h rsa.h \
salsa20.h sexp.h \
serpent.h sha.h sha1.h sha2.h sha3.h twofish.h \
umac.h yarrow.h poly1305.h
umac.h yarrow.h xts.h poly1305.h
INSTALL_HEADERS = $(HEADERS) version.h @IF_MINI_GMP@ mini-gmp.h
......
......@@ -2001,7 +2001,8 @@ Book mode, @acronym{ECB}), leaks information.
Besides @acronym{ECB}, Nettle provides several other modes of operation:
Cipher Block Chaining (@acronym{CBC}), Counter mode (@acronym{CTR}), Cipher
Feedback (@acronym{CFB} and @acronym{CFB8}) and a couple of @acronym{AEAD}
Feedback (@acronym{CFB} and @acronym{CFB8}), XEX-based tweaked-codebook mode
with ciphertext stealing (@acronym{XTS}) and a couple of @acronym{AEAD}
modes (@pxref{Authenticated encryption}). @acronym{CBC} is widely used, but
there are a few subtle issues of information leakage, see, e.g.,
@uref{http://www.kb.cert.org/vuls/id/958563, @acronym{SSH} @acronym{CBC}
......@@ -2016,6 +2017,7 @@ authenticate the message.
* CBC::
* CTR::
* CFB and CFB8::
* XTS::
@end menu
@node CBC, CTR, Cipher modes, Cipher modes
......@@ -2187,7 +2189,7 @@ last three arguments define the source and destination area for the
operation.
@end deffn
@node CFB and CFB8, , CTR, Cipher modes
@node CFB and CFB8, XTS, CTR, Cipher modes
@comment node-name, next, previous, up
@subsection Cipher Feedback mode
......@@ -2340,6 +2342,147 @@ conventions. The last three arguments define the source and destination
area for the operation.
@end deffn
@node XTS, , CFB and CFB8, Cipher modes
@comment node-name, next, previous, up
@subsection XEX-based tweaked-codebook mode with ciphertext stealing
@cindex XEX-based tweaked-codebook mode with ciphertext stealing
@cindex XTS Mode
XEX-based tweaked-codebook mode with ciphertext stealing (@acronym{XTS}) is
a block mode like (@acronym{CBC}) but tweaked to be able to encrypt partial
blocks via a technique called ciphertext stealing, where the last complete
block of ciphertext is split and part returned as the last block and part
used as plaintext for the second to last block.
This mode is principally used to encrypt data at rest where it is not possible
to store additional metadata or blocks larger than the plain text. The most
common usage is for disk encryption. Due to the fact that ciphertext expansion
is not possible, data is not authenticated. This mode should not be used where
authentication is critical.
The message is divided into @code{n} blocks @code{M_1},@dots{} @code{M_n},
where @code{M_n} is of size @code{m} which may be smaller than the block size.
XTS always uses a fixed blocksize of 128 bit (16 bytes) length.
Unlike other modes, the key is double the size of that for the used cipher mode
(for example 256bit for AES-128 and 512bit for AES-256).
@acronym{XTS} encryption mode operates given:
@itemize
@item A multiplication by a primitive element alpha.
@code{MUL a^j} here represents the multiplication, where @code{j} is the power
of alpha, and the input value is converted into a 16 bytes array
@code{a_0[k], k = 0,1,..,15}. The multiplication is calculated as
@code{a_(j+1)[0] = (2(a_j[0] mod 128)) XOR (135 * floor(a_j[15]/128)}
@code{a_(j+1)[k] = (2(a_j[k] mod 128)) XOR (floor(a_j[k-1]/128), k = 1,2,..15}
Note that this operation is practically a 1 bit left shift operation with carry
propagating from one byte to the next, and if the last bit shift results in a
carry the decimal value 135 is XORed into the first byte.
@item The encryption key is provided as the @code{Key = K1 | K2}, where @code{|}
denotes string concatenation.
@code{E_k1} is the encryption function of the block cipher using @code{K1} as
the key, and @code{E_k2} is the same encryption function using @code{K2}
@item A 128 bit tweak value is provided as input and is denoted as @code{IV}
@end itemize
The @code{n} plaintext blocks are transformed into @code{n} ciphertext blocks
@code{C_1},@dots{} @code{C_n} as follows.
For a plaintext length that is a perfect multiple of the XTS block size:
@example
T_1 = E_k2(IV)
C_1 = E_k1(P_1 XOR T_1) XOR T_1
@dots{}
T_n = T_(n-1) MUL a
C_n = E_k1(P_n XOR T_n) XOR T_n
@end example
For any other plaintext lengths:
@example
T_1 = E_k2(IV)
C_1 = E_k1(P_1 XOR T_1) XOR T_1
@dots{}
T_(n-2) = T_(n-3) MUL a
C_(n-2) = E_k1(P_(n-2) XOR T_(n-2)) XOR T_(n-2)
T_(n-1) = T_(n-2) MUL a
CC_(n-1) = E_k1(P_(n-1) XOR T_(n-1)) XOR T_(n-1)
T_n = T_(n-1) MUL a
PP = [1..m]Pn | [m+1..128]CC_(n-1)
C_(n-1) = E_k1(PP XOR T_n) XOR T_n
C_n = [1..m]CC_(n-1)
@end example
@subsubsection General (@acronym{XTS}) interface.
The two general functions to encrypt and decrypt using the @acronym{XTS} block
cipher mode are the following:
@deftypefun void xts_encrypt_message (const void *@var{enc_ctx}, const void *@var{twk_ctx}, nettle_cipher_func *@var{encf}, const uint8_t *@var{tweak}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
@deftypefunx void xts_decrypt_message (const void *@var{dec_ctx}, const void *@var{twk_ctx}, nettle_cipher_func *@var{decf}, nettle_cipher_func *@var{encf}, const uint8_t *@var{tweak}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
Applies the encryption function @var{encf} or the decryption function
@var{decf} in @acronym{XTS} mode. At least one block (16 bytes) worth
of data must be available therefore specifying a length less than 16
bytes is illegal.
The functions @var{encf} @var{decf} are of type
@code{void f (const void *@var{ctx}, size_t @var{length}, uint8_t *@var{dst},
const uint8_t *@var{src})},
@noindent and the @code{xts_encrypt_message} and @code{xts_decrypt_message}
functions pass their arguments @var{enc_ctx}, @var{twk_ctx} and @var{dec_ctx}
to the functions @var{encf}, @var{decf} as @var{ctx}.
@end deftypefun
@subsubsection @acronym{XTS}-@acronym{AES} interface
The @acronym{AES} @acronym{XTS} functions provide an API for using the
@acronym{XTS} mode with the @acronym{AES} block ciphers. The parameters
all have the same meaning as the general interface, except that the
@var{enc_ctx}, @var{dec_ctx}, @var{twk_ctx}, @var{encf} and @var{decf} are
replaced with an @acronym{AES} context structure called @var{ctx}, and a
appropriate set-key function must be called before using any of the encryption
or decryption functions in this interface.
@deftp {Context struct} {struct xts_aes128_ctx}
Holds state corresponding to the AES-128 block cipher.
@end deftp
@deftp {Context struct} {struct xts_aes256_ctx}
Holds state corresponding to the AES-256 block cipher.
@end deftp
@deftypefun void xts_aes128_set_encrypt_key (struct xts_aes128_ctx *@var{ctx}, const uint8_t *@var{key})
@deftypefunx void xts_aes256_set_encrypt_key (struct xts_aes256_ctx *@var{ctx}, const uint8_t *@var{key})
@deftypefunx void xts_aes128_set_decrypt_key (struct xts_aes128_ctx *@var{ctx}, const uint8_t *@var{key})
@deftypefunx void xts_aes256_set_decrypt_key (struct xts_aes256_ctx *@var{ctx}, const uint8_t *@var{key})
Initializes the encryption or decryption key for the AES block cipher. The
lenght of the key must be double the size of the key for the corresponding
cipher (256 bits for AES-128 and 512 bits for AES-256). One of
these functions must be called before any of the other functions.
@end deftypefun
@deftypefun void xts_aes128_encrypt_message(struct xts_aes128_ctx *@var{ctx}, uint8_t *@var{tweak}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
@deftypefunx void xts_aes256_encrypt_message(struct xts_aes256_ctx *@var{ctx}, uint8_t *@var{tweak}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
@deftypefunx void xts_aes128_decrypt_message(struct xts_aes128_ctx *@var{ctx}, uint8_t *@var{tweak}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
@deftypefunx void xts_aes256_decrypt_message(struct xts_aes256_ctx *@var{ctx}, uint8_t *@var{tweak}, size_t @var{length}, uint8_t *@var{dst}, const uint8_t *@var{src})
These are identical to @code{xts_encrypt_message} and
@code{xts_decrypt_message}, except that @var{enc_ctx}, @var{dec_ctx},
@var{twk_ctx}, @var{encf} and @var{decf} are replaced by the @var{ctx} context
structure.
@end deftypefun
@node Authenticated encryption, Keyed hash functions, Cipher modes, Reference
@comment node-name, next, previous, up
......
......@@ -95,6 +95,7 @@
/umac-test
/version-test
/yarrow-test
/xts-test
/test.in
/test1.out
......
......@@ -166,6 +166,9 @@ buffer-test$(EXEEXT): buffer-test.$(OBJEXT)
yarrow-test$(EXEEXT): yarrow-test.$(OBJEXT)
$(LINK) yarrow-test.$(OBJEXT) $(TEST_OBJS) -o yarrow-test$(EXEEXT)
xts-test$(EXEEXT): xts-test.$(OBJEXT)
$(LINK) xts-test.$(OBJEXT) $(TEST_OBJS) -o xts-test$(EXEEXT)
pbkdf2-test$(EXEEXT): pbkdf2-test.$(OBJEXT)
$(LINK) pbkdf2-test.$(OBJEXT) $(TEST_OBJS) -o pbkdf2-test$(EXEEXT)
......
......@@ -32,7 +32,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
hmac-test.c umac-test.c \
meta-hash-test.c meta-cipher-test.c\
meta-aead-test.c meta-armor-test.c \
buffer-test.c yarrow-test.c pbkdf2-test.c
buffer-test.c yarrow-test.c xts-test.c pbkdf2-test.c
TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
rsa2sexp-test.c sexp2rsa-test.c \
......
#include "testutils.h"
#include "aes.h"
#include "xts.h"
#include "nettle-internal.h"
static void
test_check_data(const char *operation,
const uint8_t *input, const uint8_t *output,
const uint8_t *expected, size_t length)
{
if (!MEMEQ(length, output, expected))
{
fprintf(stderr, "XTS %s failed:\nInput:", operation);
print_hex(length, input);
fprintf(stderr, "\nOutput: ");
print_hex(length, output);
fprintf(stderr, "\nExpected:");
print_hex(length, expected);
fprintf(stderr, "\n");
FAIL();
}
}
static void
test_cipher_xts(const struct nettle_cipher *cipher,
const struct tstring *key,
const struct tstring *tweak,
const struct tstring *cleartext,
const struct tstring *ciphertext)
{
void *twk_ctx = xalloc(cipher->context_size);
void *ctx = xalloc(cipher->context_size);
uint8_t *data, *data2;
size_t length = cleartext->length;
ASSERT (cleartext->length == ciphertext->length);
ASSERT (key->length == cipher->key_size * 2);
ASSERT (tweak->length == XTS_BLOCK_SIZE);
data = xalloc(length);
data2 = xalloc(length);
cipher->set_encrypt_key(ctx, key->data);
cipher->set_encrypt_key(twk_ctx, &key->data[key->length / 2]);
xts_encrypt_message(ctx, twk_ctx, cipher->encrypt,
tweak->data, length, data, cleartext->data);
test_check_data("encrypt", cleartext->data, data, ciphertext->data, length);
cipher->set_decrypt_key(ctx, key->data);
cipher->set_encrypt_key(twk_ctx, &key->data[key->length / 2]);
xts_decrypt_message(ctx, twk_ctx, cipher->decrypt, cipher->encrypt,
tweak->data, length, data2, data);
test_check_data("decrypt", data, data2, cleartext->data, length);
memcpy(data, cleartext->data, length);
cipher->set_encrypt_key(ctx, key->data);
cipher->set_encrypt_key(twk_ctx, &key->data[key->length / 2]);
xts_encrypt_message(ctx, twk_ctx, cipher->encrypt,
tweak->data, length, data, data);
test_check_data("inplace encrypt",
cleartext->data, data, ciphertext->data, length);
cipher->set_decrypt_key(ctx, key->data);
cipher->set_encrypt_key(twk_ctx, &key->data[key->length / 2]);
xts_decrypt_message(ctx, twk_ctx, cipher->decrypt, cipher->encrypt,
tweak->data, length, data, data);
test_check_data("inplace decrypt", data, data, cleartext->data, length);
/* make sure AES128 specific functions also works the same */
if (cipher == &nettle_aes128) {
struct xts_aes128_key xts_key;
xts_aes128_set_encrypt_key(&xts_key, key->data);
xts_aes128_encrypt_message(&xts_key, tweak->data, length, data,
cleartext->data);
test_check_data("encrypt",
cleartext->data, data, ciphertext->data, length);
xts_aes128_set_decrypt_key(&xts_key, key->data);
xts_aes128_decrypt_message(&xts_key, tweak->data, length, data,
ciphertext->data);
test_check_data("decrypt",
ciphertext->data, data, cleartext->data, length);
}
/* make sure AES256 specific functions also works the same */
if (cipher == &nettle_aes256) {
struct xts_aes256_key xts_key;
xts_aes256_set_encrypt_key(&xts_key, key->data);
xts_aes256_encrypt_message(&xts_key, tweak->data, length, data,
cleartext->data);
test_check_data("encrypt",
cleartext->data, data, ciphertext->data, length);
xts_aes256_set_decrypt_key(&xts_key, key->data);
xts_aes256_decrypt_message(&xts_key, tweak->data, length, data,
ciphertext->data);
test_check_data("decrypt",
ciphertext->data, data, cleartext->data, length);
}
free(twk_ctx);
free(ctx);
free(data);
free(data2);
}
void
test_main(void)
{
/* From NIST CAVS 11.0,
*
* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/XTSTestVectors.zip
*
* Selection of testing vectors from the above CAVS set
*/
/* AES-128 single block - exact block size multiple */
test_cipher_xts(&nettle_aes128,
SHEX("a1b90cba3f06ac353b2c343876081762"
"090923026e91771815f29dab01932f2f"),
SHEX("4faef7117cda59c66e4b92013e768ad5"),
SHEX("ebabce95b14d3c8d6fb350390790311c"),
SHEX("778ae8b43cb98d5a825081d5be471c63"));
/* AES-128 two blocks - exact block size multiple */
test_cipher_xts(&nettle_aes128,
SHEX("750372c3d82f63382867be6662acfa4a"
"259be3fa9bc662a1154ffaaed8b448a5"),
SHEX("93a29254c47e4260669621307d4f5cd3"),
SHEX("d8e3a56559a436ce0d8b212c80a88b23"
"af62b0e598f208e03c1f2e9fa563a54b"),
SHEX("495f7855535efd133464dc9a9abf8a0f"
"28facbce21bd3c22178ec489b799e491"));
/* AES-128 partial second block */
test_cipher_xts(&nettle_aes128,
SHEX("394c97881abd989d29c703e48a72b397"
"a7acf51b59649eeea9b33274d8541df4"),
SHEX("4b15c684a152d485fe9937d39b168c29"),
SHEX("2f3b9dcfbae729583b1d1ffdd16bb6fe"
"2757329435662a78f0"),
SHEX("f3473802e38a3ffef4d4fb8e6aa266eb"
"de553a64528a06463e"));
/* AES-256 two blocks - exact block size multiple */
test_cipher_xts(&nettle_aes256,
SHEX("1ea661c58d943a0e4801e42f4b094714"
"9e7f9f8e3e68d0c7505210bd311a0e7c"
"d6e13ffdf2418d8d1911c004cda58da3"
"d619b7e2b9141e58318eea392cf41b08"),
SHEX("adf8d92627464ad2f0428e84a9f87564"),
SHEX("2eedea52cd8215e1acc647e810bbc364"
"2e87287f8d2e57e36c0a24fbc12a202e"),
SHEX("cbaad0e2f6cea3f50b37f934d46a9b13"
"0b9d54f07e34f36af793e86f73c6d7db"));
/* AES-256 three blocks - exact block size multiple */
test_cipher_xts(&nettle_aes256,
SHEX("266c336b3b01489f3267f52835fd92f6"
"74374b88b4e1ebd2d36a5f457581d9d0"
"42c3eef7b0b7e5137b086496b4d9e6ac"
"658d7196a23f23f036172fdb8faee527"),
SHEX("06b209a7a22f486ecbfadb0f3137ba42"),
SHEX("ca7d65ef8d3dfad345b61ccddca1ad81"
"de830b9e86c7b426d76cb7db766852d9"
"81c6b21409399d78f42cc0b33a7bbb06"),
SHEX("c73256870cc2f4dd57acc74b5456dbd7"
"76912a128bc1f77d72cdebbf270044b7"
"a43ceed29025e1e8be211fa3c3ed002d"));
}
/* xts-aes128.c
XTS Mode using AES128 as the underlying cipher.
Copyright (C) 2018 Red Hat, Inc.
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include "aes.h"
#include "xts.h"
void
xts_aes128_set_encrypt_key(struct xts_aes128_key *xts_key, const uint8_t *key)
{
aes128_set_encrypt_key(&xts_key->cipher, key);
aes128_set_encrypt_key(&xts_key->tweak_cipher, &key[AES128_KEY_SIZE]);
}
void
xts_aes128_set_decrypt_key(struct xts_aes128_key *xts_key, const uint8_t *key)
{
aes128_set_decrypt_key(&xts_key->cipher, key);
aes128_set_encrypt_key(&xts_key->tweak_cipher, &key[AES128_KEY_SIZE]);
}
void
xts_aes128_encrypt_message(struct xts_aes128_key *xts_key,
const uint8_t *tweak, size_t length,
uint8_t *dst, const uint8_t *src)
{
xts_encrypt_message(&xts_key->cipher, &xts_key->tweak_cipher,
(nettle_cipher_func *) aes128_encrypt,
tweak, length, dst, src);
}
void
xts_aes128_decrypt_message(struct xts_aes128_key *xts_key,
const uint8_t *tweak, size_t length,
uint8_t *dst, const uint8_t *src)
{
xts_decrypt_message(&xts_key->cipher, &xts_key->tweak_cipher,
(nettle_cipher_func *) aes128_decrypt,
(nettle_cipher_func *) aes128_encrypt,
tweak, length, dst, src);
}
/* xts-aes256.c
XTS Mode using AES256 as the underlying cipher.
Copyright (C) 2018 Red Hat, Inc.
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include "aes.h"
#include "xts.h"
void
xts_aes256_set_encrypt_key(struct xts_aes256_key *xts_key, const uint8_t *key)
{
aes256_set_encrypt_key(&xts_key->cipher, key);
aes256_set_encrypt_key(&xts_key->tweak_cipher, &key[AES256_KEY_SIZE]);
}
void
xts_aes256_set_decrypt_key(struct xts_aes256_key *xts_key, const uint8_t *key)
{
aes256_set_decrypt_key(&xts_key->cipher, key);
aes256_set_encrypt_key(&xts_key->tweak_cipher, &key[AES256_KEY_SIZE]);
}
void
xts_aes256_encrypt_message(struct xts_aes256_key *xts_key,
const uint8_t *tweak, size_t length,
uint8_t *dst, const uint8_t *src)
{
xts_encrypt_message(&xts_key->cipher, &xts_key->tweak_cipher,
(nettle_cipher_func *) aes256_encrypt,
tweak, length, dst, src);
}
void
xts_aes256_decrypt_message(struct xts_aes256_key *xts_key,
const uint8_t *tweak, size_t length,
uint8_t *dst, const uint8_t *src)
{
xts_decrypt_message(&xts_key->cipher, &xts_key->tweak_cipher,
(nettle_cipher_func *) aes256_decrypt,
(nettle_cipher_func *) aes256_encrypt,
tweak, length, dst, src);
}
/* xts.c
XEX-based tweaked-codebook mode with ciphertext stealing (XTS)
Copyright (C) 2018 Red Hat, Inc.
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "xts.h"
#include "macros.h"
#include "memxor.h"
#include "nettle-internal.h"
/* shift one and XOR with 0x87. */
/* src and dest can point to the same buffer for in-place operations */
static void
xts_shift(union nettle_block16 *dst,
const union nettle_block16 *src)
{
uint8_t carry = src->b[15] >> 7;
uint64_t b0 = LE_READ_UINT64(src->b);
uint64_t b1 = LE_READ_UINT64(src->b+8);
b1 = (b1 << 1) | (b0 >> 63);
b0 = b0 << 1;
LE_WRITE_UINT64(dst->b, b0);
LE_WRITE_UINT64(dst->b+8, b1);
dst->b[0] ^= 0x87 & -carry;
}
/*
* prev is the block to steal from
* curr is the input block to the last step
* length is the partial block length
* dst is the destination partial block
* src is the source partial block
*
* In the Encryption case:
* prev -> the output of the N-1 encryption step
* curr -> the input to the Nth step (will be encrypted as Cn-1)
* dst -> the final Cn partial block
* src -> the final Pn partial block
*
* In the decryption case:
* prev -> the output of the N-1 decryption step
* curr -> the input to the Nth step (will be decrypted as Pn-1)
* dst -> the final Pn partial block
* src -> the final Cn partial block
*/
static void
xts_steal(uint8_t *prev, uint8_t *curr,
size_t length, uint8_t *dst, const uint8_t *src)
{
/* copy the remaining in the current input block */
memcpy(curr, src, length);
/* fill the current block with the last blocksize - length
* bytes of the previous block */
memcpy(&curr[length], &prev[length], XTS_BLOCK_SIZE - length);
/* This must be last or inplace operations will break
* copy 'length' bytes of the previous block in the
* destination block, which is the final partial block
* returned to the caller */
memcpy(dst, prev, length);
}
static void
check_length(size_t length, uint8_t *dst)
{
assert(length >= XTS_BLOCK_SIZE);
/* asserts may be compiled out, try to save the user by zeroing the dst in
* case the buffer contains sensitive data (like the clear text for inplace
* encryption) */
if (length < XTS_BLOCK_SIZE)
memset(dst, '\0', length);