1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

Add wc_ecc_key_new_ex (#11160)

* Add wc_ecc_key_new_ex

Rust wrapper: use wc_ecc_key_new_ex for ECC when available.

Fixes F-8300.

* Check devId after wc_ecc_key_new_ex() call in unit test
This commit is contained in:
Josh Holtrop
2026-08-20 16:05:51 -04:00
committed by GitHub
parent 79aca0b3f7
commit 25224b6827
7 changed files with 104 additions and 48 deletions

View File

@@ -682,7 +682,8 @@ int wc_ecc_init(ecc_key* key);
\param key pointer to the ecc_key object to initialize
\param heap pointer to a heap identifier
\param devId ID to use with crypto callbacks or async hardware. Set to INVALID_DEVID (-2) if not used
\param devId ID to use with crypto callbacks or async hardware. Set to
INVALID_DEVID if not used
_Example_
\code
@@ -703,8 +704,11 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId);
\brief This function uses a user defined heap and allocates space for the
key structure.
\return 0 Returned upon successfully initializing the ecc_key object
\return MEMORY_E Returned if there is an error allocating memory
\param heap pointer to a heap identifier
\return Non-null returned upon successfully allocating and initializing the
ecc_key object
\return NULL returned if there is an error allocating memory
_Example_
@@ -712,6 +716,7 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId);
wc_ecc_key_new(&heap);
\endcode
\sa wc_ecc_key_new_ex
\sa wc_ecc_make_key
\sa wc_ecc_key_free
\sa wc_ecc_init
@@ -719,6 +724,34 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId);
ecc_key* wc_ecc_key_new(void* heap);
/*!
\ingroup ECC
\brief This function uses a user defined heap and allocates space for the
key structure.
\param heap pointer to a heap identifier
\param devId ID to use with crypto callbacks or async hardware. Set to
INVALID_DEVID if not used
\return Non-null returned upon successfully allocating and initializing the
ecc_key object
\return NULL returned if there is an error allocating memory
_Example_
\code
wc_ecc_key_new_ex(&heap, MY_DEVID);
\endcode
\sa wc_ecc_key_new
\sa wc_ecc_make_key
\sa wc_ecc_key_free
\sa wc_ecc_init
*/
ecc_key* wc_ecc_key_new_ex(void* heap, int devId);
/*!
\ingroup ECC
@@ -2298,28 +2331,6 @@ int wc_ecc_set_curve(ecc_key *key, int keysize, int curve_id);
*/
mp_int* wc_ecc_key_get_priv(ecc_key* key);
/*!
\ingroup ECC
\brief Allocates and initializes new ECC key.
\return ecc_key pointer on success
\return NULL on failure
\param heap Heap hint for memory allocation
_Example_
\code
ecc_key* key = wc_ecc_key_new(NULL);
if (key != NULL) {
// use key
wc_ecc_key_free(key);
}
\endcode
\sa wc_ecc_key_free
*/
ecc_key* wc_ecc_key_new(void* heap);
/*!
\ingroup ECC
\brief Returns number of supported ECC curve sets.

View File

@@ -6366,15 +6366,10 @@ static void wc_ecc_dump_oids(void)
WOLFSSL_ABI
ecc_key* wc_ecc_key_new(void* heap)
ecc_key* wc_ecc_key_new_ex(void* heap, int devId)
{
int devId = INVALID_DEVID;
ecc_key* key;
#if defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_IMXRT1170_CAAM)
/* assume all keys are using CAAM for ECC unless explicitly set otherwise */
devId = WOLFSSL_CAAM_DEVID;
#endif
key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC);
if (key) {
if (wc_ecc_init_ex(key, heap, devId) != 0) {
@@ -6386,6 +6381,19 @@ ecc_key* wc_ecc_key_new(void* heap)
return key;
}
WOLFSSL_ABI
ecc_key* wc_ecc_key_new(void* heap)
{
#if defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_IMXRT1170_CAAM)
/* assume all keys are using CAAM for ECC unless explicitly set otherwise */
int devId = WOLFSSL_CAAM_DEVID;
#else
int devId = INVALID_DEVID;
#endif
return wc_ecc_key_new_ex(heap, devId);
}
WOLFSSL_ABI
void wc_ecc_key_free(ecc_key* key)

View File

@@ -1116,18 +1116,10 @@ static int wc_HpkeCopyPrivateKey(Hpke* hpke, void* key, void** copy)
ret = wc_ecc_export_private_only((ecc_key*)key, eccPriv,
&eccPrivSz);
if (ret == 0) {
*copy = wc_ecc_key_new(hpke->heap);
*copy = wc_ecc_key_new_ex(hpke->heap, INVALID_DEVID);
if (*copy == NULL)
ret = MEMORY_E;
}
#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB)
/* wc_ecc_key_new() adopts a platform default device id on some
* ports. The key being copied has none, so the copy must not gain
* one, or the shared secret would move onto a device the caller
* never asked for. */
if (ret == 0)
((ecc_key*)*copy)->devId = INVALID_DEVID;
#endif
if (ret == 0) {
/* The public part is not needed: the shared secret takes its
* point from the ephemeral key. */

View File

@@ -45267,6 +45267,44 @@ static wc_test_ret_t ecc_test_allocator(WC_RNG* rng)
(void)rng;
#endif
exit:
wc_ecc_key_free(key);
return ret;
}
/* Test for the wc_ecc_key_new_ex() and wc_ecc_key_free() functions. */
static wc_test_ret_t ecc_test_allocator_ex(WC_RNG* rng)
{
wc_test_ret_t ret = 0;
ecc_key* key;
#ifdef WC_NO_RNG
word32 idx = 0;
#endif
key = wc_ecc_key_new_ex(HEAP_HINT, devId);
if (key == NULL) {
ERROR_OUT(WC_TEST_RET_ENC_ERRNO, exit);
}
#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB)
if (key->devId != devId) {
ERROR_OUT(WC_TEST_RET_ENC_NC, exit);
}
#endif
#ifndef WC_NO_RNG
ret = wc_ecc_make_key(rng, ECC_KEYGEN_SIZE, key);
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_NONE);
#endif
if (ret != 0)
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit);
#else
/* use test ECC key */
ret = wc_EccPrivateKeyDecode(ecc_key_der_256, &idx, key,
(word32)sizeof_ecc_key_der_256);
(void)rng;
#endif
exit:
wc_ecc_key_free(key);
return ret;
@@ -46277,6 +46315,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t ecc_test(void)
printf("ecc_test_allocator failed!\n");
goto done;
}
ret = ecc_test_allocator_ex(&rng);
if (ret != 0) {
printf("ecc_test_allocator_ex failed!\n");
goto done;
}
#endif
#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_PUBLIC_MP) && \

