Conversation
1935260 to
3284bc5
Compare
|
Jenkins Retest this please |
120c011 to
7b0fbbb
Compare
|
Rebased to fix merge conflict with master's |
|
Jenkins retest this please |
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #9851
Scan targets checked: wolfcrypt-bugs, wolfcrypt-src
Findings: 5
High (4)
Infinite recursion in wc_RsaPublicKeyDecodeRaw when WOLF_CRYPTO_CB_FIND is defined
File: wolfcrypt/src/asn.c:45163-45185
Function: wc_RsaPublicKeyDecodeRaw
Category: Logic errors
When WOLF_CRYPTO_CB_FIND is defined, the #ifndef WOLF_CRYPTO_CB_FIND / if (key->devId != INVALID_DEVID) guard is compiled out, making the SETKEY block execute unconditionally. The function allocates tmpKey with INVALID_DEVID and then calls itself recursively: tmpErr = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, tmpKey). On the recursive call, tmpKey->devId == INVALID_DEVID, but since the guard is absent, the block executes again, allocating another tmpKey and recursing infinitely. This causes a stack overflow crash. The recursive self-call occurs before wc_CryptoCb_SetKey is reached, so even though FindDevice(INVALID_DEVID) would return NULL, execution never gets there. Compare with wc_RsaPrivateKeyDecode in the same file which correctly avoids this by calling the internal _RsaPrivateKeyDecode helper instead of itself.
#ifndef WOLF_CRYPTO_CB_FIND
if (key->devId != INVALID_DEVID)
#endif
{
...
tmpErr = wc_InitRsaKey_ex(tmpKey, key->heap, INVALID_DEVID);
...
/* Recursive call imports n, e into temp via software */
tmpErr = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, tmpKey);Recommendation: Follow the pattern used in wc_RsaPrivateKeyDecode — call an internal helper function (e.g., a static _RsaPublicKeyDecodeRaw) for the software import instead of recursing into the public API. Alternatively, add an explicit tmpKey->devId == INVALID_DEVID check inside the block to skip the SETKEY path on recursive calls, independent of the WOLF_CRYPTO_CB_FIND conditional.
Infinite recursion in multiple ECC import/export functions when WOLF_CRYPTO_CB_FIND is defined
File: wolfcrypt/src/ecc.c:10733-10753
Function: wc_ecc_import_x963_ex2
Category: Logic errors
The same infinite recursion pattern affects five functions in ecc.c. When WOLF_CRYPTO_CB_FIND is defined, the devId != INVALID_DEVID guard is compiled out, and the functions recurse into themselves with a tmpKey that has INVALID_DEVID, causing infinite recursion and stack overflow. Affected functions: (1) wc_ecc_import_x963_ex2 calls wc_ecc_import_x963_ex2(in, inLen, tmpKey, curve_id, untrusted), (2) wc_ecc_import_private_key_ex calls wc_ecc_import_private_key_ex(priv, privSz, pub, pubSz, tmpKey, curve_id), (3) wc_ecc_import_raw_private calls wc_ecc_import_raw_private(tmpKey, qx, qy, d, curve_id, encType), (4) wc_ecc_export_x963 calls wc_ecc_export_x963(tmpKey, out, outLen), (5) wc_ecc_export_ex calls wc_ecc_export_ex(tmpKey, qx, qxLen, qy, qyLen, d, dLen, encType).
#ifndef WOLF_CRYPTO_CB_FIND
if (key->devId != INVALID_DEVID)
#endif
{
...
err = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID);
...
err = wc_ecc_import_x963_ex2(in, inLen, tmpKey, curve_id, untrusted);
if (err == MP_OKAY) {
cbRet = wc_CryptoCb_SetKey(key->devId, ...);
}Recommendation: For each affected function, either (a) create an internal static helper (prefixed with _) that performs the software-only operation and call that instead of the public function, or (b) add a runtime guard within the SETKEY/EXPORT_KEY block to check key->devId != INVALID_DEVID even when WOLF_CRYPTO_CB_FIND is defined, since keys with INVALID_DEVID should never be routed through the callback path.
Infinite recursion in RSA SETKEY/EXPORT_KEY functions when WOLF_CRYPTO_CB_FIND is defined
File: wolfcrypt/src/rsa.c:5490-5516
Function: wc_RsaPrivateKeyDecodeRaw
Category: Logic errors
Three functions in rsa.c have the same infinite recursion bug when WOLF_CRYPTO_CB_FIND is defined. The devId != INVALID_DEVID guard is compiled out, causing unconditional entry into the callback block where the function calls itself with a tmpKey initialized with INVALID_DEVID. Affected functions: (1) wc_RsaPrivateKeyDecodeRaw — SETKEY path calls wc_RsaPrivateKeyDecodeRaw(n, nSz, e, eSz, d, dSz, u, uSz, p, pSz, q, qSz, dP, dPSz, dQ, dQSz, tmpKey), (2) wc_RsaFlattenPublicKey — EXPORT_KEY path calls wc_RsaFlattenPublicKey(tmpKey, e, eSz, n, nSz), (3) wc_RsaExportKey — EXPORT_KEY path calls wc_RsaExportKey(tmpKey, e, eSz, n, nSz, d, dSz, p, pSz, q, qSz).
#ifndef WOLF_CRYPTO_CB_FIND
if (err == MP_OKAY && key->devId != INVALID_DEVID)
#else
if (err == MP_OKAY)
#endif
{
...
err = wc_InitRsaKey_ex(tmpKey, key->heap, INVALID_DEVID);
...
err = wc_RsaPrivateKeyDecodeRaw(n, nSz, e, eSz, d, dSz,
u, uSz, p, pSz, q, qSz, dP, dPSz, dQ, dQSz, tmpKey);Recommendation: Use the same approach as wc_RsaPrivateKeyDecode in asn.c, which correctly calls the internal _RsaPrivateKeyDecode helper instead of the public function. Create internal static helpers for these functions, or add an unconditional devId != INVALID_DEVID check that cannot be compiled out by WOLF_CRYPTO_CB_FIND.
Infinite recursion / stack overflow when WOLF_CRYPTO_CB_FIND is defined
File: wolfcrypt/src/ecc.c:wc_ecc_import_x963_ex2, wolfcrypt/src/ecc.c:wc_ecc_import_private_key_ex, wolfcrypt/src/ecc.c:wc_ecc_import_raw_private, wolfcrypt/src/asn.c:wc_RsaPublicKeyDecodeRaw, wolfcrypt/src/rsa.c:wc_RsaPrivateKeyDecodeRaw
Function: wc_ecc_import_x963_ex2 (and 4 others)
Category: NULL pointer dereference
Five functions use a self-recursive pattern to import key material into a tmpKey with INVALID_DEVID, then pass it to wc_CryptoCb_SetKey. The guard that prevents entering the WOLF_CRYPTO_CB_SETKEY block is #ifndef WOLF_CRYPTO_CB_FIND / if (key->devId != INVALID_DEVID) / #endif. When WOLF_CRYPTO_CB_FIND is defined, the if guard is compiled out and the block executes unconditionally. Since tmpKey has INVALID_DEVID, the recursive call enters the same block again, allocates another tmpKey, recurses again, and so on — causing unbounded recursion and stack overflow. The recursive call happens before wc_CryptoCb_SetKey (which would call wc_CryptoCb_FindDevice and return CRYPTOCB_UNAVAILABLE for INVALID_DEVID), so there is no opportunity to break the cycle. Affected functions: wc_RsaPublicKeyDecodeRaw (asn.c), wc_ecc_import_x963_ex2 (ecc.c), wc_ecc_import_private_key_ex (ecc.c), wc_ecc_import_raw_private (ecc.c), wc_RsaPrivateKeyDecodeRaw (rsa.c). Note: wc_RsaPrivateKeyDecode in asn.c is NOT affected because it calls the internal _RsaPrivateKeyDecode instead of itself.
#ifndef WOLF_CRYPTO_CB_FIND
if (key->devId != INVALID_DEVID)
#endif
{
WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap);
/* ... init tmpKey with INVALID_DEVID ... */
err = wc_ecc_import_x963_ex2(in, inLen, tmpKey, curve_id, untrusted);
/* ^^^ recursive call — with WOLF_CRYPTO_CB_FIND, enters this block again */
if (err == MP_OKAY) {
cbRet = wc_CryptoCb_SetKey(...);
}
}Recommendation: Add an explicit devId != INVALID_DEVID check that is always compiled in, independent of WOLF_CRYPTO_CB_FIND. For example, change the guard to: #ifndef WOLF_CRYPTO_CB_FIND / if (key->devId != INVALID_DEVID) / #else / if (key->devId != INVALID_DEVID) / #endif — or simply always check key->devId != INVALID_DEVID before the recursive call regardless of WOLF_CRYPTO_CB_FIND. Alternatively, follow the pattern used in wc_RsaPrivateKeyDecode which calls the internal _RsaPrivateKeyDecode helper instead of recursing into itself.
Low (1)
Missing ForceZero on tmpKey holding private key material in import paths
File: wolfcrypt/src/rsa.c:wc_RsaPrivateKeyDecodeRaw, wolfcrypt/src/asn.c:wc_RsaPrivateKeyDecode
Function: wc_RsaPrivateKeyDecodeRaw, wc_RsaPrivateKeyDecode
Category: Missing ForceZero
In the new WOLF_CRYPTO_CB_SETKEY code paths, tmpKey (an RsaKey struct holding decoded private key material) is cleaned up with wc_FreeRsaKey(tmpKey); WC_FREE_VAR(tmpKey, key->heap); but without a preceding ForceZero(tmpKey, sizeof(RsaKey)). In contrast, the new export paths in the same PR (wc_RsaFlattenPublicKey and wc_RsaExportKey in rsa.c) correctly call ForceZero(tmpKey, sizeof(RsaKey)) before wc_FreeRsaKey. While wc_FreeRsaKey does call mp_forcezero on individual private mp_int components, the RsaKey struct itself (which may contain residual private key data in padding or non-mp_int fields) is not zeroed in the import paths before being freed back to heap. The same pattern applies to ecc_key tmpKeys in ecc.c import paths (wc_ecc_import_private_key_ex, wc_ecc_import_raw_private) which lack ForceZero before wc_ecc_free.
/* rsa.c wc_RsaPrivateKeyDecodeRaw - import path (missing ForceZero): */
wc_FreeRsaKey(tmpKey);
WC_FREE_VAR(tmpKey, key->heap);
/* rsa.c wc_RsaExportKey - export path (has ForceZero): */
ForceZero(tmpKey, sizeof(RsaKey));
wc_FreeRsaKey(tmpKey);
WC_FREE_VAR(tmpKey, key->heap);Recommendation: Add ForceZero(tmpKey, sizeof(RsaKey)) (or ForceZero(tmpKey, sizeof(ecc_key)) for ECC) before wc_FreeRsaKey/wc_ecc_free in the import paths, consistent with the export paths in the same PR.
This review was generated automatically by Fenrir. Findings are non-blocking.
bigbrett
left a comment
There was a problem hiding this comment.
Great work. Approved but have a few nits should you wish to address them.
As we discussed offline, this should eventually be unifed with, or supersede this, ideally leaving the existing AES-only API useable for backwards compat. No action on that front needed now.
3007dfc to
ff319fc
Compare
|
rebased |
|
Jenkins retest this please |
ff319fc to
3b64baa
Compare
|
rebased and force pushed |
|
Jenkins retest this please |
3b64baa to
9ee7c18
Compare
| int ret; | ||
| int keySz = 0; | ||
|
|
||
| ret = wc_CryptoCb_EccGetSize(key, &keySz); |
There was a problem hiding this comment.
HIGH-1: wc_ecc_size() and wc_ecc_sig_size() callback guarded too broadly — affects all WOLF_CRYPTO_CB builds
- File:
wolfcrypt/src/ecc.c:12247-12273andwolfcrypt/src/ecc.c:12295-12340 - Function:
wc_ecc_size,wc_ecc_sig_size - Category: [api]
- Confidence: High
Description: The crypto callback lookup in wc_ecc_size() and wc_ecc_sig_size() is guarded only by #ifdef WOLF_CRYPTO_CB, not by the more specific WOLF_CRYPTO_CB_SETKEY or WOLF_CRYPTO_CB_EXPORT_KEY. This means ALL builds with crypto callbacks enabled (not just those opting into the new SETKEY/EXPORT features) will incur a wc_CryptoCb_FindDevice() lookup for every wc_ecc_size() and wc_ecc_sig_size() call when key->devId != INVALID_DEVID.
These are extremely hot functions called throughout ECC operations (key gen, sign, verify, import, export, certificate handling). The overhead adds up. More importantly, existing third-party callbacks that don't handle WC_PK_TYPE_EC_GET_SIZE / WC_PK_TYPE_EC_GET_SIG_SIZE may not return CRYPTOCB_UNAVAILABLE gracefully — they could return an unrecognized-type error, causing wc_ecc_size() to return 0 and breaking downstream operations silently.
Code:
// wc_ecc_size — guarded only by WOLF_CRYPTO_CB
#ifdef WOLF_CRYPTO_CB
if (key->devId != INVALID_DEVID) {
int ret;
int keySz = 0;
ret = wc_CryptoCb_EccGetSize(key, &keySz);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
if (ret != 0) {
return 0; // silently returns 0 on error
}
return keySz;
}
}
#endifRecommendation: Either guard these with a more specific define like WOLF_CRYPTO_CB_SETKEY or WOLF_CRYPTO_CB_EXPORT_KEY, or add compile-time guard documentation that the new WC_PK_TYPE_EC_GET_SIZE/WC_PK_TYPE_EC_GET_SIG_SIZE callbacks must be handled (or return CRYPTOCB_UNAVAILABLE) by all crypto callback implementations when WOLF_CRYPTO_CB is enabled. The CRYPTO_CB_VER bump from 2→3 helps but doesn't prevent runtime breakage.
There was a problem hiding this comment.
Changed both guards from #ifdef WOLF_CRYPTO_CB to
#if defined(WOLF_CRYPTO_CB) && (defined(WOLF_CRYPTO_CB_SETKEY) || defined(WOLF_CRYPTO_CB_EXPORT_KEY)).
These callbacks are only relevant when SETKEY or EXPORT_KEY features are enabled.
| WC_PK_TYPE_RSA_PKCS = 25, | ||
| WC_PK_TYPE_RSA_PSS = 26, | ||
| WC_PK_TYPE_RSA_OAEP = 27, | ||
| WC_PK_TYPE_EC_GET_SIZE = 28, |
There was a problem hiding this comment.
MEDIUM-2: WC_PK_TYPE_EC_GET_SIZE/WC_PK_TYPE_EC_GET_SIG_SIZE exceed WC_PK_TYPE_MAX
- File:
wolfssl/wolfcrypt/types.h:1571-1573 - Function: N/A (enum definition)
- Category: [api]
- Confidence: High
Description: The new enum values WC_PK_TYPE_EC_GET_SIZE = 28 and WC_PK_TYPE_EC_GET_SIG_SIZE = 29 are placed after WC_PK_TYPE_RSA_OAEP = 27, but WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX resolves to at most 24 (with Dilithium/Falcon). This means these new values exceed WC_PK_TYPE_MAX, making the MAX misleading. While no code currently uses WC_PK_TYPE_MAX for array sizing (I verified), this continues and worsens a pattern that started with values 25-27.
Code:
WC_PK_TYPE_RSA_OAEP = 27,
WC_PK_TYPE_EC_GET_SIZE = 28, // New: above _WC_PK_TYPE_MAX
WC_PK_TYPE_EC_GET_SIG_SIZE = 29, // New: above _WC_PK_TYPE_MAX
WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX // Could be 17, 20, or 24Recommendation: The unconditional values 25-29 should update _WC_PK_TYPE_MAX after the conditional blocks, e.g.:
| WC_PK_TYPE_EC_GET_SIZE = 28, | |
| WC_PK_TYPE_EC_GET_SIG_SIZE = 29, | |
| #undef _WC_PK_TYPE_MAX | |
| #define _WC_PK_TYPE_MAX WC_PK_TYPE_EC_GET_SIG_SIZE | |
| WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX |
There was a problem hiding this comment.
Added #undef _WC_PK_TYPE_MAX / #define _WC_PK_TYPE_MAX WC_PK_TYPE_EC_GET_SIG_SIZE
before WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX so MAX correctly resolves to 29.
| return ret; | ||
| } | ||
|
|
||
| ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_RSA, |
There was a problem hiding this comment.
MEDIUM-3: Const-qualifying key parameter cast away in ExportKey calls
- File:
wolfcrypt/src/rsa.c:4533-4534andwolfcrypt/src/rsa.c:4656-4657 - Function:
wc_RsaFlattenPublicKey,wc_RsaExportKey - Category: [convention]
- Confidence: High
Description: Both wc_RsaFlattenPublicKey and wc_RsaExportKey accept const RsaKey* key, but the ExportKey callback invocation casts the const away via (void*)key. The callback implementation then treats the key as mutable (RsaKey* src = (RsaKey*)info->export_key.obj), calling wc_RsaKeyToDer(src, ...) which takes non-const RsaKey*. If a callback implementation modifies the source key, this is undefined behavior.
Code:
// In wc_RsaFlattenPublicKey (key is const RsaKey*):
ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_RSA,
(void*)key, tmpKey); // cast-away-constRecommendation: Either change wc_CryptoCb_ExportKey's obj parameter to const void*, or document that the ExportKey callback MUST NOT modify the source object. The wc_CryptoInfo struct member export_key.obj should be const void*.
There was a problem hiding this comment.
Changed export_key.obj to const void* in the struct definition (cryptocb.h),
updated the wc_CryptoCb_ExportKey declaration and definition to take const void* obj,
and removed the (void*) cast-away-const at all 4 callsites in rsa.c and ecc.c.
Test callbacks left unchanged - they cast away const from export_key.obj since the
wolfSSL export APIs take non-const key parameters.
| } | ||
| } | ||
| #endif /* WOLF_CRYPTO_CB_FREE */ | ||
| #ifdef WOLF_CRYPTO_CB_SETKEY |
There was a problem hiding this comment.
MEDIUM-4: Significant code duplication between test callback implementations
- File:
tests/api.c:28322-28625andwolfcrypt/test/test.c:65838-66177 - Function:
test_CryptoCb_Func,myCryptoDevCb - Category: [style]
- Confidence: High
Description: The SETKEY and EXPORT_KEY callback implementations in tests/api.c and wolfcrypt/test/test.c are nearly identical (~300 lines each). Every key type handler (AES, HMAC, RSA pub/priv, ECC pub/priv) is copy-pasted between the two test files. This makes maintenance error-prone — any bug fix in one copy must be manually replicated in the other.
Recommendation: Consider extracting common callback helper functions into a shared test utility header, or use a common #include file for the shared handler implementations.
There was a problem hiding this comment.
There is currently no sharing code between tests/api.c and wolfcrypt/test/test.c they have separate include structures and their existing crypto callback implementations (test_CryptoCb_Func vs myCryptoDevCb) take fundamentally different approaches even for the pre-existing operations (e.g., api.c loads RSA keys from PEM files while test.c uses pre-initialized keys directly).
The SETKEY/EXPORT_KEY handlers are the first significant duplication between them. Introducing a shared test utility header would be a new pattern for the repo.
I can look at consolidating this in a follow-up if desired.
| #endif | ||
| if (key == NULL || priv == NULL) | ||
|
|
||
| if (key == NULL || priv == NULL) { |
There was a problem hiding this comment.
MEDIUM-5: _ecc_import_private_key_ex calls public wc_ecc_import_x963_ex — potential infinite recursion if devId not cleared
- File:
wolfcrypt/src/ecc.c:11415 - Function:
_ecc_import_private_key_ex - Category: [bug]
- Confidence: Medium
Description: The software-only helper _ecc_import_private_key_ex calls wc_ecc_import_x963_ex(pub, pubSz, key, curve_id), which eventually calls wc_ecc_import_x963_ex2. The x963 import wrapper has SETKEY callback logic that checks key->devId != INVALID_DEVID. Since _ecc_import_private_key_ex is always called with tmpKey that has INVALID_DEVID, this works correctly — the x963 import skips the callback path.
However, this relies on an implicit contract that _ecc_import_private_key_ex is ONLY called with INVALID_DEVID keys. If a future caller passes a key with a valid devId, this would trigger a recursion loop: wc_ecc_import_private_key_ex → _ecc_import_private_key_ex → wc_ecc_import_x963_ex → wc_ecc_import_x963_ex2 (SETKEY path) → callback → wc_ecc_import_private_key_ex → .... The naming convention (_ prefix) suggests internal use, but there's no compile-time enforcement.
Recommendation: Add an assertion or comment at the top of _ecc_import_private_key_ex verifying key->devId == INVALID_DEVID, or call _ecc_import_x963_ex2 directly instead of going through the public wrapper.
There was a problem hiding this comment.
Changed _ecc_import_private_key_ex to call _ecc_import_x963_ex2(pub, pubSz, key, curve_id, 0) directly instead of going through the public wc_ecc_import_x963_ex wrapper. This eliminates the recursion risk entirely - the internal function bypasses the SETKEY callback block.
| int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, | ||
| const byte* iv, int dir) | ||
| { | ||
| #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) |
There was a problem hiding this comment.
LOW-6: Unused cbRet variable when WOLF_CRYPTO_CB_SETKEY not combined with WOLF_CRYPTO_CB
- File:
wolfcrypt/src/aes.c:4521-4523 - Function:
wc_AesSetKey - Category: [style]
- Confidence: Medium
Description: The variable cbRet is declared under #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) but its usage is guarded by #ifdef WOLF_CRYPTO_CB_SETKEY alone (inside an #ifdef WOLF_CRYPTO_CB block). While the outer guards make the combination safe in practice, the inconsistent guard style between declaration and use could cause compiler warnings if the guards ever diverge.
Code:
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY)
int cbRet; // Declaration
#endif
...
#ifdef WOLF_CRYPTO_CB
...
#ifdef WOLF_CRYPTO_CB_SETKEY // Usage
cbRet = wc_CryptoCb_SetKey(...);Recommendation: NIT — the code is correct as-is since WOLF_CRYPTO_CB_SETKEY is always inside #ifdef WOLF_CRYPTO_CB. No action required.
| } | ||
| return NULL; | ||
| } | ||
| #ifdef WOLF_CRYPTO_CB_SETKEY |
There was a problem hiding this comment.
LOW-7: GetSetKeyTypeStr missing default WC_SETKEY_NONE case
- File:
wolfcrypt/src/cryptocb.c:116-128 - Function:
GetSetKeyTypeStr - Category: [style]
- Confidence: Low
Description: The debug helper GetSetKeyTypeStr handles all defined WC_SETKEY_* values but returns "Unknown" for WC_SETKEY_NONE = 0. While not a bug, other similar helpers in the file (like GetPkTypeStr) return NULL for unrecognized values. This inconsistency is minor but could confuse debuggers.
Recommendation: Consider adding case WC_SETKEY_NONE: return "None"; for completeness, and returning NULL for the default case to match the pattern used by GetPkTypeStr.
There was a problem hiding this comment.
Added case WC_SETKEY_NONE: return "None"; and changed default to return NULL, matching the pattern used by GetPkTypeStr.
| '--disable-tls --enable-cryptocb --enable-aesgcm CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY -DWOLF_CRYPTO_CB_FREE"', | ||
| '--enable-all --enable-dilithium --enable-cryptocb --enable-cryptocbutils --enable-pkcallbacks', | ||
| '--enable-cryptocb --enable-aesgcm CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY"', | ||
| '--enable-cryptocb --enable-keygen --enable-cryptocbutils=setkey', |
There was a problem hiding this comment.
LOW-8: New CI test configurations don't cover WOLF_CRYPTO_CB_FIND interaction
- File:
.github/workflows/os-check.yml:87-92 - Function: N/A (CI)
- Category: [test]
- Confidence: Low
Description: Six new CI configurations test various --enable-cryptocbutils combinations but none test the interaction with WOLF_CRYPTO_CB_FIND. Several code paths have #ifndef WOLF_CRYPTO_CB_FIND guards that change behavior (e.g., skipping the devId != INVALID_DEVID check). Testing this combination would increase coverage of the new feature.
Recommendation: Consider adding at least one CI config that combines --enable-cryptocbutils with WOLF_CRYPTO_CB_FIND.
There was a problem hiding this comment.
'--enable-cryptocb --enable-keygen --enable-cryptocbutils=setkey,export CPPFLAGS="-DWOLF_CRYPTO_CB_FIND"'. Also fixed a pre-existing NULL pointer dereference in wc_RsaPrivateKeyDecode (asn.c) where *inOutIdx was accessed in the SETKEY block before validating inOutIdx != NULL. With WOLF_CRYPTO_CB_FIND the SETKEY block runs unconditionally, so the bad-args test case (which passes NULL) crashed. Added early NULL check for input and inOutIdx parameters.
utilities for generic SetKey and ExportKey operations on HMAC, RSA, ECC, and AES. Add wc_ecc_size/wc_ecc_sig_size callback hooks for hardware-only keys. Integrate into configure.ac as --enable-cryptocbutils=setkey,export options with CI test configurations in os-check.yml. Add test handlers in test.c and api.c with export/import delegation pattern, small-stack-safe allocations, custom curve support, and DEBUG_CRYPTOCB helpers.
…TYPE_MAX, const-qualify export_key.obj, call _ecc_import_x963_ex2 directly, fix GetSetKeyTypeStr, fix NULL deref in wc_RsaPrivateKeyDecode with WOLF_CRYPTO_CB_FIND, add FIND CI config.
c4f2002 to
8b6972e
Compare
|
Had to rebase and force push due to merge conflict with |
Add
WOLF_CRYPTO_CB_SETKEYandWOLF_CRYPTO_CB_EXPORT_KEYgeneric crypto callback utilities.Both callbacks use a temporary key struct pattern to bridge between raw key bytes and hardware. The temporary key is always initialized with
INVALID_DEVIDso it never recurses into the callback — it serves purely as a software intermediary.SetKey (Import): When a key import function (e.g.
wc_ecc_import_x963_ex2) is called on a hardware-bound key, a temporary key is created and the raw key material is imported into it via the normal software path. The callback handler then receives both the hardware destination key and the fully-parsed temporary key. The handler can call any wolfSSL export function on the temporary key (wc_RsaKeyToDer,wc_ecc_export_x963, raw component getters, etc.) to extract the key in whatever format the hardware needs, program it, and associate it with the destination key. The temporary key is freed after the callback returns.SetKey callbacks are wired into:
wc_AesSetKey,wc_HmacSetKey,wc_RsaPublicKeyDecodeRaw,wc_RsaPrivateKeyDecodeRaw,wc_RsaPrivateKeyDecode,wc_ecc_import_x963_ex2,wc_ecc_import_raw_private, andwc_ecc_import_private_key_ex. All RSA and ECC callsites pass the actual key size in bytes via thekeySzparameter. ECC import paths propagate custom curve parameters to the temporary key so custom curves (e.g. brainpool) work correctly through the callback.ExportKey: When an export function (e.g.
wc_ecc_export_x963) is called on a hardware-backed key, an empty temporary key is created and passed to the callback handler alongside the hardware source key. The handler extracts key material from hardware in whatever format it can and imports it into the temporary key using any wolfSSL import function. Once the callback returns, the original export function runs on the now fully-populated temporary key via the normal software path, producing the output the caller originally requested. The temporary key is freed afterward.ExportKey callbacks are wired into
wc_RsaFlattenPublicKey,wc_RsaExportKey,wc_ecc_export_x963, andwc_ecc_export_ex(which coverswc_ecc_export_private_only,wc_ecc_export_public_raw, andwc_ecc_export_private_raw).Add
wc_CryptoCb_EccGetSizeandwc_CryptoCb_EccGetSigSizecallback hookstowc_ecc_size()andwc_ecc_sig_size(), allowing hardware-only keys (wheredpmay be NULL) to report their key and signature sizes through the crypto callback rather than requiring curve info to be present in the key struct.Both features are enabled via
--enable-cryptocbutils=setkey,export,--enable-cryptocbutils, or the corresponding-DWOLF_CRYPTO_CB_SETKEYand-DWOLF_CRYPTO_CB_EXPORT_KEYdefines, with CI test configurations inos-check.yml. Includes test handlers intest.candapi.cwith small-stack-safe allocations (WC_DECLARE_VAR), aGetSetKeyTypeStrdebug helper for readable type names underDEBUG_CRYPTOCB, and RSA free callback support.