diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index b65270e567..8e45e0b281 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -61,6 +61,14 @@ 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"', + '--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/configure.ac b/configure.ac index e1e142174f..7613f865e7 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 0d40dbb636..8536e26734 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) { @@ -28306,6 +28335,304 @@ 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; + 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) { + 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; + 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); + eccObj->devId = INVALID_DEVID; + ret = wc_ecc_import_private_key_ex(privBuf, privSz, + 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 */ + 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_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; + } + + /* 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; + } + + /* 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); + } + + src->devId = savedDevId; + } + 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; diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 41b01031c4..d80e90d0c5 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 b095b5c204..6b75a740c3 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8297,9 +8297,61 @@ static int _RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { - if (key == NULL) { +#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 || input == NULL || inOutIdx == 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 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 (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); } @@ -36487,18 +36539,20 @@ 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)) -/* 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, - word32 eSz, RsaKey* key) +/* 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) + if (n == NULL || e == NULL || key == NULL) { return BAD_FUNC_ARG; + } key->type = RSA_PUBLIC; - if (mp_init(&key->n) != MP_OKAY) + 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); @@ -36537,6 +36591,63 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, 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, + 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; + } + + /* 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, + 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 */ + + return _RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key); +} #endif /* !NO_RSA && (!NO_BIG_INT || WOLFSSL_SP_MATH) */ #if defined(WOLFSSL_ACERT) && defined(WOLFSSL_ASN_TEMPLATE) diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index 069dd4e0c6..47ea9d6e1c 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -105,9 +105,31 @@ 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_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 NULL; +} +#endif /* WOLF_CRYPTO_CB_SETKEY */ static const char* GetPkTypeStr(int pk) { switch (pk) { @@ -121,6 +143,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 +315,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 +818,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 +2252,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, const 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 4752fa2630..d1db9d935d 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -9856,9 +9856,9 @@ 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; @@ -9869,15 +9869,18 @@ int wc_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); } - 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(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_IMXRT1170_CAAM) /* check if public key in secure memory */ @@ -9944,14 +9947,76 @@ 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; + /* X9.63 uncompressed point: 0x04 header + x coord + y coord */ + *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, + 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); @@ -10671,9 +10736,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 @@ -10685,8 +10751,10 @@ 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 (in == NULL || key == NULL) + + if (in == NULL || key == NULL) { return BAD_FUNC_ARG; + } /* must be odd */ if ((inLen & 1) == 0) { @@ -11064,12 +11132,81 @@ int wc_ecc_import_x963_ex2(const byte* in, word32 inLen, ecc_key* key, return err; } +/* 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) +{ +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SETKEY) + int cbRet = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + int err = 0; + WC_DECLARE_VAR(tmpKey, ecc_key, 1, NULL); +#endif + + 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 + { + 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_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; + } + } +#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) { - /* treat as untrusted: validate the point is on the curve */ - return wc_ecc_import_x963_ex2(in, inLen, key, curve_id, 1); + return wc_ecc_import_x963_ex2(in, inLen, key, curve_id, 0); } WOLFSSL_ABI @@ -11081,11 +11218,11 @@ int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) #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) +/* 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; @@ -11176,6 +11313,58 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, } +/* 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 defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_EXPORT_KEY) + int err; + 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, + 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 @@ -11224,23 +11413,26 @@ 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 (key == NULL || priv == NULL) + + if (key == NULL || priv == NULL) { return BAD_FUNC_ARG; + } /* public optional, NULL if only importing private */ 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; @@ -11424,6 +11616,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, @@ -11543,7 +11804,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; @@ -11553,7 +11816,6 @@ 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; @@ -11849,6 +12111,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 @@ -11933,8 +12266,29 @@ 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) + if (key == NULL) { + return 0; + } + +#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; + + 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; } @@ -11964,8 +12318,29 @@ int wc_ecc_sig_size(const ecc_key* key) int maxSigSz; int orderBits, keySz; - if (key == NULL || key->dp == NULL) + if (key == NULL) { return 0; + } + +#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; + + 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 */ /* if the order MSB (top bit of byte) is set then ASN encoding needs diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 4b3cfd1589..edc16f1a5f 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 4fb4393f0b..9cb70535d6 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 @@ -4452,9 +4468,10 @@ int wc_RsaEncryptSize(const RsaKey* key) } #ifndef WOLFSSL_RSA_VERIFY_ONLY -/* flatten RsaKey structure into individual elements (e, n) */ -int wc_RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, byte* n, - word32* nSz) +/* 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; @@ -4463,23 +4480,77 @@ int wc_RsaFlattenPublicKey(const RsaKey* key, byte* e, word32* eSz, byte* n, } sz = mp_unsigned_bin_size(&key->e); - if ((word32)sz > *eSz) + if ((word32)sz > *eSz) { return RSA_BUFFER_E; + } ret = mp_to_unsigned_bin(&key->e, e); - if (ret != MP_OKAY) + if (ret != MP_OKAY) { return ret; + } *eSz = (word32)sz; sz = wc_RsaEncryptSize(key); - if ((word32)sz > *nSz) + if ((word32)sz > *nSz) { return RSA_BUFFER_E; + } ret = mp_to_unsigned_bin(&key->n, n); - if (ret != MP_OKAY) + 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) +{ + 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 + { + 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; + } + 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, + key, tmpKey); + if (ret == 0) { + /* Call software helper (no callback recursion) */ + ret = _RsaFlattenPublicKey(tmpKey, e, eSz, n, nSz); + } + /* 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)) { + return ret; + } + /* fall through to software */ + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ + + return _RsaFlattenPublicKey(key, e, eSz, n, nSz); +} #endif #ifndef WOLFSSL_RSA_VERIFY_ONLY @@ -4504,27 +4575,37 @@ static int RsaGetValue(const mp_int* in, byte* out, word32* outSz) } -int wc_RsaExportKey(const RsaKey* key, - byte* e, word32* eSz, byte* n, word32* nSz, - byte* d, word32* dSz, byte* p, word32* pSz, - byte* q, word32* qSz) +/* 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 = WC_NO_ERR_TRACE(BAD_FUNC_ARG); + int ret = 0; - if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz) - 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) + if (ret == 0) { ret = RsaGetValue(&key->e, e, eSz); - if (ret == 0) + } + if (ret == 0) { ret = RsaGetValue(&key->n, n, nSz); + } #ifndef WOLFSSL_RSA_PUBLIC_ONLY - if (ret == 0) + if (ret == 0) { ret = RsaGetValue(&key->d, d, dSz); - if (ret == 0) + } + if (ret == 0) { ret = RsaGetValue(&key->p, p, pSz); - if (ret == 0) + } + 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 @@ -4540,6 +4621,63 @@ int wc_RsaExportKey(const RsaKey* key, return ret; } + +int wc_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 = WC_NO_ERR_TRACE(BAD_FUNC_ARG); + + 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_DECLARE_VAR(tmpKey, RsaKey, 1, NULL); + + 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, + key, tmpKey); + if (ret == 0) { + /* Call software helper (no callback recursion) */ + ret = _RsaExportKey(tmpKey, e, eSz, n, nSz, + d, dSz, p, pSz, q, qSz); + } + /* 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)) { + return ret; + } + ret = 0; /* fall through to software */ + } + } +#endif /* WOLF_CRYPTO_CB && WOLF_CRYPTO_CB_EXPORT_KEY */ + + if (ret == 0) { + ret = _RsaExportKey(key, e, eSz, n, nSz, d, dSz, p, pSz, q, qSz); + } + + return ret; +} #endif @@ -5386,7 +5524,9 @@ static int CalcDX(mp_int* y, mp_int* x, mp_int* d) } #endif -int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, +/* 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, @@ -5397,16 +5537,14 @@ int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, if (n == NULL || nSz == 0 || e == NULL || eSz == 0 || d == NULL || dSz == 0 || p == NULL || pSz == 0 || q == NULL || qSz == 0 || key == NULL) { - err = BAD_FUNC_ARG; + return BAD_FUNC_ARG; } #if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) - if (err == MP_OKAY) { - if ((u == NULL || uSz == 0) - || (dP != NULL && dPSz == 0) - || (dQ != NULL && dQSz == 0)) { - err = BAD_FUNC_ARG; - } + if ((u == NULL || uSz == 0) + || (dP != NULL && dPSz == 0) + || (dQ != NULL && dQSz == 0)) { + return BAD_FUNC_ARG; } #else (void)u; @@ -5417,37 +5555,47 @@ int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, (void)dQSz; #endif - if (err == MP_OKAY) + if (err == MP_OKAY) { err = mp_read_unsigned_bin(&key->n, n, nSz); - if (err == MP_OKAY) + } + if (err == MP_OKAY) { err = mp_read_unsigned_bin(&key->e, e, eSz); - if (err == MP_OKAY) + } + if (err == MP_OKAY) { err = mp_read_unsigned_bin(&key->d, d, dSz); - if (err == MP_OKAY) + } + if (err == MP_OKAY) { err = mp_read_unsigned_bin(&key->p, p, pSz); - if (err == MP_OKAY) + } + 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) + if (err == MP_OKAY) { err = mp_read_unsigned_bin(&key->u, u, uSz); + } if (err == MP_OKAY) { - if (dP != NULL) + if (dP != NULL) { err = mp_read_unsigned_bin(&key->dP, dP, dPSz); - else + } + else { err = CalcDX(&key->dP, &key->p, &key->d); + } } if (err == MP_OKAY) { - if (dQ != NULL) + if (dQ != NULL) { err = mp_read_unsigned_bin(&key->dQ, dQ, dQSz); - else + } + else { err = CalcDX(&key->dQ, &key->q, &key->d); + } } #endif if (err == MP_OKAY) { key->type = RSA_PRIVATE; } - else if (key != NULL) { + else { mp_clear(&key->n); mp_clear(&key->e); mp_forcezero(&key->d); @@ -5462,6 +5610,95 @@ int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, 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, + const byte* q, word32 qSz, const byte* dP, word32 dPSz, + 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 + || q == NULL || qSz == 0 || key == NULL) { + err = BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + if (err == MP_OKAY) { + if ((u == NULL || uSz == 0) + || (dP != NULL && dPSz == 0) + || (dQ != NULL && dQSz == 0)) { + err = BAD_FUNC_ARG; + } + } +#else + (void)u; + (void)uSz; + (void)dP; + (void)dPSz; + (void)dQ; + (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; + } + + /* 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, + WC_SETKEY_RSA_PRIV, key, tmpKey, + 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); + + 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 = _RsaPrivateKeyDecodeRaw(n, nSz, e, eSz, d, dSz, + u, uSz, p, pSz, q, qSz, dP, dPSz, dQ, dQSz, key); + } + + return err; +} #endif /* WOLFSSL_RSA_PUBLIC_ONLY */ #endif /* NO_RSA */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 5499ec8947..83e1083500 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,340 @@ 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; + } + + /* 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; + } + + /* 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); + } + + src->devId = savedDevId; + } + 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 d4f30642f5..b8aee0837c 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.) */ + 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 */ #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, + 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 ec1e87a00b..7b54e6011d 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,10 @@ 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, + #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 };