diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 11c6b5d4b2..2a80e93c52 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -251,6 +251,7 @@ HASH_DataType_8b HASH_IMR_DCIE HASH_IMR_DINIE HAVE_AESGCM_DECRYPT +HAVE_AES_CTR HAVE_BYTEREVERSE64 HAVE_CERTIFICATE_STATUS_V2 HAVE_COLDFIRE_SEC @@ -625,6 +626,7 @@ WIFI_AVAILABLE WIFI_NINA WIN_REUSE_CRYPT_HANDLE WOLFCRYPT_FIPS_CORE_DYNAMIC_HASH_VALUE +WOLFCRYPT_WARMUP WOLFSENTRY_H WOLFSENTRY_NO_JSON WOLFSSL_32BIT_MILLI_TIME diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index fc42f6fdbf..37cada0adc 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -150,6 +150,10 @@ #endif #endif +#if !defined(NO_AES) + #include +#endif + /* prevent multiple mutex initializations */ static volatile int initRefCount = 0; @@ -157,6 +161,86 @@ static volatile int initRefCount = 0; int aarch64_use_sb = 0; #endif +#ifdef WOLFCRYPT_WARMUP +static int wolfCrypt_Warmup(void) +{ + int ret = 0; + WC_RNG rng; + byte dummy; +#if !defined(NO_AES) && defined(HAVE_AESGCM) + Aes aes; + unsigned char key16[16]; + unsigned char out[16]; + unsigned char in[16]; + unsigned char iv[12]; + int devId; +#endif + +#if defined(DEBUG_WOLFSSL_MALLOC_VERBOSE) + WOLFSSL_MSG("Warming up RNG"); +#endif + ret = wc_InitRng(&rng); + if (ret == 0) { + /* forces Hash_DRBG/SHA */ + ret = wc_RNG_GenerateBlock(&rng, &dummy, 1); + if (ret != 0) { + WOLFSSL_MSG("wolfCrypt_Init wc_RNG_GenerateBlock failed"); + } + } + if (ret != 0) { + WOLFSSL_MSG("wolfCrypt_Init RNG warmup failed"); + } + ret = wc_FreeRng(&rng); + if (ret != 0) { + WOLFSSL_MSG("wolfCrypt_Init wc_FreeRng failed"); + } + +#if !defined(NO_AES) && defined(HAVE_AESGCM) +#if defined(DEBUG_WOLFSSL_MALLOC_VERBOSE) + WOLFSSL_MSG("Warming up AES"); +#endif + memset(key16, 0, sizeof(key16)); + memset(iv, 0, sizeof(iv)); + memset(in, 0, sizeof(in)); + devId = INVALID_DEVID; + + ret = wc_AesInit(&aes, NULL, devId); + if (ret == 0) { + /* Set an ECB key (no IV). This avoids pulling in GCM/GHASH. */ + ret = wc_AesSetKey(&aes, key16, (word32)sizeof(key16), NULL, + AES_ENCRYPTION); + } + if (ret == 0) { +#ifdef WOLFSSL_AES_DIRECT + /* Single direct block encrypt to exercise the core/driver. */ + ret = wc_AesEncryptDirect(&aes, out, in); +#elif !defined(NO_AES_CBC) + /* One-block CBC (tiny; no padding; does not pull GCM). */ + ret = wc_AesSetIV(&aes, iv); + if (ret == 0) { + ret = wc_AesCbcEncrypt(&aes, out, in, (word32)sizeof(in)); + } +#elif defined(HAVE_AES_CTR) || defined(WOLFSSL_AES_COUNTER) + /* As another lightweight option, CTR one-block. */ + ret = wc_AesSetIV(&aes, iv); + if (ret == 0) { + ret = wc_AesCtrEncrypt(&aes, out, in, (word32)sizeof(in)); + } +#else + /* No small mode available; setting the key already did most of the warmup. */ + ret = 0; +#endif + } + if (ret != 0) { + WOLFSSL_MSG("AES warmup failed during wolfCrypt_Init"); + } + wc_AesFree(&aes); +#endif /* !NO_AES && HAVE_AESGCM */ + + return ret; +} +#endif /* WOLFCRYPT_WARMUP */ + /* Used to initialize state for wolfcrypt return 0 on success */ @@ -164,9 +248,18 @@ WOLFSSL_ABI int wolfCrypt_Init(void) { int ret = 0; + if (initRefCount == 0) { WOLFSSL_ENTER("wolfCrypt_Init"); + #ifdef WOLFCRYPT_WARMUP + /* Warm up the hardware to allocate any heap & semaphore early */ + ret = wolfCrypt_Warmup(); + if (ret != 0) { + WOLFSSL_MSG("wolfCrypt_Warmup failed during wolfCrypt_Init"); + } + #endif + #if defined(__aarch64__) && defined(WOLFSSL_ARMASM_BARRIER_DETECT) aarch64_use_sb = IS_AARCH64_SB(cpuid_get_flags()); #endif @@ -444,11 +537,13 @@ int wolfCrypt_Init(void) return ret; } #endif - } + + } /* (initRefCount == 0) */ + initRefCount++; return ret; -} +} /* wolfCrypt_Init */ #if defined(WOLFSSL_TRACK_MEMORY_VERBOSE) && !defined(WOLFSSL_STATIC_MEMORY) long wolfCrypt_heap_peakAllocs_checkpoint(void) { diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index e57d48b85e..1b0ad65c82 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -577,6 +577,9 @@ #if defined(WOLFSSL_ESPIDF) #define SIZEOF_LONG_LONG 8 + /* Warm-up: ensures long term heap allocated early */ + #define WOLFCRYPT_WARMUP + #ifndef WOLFSSL_MAX_ERROR_SZ /* Espressif paths can be quite long. Ensure error prints full path. */ #define WOLFSSL_MAX_ERROR_SZ 200