diff --git a/configure.ac b/configure.ac index 831790136..2e5cae220 100644 --- a/configure.ac +++ b/configure.ac @@ -9065,7 +9065,6 @@ then 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.]) - test "$ENABLED_EXPERIMENTAL" = "yes" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: requires --enable-experimental.]) 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.]) test "$ENABLED_EXPERIMENTAL" = "yes" || AC_MSG_ERROR([linuxkm-lkcapi-register ${lkcapi_alg}: requires --enable-experimental.]) diff --git a/linuxkm/lkcapi_glue.c b/linuxkm/lkcapi_glue.c index 9ecd23ee1..d3c6fda67 100644 --- a/linuxkm/lkcapi_glue.c +++ b/linuxkm/lkcapi_glue.c @@ -89,9 +89,6 @@ static int disable_setkey_warnings = 0; #if defined(HAVE_AES_CBC) && \ (defined(LINUXKM_LKCAPI_REGISTER_ALL) || \ defined(LINUXKM_LKCAPI_REGISTER_AESCBC)) -#ifndef WOLFSSL_EXPERIMENTAL_SETTINGS - #error Experimental settings without WOLFSSL_EXPERIMENTAL_SETTINGS -#endif static int linuxkm_test_aescbc(void); #endif #if defined(WOLFSSL_AES_CFB) && \ @@ -214,7 +211,7 @@ static int km_AesSetKeyCommon(struct km_AesCtx * ctx, const u8 *in_key, if (unlikely(err)) { if (! disable_setkey_warnings) pr_err("%s: wc_AesSetKey for encryption key failed: %d\n", name, err); - return -ENOKEY; + return -EINVAL; } if (ctx->aes_decrypt) { @@ -225,7 +222,7 @@ static int km_AesSetKeyCommon(struct km_AesCtx * ctx, const u8 *in_key, if (! disable_setkey_warnings) pr_err("%s: wc_AesSetKey for decryption key failed: %d\n", name, err); - return -ENOKEY; + return -EINVAL; } } @@ -278,38 +275,34 @@ static int km_AesCbcEncrypt(struct skcipher_request *req) err = skcipher_walk_virt(&walk, req, false); if (unlikely(err)) { - pr_err("%s: skcipher_walk_virt failed: %d\n", - crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); return err; } - while ((nbytes = walk.nbytes) != 0) { - err = wc_AesSetIV(ctx->aes_encrypt, walk.iv); + err = wc_AesSetIV(ctx->aes_encrypt, walk.iv); - if (unlikely(err)) { - pr_err("%s: wc_AesSetIV failed: %d\n", - crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); - return -EINVAL; - } - - err = wc_AesCbcEncrypt(ctx->aes_encrypt, walk.dst.virt.addr, - walk.src.virt.addr, nbytes); - - if (unlikely(err)) { - pr_err("%s: wc_AesCbcEncrypt failed: %d\n", - crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); - return -EINVAL; - } - - err = skcipher_walk_done(&walk, walk.nbytes - nbytes); - - if (unlikely(err)) { - pr_err("%s: skcipher_walk_done failed: %d\n", - crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); - return err; - } + if (unlikely(err)) { + pr_err("%s: wc_AesSetIV failed: %d\n", + crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); + return -EINVAL; } + while ((nbytes = walk.nbytes) != 0) { + err = wc_AesCbcEncrypt(ctx->aes_encrypt, walk.dst.virt.addr, + walk.src.virt.addr, nbytes & (~(WC_AES_BLOCK_SIZE - 1))); + + if (unlikely(err)) { + pr_err("%s: wc_AesCbcEncrypt failed for %u bytes: %d\n", + crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), nbytes, err); + return -EINVAL; + } + + nbytes &= WC_AES_BLOCK_SIZE - 1; + err = skcipher_walk_done(&walk, nbytes); + } + + /* copy iv from wolfCrypt back to walk.iv */ + XMEMCPY(walk.iv, ctx->aes_encrypt->reg, WC_AES_BLOCK_SIZE); + return err; } @@ -327,39 +320,35 @@ static int km_AesCbcDecrypt(struct skcipher_request *req) err = skcipher_walk_virt(&walk, req, false); if (unlikely(err)) { - pr_err("%s: skcipher_walk_virt failed: %d\n", - crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); return err; } - while ((nbytes = walk.nbytes) != 0) { - err = wc_AesSetIV(ctx->aes_decrypt, walk.iv); + err = wc_AesSetIV(ctx->aes_decrypt, walk.iv); - if (unlikely(err)) { - if (! disable_setkey_warnings) - pr_err("%s: wc_AesSetKey failed: %d\n", - crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); - return -EINVAL; - } - - err = wc_AesCbcDecrypt(ctx->aes_decrypt, walk.dst.virt.addr, - walk.src.virt.addr, nbytes); - - if (unlikely(err)) { - pr_err("%s: wc_AesCbcDecrypt failed: %d\n", + if (unlikely(err)) { + if (! disable_setkey_warnings) + pr_err("%s: wc_AesSetKey failed: %d\n", crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); - return -EINVAL; - } - - err = skcipher_walk_done(&walk, walk.nbytes - nbytes); - - if (unlikely(err)) { - pr_err("%s: skcipher_walk_done failed: %d\n", - crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), err); - return err; - } + return -EINVAL; } + while ((nbytes = walk.nbytes) != 0) { + err = wc_AesCbcDecrypt(ctx->aes_decrypt, walk.dst.virt.addr, + walk.src.virt.addr, nbytes & (~(WC_AES_BLOCK_SIZE - 1))); + + if (unlikely(err)) { + pr_err("%s: wc_AesCbcDecrypt failed for %u bytes: %d\n", + crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), nbytes, err); + return -EINVAL; + } + + nbytes &= WC_AES_BLOCK_SIZE - 1; + err = skcipher_walk_done(&walk, nbytes); + } + + /* copy iv from wolfCrypt back to walk.iv */ + XMEMCPY(walk.iv, ctx->aes_decrypt->reg, WC_AES_BLOCK_SIZE); + return err; } @@ -556,7 +545,7 @@ static int km_AesGcmSetKey(struct crypto_aead *tfm, const u8 *in_key, if (! disable_setkey_warnings) pr_err("%s: wc_AesGcmSetKey failed: %d\n", crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)), err); - return -ENOKEY; + return -EINVAL; } return 0; diff --git a/wolfcrypt/src/misc.c b/wolfcrypt/src/misc.c index 766ce5db8..8e234b508 100644 --- a/wolfcrypt/src/misc.c +++ b/wolfcrypt/src/misc.c @@ -484,6 +484,9 @@ counts, placing the result in <*buf>. */ WC_MISC_STATIC WC_INLINE void xorbuf(void* buf, const void* mask, word32 count) { + /* Leave no doubt that WOLFSSL_WORD_SIZE is a power of 2. */ + wc_static_assert((WOLFSSL_WORD_SIZE & (WOLFSSL_WORD_SIZE - 1)) == 0); + word32 i; byte* b; const byte* m; @@ -491,8 +494,9 @@ WC_MISC_STATIC WC_INLINE void xorbuf(void* buf, const void* mask, word32 count) b = (byte*)buf; m = (const byte*)mask; - if (((wc_ptr_t)b) % WOLFSSL_WORD_SIZE == - ((wc_ptr_t)m) % WOLFSSL_WORD_SIZE) { + if ((((wc_ptr_t)b) & (WOLFSSL_WORD_SIZE - 1)) == + (((wc_ptr_t)m) & (WOLFSSL_WORD_SIZE - 1))) + { /* type-punning helpers */ union { byte* bp; @@ -505,16 +509,25 @@ WC_MISC_STATIC WC_INLINE void xorbuf(void* buf, const void* mask, word32 count) /* Alignment checks out. Possible to XOR words. */ /* Move alignment so that it lines up with a * WOLFSSL_WORD_SIZE boundary */ - while (((wc_ptr_t)buf) % WOLFSSL_WORD_SIZE != 0 && count > 0) { + while ((((wc_ptr_t)b) & (WOLFSSL_WORD_SIZE - 1)) != 0 && count > 0) + { *(b++) ^= *(m++); count--; } tpb.bp = b; tpm.bp = m; - XorWords( &tpb.wp, &tpm.wp, count / WOLFSSL_WORD_SIZE); + /* Work around false positives from linuxkm CONFIG_FORTIFY_SOURCE. */ + #if defined(WOLFSSL_LINUXKM) && defined(CONFIG_FORTIFY_SOURCE) + PRAGMA_GCC_DIAG_PUSH; + PRAGMA_GCC("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") + #endif + XorWords(&tpb.wp, &tpm.wp, count >> WOLFSSL_WORD_SIZE_LOG2); + #if defined(WOLFSSL_LINUXKM) && defined(CONFIG_FORTIFY_SOURCE) + PRAGMA_GCC_DIAG_POP; + #endif b = tpb.bp; m = tpm.bp; - count %= WOLFSSL_WORD_SIZE; + count &= (WOLFSSL_WORD_SIZE - 1); } for (i = 0; i < count; i++) @@ -524,7 +537,7 @@ WC_MISC_STATIC WC_INLINE void xorbuf(void* buf, const void* mask, word32 count) #ifndef WOLFSSL_NO_FORCE_ZERO /* This routine fills the first len bytes of the memory area pointed by mem - with zeros. It ensures compiler optimizations doesn't skip it */ + with zeros. It ensures compiler optimization doesn't skip it */ WC_MISC_STATIC WC_INLINE void ForceZero(void* mem, word32 len) { volatile byte* z = (volatile byte*)mem; diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 97b269957..02210fd04 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -327,12 +327,15 @@ decouple library dependencies with standard string, memory and so on. #if defined(NO_64BIT) typedef word32 wolfssl_word; + #define WOLFSSL_WORD_SIZE_LOG2 2 #undef WORD64_AVAILABLE #else #ifdef WC_64BIT_CPU typedef word64 wolfssl_word; + #define WOLFSSL_WORD_SIZE_LOG2 3 #else typedef word32 wolfssl_word; + #define WOLFSSL_WORD_SIZE_LOG2 2 #ifdef WORD64_AVAILABLE #define WOLFCRYPT_SLOW_WORD64 #endif @@ -344,12 +347,14 @@ decouple library dependencies with standard string, memory and so on. #undef WORD64_AVAILABLE #endif typedef word16 wolfssl_word; + #define WOLFSSL_WORD_SIZE_LOG2 1 #define MP_16BIT /* for mp_int, mp_word needs to be twice as big as \ * mp_digit, no 64 bit type so make mp_digit 16 bit */ #else #undef WORD64_AVAILABLE typedef word32 wolfssl_word; + #define WOLFSSL_WORD_SIZE_LOG2 2 #define MP_16BIT /* for mp_int, mp_word needs to be twice as big as \ * mp_digit, no 64 bit type so make mp_digit 16 bit */ #endif