linuxkm: various fixes for LKCAPI wrapper for AES-CBC (now passing kernel-native

self-test and crypto fuzzer), and de-experimentalize it.

wolfssl/wolfcrypt/types.h: add definitions for WOLFSSL_WORD_SIZE_LOG2.

wolfcrypt/src/misc.c: fix xorbuf() to make the XorWords() reachable; also,
  refactor integer division and modulus ops as masks and shifts, and add pragma
  to suppress linuxkm FORTIFY_SOURCE false positive -Wmaybe-uninitialized.
pull/8534/head
Daniel Pouzzner 2025-03-05 15:33:17 -06:00
parent 7d102a1816
commit dc2e2631bc
4 changed files with 71 additions and 65 deletions

View File

@ -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.])

View File

@ -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,12 +275,9 @@ 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);
if (unlikely(err)) {
@ -292,23 +286,22 @@ static int km_AesCbcEncrypt(struct skcipher_request *req)
return -EINVAL;
}
while ((nbytes = walk.nbytes) != 0) {
err = wc_AesCbcEncrypt(ctx->aes_encrypt, walk.dst.virt.addr,
walk.src.virt.addr, nbytes);
walk.src.virt.addr, nbytes & (~(WC_AES_BLOCK_SIZE - 1)));
if (unlikely(err)) {
pr_err("%s: wc_AesCbcEncrypt failed: %d\n",
crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), 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;
}
err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
nbytes &= WC_AES_BLOCK_SIZE - 1;
err = skcipher_walk_done(&walk, 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;
}
}
/* copy iv from wolfCrypt back to walk.iv */
XMEMCPY(walk.iv, ctx->aes_encrypt->reg, WC_AES_BLOCK_SIZE);
return err;
}
@ -327,12 +320,9 @@ 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);
if (unlikely(err)) {
@ -342,23 +332,22 @@ static int km_AesCbcDecrypt(struct skcipher_request *req)
return -EINVAL;
}
while ((nbytes = walk.nbytes) != 0) {
err = wc_AesCbcDecrypt(ctx->aes_decrypt, walk.dst.virt.addr,
walk.src.virt.addr, nbytes);
walk.src.virt.addr, nbytes & (~(WC_AES_BLOCK_SIZE - 1)));
if (unlikely(err)) {
pr_err("%s: wc_AesCbcDecrypt failed: %d\n",
crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)), 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;
}
err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
nbytes &= WC_AES_BLOCK_SIZE - 1;
err = skcipher_walk_done(&walk, 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;
}
}
/* 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;

View File

@ -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;

View File

@ -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