Merge pull request #7522 from douzzer/20240511-aes-xts-stream

20240511-aes-xts-stream
This commit is contained in:
David Garske
2024-05-15 06:22:20 -07:00
committed by GitHub
9 changed files with 4776 additions and 92 deletions

View File

@@ -39,7 +39,8 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
# List of refs to test # List of refs to test
ref: [ release/2.6, v2.6.0, master ] # disabled master on 20240514 -- see https://github.com/wolfSSL/wolfssl/issues/7508
ref: [ release/2.6, v2.6.0 ]
name: ${{ matrix.ref }} name: ${{ matrix.ref }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
# This should be a safe limit for the tests to run. # This should be a safe limit for the tests to run.

View File

@@ -939,6 +939,7 @@ then
if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -ge 6 || test "$FIPS_VERSION" = "v5-dev"; then if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -ge 6 || test "$FIPS_VERSION" = "v5-dev"; then
test "$enable_aesxts" = "" && enable_aesxts=yes test "$enable_aesxts" = "" && enable_aesxts=yes
test "$enable_aesxts_stream" = "" && test "$enable_aesxts" = "yes" && (test "$enable_armasm" = "" || test "$enable_armasm" = "no") && enable_aesxts_stream=yes
test "$enable_aessiv" = "" && enable_aessiv=yes test "$enable_aessiv" = "" && enable_aessiv=yes
fi fi
@@ -1078,6 +1079,7 @@ then
if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -ge 6 || test "$FIPS_VERSION" = "v5-dev"; then if test "$ENABLED_FIPS" = "no" || test "$HAVE_FIPS_VERSION" -ge 6 || test "$FIPS_VERSION" = "v5-dev"; then
test "$enable_aesxts" = "" && enable_aesxts=yes test "$enable_aesxts" = "" && enable_aesxts=yes
test "$enable_aesxts_stream" = "" && test "$enable_aesxts" = "yes" && (test "$enable_armasm" = "" || test "$enable_armasm" = "no") && enable_aesxts_stream=yes
test "$enable_aessiv" = "" && enable_aessiv=yes test "$enable_aessiv" = "" && enable_aessiv=yes
fi fi
@@ -4848,6 +4850,17 @@ AC_ARG_ENABLE([aesxts],
[ ENABLED_AESXTS=no ] [ ENABLED_AESXTS=no ]
) )
AS_IF([test "$ENABLED_AESXTS" = "yes" && test "$ENABLED_ARMASM" = "no"],
[ ENABLED_AESXTS_STREAM_DEFAULT=yes ],
[ ENABLED_AESXTS_STREAM_DEFAULT=no ]
)
AC_ARG_ENABLE([aesxts-stream],
[AS_HELP_STRING([--enable-aesxts-stream],[Enable wolfSSL AES-XTS support with streaming APIs (default: disabled)])],
[ ENABLED_AESXTS_STREAM=$enableval ],
[ ENABLED_AESXTS_STREAM=$ENABLED_AESXTS_STREAM_DEFAULT ]
)
# legacy old option name, for compatibility: # legacy old option name, for compatibility:
AC_ARG_ENABLE([xts], AC_ARG_ENABLE([xts],
[AS_HELP_STRING([--enable-xts],[Please use --enable-aesxts])], [AS_HELP_STRING([--enable-xts],[Please use --enable-aesxts])],
@@ -5070,6 +5083,9 @@ AS_CASE([$FIPS_VERSION],
AS_IF([test "x$ENABLED_AESXTS" = "xyes" && test "x$ENABLED_AESNI" = "xyes"], AS_IF([test "x$ENABLED_AESXTS" = "xyes" && test "x$ENABLED_AESNI" = "xyes"],
[AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_AES_XTS"]) [AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_AES_XTS"])
AS_IF([test "x$ENABLED_AESXTS_STREAM" = "xno" && ! (test "$ENABLED_ARMASM" = "yes" || test "$ENABLED_ARMASM_CRYPTO" = "no")],
[ENABLED_AESXTS_STREAM="yes"])
AS_IF([(test "$ENABLED_AESCCM" = "yes" && test "$HAVE_AESCCM_PORT" != "yes") || AS_IF([(test "$ENABLED_AESCCM" = "yes" && test "$HAVE_AESCCM_PORT" != "yes") ||
(test "$ENABLED_AESCTR" = "yes" && test "$HAVE_AESCTR_PORT" != "yes") || (test "$ENABLED_AESCTR" = "yes" && test "$HAVE_AESCTR_PORT" != "yes") ||
(test "$ENABLED_AESGCM" = "yes" && test "$HAVE_AESGCM_PORT" != "yes") || (test "$ENABLED_AESGCM" = "yes" && test "$HAVE_AESGCM_PORT" != "yes") ||
@@ -8351,15 +8367,20 @@ then
for lkcapi_alg in $(echo "$ENABLED_LINUXKM_LKCAPI_REGISTER" | tr ',' ' ') for lkcapi_alg in $(echo "$ENABLED_LINUXKM_LKCAPI_REGISTER" | tr ',' ' ')
do do
case "$lkcapi_alg" in case "$lkcapi_alg" in
all) AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_ALL" ;; all) test "$ENABLED_EXPERIMENTAL" = "yes" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: requires --enable-experimental.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_ALL" ;;
'cbc(aes)') test "$ENABLED_AESCBC" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-CBC implementation not enabled.]) 'cbc(aes)') test "$ENABLED_AESCBC" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-CBC implementation not enabled.])
test "$ENABLED_EXPERIMENTAL" = "yes" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: requires --enable-experimental.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESCBC" ;; AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESCBC" ;;
'cfb(aes)') test "$ENABLED_AESCFB" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-CFB implementation not enabled.]) 'cfb(aes)') test "$ENABLED_AESCFB" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-CFB implementation not enabled.])
test "$ENABLED_EXPERIMENTAL" = "yes" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: requires --enable-experimental.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESCFB" ;; AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESCFB" ;;
'gcm(aes)') test "$ENABLED_AESGCM" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-GCM implementation not enabled.]) 'gcm(aes)') test "$ENABLED_AESGCM" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-GCM implementation not enabled.])
test "$ENABLED_AESGCM_STREAM" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: --enable-aesgcm-stream is required for LKCAPI.]) test "$ENABLED_AESGCM_STREAM" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: --enable-aesgcm-stream is required for LKCAPI.])
test "$ENABLED_EXPERIMENTAL" = "yes" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: requires --enable-experimental.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESGCM" ;; AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESGCM" ;;
'xts(aes)') test "$ENABLED_AESXTS" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-XTS implementation not enabled.]) 'xts(aes)') test "$ENABLED_AESXTS" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: AES-XTS implementation not enabled.])
test "$ENABLED_AESXTS_STREAM" != "no" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: --enable-aesxts-stream is required for LKCAPI.])
AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESXTS" ;; AM_CFLAGS="$AM_CFLAGS -DLINUXKM_LKCAPI_REGISTER_AESXTS" ;;
*) AC_MSG_ERROR([Unsupported LKCAPI algorithm "$lkcapi_alg".]) ;; *) AC_MSG_ERROR([Unsupported LKCAPI algorithm "$lkcapi_alg".]) ;;
esac esac
@@ -9009,6 +9030,17 @@ then
fi fi
fi fi
if test "$ENABLED_AESXTS_STREAM" != "no"
then
if test "$ENABLED_AESXTS" = "no"
then
AC_MSG_ERROR([AES-XTS streaming enabled but AES-XTS is disabled])
else
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AESXTS_STREAM"
AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_AESXTS_STREAM"
fi
fi
if test "$ENABLED_IOTSAFE" != "no" if test "$ENABLED_IOTSAFE" != "no"
then then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_IOTSAFE" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_IOTSAFE"
@@ -9769,6 +9801,7 @@ echo " * AES-CTR: $ENABLED_AESCTR"
echo " * AES-CFB: $ENABLED_AESCFB" echo " * AES-CFB: $ENABLED_AESCFB"
echo " * AES-OFB: $ENABLED_AESOFB" echo " * AES-OFB: $ENABLED_AESOFB"
echo " * AES-XTS: $ENABLED_AESXTS" echo " * AES-XTS: $ENABLED_AESXTS"
echo " * AES-XTS streaming: $ENABLED_AESXTS_STREAM"
echo " * AES-SIV: $ENABLED_AESSIV" echo " * AES-SIV: $ENABLED_AESSIV"
echo " * AES-EAX: $ENABLED_AESEAX" echo " * AES-EAX: $ENABLED_AESEAX"
echo " * AES Bitspliced: $ENABLED_AESBS" echo " * AES Bitspliced: $ENABLED_AESBS"

