From d2183eea1a9b16ae7355b9724559047ea68a201f Mon Sep 17 00:00:00 2001 From: night1rider Date: Mon, 2 Mar 2026 14:15:35 -0700 Subject: [PATCH 1/6] Add WOLF_CRYPTO_CB_SETKEY and WOLF_CRYPTO_CB_EXPORT_KEY crypto callback 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. --- .github/workflows/os-check.yml | 7 + configure.ac | 14 +- tests/api.c | 135 ++++++++++++ wolfcrypt/src/aes.c | 24 +++ wolfcrypt/src/asn.c | 95 +++++++++ wolfcrypt/src/cryptocb.c | 154 ++++++++++++++ wolfcrypt/src/ecc.c | 222 +++++++++++++++++++- wolfcrypt/src/hmac.c | 16 ++ wolfcrypt/src/rsa.c | 138 ++++++++++++ wolfcrypt/test/test.c | 370 ++++++++++++++++++++++++++++++++- wolfssl/wolfcrypt/cryptocb.h | 53 ++++- wolfssl/wolfcrypt/types.h | 6 +- 12 files changed, 1220 insertions(+), 14 deletions(-) diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index b65270e5670..c46a0b8c659 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -61,6 +61,13 @@ jobs: CPPFLAGS=-DWOLFSSL_TLS13_IGNORE_PT_ALERT_ON_ENC', '--enable-all --enable-certgencache', '--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', + '--enable-cryptocb --enable-keygen --enable-cryptocbutils CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY"', + '--enable-cryptocb --enable-keygen --enable-aesgcm --enable-cryptocbutils=setkey,free CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY"', + '--enable-cryptocb --enable-keygen --enable-cryptocbutils=export', + '--enable-cryptocb --enable-keygen CPPFLAGS="-DWOLF_CRYPTO_CB_EXPORT_KEY"', + '--enable-cryptocb --enable-keygen --enable-aesgcm --enable-cryptocbutils=setkey,free,export CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY"', 'CPPFLAGS=-DWOLFSSL_NO_CLIENT_AUTH', 'CPPFLAGS=''-DNO_WOLFSSL_CLIENT -DWOLFSSL_NO_CLIENT_AUTH''', 'CPPFLAGS=''-DNO_WOLFSSL_SERVER -DWOLFSSL_NO_CLIENT_AUTH''', diff --git a/configure.ac b/configure.ac index e1e142174f6..7613f865e71 100644 --- a/configure.ac +++ b/configure.ac @@ -9968,7 +9968,7 @@ fi # Crypto Callbacks Utils (Copy/Free/etc) AC_ARG_ENABLE([cryptocbutils], - [AS_HELP_STRING([--enable-cryptocbutils@<:@=copy,free,...@:>@], + [AS_HELP_STRING([--enable-cryptocbutils@<:@=copy,free,setkey,export,...@:>@], [Enable crypto callback utilities (default: all)])], [ ENABLED_CRYPTOCB_UTILS=$enableval ], [ ENABLED_CRYPTOCB_UTILS=no ] @@ -9981,8 +9981,7 @@ if test "$ENABLED_CRYPTOCB_UTILS" != "no"; then if test "$ENABLED_CRYPTOCB_UTILS" = "yes"; then # Enable all utilities - AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB_COPY -DWOLF_CRYPTO_CB_FREE" - # Future utilities go here when added + AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB_COPY -DWOLF_CRYPTO_CB_FREE -DWOLF_CRYPTO_CB_SETKEY -DWOLF_CRYPTO_CB_EXPORT_KEY" else # Parse comma-separated list OIFS="$IFS" @@ -9995,9 +9994,14 @@ if test "$ENABLED_CRYPTOCB_UTILS" != "no"; then free) AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB_FREE" ;; - # Add future options here (e.g., malloc, realloc, etc) + setkey) + AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB_SETKEY" + ;; + export) + AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB_EXPORT_KEY" + ;; *) - AC_MSG_ERROR([Unknown cryptocbutils option: $util. Valid options: copy, free]) + AC_MSG_ERROR([Unknown cryptocbutils option: $util. Valid options: copy, free, setkey, export]) ;; esac done diff --git a/tests/api.c b/tests/api.c index 0d40dbb636b..57063e21c53 100644 --- a/tests/api.c +++ b/tests/api.c @@ -28306,6 +28306,141 @@ static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx) } } #endif /* WOLF_CRYPTO_CB_FREE */ +#ifdef WOLF_CRYPTO_CB_SETKEY + else if (info->algo_type == WC_ALGO_TYPE_SETKEY) { + #ifdef DEBUG_WOLFSSL + fprintf(stderr, "test_CryptoCb_Func: SetKey Type=%d\n", + info->setkey.type); + #endif + switch (info->setkey.type) { + #ifndef NO_AES + case WC_SETKEY_AES: + { + Aes* aes = (Aes*)info->setkey.obj; + aes->devId = INVALID_DEVID; + ret = wc_AesSetKey(aes, + (const byte*)info->setkey.key, info->setkey.keySz, + (const byte*)info->setkey.aux, info->setkey.flags); + aes->devId = thisDevId; + break; + } + #endif /* !NO_AES */ + #ifndef NO_HMAC + case WC_SETKEY_HMAC: + { + Hmac* hmac = (Hmac*)info->setkey.obj; + hmac->devId = INVALID_DEVID; + ret = wc_HmacSetKey(hmac, hmac->macType, + (const byte*)info->setkey.key, info->setkey.keySz); + hmac->devId = thisDevId; + break; + } + #endif /* !NO_HMAC */ + #if !defined(NO_RSA) && defined(WOLFSSL_KEY_TO_DER) + case WC_SETKEY_RSA_PUB: + { + RsaKey* rsaObj = (RsaKey*)info->setkey.obj; + RsaKey* rsaTmp = (RsaKey*)info->setkey.key; + int derSz; + word32 idx = 0; + byte* der = NULL; + + derSz = wc_RsaPublicKeyDerSize(rsaTmp, 1); + if (derSz <= 0) { ret = derSz; break; } + + der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { ret = MEMORY_E; break; } + + derSz = wc_RsaKeyToPublicDer_ex(rsaTmp, der, + (word32)derSz, 1); + if (derSz <= 0) { + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ret = derSz; break; + } + + rsaObj->devId = INVALID_DEVID; + ret = wc_RsaPublicKeyDecode(der, &idx, rsaObj, + (word32)derSz); + rsaObj->devId = thisDevId; + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + break; + } + case WC_SETKEY_RSA_PRIV: + { + RsaKey* rsaObj = (RsaKey*)info->setkey.obj; + RsaKey* rsaTmp = (RsaKey*)info->setkey.key; + int derSz; + word32 idx = 0; + byte* der = NULL; + + derSz = wc_RsaKeyToDer(rsaTmp, NULL, 0); + if (derSz <= 0) { ret = derSz; break; } + + der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { ret = MEMORY_E; break; } + + derSz = wc_RsaKeyToDer(rsaTmp, der, (word32)derSz); + if (derSz <= 0) { + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ret = derSz; break; + } + + rsaObj->devId = INVALID_DEVID; + ret = wc_RsaPrivateKeyDecode(der, &idx, rsaObj, + (word32)derSz); + rsaObj->devId = thisDevId; + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + break; + } + #endif /* !NO_RSA && WOLFSSL_KEY_TO_DER */ + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \ + defined(HAVE_ECC_KEY_IMPORT) + case WC_SETKEY_ECC_PUB: + { + ecc_key* eccObj = (ecc_key*)info->setkey.obj; + ecc_key* eccTmp = (ecc_key*)info->setkey.key; + byte buf[ECC_BUFSIZE]; + word32 bufSz = sizeof(buf); + int curveId; + + ret = wc_ecc_export_x963(eccTmp, buf, &bufSz); + if (ret != 0) break; + + curveId = wc_ecc_get_curve_id(eccTmp->idx); + eccObj->devId = INVALID_DEVID; + ret = wc_ecc_import_x963_ex2(buf, bufSz, eccObj, curveId, 0); + eccObj->devId = thisDevId; + break; + } + case WC_SETKEY_ECC_PRIV: + { + ecc_key* eccObj = (ecc_key*)info->setkey.obj; + ecc_key* eccTmp = (ecc_key*)info->setkey.key; + byte pubBuf[ECC_BUFSIZE]; + byte privBuf[MAX_ECC_BYTES]; + word32 pubSz = sizeof(pubBuf); + word32 privSz = sizeof(privBuf); + int curveId; + + ret = wc_ecc_export_x963(eccTmp, pubBuf, &pubSz); + if (ret != 0) break; + ret = wc_ecc_export_private_only(eccTmp, privBuf, &privSz); + if (ret != 0) break; + + curveId = wc_ecc_get_curve_id(eccTmp->idx); + eccObj->devId = INVALID_DEVID; + ret = wc_ecc_import_private_key_ex(privBuf, privSz, + pubBuf, pubSz, eccObj, curveId); + eccObj->devId = thisDevId; + break; + } + #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && HAVE_ECC_KEY_IMPORT */ + default: + ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); + break; + } + } +#endif /* WOLF_CRYPTO_CB_SETKEY */ (void)thisDevId; (void)keyFormat; diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 41b01031c41..d80e90d0c55 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -4518,6 +4518,9 @@ WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int wc_AesDecrypt( 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) + int cbRet; +#endif if ((aes == NULL) || (userKey == NULL)) { return BAD_FUNC_ARG; } @@ -4559,6 +4562,15 @@ WC_ALL_ARGS_NOT_NULL static WARN_UNUSED_RESULT int wc_AesDecrypt( } /* CRYPTOCB_UNAVAILABLE: continue to software setup */ #endif + #ifdef WOLF_CRYPTO_CB_SETKEY + cbRet = wc_CryptoCb_SetKey(aes->devId, + WC_SETKEY_AES, aes, (void*)userKey, keylen, + (void*)iv, + (iv != NULL) ? WC_AES_BLOCK_SIZE : 0, dir); + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return cbRet; + /* CRYPTOCB_UNAVAILABLE: fall through to software setup */ + #endif /* WOLF_CRYPTO_CB_SETKEY */ /* Standard CryptoCB path - copy key to devKey for encrypt/decrypt offload */ if (keylen > sizeof(aes->devKey)) { return BAD_FUNC_ARG; @@ -4955,6 +4967,9 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) int checkKeyLen) { int ret; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet; +#endif #ifdef WOLFSSL_IMX6_CAAM_BLOB byte local[32]; word32 localSz = 32; @@ -5005,6 +5020,15 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) } /* CRYPTOCB_UNAVAILABLE: continue to software setup */ #endif + #ifdef WOLF_CRYPTO_CB_SETKEY + cbRet = wc_CryptoCb_SetKey(aes->devId, + WC_SETKEY_AES, aes, (void*)userKey, keylen, + (void*)iv, + (iv != NULL) ? WC_AES_BLOCK_SIZE : 0, dir); + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return cbRet; + /* CRYPTOCB_UNAVAILABLE: fall through to software setup */ + #endif /* WOLF_CRYPTO_CB_SETKEY */ /* Standard CryptoCB path - copy key to devKey */ if (keylen > sizeof(aes->devKey)) { return BAD_FUNC_ARG; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index b095b5c204e..8e3ccf8728b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8297,9 +8297,59 @@ static int _RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + int tmpErr = 0; + word32 tmpIdx; + WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); +#endif + if (key == NULL) { return BAD_FUNC_ARG; } + +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + tmpIdx = *inOutIdx; + + WC_ALLOC_VAR(tmpKey, RsaKey, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(RsaKey)); + + tmpErr = wc_InitRsaKey_ex(tmpKey, key->heap, INVALID_DEVID); + if (tmpErr != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return tmpErr; + } + + /* Decode into temp key (software-only, no callback recursion + * since tmpKey has INVALID_DEVID) */ + tmpErr = _RsaPrivateKeyDecode(input, &tmpIdx, tmpKey, NULL, inSz); + if (tmpErr == 0) { + cbRet = wc_CryptoCb_SetKey(key->devId, + WC_SETKEY_RSA_PRIV, key, tmpKey, + wc_RsaEncryptSize(tmpKey), NULL, 0, 0); + } + + wc_FreeRsaKey(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (tmpErr != 0) { + return tmpErr; + } + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + *inOutIdx = tmpIdx; + return cbRet; + } + /* CRYPTOCB_UNAVAILABLE: fall through to software import */ + } +#endif + return _RsaPrivateKeyDecode(input, inOutIdx, key, NULL, inSz); } @@ -36492,9 +36542,54 @@ int wc_Asn1_PrintAll(Asn1* asn1, Asn1PrintOptions* opts, unsigned char* data, int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, word32 eSz, RsaKey* key) { +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + int tmpErr = 0; + WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); +#endif + if (n == NULL || e == NULL || key == NULL) return BAD_FUNC_ARG; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + /* Allocate temp key for callback to export from */ + WC_ALLOC_VAR(tmpKey, RsaKey, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(RsaKey)); + + tmpErr = wc_InitRsaKey_ex(tmpKey, key->heap, INVALID_DEVID); + if (tmpErr != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return tmpErr; + } + + /* Recursive call imports n, e into temp via software */ + tmpErr = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, tmpKey); + if (tmpErr == 0) { + cbRet = wc_CryptoCb_SetKey(key->devId, + WC_SETKEY_RSA_PUB, key, tmpKey, + wc_RsaEncryptSize(tmpKey), NULL, 0, 0); + } + + wc_FreeRsaKey(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (tmpErr != 0) { + return tmpErr; + } + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return cbRet; + } + /* CRYPTOCB_UNAVAILABLE: fall through to software import */ + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ + key->type = RSA_PUBLIC; if (mp_init(&key->n) != MP_OKAY) diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index 069dd4e0c6f..d6a3c4252a2 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -105,9 +105,29 @@ static const char* GetAlgoTypeStr(int algo) #ifdef WOLF_CRYPTO_CB_FREE case WC_ALGO_TYPE_FREE: return "Free"; #endif /* WOLF_CRYPTO_CB_FREE */ +#ifdef WOLF_CRYPTO_CB_SETKEY + case WC_ALGO_TYPE_SETKEY: return "SetKey"; +#endif /* WOLF_CRYPTO_CB_SETKEY */ +#ifdef WOLF_CRYPTO_CB_EXPORT_KEY + case WC_ALGO_TYPE_EXPORT_KEY: return "ExportKey"; +#endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ } return NULL; } +#ifdef WOLF_CRYPTO_CB_SETKEY +static const char* GetSetKeyTypeStr(int type) +{ + switch (type) { + case WC_SETKEY_HMAC: return "HMAC"; + case WC_SETKEY_RSA_PUB: return "RSA-Pub"; + case WC_SETKEY_RSA_PRIV: return "RSA-Priv"; + case WC_SETKEY_ECC_PUB: return "ECC-Pub"; + case WC_SETKEY_ECC_PRIV: return "ECC-Priv"; + case WC_SETKEY_AES: return "AES"; + } + return "Unknown"; +} +#endif /* WOLF_CRYPTO_CB_SETKEY */ static const char* GetPkTypeStr(int pk) { switch (pk) { @@ -121,6 +141,8 @@ static const char* GetPkTypeStr(int pk) case WC_PK_TYPE_CURVE25519: return "CURVE25519"; case WC_PK_TYPE_RSA_KEYGEN: return "RSA KeyGen"; case WC_PK_TYPE_EC_KEYGEN: return "ECC KeyGen"; + case WC_PK_TYPE_EC_GET_SIZE: return "ECC GetSize"; + case WC_PK_TYPE_EC_GET_SIG_SIZE: return "ECC GetSigSize"; } return NULL; } @@ -291,6 +313,19 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info) GetAlgoTypeStr(info->free.algo), info->free.type); } #endif /* WOLF_CRYPTO_CB_FREE */ +#ifdef WOLF_CRYPTO_CB_SETKEY + else if (info->algo_type == WC_ALGO_TYPE_SETKEY) { + printf("Crypto CB: %s %s KeySz=%u\n", + GetAlgoTypeStr(info->algo_type), + GetSetKeyTypeStr(info->setkey.type), info->setkey.keySz); + } +#endif /* WOLF_CRYPTO_CB_SETKEY */ +#ifdef WOLF_CRYPTO_CB_EXPORT_KEY + else if (info->algo_type == WC_ALGO_TYPE_EXPORT_KEY) { + printf("Crypto CB: %s Type=%d\n", + GetAlgoTypeStr(info->algo_type), info->export_key.type); + } +#endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ #if (defined(HAVE_HKDF) && !defined(NO_HMAC)) || \ defined(HAVE_CMAC_KDF) else if (info->algo_type == WC_ALGO_TYPE_KDF) { @@ -781,6 +816,54 @@ int wc_CryptoCb_EccCheckPrivKey(ecc_key* key, const byte* pubKey, return wc_CryptoCb_TranslateErrorCode(ret); } #endif + +int wc_CryptoCb_EccGetSize(const ecc_key* key, int* keySize) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_EC_GET_SIZE; + cryptoInfo.pk.ecc_get_size.key = key; + cryptoInfo.pk.ecc_get_size.keySize = keySize; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_EccGetSigSize(const ecc_key* key, int* sigSize) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_EC_GET_SIG_SIZE; + cryptoInfo.pk.ecc_get_sig_size.key = key; + cryptoInfo.pk.ecc_get_sig_size.sigSize = sigSize; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} #endif /* HAVE_ECC */ #ifdef HAVE_CURVE25519 @@ -2167,6 +2250,77 @@ int wc_CryptoCb_Free(int devId, int algo, int type, int subType, void* obj) } #endif /* WOLF_CRYPTO_CB_FREE */ +#ifdef WOLF_CRYPTO_CB_SETKEY +/* Generic SetKey callback for importing keys into hardware. + * devId: Device ID for the registered callback + * type: enum wc_SetKeyType (AES, HMAC, RSA_PUB, RSA_PRIV, ECC_PUB, ECC_PRIV) + * obj: Context struct being operated on (Aes*, Hmac*, RsaKey*, ecc_key*) + * key: Key material: raw bytes (AES/HMAC) or temp struct to export from (RSA/ECC) + * keySz: Key size in bytes (0 when key is a struct pointer) + * aux: Auxiliary data (IV, etc.) or NULL + * auxSz: Aux data size, 0 if unused + * flags: AES: direction (AES_ENCRYPTION/DECRYPTION). Others: 0 + * Returns: 0 on success, CRYPTOCB_UNAVAILABLE if not handled, negative on error + */ +int wc_CryptoCb_SetKey(int devId, int type, void* obj, + void* key, word32 keySz, + void* aux, word32 auxSz, + int flags) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* Find registered callback device */ + dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_SETKEY); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_SETKEY; + cryptoInfo.setkey.type = type; + cryptoInfo.setkey.obj = obj; + cryptoInfo.setkey.key = key; + cryptoInfo.setkey.keySz = keySz; + cryptoInfo.setkey.aux = aux; + cryptoInfo.setkey.auxSz = auxSz; + cryptoInfo.setkey.flags = flags; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLF_CRYPTO_CB_SETKEY */ + +#ifdef WOLF_CRYPTO_CB_EXPORT_KEY +/* Generic ExportKey callback for exporting key material from hardware. + * devId: Device ID for the registered callback + * type: enum wc_PkType (WC_PK_TYPE_RSA, WC_PK_TYPE_ECDSA, etc.) + * obj: Hardware key object (has devCtx, id[], etc.) + * out: Software key object to fill (same type as obj, caller-allocated) + * The callback exports from hardware into the software key. The caller then + * uses normal software export functions on 'out' and frees it. + * Returns: 0 on success, CRYPTOCB_UNAVAILABLE if not handled, negative on error + */ +int wc_CryptoCb_ExportKey(int devId, int type, void* obj, void* out) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + dev = wc_CryptoCb_FindDevice(devId, WC_ALGO_TYPE_EXPORT_KEY); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_EXPORT_KEY; + cryptoInfo.export_key.type = type; + cryptoInfo.export_key.obj = obj; + cryptoInfo.export_key.out = out; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ #if defined(HAVE_CMAC_KDF) /* Crypto callback for NIST SP 800 56C two-step CMAC KDF. See software diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 4752fa26305..79cbf475aad 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -10685,6 +10685,11 @@ int wc_ecc_import_x963_ex2(const byte* in, word32 inLen, ecc_key* key, const CRYS_ECPKI_Domain_t* pDomain; CRYS_ECPKI_BUILD_TempData_t tempBuff; #endif +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif + if (in == NULL || key == NULL) return BAD_FUNC_ARG; @@ -10693,6 +10698,58 @@ int wc_ecc_import_x963_ex2(const byte* in, word32 inLen, ecc_key* key, return ECC_BAD_ARG_E; } +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + /* Allocate temp key for callback to export from */ + WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(ecc_key)); + + err = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); + if (err != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + + #ifdef WOLFSSL_CUSTOM_CURVES + /* Copy custom curve params so recursive import uses correct curve */ + if (key->dp != NULL) { + err = wc_ecc_set_custom_curve(tmpKey, key->dp); + if (err != 0) { + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + } + #endif + + /* Recursive call imports X9.63 public key into temp via software */ + err = wc_ecc_import_x963_ex2(in, inLen, tmpKey, curve_id, untrusted); + if (err == MP_OKAY) { + cbRet = wc_CryptoCb_SetKey(key->devId, + WC_SETKEY_ECC_PUB, key, tmpKey, + wc_ecc_size(tmpKey), NULL, 0, 0); + } + + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (err != MP_OKAY) { + return err; + } + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return cbRet; + } + /* CRYPTOCB_UNAVAILABLE: fall through to software import */ + err = MP_OKAY; + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ + /* make sure required variables are reset */ wc_ecc_reset(key); @@ -11233,9 +11290,68 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, #ifdef WOLFSSL_CRYPTOCELL const CRYS_ECPKI_Domain_t* pDomain; #endif +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + int tmpErr = 0; + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif + if (key == NULL || priv == NULL) return BAD_FUNC_ARG; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + /* Allocate temp key for callback to export from */ + WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(ecc_key)); + + tmpErr = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); + if (tmpErr != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return tmpErr; + } + + #ifdef WOLFSSL_CUSTOM_CURVES + /* Copy custom curve params so recursive import uses correct curve */ + if (key->dp != NULL) { + tmpErr = wc_ecc_set_custom_curve(tmpKey, key->dp); + if (tmpErr != 0) { + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + return tmpErr; + } + } + #endif + + /* Recursive call imports key material into temp via software + * (no callback recursion since tmpKey has INVALID_DEVID) */ + tmpErr = wc_ecc_import_private_key_ex(priv, privSz, pub, pubSz, + tmpKey, curve_id); + if (tmpErr == 0) { + cbRet = wc_CryptoCb_SetKey(key->devId, + WC_SETKEY_ECC_PRIV, key, tmpKey, + wc_ecc_size(tmpKey), NULL, 0, 0); + } + + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (tmpErr != 0) { + return tmpErr; + } + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return cbRet; + } + /* CRYPTOCB_UNAVAILABLE: fall through to software import */ + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ + /* public optional, NULL if only importing private */ if (pub != NULL) { #ifndef NO_ASN @@ -11553,11 +11669,15 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, CRYS_ECPKI_BUILD_TempData_t tempBuff; byte keyRaw[ECC_MAX_CRYPTO_HW_SIZE*2 + 1]; #endif - #if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A) || \ defined(WOLFSSL_CRYPTOCELL) word32 keySz = 0; #endif +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + int setKeyType = WC_SETKEY_ECC_PRIV; + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif /* if d is NULL, only import as public key using Qx,Qy */ if (key == NULL || qx == NULL || qy == NULL) { @@ -11575,6 +11695,63 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, return err; } +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + /* Allocate temp key for callback to export from */ + WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(ecc_key)); + + err = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); + if (err != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + + #ifdef WOLFSSL_CUSTOM_CURVES + /* Copy custom curve params so recursive import uses correct curve */ + if (key->dp != NULL) { + err = wc_ecc_set_custom_curve(tmpKey, key->dp); + if (err != 0) { + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + } + #endif + + /* Recursive call imports key material into temp via software */ + err = wc_ecc_import_raw_private(tmpKey, qx, qy, d, curve_id, encType); + if (err == MP_OKAY) { + /* This function handles both public and private imports: + * when d is NULL, only Qx/Qy are imported (public only) */ + if (d == NULL) { + setKeyType = WC_SETKEY_ECC_PUB; + } + cbRet = wc_CryptoCb_SetKey(key->devId, + setKeyType, key, tmpKey, + wc_ecc_size(tmpKey), NULL, 0, 0); + } + + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (err != MP_OKAY) { + return err; + } + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return cbRet; + } + /* CRYPTOCB_UNAVAILABLE: fall through to software import */ + err = MP_OKAY; + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ + /* init key */ #ifdef ALT_ECC_SIZE key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; @@ -11933,7 +12110,27 @@ static int ecc_public_key_size(ecc_key* key, word32* sz) WOLFSSL_ABI int wc_ecc_size(ecc_key* key) { - if (key == NULL || key->dp == NULL) +#ifdef WOLF_CRYPTO_CB + int ret; + int keySz; +#endif + + if (key == NULL) + return 0; + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + keySz = 0; + ret = wc_CryptoCb_EccGetSize(key, &keySz); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + if (ret != 0) + return 0; + return keySz; + } + } +#endif + + if (key->dp == NULL) return 0; return key->dp->size; @@ -11963,8 +12160,27 @@ int wc_ecc_sig_size(const ecc_key* key) { int maxSigSz; int orderBits, keySz; +#ifdef WOLF_CRYPTO_CB + int ret; + int cbKeySz; +#endif - if (key == NULL || key->dp == NULL) + if (key == NULL) + return 0; + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + cbKeySz = 0; + ret = wc_CryptoCb_EccGetSigSize(key, &cbKeySz); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + if (ret != 0 || cbKeySz == 0) + return 0; + return cbKeySz; + } + } +#endif + + if (key->dp == NULL) return 0; /* the signature r and s will always be less than order */ diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 4b3cfd15890..edc16f1a5fb 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -470,6 +470,9 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length, #endif int ret = 0; void* heap = NULL; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet; +#endif if (hmac == NULL || (key == NULL && length != 0) || !(type == WC_MD5 || type == WC_SHA || @@ -543,6 +546,19 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length, } } +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (hmac->devId != INVALID_DEVID) + #endif + { + cbRet = wc_CryptoCb_SetKey(hmac->devId, + WC_SETKEY_HMAC, hmac, (void*)key, length, NULL, 0, 0); + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return cbRet; + /* fall-through to software when unavailable */ + } +#endif + #ifdef WOLF_CRYPTO_CB hmac->keyRaw = key; /* use buffer directly */ hmac->keyLen = (word16)length; diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 4fb4393f0b4..85fe43cd229 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -590,6 +590,22 @@ int wc_FreeRsaKey(RsaKey* key) return BAD_FUNC_ARG; } +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_Free(key->devId, WC_ALGO_TYPE_PK, + WC_PK_TYPE_RSA, 0, key); + /* If callback wants standard free, it returns CRYPTOCB_UNAVAILABLE. + * Otherwise assume the callback handled cleanup. */ + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through to software cleanup */ + ret = 0; + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_FREE */ + #if defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_RSA) se050_rsa_free_key(key); #endif @@ -4457,11 +4473,46 @@ int wc_RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, byte* n, word32* nSz) { int sz, ret; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); +#endif if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) { return BAD_FUNC_ARG; } +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) +#ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) +#endif + { + WC_ALLOC_VAR(tmpKey, RsaKey, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(RsaKey)); + + ret = wc_InitRsaKey_ex(tmpKey, key->heap, INVALID_DEVID); + if (ret != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return ret; + } + + ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_RSA, + (void*)key, tmpKey); + if (ret == 0) { + /* Recursive call on software tmpKey (INVALID_DEVID) */ + ret = wc_RsaFlattenPublicKey(tmpKey, e, eSz, n, nSz); + } + ForceZero(tmpKey, sizeof(RsaKey)); + wc_FreeRsaKey(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall through to software */ + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ + sz = mp_unsigned_bin_size(&key->e); if ((word32)sz > *eSz) return RSA_BUFFER_E; @@ -4510,10 +4561,48 @@ int wc_RsaExportKey(const RsaKey* key, byte* q, word32* qSz) { int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); +#endif if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz) ret = 0; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + if (ret == 0) { + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + WC_ALLOC_VAR(tmpKey, RsaKey, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(RsaKey)); + + ret = wc_InitRsaKey_ex(tmpKey, key->heap, INVALID_DEVID); + if (ret != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return ret; + } + + ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_RSA, + (void*)key, tmpKey); + if (ret == 0) { + /* Recursive call on software tmpKey (INVALID_DEVID) */ + ret = wc_RsaExportKey(tmpKey, e, eSz, n, nSz, + d, dSz, p, pSz, q, qSz); + } + ForceZero(tmpKey, sizeof(RsaKey)); + wc_FreeRsaKey(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + ret = 0; /* fall through to software */ + } + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ + if (ret == 0) ret = RsaGetValue(&key->e, e, eSz); if (ret == 0) @@ -5393,6 +5482,10 @@ int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, const byte* dQ, word32 dQSz, RsaKey* key) { int err = MP_OKAY; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); +#endif if (n == NULL || nSz == 0 || e == NULL || eSz == 0 || d == NULL || dSz == 0 || p == NULL || pSz == 0 @@ -5417,6 +5510,51 @@ int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, (void)dQSz; #endif +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (err == MP_OKAY && key->devId != INVALID_DEVID) + #else + if (err == MP_OKAY) + #endif + { + /* Allocate temp key for callback to export from */ + WC_ALLOC_VAR(tmpKey, RsaKey, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(RsaKey)); + + /* Init temp with INVALID_DEVID to prevent callback recursion */ + err = wc_InitRsaKey_ex(tmpKey, key->heap, INVALID_DEVID); + if (err != MP_OKAY) { + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + + /* Recursive call imports key material into temp via software */ + err = wc_RsaPrivateKeyDecodeRaw(n, nSz, e, eSz, d, dSz, + u, uSz, p, pSz, q, qSz, dP, dPSz, dQ, dQSz, tmpKey); + if (err == MP_OKAY) { + cbRet = wc_CryptoCb_SetKey(key->devId, + WC_SETKEY_RSA_PRIV, key, tmpKey, + wc_RsaEncryptSize(tmpKey), NULL, 0, 0); + } + + /* wc_FreeRsaKey does mp_forcezero on private components */ + wc_FreeRsaKey(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (err != MP_OKAY) { + return err; + } + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return cbRet; + } + /* CRYPTOCB_UNAVAILABLE: fall through to software import */ + err = MP_OKAY; + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ + if (err == MP_OKAY) err = mp_read_unsigned_bin(&key->n, n, nSz); if (err == MP_OKAY) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 5499ec89471..623b0a02e81 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -65332,6 +65332,37 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) info->pk.ecdh.private_key->devId = devIdArg; #endif } + else if (info->pk.type == WC_PK_TYPE_EC_GET_SIZE) { + WC_DECLARE_VAR(tmpEcc, ecc_key, 1, NULL); + WC_ALLOC_VAR(tmpEcc, ecc_key, 1, NULL); + if (!WC_VAR_OK(tmpEcc)) { + ret = MEMORY_E; + } + else { + /* Copy key to avoid const and recursive callback */ + XMEMCPY(tmpEcc, info->pk.ecc_get_size.key, sizeof(ecc_key)); + tmpEcc->devId = INVALID_DEVID; + *info->pk.ecc_get_size.keySize = wc_ecc_size(tmpEcc); + WC_FREE_VAR(tmpEcc, NULL); + ret = 0; + } + } + else if (info->pk.type == WC_PK_TYPE_EC_GET_SIG_SIZE) { + WC_DECLARE_VAR(tmpEcc, ecc_key, 1, NULL); + WC_ALLOC_VAR(tmpEcc, ecc_key, 1, NULL); + if (!WC_VAR_OK(tmpEcc)) { + ret = MEMORY_E; + } + else { + /* Copy key to avoid const and recursive callback */ + XMEMCPY(tmpEcc, info->pk.ecc_get_sig_size.key, + sizeof(ecc_key)); + tmpEcc->devId = INVALID_DEVID; + *info->pk.ecc_get_sig_size.sigSize = wc_ecc_sig_size(tmpEcc); + WC_FREE_VAR(tmpEcc, NULL); + ret = 0; + } + } #endif /* HAVE_ECC */ #ifdef HAVE_CURVE25519 if (info->pk.type == WC_PK_TYPE_CURVE25519_KEYGEN) { @@ -66092,13 +66123,21 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) break; } #endif +#ifndef NO_RSA + case WC_PK_TYPE_RSA: + { + RsaKey* rsa = (RsaKey*)info->free.obj; + rsa->devId = INVALID_DEVID; + wc_FreeRsaKey(rsa); + ret = 0; + break; + } +#endif #ifdef HAVE_DILITHIUM case WC_PK_TYPE_PQC_SIG_KEYGEN: { - if (info->free.subType == - WC_PQC_SIG_TYPE_DILITHIUM) { - dilithium_key* dil = - (dilithium_key*)info->free.obj; + if (info->free.subType == WC_PQC_SIG_TYPE_DILITHIUM) { + dilithium_key* dil = (dilithium_key*)info->free.obj; dil->devId = INVALID_DEVID; wc_dilithium_free(dil); ret = 0; @@ -66116,6 +66155,329 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) } } #endif /* WOLF_CRYPTO_CB_FREE */ +#ifdef WOLF_CRYPTO_CB_SETKEY + else if (info->algo_type == WC_ALGO_TYPE_SETKEY) { +#ifdef DEBUG_CRYPTOCB + wc_CryptoCb_InfoString(info); +#endif + switch (info->setkey.type) { +#ifndef NO_AES + case WC_SETKEY_AES: + { + Aes* aes = (Aes*)info->setkey.obj; + /* Delegate to software: disable devId, call SetKey, restore */ + aes->devId = INVALID_DEVID; + ret = wc_AesSetKey(aes, + (const byte*)info->setkey.key, info->setkey.keySz, + (const byte*)info->setkey.aux, info->setkey.flags); + aes->devId = devIdArg; + break; + } +#endif /* !NO_AES */ +#ifndef NO_HMAC + case WC_SETKEY_HMAC: + { + Hmac* hmac = (Hmac*)info->setkey.obj; + /* Delegate to software: disable devId, call SetKey, restore */ + hmac->devId = INVALID_DEVID; + ret = wc_HmacSetKey(hmac, hmac->macType, + (const byte*)info->setkey.key, info->setkey.keySz); + hmac->devId = devIdArg; + break; + } +#endif /* !NO_HMAC */ +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_TO_DER) + case WC_SETKEY_RSA_PUB: + { + RsaKey* rsaObj = (RsaKey*)info->setkey.obj; + RsaKey* rsaTmp = (RsaKey*)info->setkey.key; + int derSz; + word32 idx = 0; + byte* der = NULL; + + /* Get required DER size for public key */ + derSz = wc_RsaPublicKeyDerSize(rsaTmp, 1); + if (derSz <= 0) { + ret = derSz; + break; + } + + der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = MEMORY_E; + break; + } + + /* Export public key from temp to DER */ + derSz = wc_RsaKeyToPublicDer_ex(rsaTmp, der, + (word32)derSz, 1); + if (derSz <= 0) { + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ret = derSz; + break; + } + + /* Import DER into obj via software */ + rsaObj->devId = INVALID_DEVID; + ret = wc_RsaPublicKeyDecode(der, &idx, rsaObj, + (word32)derSz); + rsaObj->devId = devIdArg; + + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + break; + } + case WC_SETKEY_RSA_PRIV: + { + RsaKey* rsaObj = (RsaKey*)info->setkey.obj; + RsaKey* rsaTmp = (RsaKey*)info->setkey.key; + int derSz; + word32 idx = 0; + byte* der = NULL; + + /* Get required DER size for private key */ + derSz = wc_RsaKeyToDer(rsaTmp, NULL, 0); + if (derSz <= 0) { + ret = derSz; + break; + } + + der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = MEMORY_E; + break; + } + + /* Export private key from temp to DER */ + derSz = wc_RsaKeyToDer(rsaTmp, der, (word32)derSz); + if (derSz <= 0) { + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ret = derSz; + break; + } + + /* Import DER into obj via software */ + rsaObj->devId = INVALID_DEVID; + ret = wc_RsaPrivateKeyDecode(der, &idx, rsaObj, + (word32)derSz); + rsaObj->devId = devIdArg; + + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + break; + } +#endif /* !NO_RSA && WOLFSSL_KEY_TO_DER */ +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \ + defined(HAVE_ECC_KEY_IMPORT) + case WC_SETKEY_ECC_PUB: + { + ecc_key* eccObj = (ecc_key*)info->setkey.obj; + ecc_key* eccTmp = (ecc_key*)info->setkey.key; + word32 bufSz = ECC_BUFSIZE; + int curveId; + WC_DECLARE_VAR(buf, byte, ECC_BUFSIZE, NULL); + WC_ALLOC_VAR(buf, byte, ECC_BUFSIZE, NULL); + if (!WC_VAR_OK(buf)) { + ret = MEMORY_E; + break; + } + + /* Export public key from temp to X9.63 format */ + ret = wc_ecc_export_x963(eccTmp, buf, &bufSz); + if (ret != 0) { + WC_FREE_VAR(buf, NULL); + break; + } + + curveId = wc_ecc_get_curve_id(eccTmp->idx); + + /* Import into obj via software */ + eccObj->devId = INVALID_DEVID; + ret = wc_ecc_import_x963_ex2(buf, bufSz, eccObj, + curveId, 0); + eccObj->devId = devIdArg; + + WC_FREE_VAR(buf, NULL); + break; + } + case WC_SETKEY_ECC_PRIV: + { + ecc_key* eccObj = (ecc_key*)info->setkey.obj; + ecc_key* eccTmp = (ecc_key*)info->setkey.key; + word32 pubSz = ECC_BUFSIZE; + word32 privSz = MAX_ECC_BYTES; + byte* pubPtr = NULL; + int curveId; + WC_DECLARE_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); + WC_DECLARE_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); + WC_ALLOC_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); + WC_ALLOC_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); + if (!WC_VAR_OK(pubBuf) || !WC_VAR_OK(privBuf)) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + ret = MEMORY_E; + break; + } + + /* Export public key from temp (if available) */ + if (eccTmp->type != ECC_PRIVATEKEY_ONLY) { + ret = wc_ecc_export_x963(eccTmp, pubBuf, &pubSz); + if (ret != 0) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + pubPtr = pubBuf; + } + + ret = wc_ecc_export_private_only(eccTmp, privBuf, + &privSz); + if (ret != 0) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + + curveId = wc_ecc_get_curve_id(eccTmp->idx); + + /* Import into obj via software */ + eccObj->devId = INVALID_DEVID; + ret = wc_ecc_import_private_key_ex(privBuf, privSz, + pubPtr, (pubPtr != NULL) ? pubSz : 0, + eccObj, curveId); + eccObj->devId = devIdArg; + + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } +#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && HAVE_ECC_KEY_IMPORT */ + default: + ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); + break; + } + } +#endif /* WOLF_CRYPTO_CB_SETKEY */ +#ifdef WOLF_CRYPTO_CB_EXPORT_KEY + else if (info->algo_type == WC_ALGO_TYPE_EXPORT_KEY) { +#ifdef DEBUG_CRYPTOCB + wc_CryptoCb_InfoString(info); +#endif + switch (info->export_key.type) { +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_TO_DER) + case WC_PK_TYPE_RSA: + { + RsaKey* src = (RsaKey*)info->export_key.obj; + RsaKey* dst = (RsaKey*)info->export_key.out; + int derSz; + word32 idx = 0; + byte* der = NULL; + + /* Try private key export first, fall back to public */ + derSz = wc_RsaKeyToDer(src, NULL, 0); + if (derSz > 0) { + der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = MEMORY_E; + break; + } + derSz = wc_RsaKeyToDer(src, der, (word32)derSz); + if (derSz > 0) { + ret = wc_RsaPrivateKeyDecode(der, &idx, dst, + (word32)derSz); + } + else { + ret = derSz; + } + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + /* Public key only */ + derSz = wc_RsaPublicKeyDerSize(src, 1); + if (derSz <= 0) { + ret = derSz; + break; + } + der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ret = MEMORY_E; + break; + } + derSz = wc_RsaKeyToPublicDer_ex(src, der, + (word32)derSz, 1); + if (derSz > 0) { + ret = wc_RsaPublicKeyDecode(der, &idx, dst, + (word32)derSz); + } + else { + ret = derSz; + } + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + break; + } +#endif /* !NO_RSA && WOLFSSL_KEY_TO_DER */ +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \ + defined(HAVE_ECC_KEY_IMPORT) + case WC_PK_TYPE_ECDSA_SIGN: /* ECC key */ + { + ecc_key* src = (ecc_key*)info->export_key.obj; + ecc_key* dst = (ecc_key*)info->export_key.out; + word32 pubSz = ECC_BUFSIZE; + word32 privSz = MAX_ECC_BYTES; + byte* pubPtr = NULL; + int curveId; + WC_DECLARE_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); + WC_DECLARE_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); + WC_ALLOC_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); + WC_ALLOC_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); + if (!WC_VAR_OK(pubBuf) || !WC_VAR_OK(privBuf)) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + ret = MEMORY_E; + break; + } + + /* Export public key if available */ + if (src->type != ECC_PRIVATEKEY_ONLY) { + ret = wc_ecc_export_x963(src, pubBuf, &pubSz); + if (ret != 0) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + pubPtr = pubBuf; + } + + /* Export private key if available */ + if (src->type != ECC_PUBLICKEY) { + ret = wc_ecc_export_private_only(src, privBuf, &privSz); + if (ret != 0) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + + curveId = wc_ecc_get_curve_id(src->idx); + ret = wc_ecc_import_private_key_ex(privBuf, privSz, + pubPtr, (pubPtr != NULL) ? pubSz : 0, + dst, curveId); + } + else { + /* Public key only */ + curveId = wc_ecc_get_curve_id(src->idx); + ret = wc_ecc_import_x963_ex2(pubBuf, pubSz, dst, + curveId, 0); + } + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } +#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && HAVE_ECC_KEY_IMPORT */ + default: + ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); + break; + } + } +#endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ #ifndef NO_HMAC else if (info->algo_type == WC_ALGO_TYPE_HMAC) { if (info->hmac.hmac == NULL) diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index d4f30642f54..287ad64183f 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -30,7 +30,7 @@ /* Defines the Crypto Callback interface version, for compatibility */ /* Increment this when Crypto Callback interface changes are made */ -#define CRYPTO_CB_VER 2 +#define CRYPTO_CB_VER 3 #ifdef WOLF_CRYPTO_CB @@ -134,6 +134,18 @@ typedef struct { } wc_CryptoCb_AesAuthDec; #endif +#ifdef WOLF_CRYPTO_CB_SETKEY +enum wc_SetKeyType { + WC_SETKEY_NONE = 0, + WC_SETKEY_HMAC = 1, + WC_SETKEY_RSA_PUB = 2, + WC_SETKEY_RSA_PRIV = 3, + WC_SETKEY_ECC_PUB = 4, + WC_SETKEY_ECC_PRIV = 5, + WC_SETKEY_AES = 6, +}; +#endif /* WOLF_CRYPTO_CB_SETKEY */ + /* Crypto Information Structure for callbacks */ typedef struct wc_CryptoInfo { int algo_type; /* enum wc_AlgoType */ @@ -218,6 +230,14 @@ typedef struct wc_CryptoInfo { word32 pubKeySz; } ecc_check; #endif + struct { + const ecc_key* key; + int* keySize; + } ecc_get_size; + struct { + const ecc_key* key; + int* sigSize; + } ecc_get_sig_size; #endif /* HAVE_ECC */ #ifdef HAVE_CURVE25519 struct { @@ -492,6 +512,24 @@ typedef struct wc_CryptoInfo { void *obj; /* Object structure to free */ } free; #endif /* WOLF_CRYPTO_CB_FREE */ +#ifdef WOLF_CRYPTO_CB_SETKEY + struct { /* uses wc_AlgoType=WC_ALGO_TYPE_SETKEY */ + int type; /* enum wc_SetKeyType */ + void* obj; /* Aes*, Hmac*, RsaKey*, ecc_key* */ + void* key; /* Raw key bytes or temp struct to export from */ + word32 keySz; /* Key size (0 when key is a struct ptr) */ + void* aux; /* Auxiliary data (IV, etc.) or NULL */ + word32 auxSz; /* Aux data size, 0 if unused */ + int flags; /* AES: direction (AES_ENCRYPTION/DECRYPTION) */ + } setkey; +#endif /* WOLF_CRYPTO_CB_SETKEY */ +#ifdef WOLF_CRYPTO_CB_EXPORT_KEY + struct { /* uses wc_AlgoType=WC_ALGO_TYPE_EXPORT_KEY */ + int type; /* enum wc_PkType (WC_PK_TYPE_RSA, etc.) */ + void* obj; /* Hardware key (has devCtx/id[]) */ + void* out; /* Software key to fill (same type as obj) */ + } export_key; +#endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ #if defined(HAVE_HKDF) || defined(HAVE_CMAC_KDF) struct { int type; /* enum wc_KdfType */ @@ -592,6 +630,9 @@ WOLFSSL_LOCAL int wc_CryptoCb_EccVerify(const byte* sig, word32 siglen, WOLFSSL_LOCAL int wc_CryptoCb_EccCheckPrivKey(ecc_key* key, const byte* pubKey, word32 pubKeySz); + +WOLFSSL_LOCAL int wc_CryptoCb_EccGetSize(const ecc_key* key, int* keySize); +WOLFSSL_LOCAL int wc_CryptoCb_EccGetSigSize(const ecc_key* key, int* sigSize); #endif /* HAVE_ECC */ #ifdef HAVE_CURVE25519 @@ -772,6 +813,16 @@ WOLFSSL_LOCAL int wc_CryptoCb_Copy(int devId, int algo, int type, void* src, WOLFSSL_LOCAL int wc_CryptoCb_Free(int devId, int algo, int type, int subType, void* obj); #endif /* WOLF_CRYPTO_CB_FREE */ +#ifdef WOLF_CRYPTO_CB_SETKEY +WOLFSSL_LOCAL int wc_CryptoCb_SetKey(int devId, int type, void* obj, + void* key, word32 keySz, + void* aux, word32 auxSz, + int flags); +#endif /* WOLF_CRYPTO_CB_SETKEY */ +#ifdef WOLF_CRYPTO_CB_EXPORT_KEY +WOLFSSL_LOCAL int wc_CryptoCb_ExportKey(int devId, int type, + void* obj, void* out); +#endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ #endif /* WOLF_CRYPTO_CB */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index ec1e87a00b4..107e35dad32 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1424,7 +1424,9 @@ enum wc_AlgoType { WC_ALGO_TYPE_KDF = 9, WC_ALGO_TYPE_COPY = 10, WC_ALGO_TYPE_FREE = 11, - WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_FREE + WC_ALGO_TYPE_SETKEY = 12, + WC_ALGO_TYPE_EXPORT_KEY = 13, + WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_EXPORT_KEY }; /* KDF types */ @@ -1566,6 +1568,8 @@ enum wc_PkType { 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, + WC_PK_TYPE_EC_GET_SIG_SIZE = 29, WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX }; From 8b092dee598b1ddcc2f0e2659ecb500dc7fd2fd7 Mon Sep 17 00:00:00 2001 From: night1rider Date: Sat, 14 Mar 2026 20:46:00 -0600 Subject: [PATCH 2/6] Add setkey/exportkey/eccgetsize test coverage in api.c --- tests/api.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 193 insertions(+), 11 deletions(-) diff --git a/tests/api.c b/tests/api.c index 57063e21c53..8ae436fbb18 100644 --- a/tests/api.c +++ b/tests/api.c @@ -27974,6 +27974,35 @@ static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx) ret, *info->pk.eccsign.outlen); #endif } + else if (info->pk.type == WC_PK_TYPE_EC_GET_SIZE) { + WC_DECLARE_VAR(tmpEcc, ecc_key, 1, NULL); + WC_ALLOC_VAR(tmpEcc, ecc_key, 1, NULL); + if (!WC_VAR_OK(tmpEcc)) { + ret = MEMORY_E; + } + else { + XMEMCPY(tmpEcc, info->pk.ecc_get_size.key, sizeof(ecc_key)); + tmpEcc->devId = INVALID_DEVID; + *info->pk.ecc_get_size.keySize = wc_ecc_size(tmpEcc); + WC_FREE_VAR(tmpEcc, NULL); + ret = 0; + } + } + else if (info->pk.type == WC_PK_TYPE_EC_GET_SIG_SIZE) { + WC_DECLARE_VAR(tmpEcc, ecc_key, 1, NULL); + WC_ALLOC_VAR(tmpEcc, ecc_key, 1, NULL); + if (!WC_VAR_OK(tmpEcc)) { + ret = MEMORY_E; + } + else { + XMEMCPY(tmpEcc, info->pk.ecc_get_sig_size.key, + sizeof(ecc_key)); + tmpEcc->devId = INVALID_DEVID; + *info->pk.ecc_get_sig_size.sigSize = wc_ecc_sig_size(tmpEcc); + WC_FREE_VAR(tmpEcc, NULL); + ret = 0; + } + } #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 if (info->pk.type == WC_PK_TYPE_ED25519_SIGN) { @@ -28399,39 +28428,75 @@ static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx) { ecc_key* eccObj = (ecc_key*)info->setkey.obj; ecc_key* eccTmp = (ecc_key*)info->setkey.key; - byte buf[ECC_BUFSIZE]; - word32 bufSz = sizeof(buf); + word32 bufSz = ECC_BUFSIZE; int curveId; + WC_DECLARE_VAR(buf, byte, ECC_BUFSIZE, NULL); + WC_ALLOC_VAR(buf, byte, ECC_BUFSIZE, NULL); + if (!WC_VAR_OK(buf)) { + ret = MEMORY_E; + break; + } ret = wc_ecc_export_x963(eccTmp, buf, &bufSz); - if (ret != 0) break; + if (ret != 0) { + WC_FREE_VAR(buf, NULL); + break; + } curveId = wc_ecc_get_curve_id(eccTmp->idx); eccObj->devId = INVALID_DEVID; ret = wc_ecc_import_x963_ex2(buf, bufSz, eccObj, curveId, 0); eccObj->devId = thisDevId; + + WC_FREE_VAR(buf, NULL); break; } case WC_SETKEY_ECC_PRIV: { ecc_key* eccObj = (ecc_key*)info->setkey.obj; ecc_key* eccTmp = (ecc_key*)info->setkey.key; - byte pubBuf[ECC_BUFSIZE]; - byte privBuf[MAX_ECC_BYTES]; - word32 pubSz = sizeof(pubBuf); - word32 privSz = sizeof(privBuf); + word32 pubSz = ECC_BUFSIZE; + word32 privSz = MAX_ECC_BYTES; + byte* pubPtr = NULL; int curveId; + WC_DECLARE_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); + WC_DECLARE_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); + WC_ALLOC_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); + WC_ALLOC_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); + if (!WC_VAR_OK(pubBuf) || !WC_VAR_OK(privBuf)) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + ret = MEMORY_E; + break; + } + + /* Export public key from temp (if available) */ + if (eccTmp->type != ECC_PRIVATEKEY_ONLY) { + ret = wc_ecc_export_x963(eccTmp, pubBuf, &pubSz); + if (ret != 0) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + pubPtr = pubBuf; + } - ret = wc_ecc_export_x963(eccTmp, pubBuf, &pubSz); - if (ret != 0) break; ret = wc_ecc_export_private_only(eccTmp, privBuf, &privSz); - if (ret != 0) break; + if (ret != 0) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } curveId = wc_ecc_get_curve_id(eccTmp->idx); eccObj->devId = INVALID_DEVID; ret = wc_ecc_import_private_key_ex(privBuf, privSz, - pubBuf, pubSz, eccObj, curveId); + pubPtr, (pubPtr != NULL) ? pubSz : 0, + eccObj, curveId); eccObj->devId = thisDevId; + + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); break; } #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && HAVE_ECC_KEY_IMPORT */ @@ -28441,6 +28506,123 @@ static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx) } } #endif /* WOLF_CRYPTO_CB_SETKEY */ +#ifdef WOLF_CRYPTO_CB_EXPORT_KEY + else if (info->algo_type == WC_ALGO_TYPE_EXPORT_KEY) { + #ifdef DEBUG_WOLFSSL + fprintf(stderr, "test_CryptoCb_Func: ExportKey Type=%d\n", + info->export_key.type); + #endif + switch (info->export_key.type) { + #if !defined(NO_RSA) && defined(WOLFSSL_KEY_TO_DER) + case WC_PK_TYPE_RSA: + { + RsaKey* src = (RsaKey*)info->export_key.obj; + RsaKey* dst = (RsaKey*)info->export_key.out; + int derSz; + word32 idx = 0; + byte* der = NULL; + + /* Try private key export first, fall back to public */ + derSz = wc_RsaKeyToDer(src, NULL, 0); + if (derSz > 0) { + der = (byte*)XMALLOC(derSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { ret = MEMORY_E; break; } + derSz = wc_RsaKeyToDer(src, der, (word32)derSz); + if (derSz > 0) { + ret = wc_RsaPrivateKeyDecode(der, &idx, dst, + (word32)derSz); + } + else { + ret = derSz; + } + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + /* Public key only */ + derSz = wc_RsaPublicKeyDerSize(src, 1); + if (derSz <= 0) { ret = derSz; break; } + der = (byte*)XMALLOC(derSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { ret = MEMORY_E; break; } + derSz = wc_RsaKeyToPublicDer_ex(src, der, + (word32)derSz, 1); + if (derSz > 0) { + ret = wc_RsaPublicKeyDecode(der, &idx, dst, + (word32)derSz); + } + else { + ret = derSz; + } + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + break; + } + #endif /* !NO_RSA && WOLFSSL_KEY_TO_DER */ + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \ + defined(HAVE_ECC_KEY_IMPORT) + case WC_PK_TYPE_ECDSA_SIGN: /* ECC key */ + { + ecc_key* src = (ecc_key*)info->export_key.obj; + ecc_key* dst = (ecc_key*)info->export_key.out; + word32 pubSz = ECC_BUFSIZE; + word32 privSz = MAX_ECC_BYTES; + byte* pubPtr = NULL; + int curveId; + WC_DECLARE_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); + WC_DECLARE_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); + WC_ALLOC_VAR(pubBuf, byte, ECC_BUFSIZE, NULL); + WC_ALLOC_VAR(privBuf, byte, MAX_ECC_BYTES, NULL); + if (!WC_VAR_OK(pubBuf) || !WC_VAR_OK(privBuf)) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + ret = MEMORY_E; + break; + } + + /* Export public key if available */ + if (src->type != ECC_PRIVATEKEY_ONLY) { + ret = wc_ecc_export_x963(src, pubBuf, &pubSz); + if (ret != 0) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + pubPtr = pubBuf; + } + + /* Export private key if available */ + if (src->type != ECC_PUBLICKEY) { + ret = wc_ecc_export_private_only(src, privBuf, + &privSz); + if (ret != 0) { + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + + curveId = wc_ecc_get_curve_id(src->idx); + ret = wc_ecc_import_private_key_ex(privBuf, privSz, + pubPtr, (pubPtr != NULL) ? pubSz : 0, + dst, curveId); + } + else { + /* Public key only */ + curveId = wc_ecc_get_curve_id(src->idx); + ret = wc_ecc_import_x963_ex2(pubBuf, pubSz, dst, + curveId, 0); + } + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && HAVE_ECC_KEY_IMPORT */ + default: + ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); + break; + } + } +#endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ (void)thisDevId; (void)keyFormat; From 19d1e4aea72c74a34529899f4854928e7613e8f3 Mon Sep 17 00:00:00 2001 From: night1rider Date: Sun, 15 Mar 2026 21:50:37 -0600 Subject: [PATCH 3/6] Add export hooks for ecc --- tests/api.c | 64 ++++++++++++++++++++--------------- wolfcrypt/src/ecc.c | 77 +++++++++++++++++++++++++++++++++++++++++++ wolfcrypt/test/test.c | 63 ++++++++++++++++++++--------------- 3 files changed, 151 insertions(+), 53 deletions(-) diff --git a/tests/api.c b/tests/api.c index 8ae436fbb18..8536e26734a 100644 --- a/tests/api.c +++ b/tests/api.c @@ -28580,37 +28580,47 @@ static int test_CryptoCb_Func(int thisDevId, wc_CryptoInfo* info, void* ctx) break; } - /* Export public key if available */ - if (src->type != ECC_PRIVATEKEY_ONLY) { - ret = wc_ecc_export_x963(src, pubBuf, &pubSz); - if (ret != 0) { - WC_FREE_VAR(pubBuf, NULL); - WC_FREE_VAR(privBuf, NULL); - break; + /* Use software to export from src - prevent recursion */ + { + int savedDevId = src->devId; + src->devId = INVALID_DEVID; + + /* Export public key if available */ + if (src->type != ECC_PRIVATEKEY_ONLY) { + ret = wc_ecc_export_x963(src, pubBuf, &pubSz); + if (ret != 0) { + src->devId = savedDevId; + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + pubPtr = pubBuf; } - pubPtr = pubBuf; - } - /* Export private key if available */ - if (src->type != ECC_PUBLICKEY) { - ret = wc_ecc_export_private_only(src, privBuf, - &privSz); - if (ret != 0) { - WC_FREE_VAR(pubBuf, NULL); - WC_FREE_VAR(privBuf, NULL); - break; + /* Export private key if available */ + if (src->type != ECC_PUBLICKEY) { + ret = wc_ecc_export_private_only(src, privBuf, + &privSz); + if (ret != 0) { + src->devId = savedDevId; + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + + curveId = wc_ecc_get_curve_id(src->idx); + ret = wc_ecc_import_private_key_ex(privBuf, privSz, + pubPtr, (pubPtr != NULL) ? pubSz : 0, + dst, curveId); + } + else { + /* Public key only */ + curveId = wc_ecc_get_curve_id(src->idx); + ret = wc_ecc_import_x963_ex2(pubBuf, pubSz, dst, + curveId, 0); } - curveId = wc_ecc_get_curve_id(src->idx); - ret = wc_ecc_import_private_key_ex(privBuf, privSz, - pubPtr, (pubPtr != NULL) ? pubSz : 0, - dst, curveId); - } - else { - /* Public key only */ - curveId = wc_ecc_get_curve_id(src->idx); - ret = wc_ecc_import_x963_ex2(pubBuf, pubSz, dst, - curveId, 0); + src->devId = savedDevId; } WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 79cbf475aad..553ade99f29 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -9864,6 +9864,9 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) word32 numlen; WC_DECLARE_VAR(buf, byte, ECC_BUFSIZE, 0); word32 pubxlen, pubylen; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif /* return length needed only */ if (key != NULL && out == NULL && outLen != NULL) { @@ -9879,6 +9882,41 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) if (key->type == ECC_PRIVATEKEY_ONLY) return ECC_PRIVATEONLY_E; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(ecc_key)); + + ret = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); + if (ret != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return ret; + } + + ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_ECDSA_SIGN, + (void*)key, tmpKey); + if (ret == 0) { + /* Recursive call on software tmpKey (INVALID_DEVID) */ + ret = wc_ecc_export_x963(tmpKey, out, outLen); + } + + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return ret; + } + /* CRYPTOCB_UNAVAILABLE: fall through to software export */ + ret = MP_OKAY; + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ + #if defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_IMXRT1170_CAAM) /* check if public key in secure memory */ if (key->securePubKey > 0) { @@ -11146,11 +11184,50 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, { int err = 0; word32 keySz; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif if (key == NULL) { return BAD_FUNC_ARG; } +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(ecc_key)); + + err = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); + if (err != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + + err = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_ECDSA_SIGN, + (void*)key, tmpKey); + if (err == 0) { + /* Recursive call on software tmpKey (INVALID_DEVID) */ + err = wc_ecc_export_ex(tmpKey, qx, qxLen, qy, qyLen, d, dLen, + encType); + } + + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (err != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return err; + } + /* CRYPTOCB_UNAVAILABLE: fall through to software export */ + err = 0; + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ + if (wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL) { return ECC_BAD_ARG_E; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 623b0a02e81..83e1083500f 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -66436,36 +66436,47 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) break; } - /* Export public key if available */ - if (src->type != ECC_PRIVATEKEY_ONLY) { - ret = wc_ecc_export_x963(src, pubBuf, &pubSz); - if (ret != 0) { - WC_FREE_VAR(pubBuf, NULL); - WC_FREE_VAR(privBuf, NULL); - break; + /* Use software to export from src - prevent recursion */ + { + int savedDevId = src->devId; + src->devId = INVALID_DEVID; + + /* Export public key if available */ + if (src->type != ECC_PRIVATEKEY_ONLY) { + ret = wc_ecc_export_x963(src, pubBuf, &pubSz); + if (ret != 0) { + src->devId = savedDevId; + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + pubPtr = pubBuf; } - pubPtr = pubBuf; - } - /* Export private key if available */ - if (src->type != ECC_PUBLICKEY) { - ret = wc_ecc_export_private_only(src, privBuf, &privSz); - if (ret != 0) { - WC_FREE_VAR(pubBuf, NULL); - WC_FREE_VAR(privBuf, NULL); - break; + /* Export private key if available */ + if (src->type != ECC_PUBLICKEY) { + ret = wc_ecc_export_private_only(src, privBuf, + &privSz); + if (ret != 0) { + src->devId = savedDevId; + WC_FREE_VAR(pubBuf, NULL); + WC_FREE_VAR(privBuf, NULL); + break; + } + + curveId = wc_ecc_get_curve_id(src->idx); + ret = wc_ecc_import_private_key_ex(privBuf, privSz, + pubPtr, (pubPtr != NULL) ? pubSz : 0, + dst, curveId); + } + else { + /* Public key only */ + curveId = wc_ecc_get_curve_id(src->idx); + ret = wc_ecc_import_x963_ex2(pubBuf, pubSz, dst, + curveId, 0); } - curveId = wc_ecc_get_curve_id(src->idx); - ret = wc_ecc_import_private_key_ex(privBuf, privSz, - pubPtr, (pubPtr != NULL) ? pubSz : 0, - dst, curveId); - } - else { - /* Public key only */ - curveId = wc_ecc_get_curve_id(src->idx); - ret = wc_ecc_import_x963_ex2(pubBuf, pubSz, dst, - curveId, 0); + src->devId = savedDevId; } WC_FREE_VAR(pubBuf, NULL); WC_FREE_VAR(privBuf, NULL); From 94b248a54c3e9932c7887eb931dfb0671e778a60 Mon Sep 17 00:00:00 2001 From: night1rider Date: Mon, 23 Mar 2026 15:54:26 -0600 Subject: [PATCH 4/6] Address feedback from Fenrir --- wolfcrypt/src/asn.c | 104 +++++--- wolfcrypt/src/ecc.c | 635 +++++++++++++++++++++++++------------------- wolfcrypt/src/rsa.c | 288 +++++++++++++------- 3 files changed, 611 insertions(+), 416 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 8e3ccf8728b..422c7acdc6f 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8336,6 +8336,8 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, wc_RsaEncryptSize(tmpKey), NULL, 0, 0); } + /* wc_FreeRsaKey calls mp_forcezero on all private key components, + * so no separate ForceZero of the struct is needed here. */ wc_FreeRsaKey(tmpKey); WC_FREE_VAR(tmpKey, key->heap); @@ -36537,6 +36539,59 @@ int wc_Asn1_PrintAll(Asn1* asn1, Asn1PrintOptions* opts, unsigned char* data, /* Functions that parse, but are not using ASN.1 */ #if !defined(NO_RSA) && (!defined(NO_BIG_INT) || defined(WOLFSSL_SP_MATH)) +/* Software-only import of RSA public key elements (n, e) into RsaKey. + * This internal helper avoids recursion when called from the SETKEY path. */ +static int _RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, + word32 eSz, RsaKey* key) +{ + if (n == NULL || e == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + key->type = RSA_PUBLIC; + + if (mp_init(&key->n) != MP_OKAY) { + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(&key->n, n, nSz) != 0) { + mp_clear(&key->n); + return ASN_GETINT_E; + } +#ifdef HAVE_WOLF_BIGINT + if ((int)nSz > 0 && wc_bigint_from_unsigned_bin(&key->n.raw, n, nSz) != 0) { + mp_clear(&key->n); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + + if (mp_init(&key->e) != MP_OKAY) { + mp_clear(&key->n); + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(&key->e, e, eSz) != 0) { + mp_clear(&key->n); + mp_clear(&key->e); + return ASN_GETINT_E; + } +#ifdef HAVE_WOLF_BIGINT + if ((int)eSz > 0 && wc_bigint_from_unsigned_bin(&key->e.raw, e, eSz) != 0) { + mp_clear(&key->n); + mp_clear(&key->e); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + +#ifdef WOLFSSL_XILINX_CRYPT + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif + + return 0; +} + /* import RSA public key elements (n, e) into RsaKey structure (key) */ /* this function does not use any ASN.1 parsing */ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, @@ -36548,8 +36603,9 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); #endif - if (n == NULL || e == NULL || key == NULL) + if (n == NULL || e == NULL || key == NULL) { return BAD_FUNC_ARG; + } #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) #ifndef WOLF_CRYPTO_CB_FIND @@ -36569,8 +36625,8 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, return tmpErr; } - /* Recursive call imports n, e into temp via software */ - tmpErr = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, tmpKey); + /* Import into temp via software helper (no callback recursion) */ + tmpErr = _RsaPublicKeyDecodeRaw(n, nSz, e, eSz, tmpKey); if (tmpErr == 0) { cbRet = wc_CryptoCb_SetKey(key->devId, WC_SETKEY_RSA_PUB, key, tmpKey, @@ -36590,47 +36646,7 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, } #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ - key->type = RSA_PUBLIC; - - if (mp_init(&key->n) != MP_OKAY) - return MP_INIT_E; - - if (mp_read_unsigned_bin(&key->n, n, nSz) != 0) { - mp_clear(&key->n); - return ASN_GETINT_E; - } -#ifdef HAVE_WOLF_BIGINT - if ((int)nSz > 0 && wc_bigint_from_unsigned_bin(&key->n.raw, n, nSz) != 0) { - mp_clear(&key->n); - return ASN_GETINT_E; - } -#endif /* HAVE_WOLF_BIGINT */ - - if (mp_init(&key->e) != MP_OKAY) { - mp_clear(&key->n); - return MP_INIT_E; - } - - if (mp_read_unsigned_bin(&key->e, e, eSz) != 0) { - mp_clear(&key->n); - mp_clear(&key->e); - return ASN_GETINT_E; - } -#ifdef HAVE_WOLF_BIGINT - if ((int)eSz > 0 && wc_bigint_from_unsigned_bin(&key->e.raw, e, eSz) != 0) { - mp_clear(&key->n); - mp_clear(&key->e); - return ASN_GETINT_E; - } -#endif /* HAVE_WOLF_BIGINT */ - -#ifdef WOLFSSL_XILINX_CRYPT - if (wc_InitRsaHw(key) != 0) { - return BAD_STATE_E; - } -#endif - - return 0; + return _RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key); } #endif /* !NO_RSA && (!NO_BIG_INT || WOLFSSL_SP_MATH) */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 553ade99f29..05a3674b0dd 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -9856,17 +9856,14 @@ int wc_ecc_export_point_der_compressed(const int curve_idx, ecc_point* point, } #endif /* HAVE_COMP_KEY */ -/* export public ECC key in ANSI X9.63 format */ -WOLFSSL_ABI -int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) +/* Software-only export of public ECC key in ANSI X9.63 format. + * This internal helper avoids recursion when called from the EXPORT_KEY path. */ +static int _ecc_export_x963(ecc_key* key, byte* out, word32* outLen) { int ret = MP_OKAY; word32 numlen; WC_DECLARE_VAR(buf, byte, ECC_BUFSIZE, 0); word32 pubxlen, pubylen; -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) - WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); -#endif /* return length needed only */ if (key != NULL && out == NULL && outLen != NULL) { @@ -9876,46 +9873,13 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) return WC_NO_ERR_TRACE(LENGTH_ONLY_E); } - if (key == NULL || out == NULL || outLen == NULL) + if (key == NULL || out == NULL || outLen == NULL) { return ECC_BAD_ARG_E; + } - if (key->type == ECC_PRIVATEKEY_ONLY) + if (key->type == ECC_PRIVATEKEY_ONLY) { return ECC_PRIVATEONLY_E; - -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) - #ifndef WOLF_CRYPTO_CB_FIND - if (key->devId != INVALID_DEVID) - #endif - { - WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); - if (!WC_VAR_OK(tmpKey)) { - return MEMORY_E; - } - XMEMSET(tmpKey, 0, sizeof(ecc_key)); - - ret = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); - if (ret != 0) { - WC_FREE_VAR(tmpKey, key->heap); - return ret; - } - - ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_ECDSA_SIGN, - (void*)key, tmpKey); - if (ret == 0) { - /* Recursive call on software tmpKey (INVALID_DEVID) */ - ret = wc_ecc_export_x963(tmpKey, out, outLen); - } - - wc_ecc_free(tmpKey); - WC_FREE_VAR(tmpKey, key->heap); - - if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { - return ret; - } - /* CRYPTOCB_UNAVAILABLE: fall through to software export */ - ret = MP_OKAY; - } -#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ + } #if defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_IMXRT1170_CAAM) /* check if public key in secure memory */ @@ -9982,14 +9946,75 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) } +/* export public ECC key in ANSI X9.63 format */ +WOLFSSL_ABI +int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) +{ +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + int ret; + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif + + if (key == NULL || outLen == NULL) { + return ECC_BAD_ARG_E; + } + + /* return length needed only */ + if (out == NULL) { + word32 numlen = key->dp ? (word32)key->dp->size : MAX_ECC_BYTES; + *outLen = 1 + 2 * numlen; + return WC_NO_ERR_TRACE(LENGTH_ONLY_E); + } + + if (key->type == ECC_PRIVATEKEY_ONLY) { + return ECC_PRIVATEONLY_E; + } + +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(ecc_key)); + + ret = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); + if (ret != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return ret; + } + + ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_ECDSA_SIGN, + (void*)key, tmpKey); + if (ret == 0) { + /* Call software helper (no callback recursion) */ + ret = _ecc_export_x963(tmpKey, out, outLen); + } + + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return ret; + } + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ + + return _ecc_export_x963(key, out, outLen); +} + /* export public ECC key in ANSI X9.63 format, extended with * compression option */ WOLFSSL_ABI int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, int compressed) { - if (compressed == 0) + if (compressed == 0) { return wc_ecc_export_x963(key, out, outLen); + } #ifdef HAVE_COMP_KEY else return wc_ecc_export_x963_compressed(key, out, outLen); @@ -10709,9 +10734,10 @@ int wc_ecc_check_key(ecc_key* key) #ifdef HAVE_ECC_KEY_IMPORT -/* import public ECC key in ANSI X9.63 format */ -int wc_ecc_import_x963_ex2(const byte* in, word32 inLen, ecc_key* key, - int curve_id, int untrusted) +/* Software-only import of public ECC key in ANSI X9.63 format. + * This internal helper avoids recursion when called from the SETKEY path. */ +static int _ecc_import_x963_ex2(const byte* in, word32 inLen, ecc_key* key, + int curve_id, int untrusted) { int err = MP_OKAY; #ifdef HAVE_COMP_KEY @@ -10723,71 +10749,16 @@ int wc_ecc_import_x963_ex2(const byte* in, word32 inLen, ecc_key* key, const CRYS_ECPKI_Domain_t* pDomain; CRYS_ECPKI_BUILD_TempData_t tempBuff; #endif -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) - int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); - WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); -#endif - if (in == NULL || key == NULL) + if (in == NULL || key == NULL) { return BAD_FUNC_ARG; + } /* must be odd */ if ((inLen & 1) == 0) { return ECC_BAD_ARG_E; } -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) - #ifndef WOLF_CRYPTO_CB_FIND - if (key->devId != INVALID_DEVID) - #endif - { - /* Allocate temp key for callback to export from */ - WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); - if (!WC_VAR_OK(tmpKey)) { - return MEMORY_E; - } - XMEMSET(tmpKey, 0, sizeof(ecc_key)); - - err = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); - if (err != 0) { - WC_FREE_VAR(tmpKey, key->heap); - return err; - } - - #ifdef WOLFSSL_CUSTOM_CURVES - /* Copy custom curve params so recursive import uses correct curve */ - if (key->dp != NULL) { - err = wc_ecc_set_custom_curve(tmpKey, key->dp); - if (err != 0) { - wc_ecc_free(tmpKey); - WC_FREE_VAR(tmpKey, key->heap); - return err; - } - } - #endif - - /* Recursive call imports X9.63 public key into temp via software */ - err = wc_ecc_import_x963_ex2(in, inLen, tmpKey, curve_id, untrusted); - if (err == MP_OKAY) { - cbRet = wc_CryptoCb_SetKey(key->devId, - WC_SETKEY_ECC_PUB, key, tmpKey, - wc_ecc_size(tmpKey), NULL, 0, 0); - } - - wc_ecc_free(tmpKey); - WC_FREE_VAR(tmpKey, key->heap); - - if (err != MP_OKAY) { - return err; - } - if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { - return cbRet; - } - /* CRYPTOCB_UNAVAILABLE: fall through to software import */ - err = MP_OKAY; - } -#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ - /* make sure required variables are reset */ wc_ecc_reset(key); @@ -11160,39 +11131,25 @@ int wc_ecc_import_x963_ex2(const byte* in, word32 inLen, ecc_key* key, } /* import public ECC key in ANSI X9.63 format */ -int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, - int curve_id) -{ - /* treat as untrusted: validate the point is on the curve */ - return wc_ecc_import_x963_ex2(in, inLen, key, curve_id, 1); -} - -WOLFSSL_ABI -int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) -{ - return wc_ecc_import_x963_ex(in, inLen, key, ECC_CURVE_DEF); -} -#endif /* HAVE_ECC_KEY_IMPORT */ - -#ifdef HAVE_ECC_KEY_EXPORT - -/* export ecc key to component form, d is optional if only exporting public - * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR - * return MP_OKAY on success */ -int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, - byte* qy, word32* qyLen, byte* d, word32* dLen, int encType) +int wc_ecc_import_x963_ex2(const byte* in, word32 inLen, ecc_key* key, + int curve_id, int untrusted) { +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); int err = 0; - word32 keySz; -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); #endif - if (key == NULL) { + if (in == NULL || key == NULL) { return BAD_FUNC_ARG; } -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + /* must be odd */ + if ((inLen & 1) == 0) { + return ECC_BAD_ARG_E; + } + +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) #ifndef WOLF_CRYPTO_CB_FIND if (key->devId != INVALID_DEVID) #endif @@ -11209,24 +11166,68 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, return err; } - err = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_ECDSA_SIGN, - (void*)key, tmpKey); - if (err == 0) { - /* Recursive call on software tmpKey (INVALID_DEVID) */ - err = wc_ecc_export_ex(tmpKey, qx, qxLen, qy, qyLen, d, dLen, - encType); + #ifdef WOLFSSL_CUSTOM_CURVES + if (key->dp != NULL) { + err = wc_ecc_set_custom_curve(tmpKey, key->dp); + if (err != 0) { + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + } + #endif + + /* Import into temp via software helper (no callback recursion) */ + err = _ecc_import_x963_ex2(in, inLen, tmpKey, curve_id, untrusted); + if (err == MP_OKAY) { + cbRet = wc_CryptoCb_SetKey(key->devId, + WC_SETKEY_ECC_PUB, key, tmpKey, + wc_ecc_size(tmpKey), NULL, 0, 0); } wc_ecc_free(tmpKey); WC_FREE_VAR(tmpKey, key->heap); - if (err != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + if (err != MP_OKAY) { return err; } - /* CRYPTOCB_UNAVAILABLE: fall through to software export */ - err = 0; + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return cbRet; + } + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ + + return _ecc_import_x963_ex2(in, inLen, key, curve_id, untrusted); +} + +/* import public ECC key in ANSI X9.63 format */ +int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, + int curve_id) +{ + return wc_ecc_import_x963_ex2(in, inLen, key, curve_id, 0); +} + +WOLFSSL_ABI +int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) +{ + return wc_ecc_import_x963_ex(in, inLen, key, ECC_CURVE_DEF); +} +#endif /* HAVE_ECC_KEY_IMPORT */ + +#ifdef HAVE_ECC_KEY_EXPORT + +/* Software-only export of ecc key to component form. + * This internal helper avoids recursion when called from the EXPORT_KEY path. */ +static int _ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen, + int encType) +{ + int err = 0; + word32 keySz; + + if (key == NULL) { + return BAD_FUNC_ARG; } -#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ if (wc_ecc_is_valid_idx(key->idx) == 0 || key->dp == NULL) { return ECC_BAD_ARG_E; @@ -11310,25 +11311,77 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, } -/* export ecc private key only raw, outLen is in/out size as unsigned bin - return MP_OKAY on success */ -WOLFSSL_ABI -int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) +/* export ecc key to component form, d is optional if only exporting public + * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR + * return MP_OKAY on success */ +int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen, int encType) { - if (out == NULL || outLen == NULL) { - return BAD_FUNC_ARG; - } +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + int err; + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif -#if defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_IMXRT1170_CAAM) - /* check if black key in secure memory */ - if ((key->blackKey != CAAM_BLACK_KEY_CCM && - key->blackKey != CAAM_BLACK_KEY_ECB) && key->blackKey > 0) { - return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, - WC_TYPE_BLACK_KEY); + if (key == NULL) { + return BAD_FUNC_ARG; } -#endif - return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(ecc_key)); + + err = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); + if (err != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + + err = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_ECDSA_SIGN, + (void*)key, tmpKey); + if (err == 0) { + /* Call software helper (no callback recursion) */ + err = _ecc_export_ex(tmpKey, qx, qxLen, qy, qyLen, d, dLen, + encType); + } + + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (err != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return err; + } + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ + + return _ecc_export_ex(key, qx, qxLen, qy, qyLen, d, dLen, encType); +} + +/* export ecc private key only raw, outLen is in/out size as unsigned bin + return MP_OKAY on success */ +WOLFSSL_ABI +int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) +{ + if (out == NULL || outLen == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_IMXRT1170_CAAM) + /* check if black key in secure memory */ + if ((key->blackKey != CAAM_BLACK_KEY_CCM && + key->blackKey != CAAM_BLACK_KEY_ECB) && key->blackKey > 0) { + return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, + WC_TYPE_BLACK_KEY); + } +#endif + + return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, WC_TYPE_UNSIGNED_BIN); } @@ -11358,76 +11411,20 @@ int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_KEY_IMPORT -/* import private key, public part optional if (pub) passed as NULL */ -int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, - const byte* pub, word32 pubSz, ecc_key* key, - int curve_id) +/* Software-only import of private key, public part optional. + * This internal helper avoids recursion when called from the SETKEY path. */ +static int _ecc_import_private_key_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + ecc_key* key, int curve_id) { int ret; #ifdef WOLFSSL_CRYPTOCELL const CRYS_ECPKI_Domain_t* pDomain; #endif -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) - int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); - int tmpErr = 0; - WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); -#endif - if (key == NULL || priv == NULL) + if (key == NULL || priv == NULL) { return BAD_FUNC_ARG; - -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) - #ifndef WOLF_CRYPTO_CB_FIND - if (key->devId != INVALID_DEVID) - #endif - { - /* Allocate temp key for callback to export from */ - WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); - if (!WC_VAR_OK(tmpKey)) { - return MEMORY_E; - } - XMEMSET(tmpKey, 0, sizeof(ecc_key)); - - tmpErr = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); - if (tmpErr != 0) { - WC_FREE_VAR(tmpKey, key->heap); - return tmpErr; - } - - #ifdef WOLFSSL_CUSTOM_CURVES - /* Copy custom curve params so recursive import uses correct curve */ - if (key->dp != NULL) { - tmpErr = wc_ecc_set_custom_curve(tmpKey, key->dp); - if (tmpErr != 0) { - wc_ecc_free(tmpKey); - WC_FREE_VAR(tmpKey, key->heap); - return tmpErr; - } - } - #endif - - /* Recursive call imports key material into temp via software - * (no callback recursion since tmpKey has INVALID_DEVID) */ - tmpErr = wc_ecc_import_private_key_ex(priv, privSz, pub, pubSz, - tmpKey, curve_id); - if (tmpErr == 0) { - cbRet = wc_CryptoCb_SetKey(key->devId, - WC_SETKEY_ECC_PRIV, key, tmpKey, - wc_ecc_size(tmpKey), NULL, 0, 0); - } - - wc_ecc_free(tmpKey); - WC_FREE_VAR(tmpKey, key->heap); - - if (tmpErr != 0) { - return tmpErr; - } - if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { - return cbRet; - } - /* CRYPTOCB_UNAVAILABLE: fall through to software import */ } -#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ /* public optional, NULL if only importing private */ if (pub != NULL) { @@ -11617,6 +11614,75 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, return ret; } +/* import private key, public part optional if (pub) passed as NULL */ +int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ecc_key* key, + int curve_id) +{ +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + int tmpErr = 0; + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif + + if (key == NULL || priv == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(ecc_key)); + + tmpErr = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); + if (tmpErr != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return tmpErr; + } + + #ifdef WOLFSSL_CUSTOM_CURVES + if (key->dp != NULL) { + tmpErr = wc_ecc_set_custom_curve(tmpKey, key->dp); + if (tmpErr != 0) { + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + return tmpErr; + } + } + #endif + + /* Import into temp via software helper (no callback recursion) */ + tmpErr = _ecc_import_private_key_ex(priv, privSz, pub, pubSz, + tmpKey, curve_id); + if (tmpErr == 0) { + cbRet = wc_CryptoCb_SetKey(key->devId, + WC_SETKEY_ECC_PRIV, key, tmpKey, + wc_ecc_size(tmpKey), NULL, 0, 0); + } + + /* wc_ecc_free calls mp_forcezero on private key components, + * so no separate ForceZero of the struct is needed here. */ + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (tmpErr != 0) { + return tmpErr; + } + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return cbRet; + } + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ + + return _ecc_import_private_key_ex(priv, privSz, pub, pubSz, key, curve_id); +} + /* ecc private key import, public key in ANSI X9.63 format, private raw */ WOLFSSL_ABI int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub, @@ -11736,7 +11802,9 @@ int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, #endif /* !NO_ASN */ #ifdef HAVE_ECC_KEY_IMPORT -static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, +/* Software-only import of raw ECC key material. + * This internal helper avoids recursion when called from the SETKEY path. */ +static int _ecc_import_raw_private(ecc_key* key, const char* qx, const char* qy, const char* d, int curve_id, int encType) { int err = MP_OKAY; @@ -11750,11 +11818,6 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, defined(WOLFSSL_CRYPTOCELL) word32 keySz = 0; #endif -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) - int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); - int setKeyType = WC_SETKEY_ECC_PRIV; - WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); -#endif /* if d is NULL, only import as public key using Qx,Qy */ if (key == NULL || qx == NULL || qy == NULL) { @@ -11772,63 +11835,6 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, return err; } -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) - #ifndef WOLF_CRYPTO_CB_FIND - if (key->devId != INVALID_DEVID) - #endif - { - /* Allocate temp key for callback to export from */ - WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); - if (!WC_VAR_OK(tmpKey)) { - return MEMORY_E; - } - XMEMSET(tmpKey, 0, sizeof(ecc_key)); - - err = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); - if (err != 0) { - WC_FREE_VAR(tmpKey, key->heap); - return err; - } - - #ifdef WOLFSSL_CUSTOM_CURVES - /* Copy custom curve params so recursive import uses correct curve */ - if (key->dp != NULL) { - err = wc_ecc_set_custom_curve(tmpKey, key->dp); - if (err != 0) { - wc_ecc_free(tmpKey); - WC_FREE_VAR(tmpKey, key->heap); - return err; - } - } - #endif - - /* Recursive call imports key material into temp via software */ - err = wc_ecc_import_raw_private(tmpKey, qx, qy, d, curve_id, encType); - if (err == MP_OKAY) { - /* This function handles both public and private imports: - * when d is NULL, only Qx/Qy are imported (public only) */ - if (d == NULL) { - setKeyType = WC_SETKEY_ECC_PUB; - } - cbRet = wc_CryptoCb_SetKey(key->devId, - setKeyType, key, tmpKey, - wc_ecc_size(tmpKey), NULL, 0, 0); - } - - wc_ecc_free(tmpKey); - WC_FREE_VAR(tmpKey, key->heap); - - if (err != MP_OKAY) { - return err; - } - if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { - return cbRet; - } - /* CRYPTOCB_UNAVAILABLE: fall through to software import */ - err = MP_OKAY; - } -#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ - /* init key */ #ifdef ALT_ECC_SIZE key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; @@ -12103,6 +12109,77 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, return err; } +static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, + const char* qy, const char* d, int curve_id, int encType) +{ +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + int setKeyType = WC_SETKEY_ECC_PRIV; + int err; + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif + + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + WC_ALLOC_VAR(tmpKey, ecc_key, 1, key->heap); + if (!WC_VAR_OK(tmpKey)) { + return MEMORY_E; + } + XMEMSET(tmpKey, 0, sizeof(ecc_key)); + + err = wc_ecc_init_ex(tmpKey, key->heap, INVALID_DEVID); + if (err != 0) { + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + + #ifdef WOLFSSL_CUSTOM_CURVES + if (key->dp != NULL) { + err = wc_ecc_set_custom_curve(tmpKey, key->dp); + if (err != 0) { + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + return err; + } + } + #endif + + /* Import into temp via software helper (no callback recursion) */ + err = _ecc_import_raw_private(tmpKey, qx, qy, d, curve_id, encType); + if (err == MP_OKAY) { + if (d == NULL) { + setKeyType = WC_SETKEY_ECC_PUB; + } + cbRet = wc_CryptoCb_SetKey(key->devId, + setKeyType, key, tmpKey, + wc_ecc_size(tmpKey), NULL, 0, 0); + } + + /* wc_ecc_free calls mp_forcezero on private key components, + * so no separate ForceZero of the struct is needed here. */ + wc_ecc_free(tmpKey); + WC_FREE_VAR(tmpKey, key->heap); + + if (err != MP_OKAY) { + return err; + } + if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + return cbRet; + } + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ + + return _ecc_import_raw_private(key, qx, qy, d, curve_id, encType); +} + /** Import raw ECC key key The destination ecc_key structure diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 85fe43cd229..81733137773 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -4468,12 +4468,46 @@ int wc_RsaEncryptSize(const RsaKey* key) } #ifndef WOLFSSL_RSA_VERIFY_ONLY +/* Software-only export of RSA public key elements from RsaKey. + * This internal helper avoids recursion when called from the EXPORT_KEY path. */ +static int _RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, + byte* n, word32* nSz) +{ + int sz, ret; + + if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) { + return BAD_FUNC_ARG; + } + + sz = mp_unsigned_bin_size(&key->e); + if ((word32)sz > *eSz) { + return RSA_BUFFER_E; + } + ret = mp_to_unsigned_bin(&key->e, e); + if (ret != MP_OKAY) { + return ret; + } + *eSz = (word32)sz; + + sz = wc_RsaEncryptSize(key); + if ((word32)sz > *nSz) { + return RSA_BUFFER_E; + } + ret = mp_to_unsigned_bin(&key->n, n); + if (ret != MP_OKAY) { + return ret; + } + *nSz = (word32)sz; + + return 0; +} + /* flatten RsaKey structure into individual elements (e, n) */ int wc_RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, byte* n, word32* nSz) { - int sz, ret; #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + int ret; WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); #endif @@ -4501,35 +4535,23 @@ int wc_RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, byte* n, ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_RSA, (void*)key, tmpKey); if (ret == 0) { - /* Recursive call on software tmpKey (INVALID_DEVID) */ - ret = wc_RsaFlattenPublicKey(tmpKey, e, eSz, n, nSz); + /* Call software helper (no callback recursion) */ + ret = _RsaFlattenPublicKey(tmpKey, e, eSz, n, nSz); } - ForceZero(tmpKey, sizeof(RsaKey)); + /* wc_FreeRsaKey calls mp_forcezero on all private key components, + * so no separate ForceZero of the struct is needed here. Calling + * ForceZero before wc_FreeRsaKey would zero the mp_int metadata + * and cause a crash. */ wc_FreeRsaKey(tmpKey); WC_FREE_VAR(tmpKey, key->heap); - if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { return ret; + } /* fall through to software */ } #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ - sz = mp_unsigned_bin_size(&key->e); - if ((word32)sz > *eSz) - return RSA_BUFFER_E; - ret = mp_to_unsigned_bin(&key->e, e); - if (ret != MP_OKAY) - return ret; - *eSz = (word32)sz; - - sz = wc_RsaEncryptSize(key); - if ((word32)sz > *nSz) - return RSA_BUFFER_E; - ret = mp_to_unsigned_bin(&key->n, n); - if (ret != MP_OKAY) - return ret; - *nSz = (word32)sz; - - return 0; + return _RsaFlattenPublicKey(key, e, eSz, n, nSz); } #endif @@ -4555,6 +4577,53 @@ static int RsaGetValue(const mp_int* in, byte* out, word32* outSz) } +/* Software-only export of RSA key elements from RsaKey. + * This internal helper avoids recursion when called from the EXPORT_KEY path. */ +static int _RsaExportKey(const RsaKey* key, + byte* e, word32* eSz, byte* n, word32* nSz, + byte* d, word32* dSz, byte* p, word32* pSz, + byte* q, word32* qSz) +{ + int ret = 0; + + if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL + || d == NULL || dSz == NULL || p == NULL || pSz == NULL + || q == NULL || qSz == NULL) { + return BAD_FUNC_ARG; + } + + if (ret == 0) { + ret = RsaGetValue(&key->e, e, eSz); + } + if (ret == 0) { + ret = RsaGetValue(&key->n, n, nSz); + } +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + if (ret == 0) { + ret = RsaGetValue(&key->d, d, dSz); + } + if (ret == 0) { + ret = RsaGetValue(&key->p, p, pSz); + } + if (ret == 0) { + ret = RsaGetValue(&key->q, q, qSz); + } +#else + /* no private parts to key */ + if (d == NULL || p == NULL || q == NULL || dSz == NULL || pSz == NULL + || qSz == NULL) { + ret = BAD_FUNC_ARG; + } + else { + *dSz = 0; + *pSz = 0; + *qSz = 0; + } +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + return ret; +} + int wc_RsaExportKey(const RsaKey* key, byte* e, word32* eSz, byte* n, word32* nSz, byte* d, word32* dSz, byte* p, word32* pSz, @@ -4565,8 +4634,9 @@ int wc_RsaExportKey(const RsaKey* key, WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); #endif - if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz) + if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz) { ret = 0; + } #if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) if (ret == 0) { @@ -4589,43 +4659,25 @@ int wc_RsaExportKey(const RsaKey* key, ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_RSA, (void*)key, tmpKey); if (ret == 0) { - /* Recursive call on software tmpKey (INVALID_DEVID) */ - ret = wc_RsaExportKey(tmpKey, e, eSz, n, nSz, - d, dSz, p, pSz, q, qSz); + /* Call software helper (no callback recursion) */ + ret = _RsaExportKey(tmpKey, e, eSz, n, nSz, + d, dSz, p, pSz, q, qSz); } - ForceZero(tmpKey, sizeof(RsaKey)); + /* wc_FreeRsaKey calls mp_forcezero on all private key components, + * so no separate ForceZero of the struct is needed here. */ wc_FreeRsaKey(tmpKey); WC_FREE_VAR(tmpKey, key->heap); - if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { return ret; + } ret = 0; /* fall through to software */ } } #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ - if (ret == 0) - ret = RsaGetValue(&key->e, e, eSz); - if (ret == 0) - ret = RsaGetValue(&key->n, n, nSz); -#ifndef WOLFSSL_RSA_PUBLIC_ONLY - if (ret == 0) - ret = RsaGetValue(&key->d, d, dSz); - if (ret == 0) - ret = RsaGetValue(&key->p, p, pSz); - if (ret == 0) - ret = RsaGetValue(&key->q, q, qSz); -#else - /* no private parts to key */ - if (d == NULL || p == NULL || q == NULL || dSz == NULL || pSz == NULL - || qSz == NULL) { - ret = BAD_FUNC_ARG; - } - else { - *dSz = 0; - *pSz = 0; - *qSz = 0; + if (ret == 0) { + ret = _RsaExportKey(key, e, eSz, n, nSz, d, dSz, p, pSz, q, qSz); } -#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ return ret; } @@ -5475,6 +5527,93 @@ static int CalcDX(mp_int* y, mp_int* x, mp_int* d) } #endif +/* Software-only import of RSA private key elements into RsaKey. + * This internal helper avoids recursion when called from the SETKEY path. */ +static int _RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, + const byte* e, word32 eSz, const byte* d, word32 dSz, + const byte* u, word32 uSz, const byte* p, word32 pSz, + const byte* q, word32 qSz, const byte* dP, word32 dPSz, + const byte* dQ, word32 dQSz, RsaKey* key) +{ + int err = MP_OKAY; + + if (n == NULL || nSz == 0 || e == NULL || eSz == 0 + || d == NULL || dSz == 0 || p == NULL || pSz == 0 + || q == NULL || qSz == 0 || key == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + if ((u == NULL || uSz == 0) + || (dP != NULL && dPSz == 0) + || (dQ != NULL && dQSz == 0)) { + return BAD_FUNC_ARG; + } +#else + (void)u; + (void)uSz; + (void)dP; + (void)dPSz; + (void)dQ; + (void)dQSz; +#endif + + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(&key->n, n, nSz); + } + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(&key->e, e, eSz); + } + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(&key->d, d, dSz); + } + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(&key->p, p, pSz); + } + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(&key->q, q, qSz); + } +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(&key->u, u, uSz); + } + if (err == MP_OKAY) { + if (dP != NULL) { + err = mp_read_unsigned_bin(&key->dP, dP, dPSz); + } + else { + err = CalcDX(&key->dP, &key->p, &key->d); + } + } + if (err == MP_OKAY) { + if (dQ != NULL) { + err = mp_read_unsigned_bin(&key->dQ, dQ, dQSz); + } + else { + err = CalcDX(&key->dQ, &key->q, &key->d); + } + } +#endif + + if (err == MP_OKAY) { + key->type = RSA_PRIVATE; + } + else { + mp_clear(&key->n); + mp_clear(&key->e); + mp_forcezero(&key->d); + mp_forcezero(&key->p); + mp_forcezero(&key->q); +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + mp_forcezero(&key->u); + mp_forcezero(&key->dP); + mp_forcezero(&key->dQ); +#endif + } + + return err; +} + int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, word32 eSz, const byte* d, word32 dSz, const byte* u, word32 uSz, const byte* p, word32 pSz, @@ -5531,8 +5670,8 @@ int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, return err; } - /* Recursive call imports key material into temp via software */ - err = wc_RsaPrivateKeyDecodeRaw(n, nSz, e, eSz, d, dSz, + /* Import into temp via software helper (no callback recursion) */ + err = _RsaPrivateKeyDecodeRaw(n, nSz, e, eSz, d, dSz, u, uSz, p, pSz, q, qSz, dP, dPSz, dQ, dQSz, tmpKey); if (err == MP_OKAY) { cbRet = wc_CryptoCb_SetKey(key->devId, @@ -5540,7 +5679,8 @@ int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, wc_RsaEncryptSize(tmpKey), NULL, 0, 0); } - /* wc_FreeRsaKey does mp_forcezero on private components */ + /* wc_FreeRsaKey calls mp_forcezero on all private key components, + * so no separate ForceZero of the struct is needed here. */ wc_FreeRsaKey(tmpKey); WC_FREE_VAR(tmpKey, key->heap); @@ -5555,47 +5695,9 @@ int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, } #endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_SETKEY */ - if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->n, n, nSz); - if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->e, e, eSz); - if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->d, d, dSz); - if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->p, p, pSz); - if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->q, q, qSz); -#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) - if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->u, u, uSz); - if (err == MP_OKAY) { - if (dP != NULL) - err = mp_read_unsigned_bin(&key->dP, dP, dPSz); - else - err = CalcDX(&key->dP, &key->p, &key->d); - } - if (err == MP_OKAY) { - if (dQ != NULL) - err = mp_read_unsigned_bin(&key->dQ, dQ, dQSz); - else - err = CalcDX(&key->dQ, &key->q, &key->d); - } -#endif - if (err == MP_OKAY) { - key->type = RSA_PRIVATE; - } - else if (key != NULL) { - mp_clear(&key->n); - mp_clear(&key->e); - mp_forcezero(&key->d); - mp_forcezero(&key->p); - mp_forcezero(&key->q); -#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) - mp_forcezero(&key->u); - mp_forcezero(&key->dP); - mp_forcezero(&key->dQ); -#endif + err = _RsaPrivateKeyDecodeRaw(n, nSz, e, eSz, d, dSz, + u, uSz, p, pSz, q, qSz, dP, dPSz, dQ, dQSz, key); } return err; From d2ce54120b80e81bc3c83df1d2ca46fd5959eaa2 Mon Sep 17 00:00:00 2001 From: night1rider Date: Wed, 25 Mar 2026 11:25:36 -0600 Subject: [PATCH 5/6] Address pr review: add braces, move scope of variables, add X9.63 comment --- wolfcrypt/src/ecc.c | 37 ++++++++++++++++++++----------------- wolfcrypt/src/rsa.c | 13 +++++-------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 05a3674b0dd..f8d1726df54 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -9869,6 +9869,7 @@ static int _ecc_export_x963(ecc_key* key, byte* out, word32* outLen) if (key != NULL && out == NULL && outLen != NULL) { /* if key hasn't been setup assume max bytes for size estimation */ numlen = key->dp ? (word32)key->dp->size : MAX_ECC_BYTES; + /* X9.63 uncompressed point: 0x04 header + x coord + y coord */ *outLen = 1 + 2 * numlen; return WC_NO_ERR_TRACE(LENGTH_ONLY_E); } @@ -9962,6 +9963,7 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) /* return length needed only */ if (out == NULL) { word32 numlen = key->dp ? (word32)key->dp->size : MAX_ECC_BYTES; + /* X9.63 uncompressed point: 0x04 header + x coord + y coord */ *outLen = 1 + 2 * numlen; return WC_NO_ERR_TRACE(LENGTH_ONLY_E); } @@ -12264,28 +12266,28 @@ static int ecc_public_key_size(ecc_key* key, word32* sz) WOLFSSL_ABI int wc_ecc_size(ecc_key* key) { -#ifdef WOLF_CRYPTO_CB - int ret; - int keySz; -#endif - - if (key == NULL) + if (key == NULL) { return 0; + } #ifdef WOLF_CRYPTO_CB if (key->devId != INVALID_DEVID) { - keySz = 0; + int ret; + int keySz = 0; + ret = wc_CryptoCb_EccGetSize(key, &keySz); if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { - if (ret != 0) + if (ret != 0) { return 0; + } return keySz; } } #endif - if (key->dp == NULL) + if (key->dp == NULL) { return 0; + } return key->dp->size; } @@ -12314,28 +12316,29 @@ int wc_ecc_sig_size(const ecc_key* key) { int maxSigSz; int orderBits, keySz; -#ifdef WOLF_CRYPTO_CB - int ret; - int cbKeySz; -#endif - if (key == NULL) + if (key == NULL) { return 0; + } #ifdef WOLF_CRYPTO_CB if (key->devId != INVALID_DEVID) { - cbKeySz = 0; + int ret; + int cbKeySz = 0; + ret = wc_CryptoCb_EccGetSigSize(key, &cbKeySz); if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { - if (ret != 0 || cbKeySz == 0) + if (ret != 0 || cbKeySz == 0) { return 0; + } return cbKeySz; } } #endif - if (key->dp == NULL) + if (key->dp == NULL) { return 0; + } /* the signature r and s will always be less than order */ /* if the order MSB (top bit of byte) is set then ASN encoding needs diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 81733137773..4c56fa458d9 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -4506,11 +4506,6 @@ static int _RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, int wc_RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, byte* n, word32* nSz) { -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) - int ret; - WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); -#endif - if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) { return BAD_FUNC_ARG; } @@ -4520,6 +4515,9 @@ int wc_RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, byte* n, if (key->devId != INVALID_DEVID) #endif { + int ret; + WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); + WC_ALLOC_VAR(tmpKey, RsaKey, 1, key->heap); if (!WC_VAR_OK(tmpKey)) { return MEMORY_E; @@ -4630,9 +4628,6 @@ int wc_RsaExportKey(const RsaKey* key, byte* q, word32* qSz) { int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); -#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) - WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); -#endif if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz) { ret = 0; @@ -4644,6 +4639,8 @@ int wc_RsaExportKey(const RsaKey* key, if (key->devId != INVALID_DEVID) #endif { + WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); + WC_ALLOC_VAR(tmpKey, RsaKey, 1, key->heap); if (!WC_VAR_OK(tmpKey)) { return MEMORY_E; From 8b6972ec34797cdb2aa629113a259289507a592a Mon Sep 17 00:00:00 2001 From: night1rider Date: Thu, 9 Apr 2026 12:22:11 -0600 Subject: [PATCH 6/6] narrow ecc_size/sig_size guards to SETKEY||EXPORT_KEY, update _WC_PK_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. --- .github/workflows/os-check.yml | 1 + wolfcrypt/src/asn.c | 2 +- wolfcrypt/src/cryptocb.c | 6 ++++-- wolfcrypt/src/ecc.c | 12 +++++++----- wolfcrypt/src/rsa.c | 4 ++-- wolfssl/wolfcrypt/cryptocb.h | 4 ++-- wolfssl/wolfcrypt/types.h | 2 ++ 7 files changed, 19 insertions(+), 12 deletions(-) diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index c46a0b8c659..8e45e0b2819 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -68,6 +68,7 @@ jobs: '--enable-cryptocb --enable-keygen --enable-cryptocbutils=export', '--enable-cryptocb --enable-keygen CPPFLAGS="-DWOLF_CRYPTO_CB_EXPORT_KEY"', '--enable-cryptocb --enable-keygen --enable-aesgcm --enable-cryptocbutils=setkey,free,export CPPFLAGS="-DWOLF_CRYPTO_CB_AES_SETKEY"', + '--enable-cryptocb --enable-keygen --enable-cryptocbutils=setkey,export CPPFLAGS="-DWOLF_CRYPTO_CB_FIND"', 'CPPFLAGS=-DWOLFSSL_NO_CLIENT_AUTH', 'CPPFLAGS=''-DNO_WOLFSSL_CLIENT -DWOLFSSL_NO_CLIENT_AUTH''', 'CPPFLAGS=''-DNO_WOLFSSL_SERVER -DWOLFSSL_NO_CLIENT_AUTH''', diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 422c7acdc6f..6b75a740c37 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8304,7 +8304,7 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, WC_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); #endif - if (key == NULL) { + if (key == NULL || input == NULL || inOutIdx == NULL) { return BAD_FUNC_ARG; } diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index d6a3c4252a2..47ea9d6e1c9 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -118,14 +118,16 @@ static const char* GetAlgoTypeStr(int algo) static const char* GetSetKeyTypeStr(int type) { switch (type) { + case WC_SETKEY_NONE: return "None"; case WC_SETKEY_HMAC: return "HMAC"; case WC_SETKEY_RSA_PUB: return "RSA-Pub"; case WC_SETKEY_RSA_PRIV: return "RSA-Priv"; case WC_SETKEY_ECC_PUB: return "ECC-Pub"; case WC_SETKEY_ECC_PRIV: return "ECC-Priv"; case WC_SETKEY_AES: return "AES"; + default: break; } - return "Unknown"; + return NULL; } #endif /* WOLF_CRYPTO_CB_SETKEY */ static const char* GetPkTypeStr(int pk) @@ -2301,7 +2303,7 @@ int wc_CryptoCb_SetKey(int devId, int type, void* obj, * uses normal software export functions on 'out' and frees it. * Returns: 0 on success, CRYPTOCB_UNAVAILABLE if not handled, negative on error */ -int wc_CryptoCb_ExportKey(int devId, int type, void* obj, void* out) +int wc_CryptoCb_ExportKey(int devId, int type, const void* obj, void* out) { int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index f8d1726df54..d1db9d935d5 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -9990,7 +9990,7 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) } ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_ECDSA_SIGN, - (void*)key, tmpKey); + key, tmpKey); if (ret == 0) { /* Call software helper (no callback recursion) */ ret = _ecc_export_x963(tmpKey, out, outLen); @@ -11346,7 +11346,7 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, } err = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_ECDSA_SIGN, - (void*)key, tmpKey); + key, tmpKey); if (err == 0) { /* Call software helper (no callback recursion) */ err = _ecc_export_ex(tmpKey, qx, qxLen, qy, qyLen, d, dLen, @@ -11432,7 +11432,7 @@ static int _ecc_import_private_key_ex(const byte* priv, word32 privSz, if (pub != NULL) { #ifndef NO_ASN word32 idx = 0; - ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id); + ret = _ecc_import_x963_ex2(pub, pubSz, key, curve_id, 0); if (ret < 0) ret = wc_EccPublicKeyDecode(pub, &idx, key, pubSz); key->type = ECC_PRIVATEKEY; @@ -12270,7 +12270,8 @@ int wc_ecc_size(ecc_key* key) return 0; } -#ifdef WOLF_CRYPTO_CB +#if defined(WOLF_CRYPTO_CB) && \ + (defined(WOLF_CRYPTO_CB_SETKEY) || defined(WOLF_CRYPTO_CB_EXPORT_KEY)) if (key->devId != INVALID_DEVID) { int ret; int keySz = 0; @@ -12321,7 +12322,8 @@ int wc_ecc_sig_size(const ecc_key* key) return 0; } -#ifdef WOLF_CRYPTO_CB +#if defined(WOLF_CRYPTO_CB) && \ + (defined(WOLF_CRYPTO_CB_SETKEY) || defined(WOLF_CRYPTO_CB_EXPORT_KEY)) if (key->devId != INVALID_DEVID) { int ret; int cbKeySz = 0; diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 4c56fa458d9..9cb70535d69 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -4531,7 +4531,7 @@ int wc_RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, byte* n, } ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_RSA, - (void*)key, tmpKey); + key, tmpKey); if (ret == 0) { /* Call software helper (no callback recursion) */ ret = _RsaFlattenPublicKey(tmpKey, e, eSz, n, nSz); @@ -4654,7 +4654,7 @@ int wc_RsaExportKey(const RsaKey* key, } ret = wc_CryptoCb_ExportKey(key->devId, WC_PK_TYPE_RSA, - (void*)key, tmpKey); + key, tmpKey); if (ret == 0) { /* Call software helper (no callback recursion) */ ret = _RsaExportKey(tmpKey, e, eSz, n, nSz, diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 287ad64183f..b8aee0837cb 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -526,7 +526,7 @@ typedef struct wc_CryptoInfo { #ifdef WOLF_CRYPTO_CB_EXPORT_KEY struct { /* uses wc_AlgoType=WC_ALGO_TYPE_EXPORT_KEY */ int type; /* enum wc_PkType (WC_PK_TYPE_RSA, etc.) */ - void* obj; /* Hardware key (has devCtx/id[]) */ + const void* obj; /* Hardware key (has devCtx/id[]) */ void* out; /* Software key to fill (same type as obj) */ } export_key; #endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ @@ -821,7 +821,7 @@ WOLFSSL_LOCAL int wc_CryptoCb_SetKey(int devId, int type, void* obj, #endif /* WOLF_CRYPTO_CB_SETKEY */ #ifdef WOLF_CRYPTO_CB_EXPORT_KEY WOLFSSL_LOCAL int wc_CryptoCb_ExportKey(int devId, int type, - void* obj, void* out); + const void* obj, void* out); #endif /* WOLF_CRYPTO_CB_EXPORT_KEY */ #endif /* WOLF_CRYPTO_CB */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 107e35dad32..7b54e6011df 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1570,6 +1570,8 @@ enum wc_PkType { WC_PK_TYPE_RSA_OAEP = 27, 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 };