mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 12:14:38 +02:00
Merge pull request #7522 from douzzer/20240511-aes-xts-stream
20240511-aes-xts-stream
This commit is contained in:
3
.github/workflows/openvpn.yml
vendored
3
.github/workflows/openvpn.yml
vendored
@@ -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.
|
||||||
|
35
configure.ac
35
configure.ac
@@ -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"
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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
@@ -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
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user