View File

@@ -75,16 +75,25 @@
#if defined(HAVE_AES_CBC) && \ #if defined(HAVE_AES_CBC) && \
(defined(LINUXKM_LKCAPI_REGISTER_ALL) || \ (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCBC)) defined(LINUXKM_LKCAPI_REGISTER_AESCBC))
#ifndef WOLFSSL_EXPERIMENTAL_SETTINGS
#error Experimental settings without WOLFSSL_EXPERIMENTAL_SETTINGS
#endif
static int linuxkm_test_aescbc(void); static int linuxkm_test_aescbc(void);
#endif #endif
#if defined(WOLFSSL_AES_CFB) && \ #if defined(WOLFSSL_AES_CFB) && \
(defined(LINUXKM_LKCAPI_REGISTER_ALL) || \ (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
defined(LINUXKM_LKCAPI_REGISTER_AESCFB)) defined(LINUXKM_LKCAPI_REGISTER_AESCFB))
#ifndef WOLFSSL_EXPERIMENTAL_SETTINGS
#error Experimental settings without WOLFSSL_EXPERIMENTAL_SETTINGS
#endif
static int linuxkm_test_aescfb(void); static int linuxkm_test_aescfb(void);
#endif #endif
#if defined(HAVE_AESGCM) && \ #if defined(HAVE_AESGCM) && \
(defined(LINUXKM_LKCAPI_REGISTER_ALL) || \ (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
defined(LINUXKM_LKCAPI_REGISTER_AESGCM)) defined(LINUXKM_LKCAPI_REGISTER_AESGCM))
#ifndef WOLFSSL_EXPERIMENTAL_SETTINGS
#error Experimental settings without WOLFSSL_EXPERIMENTAL_SETTINGS
#endif
static int linuxkm_test_aesgcm(void); static int linuxkm_test_aesgcm(void);
#endif #endif
#if defined(WOLFSSL_AES_XTS) && \ #if defined(WOLFSSL_AES_XTS) && \
@@ -790,6 +799,10 @@ static int gcmAesAead_loaded = 0;
(defined(LINUXKM_LKCAPI_REGISTER_ALL) || \ (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \
defined(LINUXKM_LKCAPI_REGISTER_AESXTS)) defined(LINUXKM_LKCAPI_REGISTER_AESXTS))
#ifndef WOLFSSL_AESXTS_STREAM
#error LKCAPI registration of AES-XTS requires WOLFSSL_AESXTS_STREAM (--enable-aesxts-stream).
#endif
struct km_AesXtsCtx { struct km_AesXtsCtx {
XtsAes *aesXts; /* allocated in km_AesXtsInitCommon() to assure alignment XtsAes *aesXts; /* allocated in km_AesXtsInitCommon() to assure alignment
* for AESNI. * for AESNI.
@@ -835,6 +848,16 @@ static int km_AesXtsSetKey(struct crypto_skcipher *tfm, const u8 *in_key,
int err; int err;
struct km_AesXtsCtx * ctx = crypto_skcipher_ctx(tfm); struct km_AesXtsCtx * ctx = crypto_skcipher_ctx(tfm);
/* filter bad keysizes here, to avoid console noise from
* CONFIG_CRYPTO_MANAGER_EXTRA_TESTS.
*/
if ((key_len != (AES_128_KEY_SIZE*2)) &&
(key_len != (AES_192_KEY_SIZE*2)) &&
(key_len != (AES_256_KEY_SIZE*2)))
{
return -EINVAL;
}
err = wc_AesXtsSetKeyNoInit(ctx->aesXts, in_key, key_len, err = wc_AesXtsSetKeyNoInit(ctx->aesXts, in_key, key_len,
AES_ENCRYPTION_AND_DECRYPTION); AES_ENCRYPTION_AND_DECRYPTION);
@@ -852,7 +875,6 @@ static int km_AesXtsSetKey(struct crypto_skcipher *tfm, const u8 *in_key,
static int km_AesXtsEncrypt(struct skcipher_request *req) static int km_AesXtsEncrypt(struct skcipher_request *req)
{ {
int err = 0; int err = 0;
struct crypto_skcipher * tfm = NULL; struct crypto_skcipher * tfm = NULL;
struct km_AesXtsCtx * ctx = NULL; struct km_AesXtsCtx * ctx = NULL;
struct skcipher_walk walk; struct skcipher_walk walk;
@@ -861,6 +883,9 @@ static int km_AesXtsEncrypt(struct skcipher_request *req)
tfm = crypto_skcipher_reqtfm(req); tfm = crypto_skcipher_reqtfm(req);
ctx = crypto_skcipher_ctx(tfm); ctx = crypto_skcipher_ctx(tfm);
if (req->cryptlen < AES_BLOCK_SIZE)
return -EINVAL;
err = skcipher_walk_virt(&walk, req, false); err = skcipher_walk_virt(&walk, req, false);
if (unlikely(err)) { if (unlikely(err)) {
@@ -869,10 +894,9 @@ static int km_AesXtsEncrypt(struct skcipher_request *req)
return err; return err;
} }
while ((nbytes = walk.nbytes) != 0) { if (walk.nbytes == walk.total) {
err = wc_AesXtsEncrypt(ctx->aesXts, walk.dst.virt.addr, err = wc_AesXtsEncrypt(ctx->aesXts, walk.dst.virt.addr,
walk.src.virt.addr, nbytes, walk.src.virt.addr, walk.nbytes, walk.iv, walk.ivsize);
walk.iv, walk.ivsize);
if (unlikely(err)) { if (unlikely(err)) {
pr_err("%s: wc_AesXtsEncrypt failed: %d\n", pr_err("%s: wc_AesXtsEncrypt failed: %d\n",
@@ -880,6 +904,57 @@ static int km_AesXtsEncrypt(struct skcipher_request *req)
return -EINVAL; return -EINVAL;
} }
err = skcipher_walk_done(&walk, 0);
} else {
int tail = req->cryptlen % AES_BLOCK_SIZE;
struct skcipher_request subreq;
if (tail > 0) {
int blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2;
skcipher_walk_abort(&walk);
skcipher_request_set_tfm(&subreq, tfm);
skcipher_request_set_callback(&subreq,
skcipher_request_flags(req),
NULL, NULL);
skcipher_request_set_crypt(&subreq, req->src, req->dst,
blocks * AES_BLOCK_SIZE, req->iv);
req = &subreq;
err = skcipher_walk_virt(&walk, req, false);
if (!walk.nbytes)
return err ? : -EINVAL;
} else {
tail = 0;
}
err = wc_AesXtsEncryptInit(ctx->aesXts, walk.iv, walk.ivsize);
if (unlikely(err)) {
pr_err("%s: wc_AesXtsEncryptInit failed: %d\n",
crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err);
return -EINVAL;
}
while ((nbytes = walk.nbytes) != 0) {
/* if this isn't the final call, pass block-aligned data to prevent
* end-of-message ciphertext stealing.
*/
if (nbytes < walk.total)
nbytes &= ~(AES_BLOCK_SIZE - 1);
err = wc_AesXtsEncryptUpdate(ctx->aesXts, walk.dst.virt.addr,
walk.src.virt.addr, nbytes,
walk.iv);
if (unlikely(err)) {
pr_err("%s: wc_AesXtsEncryptUpdate failed: %d\n",
crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err);
return -EINVAL;
}
err = skcipher_walk_done(&walk, walk.nbytes - nbytes); err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
if (unlikely(err)) { if (unlikely(err)) {
@@ -889,6 +964,35 @@ static int km_AesXtsEncrypt(struct skcipher_request *req)
} }
} }
if (unlikely(tail > 0)) {
struct scatterlist sg_src[2], sg_dst[2];
struct scatterlist *src, *dst;
dst = src = scatterwalk_ffwd(sg_src, req->src, req->cryptlen);
if (req->dst != req->src)
dst = scatterwalk_ffwd(sg_dst, req->dst, req->cryptlen);
skcipher_request_set_crypt(req, src, dst, AES_BLOCK_SIZE + tail,
req->iv);
err = skcipher_walk_virt(&walk, &subreq, false);
if (err)
return err;
err = wc_AesXtsEncryptUpdate(ctx->aesXts, walk.dst.virt.addr,
walk.src.virt.addr, walk.nbytes,
walk.iv);
if (unlikely(err)) {
pr_err("%s: wc_AesXtsEncryptUpdate failed: %d\n",
crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err);
return -EINVAL;
}
err = skcipher_walk_done(&walk, 0);
}
}
return err; return err;
} }
@@ -903,6 +1007,9 @@ static int km_AesXtsDecrypt(struct skcipher_request *req)
tfm = crypto_skcipher_reqtfm(req); tfm = crypto_skcipher_reqtfm(req);
ctx = crypto_skcipher_ctx(tfm); ctx = crypto_skcipher_ctx(tfm);
if (req->cryptlen < AES_BLOCK_SIZE)
return -EINVAL;
err = skcipher_walk_virt(&walk, req, false); err = skcipher_walk_virt(&walk, req, false);
if (unlikely(err)) { if (unlikely(err)) {
@@ -911,13 +1018,65 @@ static int km_AesXtsDecrypt(struct skcipher_request *req)
return err; return err;
} }
while ((nbytes = walk.nbytes) != 0) { if (walk.nbytes == walk.total) {
err = wc_AesXtsDecrypt(ctx->aesXts, walk.dst.virt.addr,
walk.src.virt.addr, nbytes, err = wc_AesXtsDecrypt(ctx->aesXts,
walk.iv, walk.ivsize); walk.dst.virt.addr, walk.src.virt.addr,
walk.nbytes, walk.iv, walk.ivsize);
if (unlikely(err)) { if (unlikely(err)) {
pr_err("%s: wc_AesCbcDecrypt failed: %d\n", pr_err("%s: wc_AesXtsDecrypt failed: %d\n",
crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err);
return -EINVAL;
}
err = skcipher_walk_done(&walk, 0);
} else {
int tail = req->cryptlen % AES_BLOCK_SIZE;
struct skcipher_request subreq;
if (unlikely(tail > 0)) {
int blocks = DIV_ROUND_UP(req->cryptlen, AES_BLOCK_SIZE) - 2;
skcipher_walk_abort(&walk);
skcipher_request_set_tfm(&subreq, tfm);
skcipher_request_set_callback(&subreq,
skcipher_request_flags(req),
NULL, NULL);
skcipher_request_set_crypt(&subreq, req->src, req->dst,
blocks * AES_BLOCK_SIZE, req->iv);
req = &subreq;
err = skcipher_walk_virt(&walk, req, false);
if (!walk.nbytes)
return err ? : -EINVAL;
} else {
tail = 0;
}
err = wc_AesXtsDecryptInit(ctx->aesXts, walk.iv, walk.ivsize);
if (unlikely(err)) {
pr_err("%s: wc_AesXtsDecryptInit failed: %d\n",
crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err);
return -EINVAL;
}
while ((nbytes = walk.nbytes) != 0) {
/* if this isn't the final call, pass block-aligned data to prevent
* end-of-message ciphertext stealing.
*/
if (nbytes < walk.total)
nbytes &= ~(AES_BLOCK_SIZE - 1);
err = wc_AesXtsDecryptUpdate(ctx->aesXts, walk.dst.virt.addr,
walk.src.virt.addr, nbytes,
walk.iv);
if (unlikely(err)) {
pr_err("%s: wc_AesXtsDecryptUpdate failed: %d\n",
crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err);
return -EINVAL; return -EINVAL;
} }
@@ -931,6 +1090,35 @@ static int km_AesXtsDecrypt(struct skcipher_request *req)
} }
} }
if (unlikely(tail > 0)) {
struct scatterlist sg_src[2], sg_dst[2];
struct scatterlist *src, *dst;
dst = src = scatterwalk_ffwd(sg_src, req->src, req->cryptlen);
if (req->dst != req->src)
dst = scatterwalk_ffwd(sg_dst, req->dst, req->cryptlen);
skcipher_request_set_crypt(req, src, dst, AES_BLOCK_SIZE + tail,
req->iv);
err = skcipher_walk_virt(&walk, &subreq, false);
if (err)
return err;
err = wc_AesXtsDecryptUpdate(ctx->aesXts, walk.dst.virt.addr,
walk.src.virt.addr, walk.nbytes,
walk.iv);
if (unlikely(err)) {
pr_err("%s: wc_AesXtsDecryptUpdate failed: %d\n",
crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err);
return -EINVAL;
}
err = skcipher_walk_done(&walk, 0);
}
}
return err; return err;
} }
@@ -1834,6 +2022,25 @@ static int aes_xts_128_test(void)
XMEMSET(buf, 0, AES_XTS_128_TEST_BUF_SIZ); XMEMSET(buf, 0, AES_XTS_128_TEST_BUF_SIZ);
XMEMCPY(iv, i2, sizeof(i2));
ret = wc_AesXtsEncryptInit(aes, iv, sizeof(iv));
if (ret != 0)
goto out;
ret = wc_AesXtsEncryptUpdate(aes, buf, p2, AES_BLOCK_SIZE, iv);
if (ret != 0)
goto out;
ret = wc_AesXtsEncryptUpdate(aes, buf + AES_BLOCK_SIZE,
p2 + AES_BLOCK_SIZE,
sizeof(p2) - AES_BLOCK_SIZE, iv);
if (ret != 0)
goto out;
if (XMEMCMP(c2, buf, sizeof(c2))) {
ret = LINUXKM_LKCAPI_AES_KAT_MISMATCH_E;
goto out;
}
XMEMSET(buf, 0, AES_XTS_128_TEST_BUF_SIZ);
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_ENCRYPTION); ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_ENCRYPTION);
if (ret != 0) if (ret != 0)
goto out; goto out;
@@ -1985,6 +2192,7 @@ static int aes_xts_128_test(void)
#define LARGE_XTS_SZ 1024 #define LARGE_XTS_SZ 1024
int i; int i;
int j; int j;
int k;
large_input = (byte *)XMALLOC(LARGE_XTS_SZ, NULL, large_input = (byte *)XMALLOC(LARGE_XTS_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER); DYNAMIC_TYPE_TMP_BUFFER);
@@ -1996,6 +2204,38 @@ static int aes_xts_128_test(void)
for (i = 0; i < (int)LARGE_XTS_SZ; i++) for (i = 0; i < (int)LARGE_XTS_SZ; i++)
large_input[i] = (byte)i; large_input[i] = (byte)i;
/* first, encrypt block by block then decrypt with a one-shot call. */
for (j = 16; j < (int)LARGE_XTS_SZ; j++) {
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_ENCRYPTION);
if (ret != 0)
goto out;
XMEMCPY(iv, i1, sizeof(i1));
ret = wc_AesXtsEncryptInit(aes, iv, sizeof(iv));
if (ret != 0)
goto out;
for (k = 0; k < j; k += AES_BLOCK_SIZE) {
ret = wc_AesXtsEncryptUpdate(aes, large_input + k, large_input + k, (j - k) < AES_BLOCK_SIZE*2 ? j - k : AES_BLOCK_SIZE, iv);
if (ret != 0)
goto out;
if ((j - k) < AES_BLOCK_SIZE*2)
break;
}
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_DECRYPTION);
if (ret != 0)
goto out;
ret = wc_AesXtsDecrypt(aes, large_input, large_input, j, i1,
sizeof(i1));
if (ret != 0)
goto out;
for (i = 0; i < j; i++) {
if (large_input[i] != (byte)i) {
ret = LINUXKM_LKCAPI_AES_KAT_MISMATCH_E;
goto out;
}
}
}
/* second, encrypt with a one-shot call then decrypt block by block. */
for (j = 16; j < (int)LARGE_XTS_SZ; j++) { for (j = 16; j < (int)LARGE_XTS_SZ; j++) {
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_ENCRYPTION); ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_ENCRYPTION);
if (ret != 0) if (ret != 0)
@@ -2004,14 +2244,20 @@ static int aes_xts_128_test(void)
sizeof(i1)); sizeof(i1));
if (ret != 0) if (ret != 0)
goto out; goto out;
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_DECRYPTION); ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_DECRYPTION);
if (ret != 0) if (ret != 0)
goto out; goto out;
ret = wc_AesXtsDecrypt(aes, large_input, large_input, j, i1, XMEMCPY(iv, i1, sizeof(i1));
sizeof(i1)); ret = wc_AesXtsDecryptInit(aes, iv, sizeof(iv));
if (ret != 0) if (ret != 0)
goto out; goto out;
for (k = 0; k < j; k += AES_BLOCK_SIZE) {
ret = wc_AesXtsDecryptUpdate(aes, large_input + k, large_input + k, (j - k) < AES_BLOCK_SIZE*2 ? j - k : AES_BLOCK_SIZE, iv);
if (ret != 0)
goto out;
if ((j - k) < AES_BLOCK_SIZE*2)
break;
}
for (i = 0; i < j; i++) { for (i = 0; i < j; i++) {
if (large_input[i] != (byte)i) { if (large_input[i] != (byte)i) {
ret = LINUXKM_LKCAPI_AES_KAT_MISMATCH_E; ret = LINUXKM_LKCAPI_AES_KAT_MISMATCH_E;
@@ -2237,6 +2483,7 @@ static int aes_xts_256_test(void)
struct crypto_skcipher *tfm = NULL; struct crypto_skcipher *tfm = NULL;
struct skcipher_request *req = NULL; struct skcipher_request *req = NULL;
u8 iv[AES_BLOCK_SIZE]; u8 iv[AES_BLOCK_SIZE];
byte* large_input = NULL;
/* 256 key tests */ /* 256 key tests */
static const unsigned char k1[] = { static const unsigned char k1[] = {
@@ -2355,6 +2602,25 @@ static int aes_xts_256_test(void)
goto out; goto out;
} }
XMEMSET(buf, 0, AES_XTS_256_TEST_BUF_SIZ);
XMEMCPY(iv, i2, sizeof(i2));
ret = wc_AesXtsEncryptInit(aes, iv, sizeof(iv));
if (ret != 0)
goto out;
ret = wc_AesXtsEncryptUpdate(aes, buf, p2, AES_BLOCK_SIZE, iv);
if (ret != 0)
goto out;
ret = wc_AesXtsEncryptUpdate(aes, buf + AES_BLOCK_SIZE,
p2 + AES_BLOCK_SIZE,
sizeof(p2) - AES_BLOCK_SIZE, iv);
if (ret != 0)
goto out;
if (XMEMCMP(c2, buf, sizeof(c2))) {
ret = LINUXKM_LKCAPI_AES_KAT_MISMATCH_E;
goto out;
}
XMEMSET(buf, 0, AES_XTS_256_TEST_BUF_SIZ); XMEMSET(buf, 0, AES_XTS_256_TEST_BUF_SIZ);
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_ENCRYPTION); ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_ENCRYPTION);
if (ret != 0) if (ret != 0)
@@ -2408,6 +2674,85 @@ static int aes_xts_256_test(void)
goto out; goto out;
} }
{
#define LARGE_XTS_SZ 1024
int i;
int j;
int k;
large_input = (byte *)XMALLOC(LARGE_XTS_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (large_input == NULL) {
ret = MEMORY_E;
goto out;
}
for (i = 0; i < (int)LARGE_XTS_SZ; i++)
large_input[i] = (byte)i;
/* first, encrypt block by block then decrypt with a one-shot call. */
for (j = 16; j < (int)LARGE_XTS_SZ; j++) {
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_ENCRYPTION);
if (ret != 0)
goto out;
XMEMCPY(iv, i1, sizeof(i1));
ret = wc_AesXtsEncryptInit(aes, iv, sizeof(iv));
if (ret != 0)
goto out;
for (k = 0; k < j; k += AES_BLOCK_SIZE) {
ret = wc_AesXtsEncryptUpdate(aes, large_input + k, large_input + k, (j - k) < AES_BLOCK_SIZE*2 ? j - k : AES_BLOCK_SIZE, iv);
if (ret != 0)
goto out;
if ((j - k) < AES_BLOCK_SIZE*2)
break;
}
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_DECRYPTION);
if (ret != 0)
goto out;
ret = wc_AesXtsDecrypt(aes, large_input, large_input, j, i1,
sizeof(i1));
if (ret != 0)
goto out;
for (i = 0; i < j; i++) {
if (large_input[i] != (byte)i) {
ret = LINUXKM_LKCAPI_AES_KAT_MISMATCH_E;
goto out;
}
}
}
/* second, encrypt with a one-shot call then decrypt block by block. */
for (j = 16; j < (int)LARGE_XTS_SZ; j++) {
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_ENCRYPTION);
if (ret != 0)
goto out;
ret = wc_AesXtsEncrypt(aes, large_input, large_input, j, i1,
sizeof(i1));
if (ret != 0)
goto out;
ret = wc_AesXtsSetKeyNoInit(aes, k1, sizeof(k1), AES_DECRYPTION);
if (ret != 0)
goto out;
XMEMCPY(iv, i1, sizeof(i1));
ret = wc_AesXtsDecryptInit(aes, iv, sizeof(iv));
if (ret != 0)
goto out;
for (k = 0; k < j; k += AES_BLOCK_SIZE) {
ret = wc_AesXtsDecryptUpdate(aes, large_input + k, large_input + k, (j - k) < AES_BLOCK_SIZE*2 ? j - k : AES_BLOCK_SIZE, iv);
if (ret != 0)
goto out;
if ((j - k) < AES_BLOCK_SIZE*2)
break;
}
for (i = 0; i < j; i++) {
if (large_input[i] != (byte)i) {
ret = LINUXKM_LKCAPI_AES_KAT_MISMATCH_E;
goto out;
}
}
}
}
/* now the kernel crypto part */ /* now the kernel crypto part */
enc2 = XMALLOC(sizeof(p1), NULL, DYNAMIC_TYPE_AES); enc2 = XMALLOC(sizeof(p1), NULL, DYNAMIC_TYPE_AES);
@@ -2587,6 +2932,9 @@ static int aes_xts_256_test(void)
out: out:
if (large_input)
XFREE(large_input, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (aes_inited) if (aes_inited)
wc_AesXtsFree(aes); wc_AesXtsFree(aes);

View File

@@ -189,8 +189,7 @@ static struct wc_thread_fpu_count_ent *wc_linuxkm_fpu_state_assoc(int create_p)
* dependency loop on intelasm builds, we allocate here. * dependency loop on intelasm builds, we allocate here.
* this is not thread-safe and doesn't need to be. * this is not thread-safe and doesn't need to be.
*/ */
int ret = allocate_wolfcrypt_linuxkm_fpu_states(); if ((! create_p) || (allocate_wolfcrypt_linuxkm_fpu_states() != 0))
if (ret != 0)
#endif #endif
{ {
if (_warned_on_null == 0) { if (_warned_on_null == 0) {

View File

@@ -12336,12 +12336,16 @@ int wc_AesXtsSetKeyNoInit(XtsAes* aes, const byte* key, word32 len, int dir)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
keySz = len/2; if ((len != (AES_128_KEY_SIZE*2)) &&
if (keySz != AES_128_KEY_SIZE && keySz != AES_256_KEY_SIZE) { (len != (AES_192_KEY_SIZE*2)) &&
(len != (AES_256_KEY_SIZE*2)))
{
WOLFSSL_MSG("Unsupported key size"); WOLFSSL_MSG("Unsupported key size");
return WC_KEY_SIZE_E; return WC_KEY_SIZE_E;
} }
keySz = len/2;
#ifdef HAVE_FIPS #ifdef HAVE_FIPS
if (XMEMCMP(key, key + keySz, keySz) == 0) { if (XMEMCMP(key, key + keySz, keySz) == 0) {
WOLFSSL_MSG("FIPS AES-XTS main and tweak keys must differ"); WOLFSSL_MSG("FIPS AES-XTS main and tweak keys must differ");
@@ -12525,12 +12529,28 @@ void AES_XTS_encrypt_aesni(const unsigned char *in, unsigned char *out, word32 s
const unsigned char* i, const unsigned char* key, const unsigned char* i, const unsigned char* key,
const unsigned char* key2, int nr) const unsigned char* key2, int nr)
XASM_LINK("AES_XTS_encrypt_aesni"); XASM_LINK("AES_XTS_encrypt_aesni");
#ifdef WOLFSSL_AESXTS_STREAM
void AES_XTS_init_aesni(unsigned char* i, const unsigned char* tweak_key,
int tweak_nr)
XASM_LINK("AES_XTS_init_aesni");
void AES_XTS_encrypt_update_aesni(const unsigned char *in, unsigned char *out, word32 sz,
const unsigned char* key, unsigned char *i, int nr)
XASM_LINK("AES_XTS_encrypt_update_aesni");
#endif
#ifdef HAVE_INTEL_AVX1 #ifdef HAVE_INTEL_AVX1
void AES_XTS_encrypt_avx1(const unsigned char *in, unsigned char *out, void AES_XTS_encrypt_avx1(const unsigned char *in, unsigned char *out,
word32 sz, const unsigned char* i, word32 sz, const unsigned char* i,
const unsigned char* key, const unsigned char* key2, const unsigned char* key, const unsigned char* key2,
int nr) int nr)
XASM_LINK("AES_XTS_encrypt_avx1"); XASM_LINK("AES_XTS_encrypt_avx1");
#ifdef WOLFSSL_AESXTS_STREAM
void AES_XTS_init_avx1(unsigned char* i, const unsigned char* tweak_key,
int tweak_nr)
XASM_LINK("AES_XTS_init_avx1");
void AES_XTS_encrypt_update_avx1(const unsigned char *in, unsigned char *out, word32 sz,
const unsigned char* key, unsigned char *i, int nr)
XASM_LINK("AES_XTS_encrypt_update_avx1");
#endif
#endif /* HAVE_INTEL_AVX1 */ #endif /* HAVE_INTEL_AVX1 */
#ifdef HAVE_AES_DECRYPT #ifdef HAVE_AES_DECRYPT
@@ -12538,12 +12558,22 @@ void AES_XTS_decrypt_aesni(const unsigned char *in, unsigned char *out, word32 s
const unsigned char* i, const unsigned char* key, const unsigned char* i, const unsigned char* key,
const unsigned char* key2, int nr) const unsigned char* key2, int nr)
XASM_LINK("AES_XTS_decrypt_aesni"); XASM_LINK("AES_XTS_decrypt_aesni");
#ifdef WOLFSSL_AESXTS_STREAM
void AES_XTS_decrypt_update_aesni(const unsigned char *in, unsigned char *out, word32 sz,
const unsigned char* key, unsigned char *i, int nr)
XASM_LINK("AES_XTS_decrypt_update_aesni");
#endif
#ifdef HAVE_INTEL_AVX1 #ifdef HAVE_INTEL_AVX1
void AES_XTS_decrypt_avx1(const unsigned char *in, unsigned char *out, void AES_XTS_decrypt_avx1(const unsigned char *in, unsigned char *out,
word32 sz, const unsigned char* i, word32 sz, const unsigned char* i,
const unsigned char* key, const unsigned char* key2, const unsigned char* key, const unsigned char* key2,
int nr) int nr)
XASM_LINK("AES_XTS_decrypt_avx1"); XASM_LINK("AES_XTS_decrypt_avx1");
#ifdef WOLFSSL_AESXTS_STREAM
void AES_XTS_decrypt_update_avx1(const unsigned char *in, unsigned char *out, word32 sz,
const unsigned char* key, unsigned char *i, int nr)
XASM_LINK("AES_XTS_decrypt_update_avx1");
#endif
#endif /* HAVE_INTEL_AVX1 */ #endif /* HAVE_INTEL_AVX1 */
#endif /* HAVE_AES_DECRYPT */ #endif /* HAVE_AES_DECRYPT */
@@ -12590,7 +12620,6 @@ static WARN_UNUSED_RESULT int _AesXtsHelper(
} }
#endif /* HAVE_AES_ECB */ #endif /* HAVE_AES_ECB */
/* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing. /* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing.
* *
* xaes AES keys to use for block encrypt/decrypt * xaes AES keys to use for block encrypt/decrypt
@@ -12602,27 +12631,63 @@ static WARN_UNUSED_RESULT int _AesXtsHelper(
* returns 0 on success * returns 0 on success
*/ */
/* Software AES - XTS Encrypt */ /* Software AES - XTS Encrypt */
static int AesXtsEncryptUpdate_sw(XtsAes* xaes, byte* out, const byte* in,
word32 sz,
byte *i);
static int AesXtsEncrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, static int AesXtsEncrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
const byte* i) const byte* i)
{
int ret;
byte tweak_block[AES_BLOCK_SIZE];
ret = wc_AesEncryptDirect(&xaes->tweak, tweak_block, i);
if (ret != 0)
return ret;
return AesXtsEncryptUpdate_sw(xaes, out, in, sz, tweak_block);
}
#ifdef WOLFSSL_AESXTS_STREAM
/* Block-streaming AES-XTS tweak setup.
*
* xaes AES keys to use for block encrypt/decrypt
* i readwrite value to use for tweak
*
* returns 0 on success
*/
static int AesXtsInitTweak_sw(XtsAes* xaes, byte* i) {
return wc_AesEncryptDirect(&xaes->tweak, i, i);
}
#endif /* WOLFSSL_AESXTS_STREAM */
/* Block-streaming AES-XTS.
*
* Supply block-aligned input data with successive calls. Final call need not
* be block aligned.
*
* xaes AES keys to use for block encrypt/decrypt
* out output buffer to hold cipher text
* in input plain text buffer to encrypt
* sz size of both out and in buffers
*
* returns 0 on success
*/
/* Software AES - XTS Encrypt */
static int AesXtsEncryptUpdate_sw(XtsAes* xaes, byte* out, const byte* in,
word32 sz,
byte *i)
{ {
int ret = 0; int ret = 0;
word32 blocks = (sz / AES_BLOCK_SIZE); word32 blocks = (sz / AES_BLOCK_SIZE);
Aes *aes = &xaes->aes; Aes *aes = &xaes->aes;
Aes *tweak = &xaes->tweak;
byte tmp[AES_BLOCK_SIZE];
XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES
* key setup passed to encrypt direct*/
ret = wc_AesEncryptDirect(tweak, tmp, i);
if (ret != 0)
return ret;
#ifdef HAVE_AES_ECB #ifdef HAVE_AES_ECB
/* encrypt all of buffer at once when possible */ /* encrypt all of buffer at once when possible */
if (in != out) { /* can not handle inline */ if (in != out) { /* can not handle inline */
XMEMCPY(out, tmp, AES_BLOCK_SIZE); XMEMCPY(out, i, AES_BLOCK_SIZE);
if ((ret = _AesXtsHelper(aes, out, in, sz, AES_ENCRYPTION)) != 0) if ((ret = _AesXtsHelper(aes, out, in, sz, AES_ENCRYPTION)) != 0)
return ret; return ret;
} }
@@ -12639,23 +12704,23 @@ static int AesXtsEncrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
byte buf[AES_BLOCK_SIZE]; byte buf[AES_BLOCK_SIZE];
XMEMCPY(buf, in, AES_BLOCK_SIZE); XMEMCPY(buf, in, AES_BLOCK_SIZE);
xorbuf(buf, tmp, AES_BLOCK_SIZE); xorbuf(buf, i, AES_BLOCK_SIZE);
ret = wc_AesEncryptDirect(aes, out, buf); ret = wc_AesEncryptDirect(aes, out, buf);
if (ret != 0) if (ret != 0)
return ret; return ret;
} }
xorbuf(out, tmp, AES_BLOCK_SIZE); xorbuf(out, i, AES_BLOCK_SIZE);
/* multiply by shift left and propagate carry */ /* multiply by shift left and propagate carry */
for (j = 0; j < AES_BLOCK_SIZE; j++) { for (j = 0; j < AES_BLOCK_SIZE; j++) {
byte tmpC; byte tmpC;
tmpC = (tmp[j] >> 7) & 0x01; tmpC = (i[j] >> 7) & 0x01;
tmp[j] = (byte)((tmp[j] << 1) + carry); i[j] = (byte)((i[j] << 1) + carry);
carry = tmpC; carry = tmpC;
} }
if (carry) { if (carry) {
tmp[0] ^= GF_XTS; i[0] ^= GF_XTS;
} }
in += AES_BLOCK_SIZE; in += AES_BLOCK_SIZE;
@@ -12684,10 +12749,10 @@ static int AesXtsEncrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
XMEMCPY(out, buf2, sz); XMEMCPY(out, buf2, sz);
} }
xorbuf(buf, tmp, AES_BLOCK_SIZE); xorbuf(buf, i, AES_BLOCK_SIZE);
ret = wc_AesEncryptDirect(aes, out - AES_BLOCK_SIZE, buf); ret = wc_AesEncryptDirect(aes, out - AES_BLOCK_SIZE, buf);
if (ret == 0) if (ret == 0)
xorbuf(out - AES_BLOCK_SIZE, tmp, AES_BLOCK_SIZE); xorbuf(out - AES_BLOCK_SIZE, i, AES_BLOCK_SIZE);
} }
return ret; return ret;
@@ -12773,6 +12838,144 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
return ret; return ret;
} }
#ifdef WOLFSSL_AESXTS_STREAM
/* Block-streaming AES-XTS.
*
* xaes AES keys to use for block encrypt/decrypt
* i readwrite value to use for tweak
* iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input
* adds a sanity check on how the user calls the function.
*
* returns 0 on success
*/
int wc_AesXtsEncryptInit(XtsAes* xaes, byte* i, word32 iSz)
{
int ret;
Aes *aes;
if ((xaes == NULL) || (i == NULL)) {
return BAD_FUNC_ARG;
}
if (iSz < AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
aes = &xaes->aes;
if (aes->keylen == 0) {
WOLFSSL_MSG("wc_AesXtsEncrypt called with unset encryption key.");
return BAD_FUNC_ARG;
}
if (iSz < AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
{
#ifdef WOLFSSL_AESNI
if (aes->use_aesni) {
SAVE_VECTOR_REGISTERS(return _svr_ret;);
#if defined(HAVE_INTEL_AVX1)
if (IS_INTEL_AVX1(intel_flags)) {
AES_XTS_init_avx1(i, (const byte*)xaes->tweak.key,
(int)xaes->tweak.rounds);
ret = 0;
}
else
#endif
{
AES_XTS_init_aesni(i, (const byte*)xaes->tweak.key,
(int)xaes->tweak.rounds);
ret = 0;
}
RESTORE_VECTOR_REGISTERS();
}
else
#endif /* WOLFSSL_AESNI */
{
ret = AesXtsInitTweak_sw(xaes, i);
}
}
return ret;
}
/* Block-streaming AES-XTS
*
* Note that sz must be greater than AES_BLOCK_SIZE in each call, and must be a
* multiple of AES_BLOCK_SIZE in all but the final call.
*
* xaes AES keys to use for block encrypt/decrypt
* out output buffer to hold cipher text
* in input plain text buffer to encrypt
* sz size of both out and in buffers -- must be >= AES_BLOCK_SIZE.
* i value to use for tweak
* iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input
* adds a sanity check on how the user calls the function.
*
* returns 0 on success
*/
int wc_AesXtsEncryptUpdate(XtsAes* xaes, byte* out, const byte* in, word32 sz,
byte *i)
{
int ret;
#ifdef WOLFSSL_AESNI
Aes *aes;
#endif
if (xaes == NULL || out == NULL || in == NULL || i == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_AESNI
aes = &xaes->aes;
#endif
if (sz < AES_BLOCK_SIZE) {
WOLFSSL_MSG("Plain text input too small for encryption");
return BAD_FUNC_ARG;
}
{
#ifdef WOLFSSL_AESNI
if (aes->use_aesni) {
SAVE_VECTOR_REGISTERS(return _svr_ret;);
#if defined(HAVE_INTEL_AVX1)
if (IS_INTEL_AVX1(intel_flags)) {
AES_XTS_encrypt_update_avx1(in, out, sz,
(const byte*)aes->key,
i,
(int)aes->rounds);
ret = 0;
}
else
#endif
{
AES_XTS_encrypt_update_aesni(in, out, sz,
(const byte*)aes->key,
i,
(int)aes->rounds);
ret = 0;
}
RESTORE_VECTOR_REGISTERS();
}
else
#endif /* WOLFSSL_AESNI */
{
ret = AesXtsEncryptUpdate_sw(xaes, out, in, sz, i);
}
}
return ret;
}
#endif /* WOLFSSL_AESXTS_STREAM */
/* Same process as encryption but use aes_decrypt key. /* Same process as encryption but use aes_decrypt key.
* *
* xaes AES keys to use for block encrypt/decrypt * xaes AES keys to use for block encrypt/decrypt
@@ -12784,8 +12987,41 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
* returns 0 on success * returns 0 on success
*/ */
/* Software AES - XTS Decrypt */ /* Software AES - XTS Decrypt */
static int AesXtsDecryptUpdate_sw(XtsAes* xaes, byte* out, const byte* in,
word32 sz, byte *i);
static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
const byte* i) const byte* i)
{
int ret;
byte tweak_block[AES_BLOCK_SIZE];
ret = wc_AesEncryptDirect(&xaes->tweak, tweak_block, i);
if (ret != 0)
return ret;
return AesXtsDecryptUpdate_sw(xaes, out, in, sz, tweak_block);
}
/* Block-streaming AES-XTS.
*
* Same process as encryption but use decrypt key.
*
* Supply block-aligned input data with successive calls. Final call need not
* be block aligned.
*
* xaes AES keys to use for block encrypt/decrypt
* out output buffer to hold plain text
* in input cipher text buffer to decrypt
* sz size of both out and in buffers
* i value to use for tweak
*
* returns 0 on success
*/
/* Software AES - XTS Decrypt */
static int AesXtsDecryptUpdate_sw(XtsAes* xaes, byte* out, const byte* in,
word32 sz, byte *i)
{ {
int ret = 0; int ret = 0;
word32 blocks = (sz / AES_BLOCK_SIZE); word32 blocks = (sz / AES_BLOCK_SIZE);
@@ -12794,19 +13030,10 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
#else #else
Aes *aes = &xaes->aes; Aes *aes = &xaes->aes;
#endif #endif
Aes *tweak = &xaes->tweak;
word32 j; word32 j;
byte carry = 0; byte carry = 0;
byte tmp[AES_BLOCK_SIZE];
byte stl = (sz % AES_BLOCK_SIZE); byte stl = (sz % AES_BLOCK_SIZE);
XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES
* key setup passed to decrypt direct*/
ret = wc_AesEncryptDirect(tweak, tmp, i);
if (ret != 0)
return ret;
/* if Stealing then break out of loop one block early to handle special /* if Stealing then break out of loop one block early to handle special
* case */ * case */
if (stl > 0) { if (stl > 0) {
@@ -12816,7 +13043,7 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
#ifdef HAVE_AES_ECB #ifdef HAVE_AES_ECB
/* decrypt all of buffer at once when possible */ /* decrypt all of buffer at once when possible */
if (in != out) { /* can not handle inline */ if (in != out) { /* can not handle inline */
XMEMCPY(out, tmp, AES_BLOCK_SIZE); XMEMCPY(out, i, AES_BLOCK_SIZE);
if ((ret = _AesXtsHelper(aes, out, in, sz, AES_DECRYPTION)) != 0) if ((ret = _AesXtsHelper(aes, out, in, sz, AES_DECRYPTION)) != 0)
return ret; return ret;
} }
@@ -12830,23 +13057,23 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
byte buf[AES_BLOCK_SIZE]; byte buf[AES_BLOCK_SIZE];
XMEMCPY(buf, in, AES_BLOCK_SIZE); XMEMCPY(buf, in, AES_BLOCK_SIZE);
xorbuf(buf, tmp, AES_BLOCK_SIZE); xorbuf(buf, i, AES_BLOCK_SIZE);
ret = wc_AesDecryptDirect(aes, out, buf); ret = wc_AesDecryptDirect(aes, out, buf);
if (ret != 0) if (ret != 0)
return ret; return ret;
} }
xorbuf(out, tmp, AES_BLOCK_SIZE); xorbuf(out, i, AES_BLOCK_SIZE);
/* multiply by shift left and propagate carry */ /* multiply by shift left and propagate carry */
for (j = 0; j < AES_BLOCK_SIZE; j++) { for (j = 0; j < AES_BLOCK_SIZE; j++) {
byte tmpC; byte tmpC;
tmpC = (tmp[j] >> 7) & 0x01; tmpC = (i[j] >> 7) & 0x01;
tmp[j] = (byte)((tmp[j] << 1) + carry); i[j] = (byte)((i[j] << 1) + carry);
carry = tmpC; carry = tmpC;
} }
if (carry) { if (carry) {
tmp[0] ^= GF_XTS; i[0] ^= GF_XTS;
} }
carry = 0; carry = 0;
@@ -12865,8 +13092,8 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
for (j = 0; j < AES_BLOCK_SIZE; j++) { for (j = 0; j < AES_BLOCK_SIZE; j++) {
byte tmpC; byte tmpC;
tmpC = (tmp[j] >> 7) & 0x01; tmpC = (i[j] >> 7) & 0x01;
tmp2[j] = (byte)((tmp[j] << 1) + carry); tmp2[j] = (byte)((i[j] << 1) + carry);
carry = tmpC; carry = tmpC;
} }
if (carry) { if (carry) {
@@ -12894,11 +13121,11 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz,
XMEMCPY(buf, in, sz); XMEMCPY(buf, in, sz);
XMEMCPY(out, tmp2, sz); XMEMCPY(out, tmp2, sz);
xorbuf(buf, tmp, AES_BLOCK_SIZE); xorbuf(buf, i, AES_BLOCK_SIZE);
ret = wc_AesDecryptDirect(aes, tmp2, buf); ret = wc_AesDecryptDirect(aes, tmp2, buf);
if (ret != 0) if (ret != 0)
return ret; return ret;
xorbuf(tmp2, tmp, AES_BLOCK_SIZE); xorbuf(tmp2, i, AES_BLOCK_SIZE);
XMEMCPY(out - AES_BLOCK_SIZE, tmp2, AES_BLOCK_SIZE); XMEMCPY(out - AES_BLOCK_SIZE, tmp2, AES_BLOCK_SIZE);
} }
@@ -12987,6 +13214,145 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz,
return ret; return ret;
} }
} }
#ifdef WOLFSSL_AESXTS_STREAM
/* Same process as encryption but Aes key is AES_DECRYPTION type.
*
* xaes AES keys to use for block encrypt/decrypt
* i readwrite value to use for tweak
* iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input
* adds a sanity check on how the user calls the function.
*
* returns 0 on success
*/
int wc_AesXtsDecryptInit(XtsAes* xaes, byte* i, word32 iSz)
{
int ret;
Aes *aes;
if (xaes == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS
aes = &xaes->aes_decrypt;
#else
aes = &xaes->aes;
#endif
if (aes->keylen == 0) {
WOLFSSL_MSG("wc_AesXtsDecrypt called with unset decryption key.");
return BAD_FUNC_ARG;
}
if (iSz < AES_BLOCK_SIZE) {
return BAD_FUNC_ARG;
}
{
#ifdef WOLFSSL_AESNI
if (aes->use_aesni) {
SAVE_VECTOR_REGISTERS(return _svr_ret;);
#if defined(HAVE_INTEL_AVX1)
if (IS_INTEL_AVX1(intel_flags)) {
AES_XTS_init_avx1(i, (const byte*)xaes->tweak.key,
(int)xaes->tweak.rounds);
ret = 0;
}
else
#endif
{
AES_XTS_init_aesni(i, (const byte*)xaes->tweak.key,
(int)xaes->tweak.rounds);
ret = 0;
}
RESTORE_VECTOR_REGISTERS();
}
else
#endif /* WOLFSSL_AESNI */
{
ret = AesXtsInitTweak_sw(xaes, i);
}
}
return ret;
}
/* Block-streaming AES-XTS
*
* Note that sz must be greater than AES_BLOCK_SIZE in each call, and must be a
* multiple of AES_BLOCK_SIZE in all but the final call.
*
* xaes AES keys to use for block encrypt/decrypt
* out output buffer to hold plain text
* in input cipher text buffer to decrypt
* sz size of both out and in buffers
* i tweak buffer of size AES_BLOCK_SIZE.
*
* returns 0 on success
*/
int wc_AesXtsDecryptUpdate(XtsAes* xaes, byte* out, const byte* in, word32 sz,
byte *i)
{
int ret;
#ifdef WOLFSSL_AESNI
Aes *aes;
#endif
if (xaes == NULL || out == NULL || in == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLFSSL_AESNI
#ifdef WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS
aes = &xaes->aes_decrypt;
#else
aes = &xaes->aes;
#endif
#endif
if (sz < AES_BLOCK_SIZE) {
WOLFSSL_MSG("Cipher text input too small for decryption");
return BAD_FUNC_ARG;
}
{
#ifdef WOLFSSL_AESNI
if (aes->use_aesni) {
SAVE_VECTOR_REGISTERS(return _svr_ret;);
#if defined(HAVE_INTEL_AVX1)
if (IS_INTEL_AVX1(intel_flags)) {
AES_XTS_decrypt_update_avx1(in, out, sz,
(const byte*)aes->key,
i,
(int)aes->rounds);
ret = 0;
}
else
#endif
{
AES_XTS_decrypt_update_aesni(in, out, sz,
(const byte*)aes->key,
i,
(int)aes->rounds);
ret = 0;
}
RESTORE_VECTOR_REGISTERS();
}
else
#endif /* WOLFSSL_AESNI */
{
ret = AesXtsDecryptUpdate_sw(xaes, out, in, sz, i);
}
}
return ret;
}
#endif /* WOLFSSL_AESXTS_STREAM */
#endif /* !WOLFSSL_ARMASM || WOLFSSL_ARMASM_NO_HW_CRYPTO */ #endif /* !WOLFSSL_ARMASM || WOLFSSL_ARMASM_NO_HW_CRYPTO */
/* Same as wc_AesXtsEncryptSector but the sector gets incremented by one every /* Same as wc_AesXtsEncryptSector but the sector gets incremented by one every

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -669,6 +669,20 @@ WOLFSSL_API int wc_AesXtsDecryptConsecutiveSectors(XtsAes* aes,
byte* out, const byte* in, word32 sz, word64 sector, byte* out, const byte* in, word32 sz, word64 sector,
word32 sectorSz); word32 sectorSz);
#ifdef WOLFSSL_AESXTS_STREAM
WOLFSSL_API int wc_AesXtsEncryptInit(XtsAes* aes, byte* i, word32 iSz);
WOLFSSL_API int wc_AesXtsDecryptInit(XtsAes* aes, byte* i, word32 iSz);
WOLFSSL_API int wc_AesXtsEncryptUpdate(XtsAes* aes, byte* out,
const byte* in, word32 sz, byte *i);
WOLFSSL_API int wc_AesXtsDecryptUpdate(XtsAes* aes, byte* out,
const byte* in, word32 sz, byte *i);
#endif /* WOLFSSL_AESXTS_STREAM */
WOLFSSL_API int wc_AesXtsFree(XtsAes* aes); WOLFSSL_API int wc_AesXtsFree(XtsAes* aes);
#endif #endif