Introduce wolfCrypt_Init warmup, WOLFCRYPT_WARMUP
Description
Adds a wolfCrypt_Init() warmup, disabled by default, enable with WOLFCRYPT_WARMUP.
Reason
The random number generator and AES functions were observed allocating long term (perhaps permanent?) heap memory. This PR "warms up" wolfCrypt by calling some sample code early, ensuring (hoping?) any heap allocations are at the edge of the heap and not in the middle.
A long term heap allocation in the middle of the heap, say after reading a large object such as a certificate, may interfere with the long term maximum memory availability.
This PR also makes the wolfcrypt test result more pretty.
Background
I've been optimizing wolfssl for small embedded targets. Some time ago, I introduced a heap discrepancy alert in the wolfcrypt tests. It was intended to find memory leaks after repeatedly running the tests, for example https://github.com/wolfSSL/wolfssl/pull/8506
See the wolfcrypt/test/test.c around line 154 for the PRINT_HEAP_CHECKPOINT implementation for WOLFSSL_ESPIDF targets.
There's been a nagging reminder in the tests:
...
RANDOM test passed!
I (1351) wc_test: Breadcrumb: TEST_PASS
W (1351) wc_test: Warning: this heap 437488 != last 437576
...
HPKE test passed!
I (17095) wc_test: Breadcrumb: TEST_PASS
W (17095) wc_test: Warning: this heap 437400 != last 437488
As it only occurs on the first pass of these tests, I did not consider it a memory leak. Still, it's not pretty. But until recently "not pretty" did not warrant attention. Until today when considering the location of the heap object.
Update
Initially this was on-for-everyone. Turns out the initial footprint was unacceptably increased (See Arduino failure). I've updated the PR to be opt-in-only, instead.
Also made these recommended changes after message from PRB-multi-test-script/7178:
unneeded entries in .wolfssl_known_macro_extras:
WOLFSSL_KEY_TO_DER
unrecognized macros used:
HAVE_AES_CTR
WC_NO_AES
add well-formed but unknown macros to .wolfssl_known_macro_extras at top of source tree.
Fixes zd# n/a
Testing
How did you test?
Tested on Espressif ESP32 embedded target and the usual:
./autogen.sh
./configure --enable-all
make
./wolfcrypt/test/testwolfcrypt
Checklist
- [ ] added tests
- [ ] updated/added doxygen
- [ ] updated appropriate READMEs
- [ ] Updated manual and documentation
🛟 Devin Lifeguard found 1 likely issues in this PR
check-return-codessnippet snippet: After calling wc_RNG_GenerateBlock and wc_AesGcmEncrypt, testret(or the direct return value) and propagate or handle any error before proceeding; e.g.,ret = wc_RNG_GenerateBlock(...); if (ret != 0) { wc_FreeRng(&rng); return ret; }.
@gojimmypi please take a look at the above issues which Devin flagged. Devin will not fix these issues automatically.
Jenkins retest this please
For AgentOfflineException: Unable to create live FilePath for wolf-linux-cloud-node-[n]; wolf-linux-cloud-node-[n] was marked offline: Connection was broken
🛟 Devin Lifeguard found 1 likely issues in this PR
check-return-codessnippet: Addif (ret != 0) return ret;immediately after theret = wolfCrypt_Warmup();call (or otherwise handle the error) so a warm-up failure is not ignored.
@gojimmypi please take a look at the above issues which Devin flagged. Devin will not fix these issues automatically.
Jenkins retest this please.
For AgentOfflineException: Unable to create live FilePath for wolf-linux-cloud-node-[n]; wolf-linux-cloud-node-[n] was marked offline: Connection was broken.
Hi @JacobBarthelmeh
something an application does on an individual basis due to the wide range of use cases
I've given this a lot of thought, and I tend to agree with you.
Still, there's value in this for many targets. I'm considering something that's not specific to any given platform, available to everyone, but not baked into wolfCrypt_Init(). Open to suggestions.
if the application has long standing RNG and AES structs
I'm not certain this is an application feature, rather something like a FreeRTOS semaphore that gets allocated and used forever in RNG. But you are right: perhaps RNG and AES are never used in the application, so why init.