From 43b9909c38efe724774d4102915c4a1657383070 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Fri, 25 Oct 2024 18:02:18 -0500 Subject: [PATCH] fixes for gating and ARM32 alignment defects: wolfcrypt/src/port/arm/armv8-aes.c: in the WOLFSSL_ARMASM_NO_HW_CRYPTO version of wc_AesSetKey(), copy the supplied userKey to a properly aligned buffer if necessary before calling AES_set_encrypt_key(); src/dtls13.c: in Dtls13GetRnMask(), if defined(WOLFSSL_LINUXKM)), return retval of wc_AesEncryptDirect(); wolfcrypt/src/misc.c: add readUnalignedWord32(), writeUnalignedWord32(), readUnalignedWords32(), and writeUnalignedWords32(); wolfcrypt/src/siphash.c: use readUnalignedWord64(), readUnalignedWord32(), and writeUnalignedWord64(), to avoid unaligned access faults, and fix cast in byte-reversing version of GET_U32(). --- src/dtls13.c | 3 +- src/ssl_crypto.c | 3 +- wolfcrypt/src/misc.c | 47 ++++++++++++++++++++++++++++++ wolfcrypt/src/port/arm/armv8-aes.c | 21 ++++++++++++- wolfcrypt/src/siphash.c | 8 ++--- 5 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/dtls13.c b/src/dtls13.c index 6f2f014895..5011f7d85b 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -260,7 +260,8 @@ static int Dtls13GetRnMask(WOLFSSL* ssl, const byte* ciphertext, byte* mask, if (c->aes == NULL) return BAD_STATE_E; #if !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)) \ + || defined(WOLFSSL_LINUXKM)) return wc_AesEncryptDirect(c->aes, mask, ciphertext); #else wc_AesEncryptDirect(c->aes, mask, ciphertext); diff --git a/src/ssl_crypto.c b/src/ssl_crypto.c index 0730c45218..58fca44995 100644 --- a/src/ssl_crypto.c +++ b/src/ssl_crypto.c @@ -3002,7 +3002,8 @@ void wolfSSL_AES_encrypt(const unsigned char* input, unsigned char* output, } else #if !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)) \ + || defined(WOLFSSL_LINUXKM)) /* Encrypt a block with wolfCrypt AES. */ if (wc_AesEncryptDirect((Aes*)key, output, input) != 0) { WOLFSSL_MSG("wc_AesEncryptDirect failed"); diff --git a/wolfcrypt/src/misc.c b/wolfcrypt/src/misc.c index e4b53d91f1..4f8f09ce72 100644 --- a/wolfcrypt/src/misc.c +++ b/wolfcrypt/src/misc.c @@ -209,6 +209,53 @@ WC_MISC_STATIC WC_INLINE void ByteReverseWords(word32* out, const word32* in, #endif } +WC_MISC_STATIC WC_INLINE word32 readUnalignedWord32(const byte *in) +{ + if (((wc_ptr_t)in & (wc_ptr_t)(sizeof(word32) - 1U)) == (wc_ptr_t)0) + return *(word32 *)in; + else { + word32 out; + XMEMCPY(&out, in, sizeof(word32)); + return out; + } +} + +WC_MISC_STATIC WC_INLINE word32 writeUnalignedWord32(void *out, word32 in) +{ + if (((wc_ptr_t)out & (wc_ptr_t)(sizeof(word32) - 1U)) == (wc_ptr_t)0) + *(word32 *)out = in; + else { + XMEMCPY(out, &in, sizeof(word32)); + } + return in; +} + +WC_MISC_STATIC WC_INLINE void readUnalignedWords32(word32 *out, const byte *in, + size_t count) +{ + if (((wc_ptr_t)in & (wc_ptr_t)(sizeof(word32) - 1U)) == (wc_ptr_t)0) { + const word32 *in_word32 = (const word32 *)in; + while (count-- > 0) + *out++ = *in_word32++; + } + else { + XMEMCPY(out, in, count * sizeof(word32)); + } +} + +WC_MISC_STATIC WC_INLINE void writeUnalignedWords32(byte *out, const word32 *in, + size_t count) +{ + if (((wc_ptr_t)out & (wc_ptr_t)(sizeof(word32) - 1U)) == (wc_ptr_t)0) { + word32 *out_word32 = (word32 *)out; + while (count-- > 0) + *out_word32++ = *in++; + } + else { + XMEMCPY(out, in, count * sizeof(word32)); + } +} + #if defined(WORD64_AVAILABLE) && !defined(WOLFSSL_NO_WORD64_OPS) WC_MISC_STATIC WC_INLINE word64 readUnalignedWord64(const byte *in) diff --git a/wolfcrypt/src/port/arm/armv8-aes.c b/wolfcrypt/src/port/arm/armv8-aes.c index 0baa39b5ca..9e2f3cb6b9 100644 --- a/wolfcrypt/src/port/arm/armv8-aes.c +++ b/wolfcrypt/src/port/arm/armv8-aes.c @@ -16561,6 +16561,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, { #if defined(AES_MAX_KEY_SIZE) const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); + word32 userKey_aligned[AES_MAX_KEY_SIZE / WOLFSSL_BIT_SIZE / sizeof(word32)]; #endif if (((keylen != 16) && (keylen != 24) && (keylen != 32)) || @@ -16574,6 +16575,14 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, return BAD_FUNC_ARG; } #endif + +#if !defined(AES_MAX_KEY_SIZE) + /* Check alignment */ + if ((unsigned long)userKey & (sizeof(aes->key[0]) - 1U)) { + return BAD_FUNC_ARG; + } +#endif + #ifdef WOLF_CRYPTO_CB if (aes->devId != INVALID_DEVID) { if (keylen > sizeof(aes->devKey)) { @@ -16590,7 +16599,17 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, aes->keylen = keylen; aes->rounds = keylen/4 + 6; - AES_set_encrypt_key(userKey, keylen * 8, (byte*)aes->key); +#if defined(AES_MAX_KEY_SIZE) + if ((unsigned long)userKey & (sizeof(aes->key[0]) - 1U)) { + XMEMCPY(userKey_aligned, userKey, keylen); + AES_set_encrypt_key((byte *)userKey_aligned, keylen * 8, (byte*)aes->key); + } + else +#endif + { + AES_set_encrypt_key(userKey, keylen * 8, (byte*)aes->key); + } + #ifdef HAVE_AES_DECRYPT if (dir == AES_DECRYPTION) { AES_invert_key((byte*)aes->key, aes->rounds); diff --git a/wolfcrypt/src/siphash.c b/wolfcrypt/src/siphash.c index 54c02f6a58..d455c663ec 100644 --- a/wolfcrypt/src/siphash.c +++ b/wolfcrypt/src/siphash.c @@ -69,14 +69,14 @@ * @param [in] a Little-endian byte array. * @return 64-bit number. */ -#define GET_U64(a) (*(word64*)(a)) +#define GET_U64(a) readUnalignedWord64(a) /** * Decode little-endian byte array to 32-bit number. * * @param [in] a Little-endian byte array. * @return 32-bit number. */ -#define GET_U32(a) (*(word32*)(a)) +#define GET_U32(a) readUnalignedWord32(a) /** * Decode little-endian byte array to 16-bit number. * @@ -90,7 +90,7 @@ * @param [out] a Byte array to write into. * @param [in] n Number to encode. */ -#define SET_U64(a, n) ((*(word64*)(a)) = (n)) +#define SET_U64(a, n) writeUnalignedWord64(a, n) #else /** * Decode little-endian byte array to 64-bit number. @@ -112,7 +112,7 @@ * @param [in] a Little-endian byte array. * @return 32-bit number. */ -#define GET_U32(a) (((word64)((a)[3]) << 24) | \ +#define GET_U32(a) (((word32)((a)[3]) << 24) | \ ((word32)((a)[2]) << 16) | \ ((word32)((a)[1]) << 8) | \ ((word32)((a)[0]) ))