View File

@@ -701,6 +701,7 @@ WOLFSSL_API mp_int* wc_ecc_key_get_priv(ecc_key* key);
WOLFSSL_ABI WOLFSSL_API ecc_key* wc_ecc_key_new(void* heap);
WOLFSSL_ABI WOLFSSL_API ecc_key* wc_ecc_key_new_ex(void* heap, int devId);
WOLFSSL_ABI WOLFSSL_API void wc_ecc_key_free(ecc_key* key);

View File

@@ -397,6 +397,7 @@ fn scan_cfg() -> Result<()> {
/* ecc */
check_cfg(&binding, "wc_ecc_init", "ecc");
check_cfg(&binding, "wc_ecc_key_new_ex", "ecc_key_new_ex");
check_cfg(&binding, "wc_ecc_export_point_der_compressed", "ecc_comp_key");
check_cfg(&binding, "wc_ecc_shared_secret", "ecc_dh");
check_cfg(&binding, "wc_ecc_sign_hash", "ecc_sign");

View File

@@ -398,19 +398,19 @@ impl ECC {
/// Allocate and initialize a new `sys::ecc_key` on the C heap.
fn new_ecc_key(heap: *mut core::ffi::c_void, dev_id: i32) -> Result<*mut sys::ecc_key, i32> {
#[cfg(ecc_key_new_ex)]
let key = unsafe { sys::wc_ecc_key_new_ex(heap, dev_id) };
#[cfg(not(ecc_key_new_ex))]
let key = unsafe { sys::wc_ecc_key_new(heap) };
if key.is_null() {
return Err(sys::wolfCrypt_ErrorCodes_MEMORY_E);
}
// wc_ecc_key_new() always initializes the key with INVALID_DEVID.
// Calling wc_ecc_init_ex() a second time to install the user's dev_id
// would re-run every initialization step (including allocations under
// some build configurations such as async crypto without WOLF_CRYPTO_CB)
// and orphan resources from the first init. Instead, just patch devId
// in place for WOLF_CRYPTO_CB builds.
#[cfg(wolf_crypto_cb)]
// wc_ecc_key_new() does not take a devId argument. Patch devId in
// place for WOLF_CRYPTO_CB builds where wc_ecc_key_new_ex() is not
// available.
#[cfg(all(not(ecc_key_new_ex), wolf_crypto_cb))]
unsafe { (*key).devId = dev_id; }
#[cfg(not(wolf_crypto_cb))]
#[cfg(all(not(ecc_key_new_ex), not(wolf_crypto_cb)))]
let _ = dev_id;
Ok(key)
}