mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-10-24 04:09:07 +03:00
Merge pull request #11248 from night1rider/ASU-ECIES-Improvements
Asu ecies improvements
This commit is contained in:
@@ -1679,8 +1679,9 @@ int test_wc_ecc_ctx_set_info(void)
|
||||
|
||||
/*
|
||||
* Testing the crypto-callback context accessors wc_ecc_ctx_get_algo,
|
||||
* wc_ecc_ctx_get_kdf_salt, wc_ecc_ctx_get_info, wc_ecc_ctx_get_mac_salt and
|
||||
* wc_ecc_ctx_get_protocol (built only when WOLF_CRYPTO_CB is enabled).
|
||||
* wc_ecc_ctx_get_kdf_salt, wc_ecc_ctx_get_info, wc_ecc_ctx_get_mac_salt,
|
||||
* wc_ecc_ctx_get_protocol and wc_ecc_ctx_get_rng (built only when
|
||||
* WOLF_CRYPTO_CB is enabled).
|
||||
*/
|
||||
int test_wc_ecc_ctx_getters(void)
|
||||
{
|
||||
@@ -1807,6 +1808,39 @@ int test_wc_ecc_ctx_getters(void)
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
}
|
||||
|
||||
/* get_rng: the caller's RNG must come back out unchanged. The ASU ECIES
|
||||
* offload uses it for the GCM nonce instead of standing up its own DRBG,
|
||||
* so a getter that returned NULL or a different RNG would silently change
|
||||
* where that nonce comes from. */
|
||||
{
|
||||
WC_RNG rng2;
|
||||
WC_RNG* gotRng = NULL;
|
||||
|
||||
XMEMSET(&rng2, 0, sizeof(rng2));
|
||||
|
||||
/* Point the out-parameter somewhere else first, so the checks fail if
|
||||
* the getter never writes it. */
|
||||
gotRng = &rng2;
|
||||
ExpectIntEQ(wc_ecc_ctx_get_rng(ctx, &gotRng), 0);
|
||||
ExpectPtrEq(gotRng, &rng);
|
||||
|
||||
/* wc_ecc_ctx_reset() swaps the RNG, and the getter has to follow. */
|
||||
ExpectIntEQ(wc_InitRng(&rng2), 0);
|
||||
ExpectIntEQ(wc_ecc_ctx_reset(ctx, &rng2), 0);
|
||||
gotRng = NULL;
|
||||
ExpectIntEQ(wc_ecc_ctx_get_rng(ctx, &gotRng), 0);
|
||||
ExpectPtrEq(gotRng, &rng2);
|
||||
/* Put the original RNG back so rng2 can be freed here. */
|
||||
ExpectIntEQ(wc_ecc_ctx_reset(ctx, &rng), 0);
|
||||
DoExpectIntEQ(wc_FreeRng(&rng2), 0);
|
||||
|
||||
/* bad args: NULL ctx / NULL out-parameter */
|
||||
ExpectIntEQ(wc_ecc_ctx_get_rng(NULL, &gotRng),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
ExpectIntEQ(wc_ecc_ctx_get_rng(ctx, NULL),
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
|
||||
}
|
||||
|
||||
wc_ecc_ctx_free(ctx);
|
||||
DoExpectIntEQ(wc_FreeRng(&rng), 0);
|
||||
#endif
|
||||
|
||||
@@ -15094,6 +15094,18 @@ int wc_ecc_ctx_get_protocol(ecEncCtx* ctx, int* protocol)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the RNG a caller set on the context, for backends that need one
|
||||
* instead of standing up a DRBG of their own. */
|
||||
int wc_ecc_ctx_get_rng(ecEncCtx* ctx, WC_RNG** rng)
|
||||
{
|
||||
if (ctx == NULL || rng == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
*rng = ctx->rng;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLF_CRYPTO_CB */
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ The BSP must have the `xilasu` and `xilmailbox` libraries enabled.
|
||||
|
||||
Anything outside this list is declined and wolfSSL runs it in software. That
|
||||
includes AES-192, partial AES blocks, SHA-512/224 and 512/256, Keccak padding,
|
||||
SHAKE128, deterministic ECDSA, and the older ECIES layouts.
|
||||
SHAKE128 and deterministic ECDSA. The older ECIES layouts are different: the
|
||||
port is not built at all, see below.
|
||||
|
||||
## Settings
|
||||
|
||||
@@ -86,6 +87,9 @@ only with firmware that front-pads.
|
||||
|
||||
**ECIES needs the KDF context path.** See below.
|
||||
|
||||
**ECIES needs `WOLFSSL_ECIES_GEN_IV`, and only offloads one direction.** See
|
||||
below.
|
||||
|
||||
## ECIES on hardware
|
||||
|
||||
The ASU runs ECIES as one command: ECDH, then HKDF, then AES-GCM. It has no
|
||||
@@ -115,12 +119,14 @@ What the offload requires:
|
||||
|
||||
| Setting | Value |
|
||||
| --- | --- |
|
||||
| Build | `WOLFSSL_ECIES_GEN_IV`, with neither `WOLFSSL_ECIES_OLD` nor `WOLFSSL_ECIES_ISO18033` |
|
||||
| RNG | one on the key or on the context, see below |
|
||||
| Scheme | `ecAES_128_GCM` or `ecAES_256_GCM` with `ecHKDF_SHA256` |
|
||||
| KDF salt | `wc_ecc_ctx_set_kdf_salt`, passed through as given |
|
||||
| KDF context | `wc_ecc_ctx_set_info`, must not be empty |
|
||||
| MAC salt | must be empty, so no `wc_ecc_ctx_set_peer_salt` |
|
||||
| Protocol | `REQ_RESP_CLIENT` to encrypt, `REQ_RESP_SERVER` to decrypt |
|
||||
| Curves | P-256, P-384, Brainpool P-256, P-320, P-384, P-512 |
|
||||
| Curves | P-192, P-256, P-384, Brainpool P-256, P-320, P-384, P-512 |
|
||||
|
||||
`wc_ecc_ctx_set_peer_salt` is the usual wolfSSL way to key ECIES, and it sets a
|
||||
MAC salt as a side effect. wolfSSL feeds that salt to AES-GCM as extra
|
||||
@@ -140,6 +146,24 @@ exchange works and matches software on the wire, but the key you passed in does
|
||||
not appear in the result. Decrypt is not affected, and uses the private key you
|
||||
supply.
|
||||
|
||||
## What ECIES needs to reach the ASU
|
||||
|
||||
Two things on top of the table above.
|
||||
|
||||
**The build must use `WOLFSSL_ECIES_GEN_IV`.** The ASU puts the GCM nonce in
|
||||
the message, which is what that mode does. `WOLFSSL_ECIES_OLD` and
|
||||
`WOLFSSL_ECIES_ISO18033` keep the nonce elsewhere, so in those modes the port
|
||||
is not built at all and wolfSSL never calls it.
|
||||
|
||||
**Only one direction offloads.** Client and server each use their own half of
|
||||
the derived key. The ASU always uses the first half, which is the half the
|
||||
client encrypts with and the server decrypts with. So a client encrypting, or
|
||||
a server decrypting, runs on hardware. The reply going back uses the second
|
||||
half and runs in software.
|
||||
|
||||
Encrypt needs an RNG, on the key or on the context, or it returns
|
||||
`MISSING_RNG_E`. Decrypt does not, since the nonce arrives in the message.
|
||||
|
||||
## Files
|
||||
|
||||
```
|
||||
|
||||
@@ -156,6 +156,10 @@ static int wc_AsuEciesCurve(ecc_key* key, u8* curveType, u8* keyLen)
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
switch (key->dp->id) {
|
||||
case ECC_SECP192R1:
|
||||
*curveType = (u8)XASU_ECC_NIST_P192;
|
||||
*keyLen = (u8)XASU_ECC_P192_SIZE_IN_BYTES;
|
||||
break;
|
||||
case ECC_SECP256R1:
|
||||
*curveType = (u8)XASU_ECC_NIST_P256;
|
||||
*keyLen = (u8)XASU_ECC_P256_SIZE_IN_BYTES;
|
||||
@@ -285,6 +289,12 @@ static int wc_AsuEciesEncrypt(wc_CryptoInfo* info)
|
||||
word32 need;
|
||||
word32 status;
|
||||
word32 addl = 0;
|
||||
const byte* macSalt = NULL;
|
||||
const byte* infoP = NULL;
|
||||
word32 macSaltSz = 0;
|
||||
word32 infoSz = 0;
|
||||
int proto = 0;
|
||||
WC_RNG* rng = NULL;
|
||||
int ret;
|
||||
|
||||
/* Return the decline code, not an error, so wolfSSL can use software. */
|
||||
@@ -309,27 +319,29 @@ static int wc_AsuEciesEncrypt(wc_CryptoInfo* info)
|
||||
}
|
||||
/* Only GCM here. The ASU cannot take extra salt and needs a context, so
|
||||
* software handles those cases. */
|
||||
{
|
||||
const byte* macSalt = NULL;
|
||||
const byte* infoP = NULL;
|
||||
word32 macSaltSz = 0;
|
||||
word32 infoSz = 0;
|
||||
int proto = 0;
|
||||
(void)wc_ecc_ctx_get_mac_salt(ctx, &macSalt, &macSaltSz);
|
||||
(void)wc_ecc_ctx_get_info(ctx, &infoP, &infoSz);
|
||||
(void)wc_ecc_ctx_get_protocol(ctx, &proto);
|
||||
if (macSaltSz > 0U) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
if (infoSz == 0U) {
|
||||
WC_ASU_PRINTF("[ASU] ecies: GCM needs a non-empty KDF context\r\n");
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
/* The ASU always uses the first half of the derived key, which is the
|
||||
* client half. A context is never built with protocol zero. */
|
||||
if (proto != REQ_RESP_CLIENT) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
ret = wc_ecc_ctx_get_mac_salt(ctx, &macSalt, &macSaltSz);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = wc_ecc_ctx_get_info(ctx, &infoP, &infoSz);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = wc_ecc_ctx_get_protocol(ctx, &proto);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
if (macSaltSz > 0U) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
if (infoSz == 0U) {
|
||||
WC_ASU_PRINTF("[ASU] ecies: GCM needs a non-empty KDF context\r\n");
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
/* The ASU always uses the first half of the derived key, which is the
|
||||
* client half. A context is never built with protocol zero. */
|
||||
if (proto != REQ_RESP_CLIENT) {
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
}
|
||||
/* The caller passes a key here, but the ASU makes its own. */
|
||||
if (privKey == NULL) {
|
||||
@@ -374,21 +386,30 @@ static int wc_AsuEciesEncrypt(wc_CryptoInfo* info)
|
||||
wc_AsuEciesReqFree(&mem);
|
||||
return ret;
|
||||
}
|
||||
/* Make the GCM nonce with a local RNG on the ASU device id. */
|
||||
{
|
||||
WC_RNG rng;
|
||||
ret = wc_InitRng_ex(&rng, NULL, WOLFSSL_VERSAL_GEN2_ASU_DEVID);
|
||||
if (ret == 0) {
|
||||
ret = wc_RNG_GenerateBlock(&rng, mem.req->iv,
|
||||
WC_ASU_ECIES_NONCE_SZ);
|
||||
wc_FreeRng(&rng);
|
||||
}
|
||||
}
|
||||
/* Nonce from the caller's RNG, key first then context, as software does.
|
||||
* A private DRBG here would ignore the RNG the application chose. */
|
||||
ret = wc_ecc_ctx_get_rng(ctx, &rng);
|
||||
if (ret != 0) {
|
||||
/* That RNG needs a seed source this build may not have, so decline
|
||||
* and let wolfSSL try again in software. */
|
||||
wc_AsuEciesReqFree(&mem);
|
||||
return CRYPTOCB_UNAVAILABLE;
|
||||
return ret;
|
||||
}
|
||||
#ifdef ECC_TIMING_RESISTANT
|
||||
/* The key's own RNG wins when it has one, which is what software uses. */
|
||||
if (privKey->rng != NULL) {
|
||||
rng = privKey->rng;
|
||||
}
|
||||
#endif
|
||||
if (rng == NULL) {
|
||||
/* Software will not invent a nonce either, so report the missing RNG
|
||||
* rather than declining and having it rediscover the same thing. */
|
||||
WC_ASU_PRINTF("[ASU] ecies enc: no RNG for the GCM nonce\r\n");
|
||||
wc_AsuEciesReqFree(&mem);
|
||||
return MISSING_RNG_E;
|
||||
}
|
||||
ret = wc_RNG_GenerateBlock(rng, mem.req->iv, WC_ASU_ECIES_NONCE_SZ);
|
||||
if (ret != 0) {
|
||||
wc_AsuEciesReqFree(&mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
wc_AsuEciesFillParams(&mem.req->params, ctx, curveType, keyLen, aesKeySize,
|
||||
|
||||
@@ -1129,6 +1129,8 @@ WOLFSSL_API
|
||||
int wc_ecc_ctx_get_mac_salt(ecEncCtx* ctx, const byte** salt, word32* sz);
|
||||
WOLFSSL_API
|
||||
int wc_ecc_ctx_get_protocol(ecEncCtx* ctx, int* protocol);
|
||||
WOLFSSL_API
|
||||
int wc_ecc_ctx_get_rng(ecEncCtx* ctx, WC_RNG** rng);
|
||||
#endif /* WOLF_CRYPTO_CB */
|
||||
WOLFSSL_API
|
||||
const byte* wc_ecc_ctx_get_own_salt(ecEncCtx* ctx);
|
||||
|
||||
Reference in New Issue
Block a user