From 43cd1723fc81489ce7fdc549b6be7cf9558120c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Thu, 5 Nov 2026 18:21:03 +0100 Subject: [PATCH] Return BAD_ALIGN_E from init for misaligned contexts on x86_64 wc_Sha256, Aes, Hmac, curve25519_key and ed25519_key are 16-byte aligned types in default builds. A caller that places one at an offset that is only 8-byte aligned, as curl's Curl_HMAC_init() did by putting the hash contexts after a 24-byte header, crashes on x86_64: the compiler zeroes the context with aligned SSE stores and the CPU faults. Add WC_ALIGNOF() and WC_IS_ALIGNED() to types.h, plus WC_CTX_IS_ALIGNED(), which checks a context pointer against its type's alignment capped at 16, the alignment malloc() guarantees on x86_64. WC_ALIGNOF() prefers C11 _Alignof, since GCC's __alignof__ reports the preferred rather than the required alignment on some targets. The init functions for these types now return BAD_ALIGN_E before touching a misaligned context, following the existing BAD_ALIGN_E checks on AES-NI and MMCAU buffers. This includes the crypto callback only SHA-256/SHA-224 init, the KCAPI SHA-256, SHA-224 and HMAC init and the devcrypto SHA-256 init, whose contexts keep the aligned fields. The AF_ALG SHA-256 init and copy and the SE050 SHA-256/SHA-224 init check as well: their contexts are not aligned types, but they share the generic free, which returns early on a context below its type's alignment and would leak their sockets or SE050 state. KCAPI wc_HmacSetKey() checks too, so an Hmac keyed without init never owns a handle its free skips. PSA has its own hash free and needs no check. wc_Sha256Copy(), wc_Sha224Copy() and wc_HmacCopy(), including the KCAPI and devcrypto versions, reject a misaligned destination the same way. A rejected context is left unmodified. The matching free functions wipe a misaligned context with ForceZero(), which does not assume the type's alignment, and return without touching its fields, so the usual cleanup that calls free after a failed init does not run on uninitialized memory. Before this change that memory was at least zeroed by init, and builds whose compiler emits unaligned stores did not crash. The wipe keeps key material from a context that was keyed without init, such as an Aes passed straight to wc_AesSetKey(). The check is limited to x86_64 user space, the only place a misaligned context faults. Cortex-M builds that force WOLFSSL_USE_ALIGN get less than 16-byte alignment from malloc(), so a check on other CPUs would reject contexts wolfSSL allocates itself. Kernel builds compile without SSE code generation and are excluded as well. So are freestanding builds (__STDC_HOSTED__ is 0), whose RTOS or bare-metal malloc() may align to 8 only, and static memory builds, whose blocks are only as aligned as the configured bucket sizes. Define WC_NO_CTX_ALIGN_CHECK to disable it; that removes the check, not the alignment the types need. The wolfSSL_SetAllocators() doxygen states the 16-byte requirement. The API test covers init and copy into a misaligned context, and checks that a rejected context is left untouched by init and copy and zeroed by free. The copy cases run only for types aligned to 16, since copy frees an accepted destination first. It is skipped for FIPS and selftest builds, which take these init functions from frozen sources without the check. Forming a misaligned pointer is already undefined behavior, so this is best effort; current gcc and clang keep the check. --- .wolfssl_known_macro_extras | 2 + doc/dox_comments/header_files/aes.h | 8 ++ doc/dox_comments/header_files/curve25519.h | 4 + doc/dox_comments/header_files/ed25519.h | 8 ++ doc/dox_comments/header_files/memory.h | 3 +- doc/dox_comments/header_files/sha256.h | 12 ++ tests/api.c | 121 ++++++++++++++++++ wolfcrypt/src/aes.c | 10 ++ wolfcrypt/src/curve25519.c | 11 ++ wolfcrypt/src/ed25519.c | 10 ++ wolfcrypt/src/hmac.c | 14 ++ wolfcrypt/src/port/af_alg/afalg_hash.c | 10 ++ wolfcrypt/src/port/devcrypto/devcrypto_hash.c | 10 ++ wolfcrypt/src/port/kcapi/kcapi_hash.c | 20 +++ wolfcrypt/src/port/kcapi/kcapi_hmac.c | 23 ++++ wolfcrypt/src/sha256.c | 52 ++++++++ wolfssl/wolfcrypt/types.h | 24 ++++ 17 files changed, 341 insertions(+), 1 deletion(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 36f3f3f5ede..7860acc72ef 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -863,6 +863,7 @@ WC_MPFS_ATHENA_NO_BASE_ADDR WC_MPFS_ATHENA_NO_HW_INIT WC_MPFS_ATHENA_NO_HW_MUTEX WC_NO_ASYNC_SLEEP +WC_NO_CTX_ALIGN_CHECK WC_NO_RNG_SIMPLE WC_NO_STATIC_ASSERT WC_NO_VERBOSE_RNG @@ -1442,6 +1443,7 @@ __SDCC_VERSION_PATCH __SIZEOF_INT128__ __SIZEOF_LONG_LONG__ __SIZEOF_LONG__ +__STDC_HOSTED__ __STDC_NO_ATOMICS__ __STDC_VERSION__ __STDC__ diff --git a/doc/dox_comments/header_files/aes.h b/doc/dox_comments/header_files/aes.h index f39d1c5ee68..98a5914768e 100644 --- a/doc/dox_comments/header_files/aes.h +++ b/doc/dox_comments/header_files/aes.h @@ -787,6 +787,8 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, wc_AesXtsFree on aes key when done. \return 0 Success + \return BAD_ALIGN_E On x86_64, if aes is not 16-byte aligned. + The structure is left unmodified. \param aes AES keys for encrypt/decrypt process \param heap heap hint to use for memory. Can be NULL @@ -1093,6 +1095,8 @@ int wc_AesXtsFree(XtsAes* aes); with async hardware. It is up to the user to call wc_AesFree on the Aes structure when done. \return 0 Success + \return BAD_ALIGN_E On x86_64, if aes is not 16-byte aligned. + The structure is left unmodified. \param aes aes structure in to initialize \param heap heap hint to use for malloc / free if needed @@ -3617,6 +3621,8 @@ int wc_AesGetKeySize(Aes* aes, word32* keySize); \return BAD_FUNC_ARG If aes is NULL, or if id is NULL while len is positive. \return BUFFER_E If len is negative or greater than AES_MAX_ID_LEN. + \return BAD_ALIGN_E On x86_64, if aes is not 16-byte aligned. + The structure is left unmodified. \param aes pointer to the AES structure to initialize \param id pointer to the ID buffer @@ -3654,6 +3660,8 @@ int wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, \return 0 On success. \return BAD_FUNC_ARG If aes or label is NULL. + \return BAD_ALIGN_E On x86_64, if aes is not 16-byte aligned. + The structure is left unmodified. \param aes pointer to the AES structure to initialize \param label pointer to the null-terminated label string diff --git a/doc/dox_comments/header_files/curve25519.h b/doc/dox_comments/header_files/curve25519.h index 33d276d2841..ef7ad04bada 100644 --- a/doc/dox_comments/header_files/curve25519.h +++ b/doc/dox_comments/header_files/curve25519.h @@ -148,6 +148,8 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key, \return 0 Returned on successfully initializing the curve25519_key structure. \return BAD_FUNC_ARG Returned when key is NULL. + \return BAD_ALIGN_E On x86_64, if key is not 16-byte aligned. + The structure is left unmodified. \param [in,out] key Pointer to the curve25519_key structure to initialize. @@ -968,6 +970,8 @@ int wc_curve25519_make_priv(WC_RNG* rng, int keysize, byte* priv); \return 0 On successfully initializing the key \return BAD_FUNC_ARG If key is NULL + \return BAD_ALIGN_E On x86_64, if key is not 16-byte aligned. + The structure is left unmodified. \param key Pointer to the curve25519_key structure to initialize \param heap Pointer to heap hint for memory allocation (can be diff --git a/doc/dox_comments/header_files/ed25519.h b/doc/dox_comments/header_files/ed25519.h index 4e741c6e3e0..8683406dfe9 100644 --- a/doc/dox_comments/header_files/ed25519.h +++ b/doc/dox_comments/header_files/ed25519.h @@ -528,6 +528,8 @@ int wc_ed25519ph_verify_msg(const byte* sig, word32 siglen, const byte* msg, \return 0 Returned upon successfully initializing the ed25519_key object. \return BAD_FUNC_ARG Returned if key is NULL. + \return BAD_ALIGN_E On x86_64, if key is not 16-byte aligned. + The structure is left unmodified. \param [in,out] key Pointer to the ed25519_key object to initialize. @@ -1241,6 +1243,8 @@ int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, \return 0 on success \return negative on failure + \return BAD_ALIGN_E On x86_64, if key is not 16-byte aligned. + The structure is left unmodified. \param key Ed25519 key structure \param heap Heap hint for memory allocation @@ -1267,6 +1271,8 @@ int wc_ed25519_init_ex(ed25519_key* key, void* heap, int devId); \return BAD_FUNC_ARG if key is NULL, or id is NULL and len is greater than 0. \return BUFFER_E if len is negative or greater than ED25519_MAX_ID_LEN. + \return BAD_ALIGN_E On x86_64, if key is not 16-byte aligned. + The structure is left unmodified. \param [in,out] key Pointer to the ed25519_key to initialize. \param [in] id Key identifier bytes. @@ -1297,6 +1303,8 @@ int wc_ed25519_init_id(ed25519_key* key, const unsigned char* id, int len, \return 0 on success. \return BAD_FUNC_ARG if key or label is NULL. \return BUFFER_E if label is empty or longer than ED25519_MAX_LABEL_LEN. + \return BAD_ALIGN_E On x86_64, if key is not 16-byte aligned. + The structure is left unmodified. \param [in,out] key Pointer to the ed25519_key to initialize. \param [in] label NUL-terminated label string. diff --git a/doc/dox_comments/header_files/memory.h b/doc/dox_comments/header_files/memory.h index b5430758a30..6b88667fd62 100644 --- a/doc/dox_comments/header_files/memory.h +++ b/doc/dox_comments/header_files/memory.h @@ -109,7 +109,8 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type); \brief This function registers the allocation functions used by wolfSSL. By default, if the system supports it, malloc/free and realloc are used. Using this function allows the user at runtime to install their own - memory handlers. + memory handlers. On x86_64 the allocator must return 16-byte aligned + memory like malloc(). \return Success If successful this function will return 0. \return BAD_FUNC_ARG is the error that will be returned if a diff --git a/doc/dox_comments/header_files/sha256.h b/doc/dox_comments/header_files/sha256.h index 06bf6923337..d647d226042 100644 --- a/doc/dox_comments/header_files/sha256.h +++ b/doc/dox_comments/header_files/sha256.h @@ -5,6 +5,8 @@ called by wc_Sha256Hash. \return 0 Returned upon successfully initializing + \return BAD_ALIGN_E On x86_64, if sha256 is not 16-byte aligned. + The structure is left unmodified. \param sha256 pointer to the sha256 structure to use for encryption @@ -199,6 +201,8 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash); \return 0 Success \return 1 Error returned because sha224 is null. + \return BAD_ALIGN_E On x86_64, if sha224 is not 16-byte aligned. + The structure is left unmodified. \param sha224 Pointer to a Sha224 struct to initialize. @@ -291,6 +295,8 @@ int wc_Sha224Final(wc_Sha224* sha224, byte* hash); \return 0 on success \return negative on error + \return BAD_ALIGN_E On x86_64, if sha256 is not 16-byte aligned. + The structure is left unmodified. \param sha SHA256 structure \param heap Heap hint @@ -407,6 +413,8 @@ int wc_Sha256_Grow(wc_Sha256* sha256, const byte* in, int inSz); \return 0 on success \return negative on error + \return BAD_ALIGN_E On x86_64, if dst is not 16-byte aligned. + dst is left unmodified. \param src Source SHA256 structure \param dst Destination SHA256 structure; @@ -491,6 +499,8 @@ int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags); \return 0 on success \return negative on error + \return BAD_ALIGN_E On x86_64, if sha224 is not 16-byte aligned. + The structure is left unmodified. \param sha224 SHA224 structure \param heap Heap hint @@ -621,6 +631,8 @@ int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash); \return 0 on success \return negative on error + \return BAD_ALIGN_E On x86_64, if dst is not 16-byte aligned. + dst is left unmodified. \param src Source SHA224 structure \param dst Destination SHA224 structure diff --git a/tests/api.c b/tests/api.c index 1d60e540cda..fee88f3ed37 100644 --- a/tests/api.c +++ b/tests/api.c @@ -14145,6 +14145,126 @@ static int test_wc_SetMutexCb(void) return EXPECT_RESULT(); } /* End test_wc_SetMutexCb*/ +#if defined(WC_CTX_IS_ALIGNED) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) && (!defined(NO_SHA256) || !defined(NO_AES) || \ + !defined(NO_HMAC) || defined(HAVE_CURVE25519) || defined(HAVE_ED25519)) +#define TEST_CTX_MISALIGNED_ENABLED + +/* Returns sz usable bytes starting 8 bytes past a 16-byte boundary. */ +static void* test_misaligned_alloc(byte** buf, size_t sz) +{ + *buf = (byte*)XMALLOC(sz + 32, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (*buf == NULL) + return NULL; + return *buf + 24 - ((wc_ptr_t)*buf & 15); +} + +static int test_misaligned_filled(const void* ctx, size_t sz, byte val) +{ + const byte* p = (const byte*)ctx; + size_t i; + + for (i = 0; i < sz; i++) { + if (p[i] != val) + return 0; + } + return 1; +} + +#define TEST_MISALIGNED_RET(T) \ + ((WC_ALIGNOF(T) >= 16) ? WC_NO_ERR_TRACE(BAD_ALIGN_E) : 0) + +#define TEST_CTX_MISALIGNED(T, initCall, freeCall) \ + do { \ + ExpectNotNull(ctx = test_misaligned_alloc(&buf, sizeof(T))); \ + if (ctx != NULL) { \ + XMEMSET(ctx, 0xA5, sizeof(T)); \ + ret = (initCall); \ + ExpectIntEQ(ret, TEST_MISALIGNED_RET(T)); \ + if (ret != 0) \ + ExpectTrue(test_misaligned_filled(ctx, sizeof(T), 0xA5)); \ + freeCall; \ + if (ret != 0) \ + ExpectTrue(test_misaligned_filled(ctx, sizeof(T), 0)); \ + } \ + XFREE(buf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); \ + buf = NULL; \ + ctx = NULL; \ + } while (0) +#endif + +/* + * Testing init functions on a context below its type's alignment + */ +static int test_wc_CtxInit_misaligned(void) +{ + EXPECT_DECLS; +#ifdef TEST_CTX_MISALIGNED_ENABLED + byte* buf = NULL; + void* ctx = NULL; + int ret = 0; +#ifndef NO_SHA256 + wc_Sha256 sha256; +#endif +#ifdef WOLFSSL_SHA224 + wc_Sha224 sha224; +#endif +#ifndef NO_HMAC + Hmac hmac; +#endif + +#ifndef NO_SHA256 + TEST_CTX_MISALIGNED(wc_Sha256, wc_InitSha256((wc_Sha256*)ctx), + wc_Sha256Free((wc_Sha256*)ctx)); + XMEMSET(&sha256, 0, sizeof(sha256)); + ExpectIntEQ(wc_InitSha256(&sha256), 0); + if (WC_ALIGNOF(wc_Sha256) >= 16) { + TEST_CTX_MISALIGNED(wc_Sha256, + wc_Sha256Copy(&sha256, (wc_Sha256*)ctx), + wc_Sha256Free((wc_Sha256*)ctx)); + } + wc_Sha256Free(&sha256); +#endif +#ifdef WOLFSSL_SHA224 + TEST_CTX_MISALIGNED(wc_Sha224, wc_InitSha224((wc_Sha224*)ctx), + wc_Sha224Free((wc_Sha224*)ctx)); + XMEMSET(&sha224, 0, sizeof(sha224)); + ExpectIntEQ(wc_InitSha224(&sha224), 0); + if (WC_ALIGNOF(wc_Sha224) >= 16) { + TEST_CTX_MISALIGNED(wc_Sha224, + wc_Sha224Copy(&sha224, (wc_Sha224*)ctx), + wc_Sha224Free((wc_Sha224*)ctx)); + } + wc_Sha224Free(&sha224); +#endif +#ifndef NO_AES + TEST_CTX_MISALIGNED(Aes, wc_AesInit((Aes*)ctx, HEAP_HINT, INVALID_DEVID), + wc_AesFree((Aes*)ctx)); +#endif +#ifndef NO_HMAC + TEST_CTX_MISALIGNED(Hmac, wc_HmacInit((Hmac*)ctx, HEAP_HINT, + INVALID_DEVID), wc_HmacFree((Hmac*)ctx)); + XMEMSET(&hmac, 0, sizeof(hmac)); + ExpectIntEQ(wc_HmacInit(&hmac, HEAP_HINT, INVALID_DEVID), 0); + if (WC_ALIGNOF(Hmac) >= 16) { + TEST_CTX_MISALIGNED(Hmac, wc_HmacCopy(&hmac, (Hmac*)ctx), + wc_HmacFree((Hmac*)ctx)); + } + wc_HmacFree(&hmac); +#endif +#ifdef HAVE_CURVE25519 + TEST_CTX_MISALIGNED(curve25519_key, + wc_curve25519_init((curve25519_key*)ctx), + wc_curve25519_free((curve25519_key*)ctx)); +#endif +#ifdef HAVE_ED25519 + TEST_CTX_MISALIGNED(ed25519_key, wc_ed25519_init((ed25519_key*)ctx), + wc_ed25519_free((ed25519_key*)ctx)); +#endif +#endif + return EXPECT_RESULT(); +} /* End test_wc_CtxInit_misaligned */ + /* * Testing ToTraditional @@ -46968,6 +47088,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_ForceZero), TEST_DECL(test_wolfCrypt_Init), + TEST_DECL(test_wc_CtxInit_misaligned), TEST_DECL(test_wc_LoadStaticMemory_ex), TEST_DECL(test_wc_LoadStaticMemory_CTX), diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 8659e65f12f..e50e91466e3 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -17045,6 +17045,10 @@ int wc_AesInit(Aes* aes, void* heap, int devId) if (aes == NULL) return BAD_FUNC_ARG; +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(aes, Aes)) + return BAD_ALIGN_E; +#endif XMEMSET(aes, 0, sizeof(*aes)); @@ -17141,6 +17145,12 @@ void wc_AesFree(Aes* aes) if (aes == NULL) { return; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(aes, Aes)) { + ForceZero(aes, sizeof(Aes)); + return; + } +#endif #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) #ifndef WOLF_CRYPTO_CB_FIND diff --git a/wolfcrypt/src/curve25519.c b/wolfcrypt/src/curve25519.c index 93ff76d0cdd..59acb026c0f 100644 --- a/wolfcrypt/src/curve25519.c +++ b/wolfcrypt/src/curve25519.c @@ -1384,6 +1384,11 @@ int wc_curve25519_init_ex(curve25519_key* key, void* heap, int devId) if (key == NULL) { ret = BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + else if (!WC_CTX_IS_ALIGNED(key, curve25519_key)) { + ret = BAD_ALIGN_E; + } +#endif else { XMEMSET(key, 0, sizeof(*key)); @@ -1426,6 +1431,12 @@ void wc_curve25519_free(curve25519_key* key) { if (key == NULL) return; +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(key, curve25519_key)) { + ForceZero(key, sizeof(*key)); + return; + } +#endif #ifdef WOLFSSL_SE050 se050_curve25519_free_key(key); diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 9f96b57c01f..0a9f75740c7 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -1461,6 +1461,10 @@ int wc_ed25519_init_ex(ed25519_key* key, void* heap, int devId) { if (key == NULL) return BAD_FUNC_ARG; +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(key, ed25519_key)) + return BAD_ALIGN_E; +#endif /* for init, ensure the key is zeroed*/ XMEMSET(key, 0, sizeof(ed25519_key)); @@ -1544,6 +1548,12 @@ void wc_ed25519_free(ed25519_key* key) { if (key == NULL) return; +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(key, ed25519_key)) { + ForceZero(key, sizeof(*key)); + return; + } +#endif #ifdef WOLFSSL_ED25519_PERSISTENT_SHA ed25519_hash_free(key, &key->sha); diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 52f9c56411e..cc13c5b414e 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -474,6 +474,10 @@ int wc_HmacCopy(Hmac* src, Hmac* dst) { if ((src == NULL) || (dst == NULL)) return BAD_FUNC_ARG; +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(dst, Hmac)) + return BAD_ALIGN_E; +#endif XMEMCPY(dst, src, sizeof(*dst)); @@ -1734,6 +1738,10 @@ int wc_HmacInit(Hmac* hmac, void* heap, int devId) if (hmac == NULL) return BAD_FUNC_ARG; +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(hmac, Hmac)) + return BAD_ALIGN_E; +#endif XMEMSET(hmac, 0, sizeof(Hmac)); hmac->macType = WC_HASH_TYPE_NONE; @@ -1807,6 +1815,12 @@ void wc_HmacFree(Hmac* hmac) { if (hmac == NULL) return; +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(hmac, Hmac)) { + ForceZero(hmac, sizeof(*hmac)); + return; + } +#endif #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) /* Let a device release any per-context state it hung off devCtx directly. If diff --git a/wolfcrypt/src/port/af_alg/afalg_hash.c b/wolfcrypt/src/port/af_alg/afalg_hash.c index c0e945b5d23..87efd4c9fdf 100644 --- a/wolfcrypt/src/port/af_alg/afalg_hash.c +++ b/wolfcrypt/src/port/af_alg/afalg_hash.c @@ -65,6 +65,11 @@ static int AfalgHashInit(wolfssl_AFALG_Hash* hash, void* heap, int devId, if (hash == NULL) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(hash, wolfssl_AFALG_Hash)) { + return BAD_ALIGN_E; + } +#endif (void)devId; /* no async for now */ XMEMSET(hash, 0, sizeof(wolfssl_AFALG_Hash)); @@ -213,6 +218,11 @@ static int AfalgHashCopy(wolfssl_AFALG_Hash* src, wolfssl_AFALG_Hash* dst) if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(dst, wolfssl_AFALG_Hash)) { + return BAD_ALIGN_E; + } +#endif XMEMCPY(dst, src, sizeof(wolfssl_AFALG_Hash)); diff --git a/wolfcrypt/src/port/devcrypto/devcrypto_hash.c b/wolfcrypt/src/port/devcrypto/devcrypto_hash.c index 19e84b73504..b1df8b15f9d 100644 --- a/wolfcrypt/src/port/devcrypto/devcrypto_hash.c +++ b/wolfcrypt/src/port/devcrypto/devcrypto_hash.c @@ -117,6 +117,11 @@ int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId) if (sha == NULL) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha, wc_Sha256)) { + return BAD_ALIGN_E; + } +#endif (void)devId; /* no async for now */ XMEMSET(sha, 0, sizeof(wc_Sha256)); @@ -229,6 +234,11 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(dst, wc_Sha256)) { + return BAD_ALIGN_E; + } +#endif #ifdef WOLFSSL_DEVCRYPTO_HASH_KEEP wc_Sha256Free(dst); diff --git a/wolfcrypt/src/port/kcapi/kcapi_hash.c b/wolfcrypt/src/port/kcapi/kcapi_hash.c index cd6945b467b..c444a9c31cb 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_hash.c +++ b/wolfcrypt/src/port/kcapi/kcapi_hash.c @@ -276,6 +276,11 @@ int wc_InitSha224_ex(wc_Sha224* sha, void* heap, int devId) if (sha == NULL) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha, wc_Sha224)) { + return BAD_ALIGN_E; + } +#endif return KcapiHashInit(&sha->kcapi, heap, devId, WC_NAME_SHA224); } @@ -313,6 +318,11 @@ int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(dst, wc_Sha224)) { + return BAD_ALIGN_E; + } +#endif return KcapiHashCopy(&src->kcapi, &dst->kcapi); } #endif /* WOLFSSL_SHA224 */ @@ -328,6 +338,11 @@ int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devid) if (sha == NULL) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha, wc_Sha256)) { + return BAD_ALIGN_E; + } +#endif return KcapiHashInit(&sha->kcapi, heap, devid, WC_NAME_SHA256); } @@ -364,6 +379,11 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(dst, wc_Sha256)) { + return BAD_ALIGN_E; + } +#endif return KcapiHashCopy(&src->kcapi, &dst->kcapi); } #endif /* !NO_SHA256 */ diff --git a/wolfcrypt/src/port/kcapi/kcapi_hmac.c b/wolfcrypt/src/port/kcapi/kcapi_hmac.c index a5c39cf0aad..1b763ff5316 100644 --- a/wolfcrypt/src/port/kcapi/kcapi_hmac.c +++ b/wolfcrypt/src/port/kcapi/kcapi_hmac.c @@ -29,6 +29,13 @@ #include #include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + #if !defined(NO_SHA) && !defined(WOLFSSL_NO_KCAPI_HMAC_SHA1) static const char WC_NAME_HMAC_SHA1[] = "hmac(sha1)"; #endif @@ -52,6 +59,11 @@ int wc_HmacInit(Hmac* hmac, void* heap, int devId) if (hmac == NULL) { ret = BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + else if (!WC_CTX_IS_ALIGNED(hmac, Hmac)) { + ret = BAD_ALIGN_E; + } +#endif if (ret == 0) { XMEMSET(hmac, 0, sizeof(*hmac)); @@ -66,6 +78,12 @@ int wc_HmacInit(Hmac* hmac, void* heap, int devId) void wc_HmacFree(Hmac* hmac) { +#ifdef WC_CTX_IS_ALIGNED + if (hmac != NULL && !WC_CTX_IS_ALIGNED(hmac, Hmac)) { + ForceZero(hmac, sizeof(*hmac)); + return; + } +#endif if (hmac != NULL) { if (hmac->handle != NULL) { kcapi_md_destroy(hmac->handle); @@ -82,6 +100,11 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) if ((hmac == NULL || (key == NULL && length != 0))) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(hmac, Hmac)) { + return BAD_ALIGN_E; + } +#endif #ifdef HAVE_FIPS if (length < HMAC_FIPS_MIN_KEY) diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 0c57e27ba85..b581732bff8 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -913,6 +913,10 @@ wc_static_assert(sizeof(Sha256TScratch) == WC_SHA256_TSCRATCH_SIZE); int ret = 0; if (sha256 == NULL) return BAD_FUNC_ARG; + #ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha256, wc_Sha256)) + return BAD_ALIGN_E; + #endif WC_SILABS_CLEAR_HASH_CTX(sha256); sha256->heap = heap; @@ -1125,6 +1129,11 @@ wc_static_assert(sizeof(Sha256TScratch) == WC_SHA256_TSCRATCH_SIZE); if (sha256 == NULL) { return BAD_FUNC_ARG; } + #ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha256, wc_Sha256)) { + return BAD_ALIGN_E; + } + #endif WC_SILABS_CLEAR_HASH_CTX(sha256); (void)devId; @@ -1805,6 +1814,10 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, int ret; if (sha256 == NULL) return BAD_FUNC_ARG; + #ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha256, wc_Sha256)) + return BAD_ALIGN_E; + #endif WC_SILABS_CLEAR_HASH_CTX(sha256); ret = InitSha256(sha256); if (ret != 0) @@ -1822,6 +1835,10 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, int ret = 0; if (sha256 == NULL) return BAD_FUNC_ARG; + #ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha256, wc_Sha256)) + return BAD_ALIGN_E; + #endif WC_SILABS_CLEAR_HASH_CTX(sha256); ret = InitSha256(sha256); if (ret != 0) @@ -2846,6 +2863,11 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, if (sha224 == NULL) { return BAD_FUNC_ARG; } + #ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha224, wc_Sha224)) { + return BAD_ALIGN_E; + } + #endif WC_SILABS_CLEAR_HASH_CTX(sha224); (void)devId; @@ -2905,6 +2927,10 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, int ret; if (sha224 == NULL) return BAD_FUNC_ARG; + #ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha224, wc_Sha224)) + return BAD_ALIGN_E; + #endif WC_SILABS_CLEAR_HASH_CTX(sha224); ret = InitSha256((wc_Sha256*)sha224); if (ret != 0) @@ -3027,6 +3053,10 @@ int wc_Sha224Reset(wc_Sha224* sha224) { if (sha224 == NULL) return BAD_FUNC_ARG; + #ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha224, wc_Sha224)) + return BAD_ALIGN_E; + #endif WC_SILABS_CLEAR_HASH_CTX(sha224); sha224->heap = heap; @@ -3246,6 +3276,12 @@ int wc_Sha224Reset(wc_Sha224* sha224) { if (sha224 == NULL) return; + #ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha224, wc_Sha224)) { + ForceZero(sha224, sizeof(*sha224)); + return; + } + #endif #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) #ifndef WOLF_CRYPTO_CB_FIND @@ -3323,6 +3359,12 @@ void wc_Sha256Free(wc_Sha256* sha256) if (sha256 == NULL) return; +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(sha256, wc_Sha256)) { + ForceZero(sha256, sizeof(*sha256)); + return; + } +#endif #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) #ifndef WOLF_CRYPTO_CB_FIND @@ -3566,6 +3608,11 @@ int wc_Sha224Reset(wc_Sha224* sha224) { if (src == NULL || dst == NULL || src == dst) { return BAD_FUNC_ARG; } + #ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(dst, wc_Sha224)) { + return BAD_ALIGN_E; + } + #endif #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_COPY) #ifndef WOLF_CRYPTO_CB_FIND @@ -3725,6 +3772,11 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) if (src == NULL || dst == NULL || src == dst) { return BAD_FUNC_ARG; } +#ifdef WC_CTX_IS_ALIGNED + if (!WC_CTX_IS_ALIGNED(dst, wc_Sha256)) { + return BAD_ALIGN_E; + } +#endif #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_COPY) #ifndef WOLF_CRYPTO_CB_FIND diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index bcae15817a9..f7390c3be2e 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -2034,6 +2034,30 @@ WOLFSSL_API word32 CheckRunTimeSettings(void); #define ALIGN256 WOLFSSL_ALIGN(256) #endif +#ifndef WC_ALIGNOF + #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) + #define WC_ALIGNOF(T) _Alignof(T) + #elif defined(__GNUC__) || defined(__clang__) + #define WC_ALIGNOF(T) __alignof__(T) + #elif defined(_MSC_VER) + #define WC_ALIGNOF(T) __alignof(T) + #endif +#endif + +#ifndef WC_IS_ALIGNED + #define WC_IS_ALIGNED(p, a) \ + ((((wc_ptr_t)(p)) & ((wc_ptr_t)(a) - 1)) == 0) +#endif + +/* Capped at 16, the alignment malloc() guarantees on x86_64. */ +#if defined(WC_ALIGNOF) && (defined(__x86_64__) || defined(_M_X64)) && \ + !defined(WOLFSSL_KERNEL_MODE) && !defined(WOLFSSL_STATIC_MEMORY) && \ + (!defined(__STDC_HOSTED__) || (__STDC_HOSTED__ != 0)) && \ + !defined(WC_NO_CTX_ALIGN_CHECK) + #define WC_CTX_IS_ALIGNED(p, T) \ + WC_IS_ALIGNED(p, (WC_ALIGNOF(T) < 16) ? WC_ALIGNOF(T) : 16) +#endif + /* Define the unaligned type modifier across different compilers */ #if defined(__GNUC__) || defined(__clang__) /* Works on GCC 2.0+ and all versions of Clang */