From 7301fd84f2f6241c34369c7f98b929bfa10cf905 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 27 Oct 2026 16:42:30 -0700 Subject: [PATCH] Fix STM32 bare-metal V2 PKA ECC scalar multiply and cold init --- wolfcrypt/src/port/st/stm32.c | 27 ++++++++++++++++++++++++--- wolfcrypt/test/test.c | 11 +++++++---- wolfssl/wolfcrypt/settings.h | 6 ++++++ 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/wolfcrypt/src/port/st/stm32.c b/wolfcrypt/src/port/st/stm32.c index 064043ca0c6..597e4cdfe9e 100644 --- a/wolfcrypt/src/port/st/stm32.c +++ b/wolfcrypt/src/port/st/stm32.c @@ -138,6 +138,9 @@ typedef struct { * (in bytes) at sign-setup time so GetResult can use it. V1 HAL * reads from RAM and works fine; V2 HAL keeps it on the handle. */ uint32_t primeordersize; + /* Same for RAM[PKA_ECC_SCALAR_MUL_IN_OP_NB_BITS] and the scalar + * multiply: saved at ECCMul-setup time for ECCMul_GetResult. */ + uint32_t modulussize; } PKA_HandleTypeDef; typedef struct { @@ -518,7 +521,17 @@ static HAL_StatusTypeDef HAL_PKA_Init(PKA_HandleTypeDef *hpkah) * wait, an immediate ECDSA SIGN can race the init and silently * fail with OUT_ERROR = 0xCBC9 (PKA_FAILED_COMPUTATION) on U5 / H5 * / WBA / N6 / C5 / H7S. V1 PKA does not have INITOK and the bit - * is undefined there. */ + * is undefined there. + * + * The V2 PKA draws on the RNG during that self-check: with the RNG + * IP unclocked, INITOK never asserts (CR.EN sticks at 1, SR stays + * 0) and every PKA operation afterwards fails with WC_HW_E. Bring + * the RNG up first -- ST's own C5 PKA sequence does the same. + * wc_stm32_rng_ensure_ready() is the mutex-free bring-up already + * shared with the SAES self-init path. */ +#ifdef WC_STM32_HAS_RNG_READY + (void)wc_stm32_rng_ensure_ready(); +#endif t = 0; while ((hpkah->Instance->SR & PKA_SR_INITOK) == 0U) { if (++t >= WC_STM32_PKA_INIT_TIMEOUT) { @@ -768,6 +781,8 @@ static HAL_StatusTypeDef HAL_PKA_ECCMul(PKA_HandleTypeDef *hpkah, } #endif /* WOLFSSL_STM32_PKA_V2 */ + hpkah->modulussize = in->modulusSize; + return wc_stm32_pka_process(hpkah, PKA_MODE_ECC_MUL); } @@ -781,9 +796,15 @@ static void HAL_PKA_ECCMul_GetResult(PKA_HandleTypeDef *hpkah, /* Word view: STM32C5 types PKA RAM as uint8_t[]; others as uint32_t[]. */ RAM = (volatile const uint32_t*)(void*)hpkah->Instance->RAM; - /* The HAL recomputes the byte size from the saved IN_OP_NB_BITS - * slot. We do the same. */ + /* V2 PKA clobbers RAM[IN_OP_NB_BITS] during compute, leaving a size + * of zero and a result read of nothing -- the caller then sees its + * own input point handed back. Use the size saved on the handle, as + * the V2 HAL does. V1 still reads from RAM. */ +#ifdef WOLFSSL_STM32_PKA_V2 + size = hpkah->modulussize; +#else size = (RAM[PKA_ECC_SCALAR_MUL_IN_OP_NB_BITS] + 7U) / 8U; +#endif if (out->ptX != NULL) { wc_stm32_pka_read_be(out->ptX, diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e6f9493ed93..1b99c2d2760 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -1173,7 +1173,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t argon2_test(void); #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs7authenveloped_test(void); #endif - #if !defined(NO_AES) && defined(HAVE_AES_CBC) + #if !defined(NO_AES) && defined(HAVE_AES_CBC) && \ + !defined(NO_PKCS7_ENCRYPTED_DATA) WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs7callback_test(byte* cert, word32 certSz, byte* key, word32 keySz); #endif @@ -86402,7 +86403,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs7authenveloped_test(void) #endif /* HAVE_AESGCM || HAVE_AESCCM */ #if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) && \ - defined(HAVE_AES_KEYWRAP) + defined(HAVE_AES_KEYWRAP) && !defined(NO_PKCS7_ENCRYPTED_DATA) static const byte p7DefKey[] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, @@ -86834,7 +86835,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs7callback_test(byte* cert, word32 cert return ret; } -#endif /* !NO_AES && HAVE_AES_CBC && WOLFSSL_AES_256 && HAVE_AES_KEYWRAP */ +#endif /* !NO_AES && HAVE_AES_CBC && WOLFSSL_AES_256 && HAVE_AES_KEYWRAP && + * !NO_PKCS7_ENCRYPTED_DATA */ #ifndef NO_PKCS7_ENCRYPTED_DATA @@ -89828,7 +89830,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pkcs7signed_test(void) eccClientPrivKeyBuf, (word32)eccClientPrivKeyBufSz); #if !defined(NO_RSA) && !defined(NO_AES) && defined(HAVE_AES_CBC) && \ - defined(WOLFSSL_AES_256) && defined(HAVE_AES_KEYWRAP) + defined(WOLFSSL_AES_256) && defined(HAVE_AES_KEYWRAP) && \ + !defined(NO_PKCS7_ENCRYPTED_DATA) if (ret >= 0) ret = pkcs7callback_test( rsaClientCertBuf, (word32)rsaClientCertBufSz, diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 4a7342e18ee..864da577332 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -2630,6 +2630,12 @@ defined(WOLFSSL_STM32C5) || defined(WOLFSSL_STM32V8) #define SIZEOF_LONG_LONG 8 + /* Pull before falling back, or the fallback suppresses the + * tfm.h / integer.h include that is gated on CHAR_BIT and leaves + * INT_MAX undeclared on a USE_FAST_MATH build. */ + #if !defined(CHAR_BIT) && !defined(NO_LIMITS_H) + #include + #endif #ifndef CHAR_BIT #define CHAR_BIT 8 #endif