mirror of https://github.com/wolfSSL/wolfssl.git
ecc: take the curve id in wc_ecc_import_wrapped_private so an imported DHUK key is ready to sign
parent
31b9da2c8d
commit
1aa693da3b
|
|
@ -1326,31 +1326,35 @@ int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
|
|||
a chip-bound wrapped blob together with the 256-bit derivation seed; the
|
||||
plaintext scalar is never imported. The key must be bound to the STM32 DHUK
|
||||
crypto-callback device (init with wc_ecc_init_ex(&key, heap, WC_DHUK_DEVID)
|
||||
after registering the device with wc_Stm32_DhukRegister). Available only on
|
||||
after registering the device with wc_Stm32_DhukRegister). The curve is set
|
||||
from curve_id, so the key is ready to sign on return. Available only on
|
||||
STM32 builds with WOLFSSL_DHUK and a DHUK-capable SAES (WC_STM32_HAS_DHUK).
|
||||
|
||||
\return 0 Returned on success.
|
||||
\return BAD_FUNC_ARG Returned if key, seed, or wrapped is NULL; if seedSz is
|
||||
not 32; if wrappedLen is zero or not a multiple of the AES block size; if
|
||||
wrappedLen exceeds the on-key blob buffer; if plainLen is zero or larger
|
||||
than wrappedLen; or if wrappedLen is larger than plainLen padded to a full
|
||||
AES block.
|
||||
than wrappedLen; if wrappedLen is larger than plainLen padded to a full
|
||||
AES block; or if plainLen does not match the scalar size of curve_id.
|
||||
\return <0 An error from the curve lookup if curve_id is not supported.
|
||||
|
||||
\param key pointer to the ecc_key (bound to WC_DHUK_DEVID) to import into.
|
||||
\param curve_id curve the scalar belongs to, e.g. ECC_SECP256R1.
|
||||
\param seed pointer to the 256-bit (32-byte) per-key DHUK derivation seed.
|
||||
\param seedSz length of seed in bytes; must be 32.
|
||||
\param wrapped pointer to the DHUK-wrapped private scalar blob.
|
||||
\param wrappedLen length of the wrapped blob; a non-zero multiple of the AES
|
||||
block size, no larger than the on-key buffer.
|
||||
\param plainLen length in bytes of the plaintext scalar inside the blob.
|
||||
\param plainLen length in bytes of the plaintext scalar inside the blob;
|
||||
must equal the scalar size of curve_id (32 for P-256, 48 for P-384).
|
||||
|
||||
_Example_
|
||||
\code
|
||||
ecc_key key;
|
||||
wc_Stm32_DhukRegister(WC_DHUK_DEVID);
|
||||
wc_ecc_init_ex(&key, NULL, WC_DHUK_DEVID);
|
||||
if (wc_ecc_import_wrapped_private(&key, seed, 32, wrapped, wrappedLen,
|
||||
plainLen) == 0) {
|
||||
if (wc_ecc_import_wrapped_private(&key, ECC_SECP256R1, seed, 32, wrapped,
|
||||
wrappedLen, plainLen) == 0) {
|
||||
wc_ecc_sign_hash(hash, hashLen, sig, &sigLen, &rng, &key);
|
||||
}
|
||||
wc_ecc_free(&key);
|
||||
|
|
@ -1360,7 +1364,8 @@ int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
|
|||
\sa wc_ecc_sign_hash
|
||||
\sa wc_ecc_init_ex
|
||||
*/
|
||||
int wc_ecc_import_wrapped_private(ecc_key* key, const byte* seed, word32 seedSz,
|
||||
int wc_ecc_import_wrapped_private(ecc_key* key, int curve_id,
|
||||
const byte* seed, word32 seedSz,
|
||||
const byte* wrapped, word32 wrappedLen,
|
||||
word32 plainLen);
|
||||
|
||||
|
|
|
|||
|
|
@ -8307,10 +8307,13 @@ int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key)
|
|||
* at sign time it is decrypted into a short-lived buffer. The devId is NOT set
|
||||
* here -- enable the device by setting devId at init
|
||||
* (wc_ecc_init_ex(&key, heap, WC_DHUK_DEVID)). See ecc.h for the contract. */
|
||||
int wc_ecc_import_wrapped_private(ecc_key* key, const byte* seed, word32 seedSz,
|
||||
int wc_ecc_import_wrapped_private(ecc_key* key, int curve_id,
|
||||
const byte* seed, word32 seedSz,
|
||||
const byte* wrapped, word32 wrappedLen,
|
||||
word32 plainLen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (key == NULL || seed == NULL || wrapped == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
|
@ -8335,6 +8338,25 @@ int wc_ecc_import_wrapped_private(ecc_key* key, const byte* seed, word32 seedSz,
|
|||
if (wrappedLen > ((plainLen + 15u) & ~15u)) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
/* Validate the scalar size against the curve before touching the key, so a
|
||||
* rejected import leaves no curve behind on a key that has no blob. */
|
||||
ret = wc_ecc_get_curve_size_from_id(curve_id);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if ((word32)ret != plainLen) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* The sign path needs the domain parameters to drive the PKA and returns
|
||||
* ECC_BAD_ARG_E without them, and a caller starting from a bare
|
||||
* wc_ecc_init() has no other way to supply them for a key that never holds
|
||||
* its scalar in software. */
|
||||
ret = wc_ecc_set_curve(key, (int)plainLen, curve_id);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
XMEMCPY(key->dhuk_wrapped_priv, wrapped, wrappedLen);
|
||||
XMEMCPY(key->dhuk_seed, seed, seedSz);
|
||||
key->dhuk_wrapped_priv_len = wrappedLen;
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ wc_AesFree(&aes);
|
|||
wc_Stm32_DhukUnRegister(WC_DHUK_DEVID);
|
||||
```
|
||||
|
||||
ECDSA mirrors this: init the key with `wc_ecc_init_ex(&key, NULL, WC_DHUK_DEVID)`, import the wrapped private scalar plus its derivation seed with `wc_ecc_import_wrapped_private(&key, seed, seedSz, wrapped, wrappedLen, plainLen)`, then call the normal `wc_ecc_sign_hash()`; verification uses the in-clear public key unchanged. The seed reaches the device as the AES key bytes (`aes->devKey`, set by the normal `wc_AesSetKey` / `wc_AesGcmSetKey`) or, for ECC, on the `ecc_key`; the STM32 callback reads it and derives the working key inside SAES.
|
||||
ECDSA mirrors this: init the key with `wc_ecc_init_ex(&key, NULL, WC_DHUK_DEVID)`, import the wrapped private scalar plus its derivation seed with `wc_ecc_import_wrapped_private(&key, ECC_SECP256R1, seed, seedSz, wrapped, wrappedLen, plainLen)`, then call the normal `wc_ecc_sign_hash()`. The curve argument is required: it is what gives the sign path the domain parameters to drive the PKA, and the key is ready to sign on return. Verification uses the in-clear public key unchanged. The seed reaches the device as the AES key bytes (`aes->devKey`, set by the normal `wc_AesSetKey` / `wc_AesGcmSetKey`) or, for ECC, on the `ecc_key`; the STM32 callback reads it and derives the working key inside SAES.
|
||||
|
||||
Worked example: [`STM32_Bare_Test/src/main_dhuk.c`](https://github.com/wolfSSL/wolfssl-examples-stm32/blob/master/STM32_Bare_Test/src/main_dhuk.c) drives `wc_Stm32_DhukRegister` through transparent GMAC, AES-ECB, and ECDSA, and exercises the `wc_ecc_import_wrapped_private` argument validation in its `test_ecc_dhuk_setter()` block.
|
||||
|
||||
|
|
|
|||
|
|
@ -801,22 +801,29 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
|
|||
#if defined(WOLFSSL_DHUK) && defined(WC_STM32_HAS_DHUK) && \
|
||||
(defined(WOLFSSL_STM32_BARE) || defined(WOLFSSL_STM32_CUBEMX))
|
||||
/* DHUK ECC sign: import a hardware-wrapped ECC private scalar + its derivation
|
||||
* seed onto the ecc_key for the crypto-callback sign path. The caller MUST also
|
||||
* populate key->pubkey (via wc_ecc_import_x963) so verify can use the
|
||||
* in-clear public counterpart, and enable the device by setting devId at init
|
||||
* (wc_ecc_init_ex(&key, heap, WC_DHUK_DEVID)).
|
||||
* seed onto the ecc_key for the crypto-callback sign path. Sets the curve, so
|
||||
* the key is ready to sign on return. Enable the device by setting devId at
|
||||
* init (wc_ecc_init_ex(&key, heap, WC_DHUK_DEVID)). To verify with this same
|
||||
* key, also populate key->pubkey (via wc_ecc_import_x963) -- verify uses the
|
||||
* in-clear public counterpart and does not touch the wrapped scalar.
|
||||
* curve_id -- curve the scalar belongs to (e.g. ECC_SECP256R1); without
|
||||
* it the sign path has no parameters to drive the PKA and
|
||||
* returns ECC_BAD_ARG_E
|
||||
* seed -- 256-bit derivation seed (mixed with the silicon DHUK to
|
||||
* derive the key that unwraps the scalar)
|
||||
* seedSz -- seed length, must be 32
|
||||
* wrapped -- ECC scalar AES-encrypted with the SAES-derived device key;
|
||||
* length is a multiple of 16, <= 96
|
||||
* wrappedLen -- length of the wrapped blob
|
||||
* plainLen -- actual scalar size (e.g. 32 for P-256)
|
||||
* plainLen -- actual scalar size, and must match the curve (32 for
|
||||
* P-256, 48 for P-384)
|
||||
*
|
||||
* On success: stores seed + blob + lengths, returns 0 (does NOT set devId).
|
||||
* On failure: BAD_FUNC_ARG. */
|
||||
* On success: sets the curve, stores seed + blob + lengths, returns 0 (does
|
||||
* NOT set devId).
|
||||
* On failure: BAD_FUNC_ARG, or an error from the curve lookup. */
|
||||
WOLFSSL_API
|
||||
int wc_ecc_import_wrapped_private(ecc_key* key, const byte* seed, word32 seedSz,
|
||||
int wc_ecc_import_wrapped_private(ecc_key* key, int curve_id,
|
||||
const byte* seed, word32 seedSz,
|
||||
const byte* wrapped, word32 wrappedLen,
|
||||
word32 plainLen);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue