diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index f76c82b8d5..d19f3af727 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -130,6 +130,7 @@ CONFIG_IDF_TARGET_ESP32S3 CONFIG_IDF_TARGET_ESP8266 CONFIG_IDF_TARGET_ESP8684 CONFIG_KASAN +CONFIG_KMSAN CONFIG_KPROBES CONFIG_MAIN_TASK_STACK_SIZE CONFIG_MBEDTLS_CERTIFICATE_BUNDLE diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index 0e64c14be7..8b7b33c1f1 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -349,14 +349,34 @@ _Pragma("clang diagnostic ignored \"-Wshorten-64-to-32\""); _Pragma("clang diagnostic ignored \"-Wframe-address\""); #endif +#if defined(__GNUC__) && (__GNUC__ >= 17) + _Pragma("GCC diagnostic ignored \"-Wconstant-logical-operand\""); +#endif - #ifdef CONFIG_KASAN + /* KASAN and KMSAN are mutually exclusive, so we need to consider at most + * one of them here. + */ + #if defined(CONFIG_KASAN) #ifndef WC_SANITIZE_DISABLE #define WC_SANITIZE_DISABLE() kasan_disable_current() #endif #ifndef WC_SANITIZE_ENABLE #define WC_SANITIZE_ENABLE() kasan_enable_current() #endif + #elif defined(CONFIG_KMSAN) + #ifndef WC_SANITIZE_DISABLE + #define WC_SANITIZE_DISABLE() kmsan_disable_current() + #endif + #ifndef WC_SANITIZE_ENABLE + #define WC_SANITIZE_ENABLE() kmsan_enable_current() + #endif + #else + #ifndef WC_SANITIZE_DISABLE + #define WC_SANITIZE_DISABLE() do {} while (0) + #endif + #ifndef WC_SANITIZE_ENABLE + #define WC_SANITIZE_ENABLE() do {} while (0) + #endif #endif #if defined(CONFIG_FORTIFY_SOURCE) && \ @@ -1725,12 +1745,12 @@ pr_err("ERROR: bottom of stack is not STACK_END_MAGIC.\n"); local_irq_save(flags); - kasan_disable_current(); + WC_SANITIZE_DISABLE(); z = wc_linuxkm_stack_left(); if (z > WC_KERNEL_STACK_MARGIN_BOTTOM + WC_KERNEL_STACK_MARGIN_TOP) memset((void *)(s + WC_KERNEL_STACK_MARGIN_BOTTOM), sentinel, z - (WC_KERNEL_STACK_MARGIN_BOTTOM + WC_KERNEL_STACK_MARGIN_TOP)); - kasan_enable_current(); + WC_SANITIZE_ENABLE(); local_irq_restore(flags); if (z <= WC_KERNEL_STACK_MARGIN_BOTTOM + WC_KERNEL_STACK_MARGIN_TOP) pr_err("ERROR: wc_linuxkm_stack_hwm_prepare() called with only %lu bytes of stack left, " @@ -1742,11 +1762,11 @@ unsigned char *i; if (z <= WC_KERNEL_STACK_MARGIN_BOTTOM + WC_KERNEL_STACK_MARGIN_TOP) return (unsigned long)-1; - kasan_disable_current(); + WC_SANITIZE_DISABLE(); for (i = (unsigned char *)s + WC_KERNEL_STACK_MARGIN_BOTTOM; i < ((unsigned char *)s + z) && (*i == sentinel); ++i); - kasan_enable_current(); + WC_SANITIZE_ENABLE(); return z - ((unsigned long)i - s); } static __always_inline unsigned long wc_linuxkm_stack_hwm_measure_total(unsigned char sentinel) { @@ -1809,6 +1829,21 @@ #define XGMTIME(c, t) gmtime(c) #define NO_TIMEVAL 1 + /* MSAN needs to intercept these string functions to properly instrument + * them, but we build with -ffreestanding, which inhibits the interception. + * Fix that with explicit mappings here. + */ + #ifdef CONFIG_KMSAN + #define memcpy(d, s, l) __builtin_memcpy(d, s, l) + #define memset(d, v, l) __builtin_memset(d, v, l) + #define memmove(d, s, l) __builtin_memmove(d, s, l) + #define strcpy(d, s) __builtin_strcpy(d, s) + #if LINUX_VERSION_CODE < KERNEL_VERSION(7, 2, 0) + #define strncpy(d, s, l) __builtin_strncpy(d, s, l) + #endif + #define strncat(d, s, l) __builtin_strncat(d, s, l) + #endif + #endif /* BUILDING_WOLFSSL */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(7, 2, 0) diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 80b94efa14..13cace7ab1 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -907,7 +907,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits /* Pick the widest available implementation at runtime. Callers must * already be inside a VECTOR_REGISTERS_PUSH / SAVE_VECTOR_REGISTERS * region (all bulk AES-NI call sites are). */ - static WC_INLINE void AesEcbEncryptBlocks(const unsigned char* in, + static WC_MAYBE_UNUSED WC_INLINE void AesEcbEncryptBlocks(const unsigned char* in, unsigned char* out, word32 sz, const unsigned char* key, int nr) { #ifdef HAVE_INTEL_AVX512 @@ -936,7 +936,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits } #ifdef HAVE_AES_DECRYPT - static WC_INLINE void AesEcbDecryptBlocks(const unsigned char* in, + static WC_MAYBE_UNUSED WC_INLINE void AesEcbDecryptBlocks(const unsigned char* in, unsigned char* out, word32 sz, const unsigned char* key, int nr) { #ifdef HAVE_INTEL_AVX512 @@ -966,7 +966,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #endif #ifdef HAVE_AES_CBC - static WC_INLINE void AesCbcEncryptBlocks(const unsigned char* in, + static WC_MAYBE_UNUSED WC_INLINE void AesCbcEncryptBlocks(const unsigned char* in, unsigned char* out, unsigned char* iv, word32 sz, const unsigned char* key, int nr) { @@ -997,7 +997,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #endif /* HAVE_AES_CBC */ #ifdef HAVE_AES_DECRYPT - static WC_INLINE void AesCbcDecryptBlocks(const unsigned char* in, + static WC_MAYBE_UNUSED WC_INLINE void AesCbcDecryptBlocks(const unsigned char* in, unsigned char* out, unsigned char* iv, word32 sz, const unsigned char* key, int nr) { @@ -1027,7 +1027,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits } #endif /* HAVE_AES_DECRYPT */ - static WC_INLINE void AesCtrEncryptBlocks(const unsigned char* in, + static WC_MAYBE_UNUSED WC_INLINE void AesCtrEncryptBlocks(const unsigned char* in, unsigned char* out, word32 sz, const unsigned char* key, int nr, unsigned char* ctr) { @@ -5928,6 +5928,14 @@ int wc_AesSetIV(Aes* aes, const byte* iv) } \ WC_DO_NOTHING +#define VECTOR_REGISTERS_PUSH2(fail_clause) { \ + int orig_use_aesni = aes->use_aesni; \ + if (aes->use_aesni && (SAVE_VECTOR_REGISTERS2() != 0)) { \ + aes->use_aesni = 0; \ + } \ + WC_DO_NOTHING + + #define VECTOR_REGISTERS_POP \ if (aes->use_aesni) \ RESTORE_VECTOR_REGISTERS(); \ @@ -5941,18 +5949,28 @@ int wc_AesSetIV(Aes* aes, const byte* iv) #define VECTOR_REGISTERS_PUSH { \ WC_DO_NOTHING +#define VECTOR_REGISTERS_PUSH2(fail_clause) { \ + WC_DO_NOTHING + #define VECTOR_REGISTERS_POP \ } \ WC_DO_NOTHING #else -#define VECTOR_REGISTERS_PUSH { \ +#define VECTOR_REGISTERS_PUSH { \ if (aes->use_aesni && ((ret = SAVE_VECTOR_REGISTERS2()) != 0)) { \ return ret; \ } \ WC_DO_NOTHING +#define VECTOR_REGISTERS_PUSH2(fail_clause) { \ + if (aes->use_aesni && ((ret = SAVE_VECTOR_REGISTERS2()) != 0)) { \ + { fail_clause } \ + return ret; \ + } \ + WC_DO_NOTHING + #define VECTOR_REGISTERS_POP \ if (aes->use_aesni) { \ RESTORE_VECTOR_REGISTERS(); \ @@ -5965,6 +5983,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv) #else /* !WOLFSSL_AESNI */ #define VECTOR_REGISTERS_PUSH WC_DO_NOTHING +#define VECTOR_REGISTERS_PUSH2(fail_clause) WC_DO_NOTHING #define VECTOR_REGISTERS_POP WC_DO_NOTHING #endif /* !WOLFSSL_AESNI */ @@ -15511,6 +15530,14 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out, #ifdef WC_AES_HAVE_PREFETCH_ARG int did_prefetches = 0; #endif +#ifndef WC_AES_CFB_DEC_BUF_BLOCKS + #define WC_AES_CFB_DEC_BUF_BLOCKS 32 +#elif WC_AES_CFB_DEC_BUF_BLOCKS < 2 + #error Invalid WC_AES_CFB_DEC_BUF_BLOCKS +#endif +#ifdef WOLFSSL_SMALL_STACK + byte *tmp = NULL; +#endif (void)mode; @@ -15534,18 +15561,32 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out, sz -= processed; } - VECTOR_REGISTERS_PUSH; +#if defined(WOLFSSL_SMALL_STACK) && defined(HAVE_AES_ECB) && \ + !defined(WOLFSSL_PIC32MZ_CRYPT) && \ + (defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_ARMASM)) + /* Only suffer the heap overhead if sz is enough to warrant it. + * + * Allocate the working buffer before suspending interrupts, so that we can + * allocate with regular GFP_KERNEL. + */ + if (sz >= WC_AES_CFB_DEC_BUF_BLOCKS * WC_AES_BLOCK_SIZE) + tmp = (byte *)XMALLOC(WC_AES_CFB_DEC_BUF_BLOCKS * WC_AES_BLOCK_SIZE, NULL, DYNAMIC_TYPE_AES); - #if !defined(WOLFSSL_SMALL_STACK) && defined(HAVE_AES_ECB) && \ + VECTOR_REGISTERS_PUSH2(XFREE(tmp, NULL, DYNAMIC_TYPE_AES);); +#else + VECTOR_REGISTERS_PUSH; +#endif + + #if defined(HAVE_AES_ECB) && \ !defined(WOLFSSL_PIC32MZ_CRYPT) && \ (defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_ARMASM)) +#ifdef WOLFSSL_SMALL_STACK + if (tmp != NULL) +#endif { - #ifndef WC_AES_CFB_DEC_BUF_BLOCKS - #define WC_AES_CFB_DEC_BUF_BLOCKS 32 - #elif WC_AES_CFB_DEC_BUF_BLOCKS < 2 - #error Invalid WC_AES_CFB_DEC_BUF_BLOCKS - #endif +#ifndef WOLFSSL_SMALL_STACK ALIGN16 byte tmp[WC_AES_CFB_DEC_BUF_BLOCKS * WC_AES_BLOCK_SIZE]; +#endif while (sz >= 2 * WC_AES_BLOCK_SIZE) { word32 blocks = sz / WC_AES_BLOCK_SIZE; word32 nbytes; @@ -15592,6 +15633,11 @@ static WARN_UNUSED_RESULT int AesCfbDecrypt_C(Aes* aes, byte* out, VECTOR_REGISTERS_POP; +#ifdef WOLFSSL_SMALL_STACK + /* Free tmp after restoring interrupts, so that GFP_KERNEL is usable. */ + XFREE(tmp, NULL, DYNAMIC_TYPE_AES); +#endif + return ret; } #endif /* HAVE_AES_DECRYPT */ diff --git a/wolfcrypt/src/port/kcapi/kcapi_aes.c b/wolfcrypt/src/port/kcapi/kcapi_aes.c index 30ad3e9d03..71d86ec534 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_aes.c +++ b/wolfcrypt/src/port/kcapi/kcapi_aes.c @@ -240,14 +240,21 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, ret = BAD_FUNC_ARG; } - if ((ret == 0) && ((ivSz != WC_SYSTEM_AESGCM_IV) || - (authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ))) { + if ((ret == 0) && ((ivSz != WC_SYSTEM_AESGCM_IV) +#if defined(HAVE_FIPS) && FIPS_VERSION3_LT(7,0,0) + || (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) + || (authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ) +#endif + )) + { WOLFSSL_MSG("IV/AAD size not supported on system"); ret = BAD_FUNC_ARG; } +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0) if (ret == 0) ret = wc_local_AesGcmCheckTagSz(authTagSz); +#endif if (ret == 0) { ret = kcapi_aead_init(&aes->handle, WC_NAME_AESGCM, 0); @@ -353,14 +360,21 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, ret = BAD_FUNC_ARG; } - if ((ret == 0) && ((ivSz != WC_SYSTEM_AESGCM_IV) || - (authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ))) { + if ((ret == 0) && ((ivSz != WC_SYSTEM_AESGCM_IV) +#if defined(HAVE_FIPS) && FIPS_VERSION3_LT(7,0,0) + || (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) + || (authTagSz > WOLFSSL_MAX_AUTH_TAG_SZ) +#endif + )) + { WOLFSSL_MSG("IV/AAD size not supported on system"); ret = BAD_FUNC_ARG; } +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0) if (ret == 0) ret = wc_local_AesGcmCheckTagSz(authTagSz); +#endif if (ret == 0) { ret = kcapi_aead_init(&aes->handle, WC_NAME_AESGCM, 0);