Skip to content

Commit 8ce0584

Browse files
committed
pkcs7, tls, openssl: derive the public point for a private-only key
These decode SEC1 and then need the point. The static ECDH key derives at load, so the stored key stays as set. pk_ec.c tried before, under a guard private to ecc.c that is never defined there.
1 parent d6dafb4 commit 8ce0584

9 files changed

Lines changed: 637 additions & 92 deletions

File tree

‎src/pk_ec.c‎

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3499,22 +3499,12 @@ WOLFSSL_EC_KEY* wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY** key,
34993499
/* Internal EC key setup. */
35003500
ret->inSet = 1;
35013501

3502-
/* When the RFC 5915 DER encoding omits the optional publicKey field,
3503-
* wc_EccPrivateKeyDecode leaves type == ECC_PRIVATEKEY_ONLY with the
3504-
* public point uninitialised. Derive the public point now so that
3505-
* all downstream operations (sign, ECDH, export) have a valid key,
3506-
* matching the behaviour of OpenSSL's d2i_ECPrivateKey.
3507-
* In builds without HAVE_ECC_MAKE_PUB (e.g. hardware/CB-only),
3508-
* keep the historical import behaviour and leave the key as
3509-
* private-only instead of failing import. */
3510-
#ifdef HAVE_ECC_MAKE_PUB
3511-
if (((ecc_key*)ret->internal)->type == ECC_PRIVATEKEY_ONLY) {
3512-
if (wc_ecc_make_pub((ecc_key*)ret->internal, NULL) != 0) {
3513-
WOLFSSL_MSG("wc_ecc_make_pub error deriving public key");
3514-
err = 1;
3515-
}
3502+
/* RFC 5915 makes publicKey optional: derive the point, as OpenSSL
3503+
* does, so sign, ECDH and export have a full key. */
3504+
if (wc_ecc_derive_pub_if_needed((ecc_key*)ret->internal, NULL) != 0) {
3505+
WOLFSSL_MSG("error deriving public key");
3506+
err = 1;
35163507
}
3517-
#endif
35183508
}
35193509

35203510
if (!err) {
@@ -3696,8 +3686,40 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
36963686
if (res == 1) {
36973687
/* Load into internal EC key based on key type option. */
36983688
if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) {
3699-
ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
3700-
(word32)derSz);
3689+
void* heap = ((ecc_key*)key->internal)->heap;
3690+
#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB)
3691+
int devId = ((ecc_key*)key->internal)->devId;
3692+
#else
3693+
int devId = INVALID_DEVID;
3694+
#endif
3695+
/* Decode into a new key so a rejected one leaves the internal key
3696+
* as it was. */
3697+
ecc_key* tmp = (ecc_key*)XMALLOC(sizeof(ecc_key), heap,
3698+
DYNAMIC_TYPE_ECC);
3699+
3700+
if (tmp == NULL) {
3701+
ret = MEMORY_E;
3702+
}
3703+
else {
3704+
ret = wc_ecc_init_ex(tmp, heap, devId);
3705+
if (ret == 0) {
3706+
ret = wc_EccPrivateKeyDecode(derBuf, &idx, tmp,
3707+
(word32)derSz);
3708+
/* RFC 5915 makes publicKey optional. */
3709+
if (ret == 0) {
3710+
ret = wc_ecc_derive_pub_if_needed(tmp, NULL);
3711+
}
3712+
if (ret == 0) {
3713+
/* Take ownership of new key - set tmp to the old
3714+
* key which will then be freed below. */
3715+
ecc_key* old = (ecc_key*)key->internal;
3716+
key->internal = tmp;
3717+
tmp = old;
3718+
}
3719+
wc_ecc_free(tmp);
3720+
}
3721+
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
3722+
}
37013723
}
37023724
else {
37033725
ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal,
@@ -4419,7 +4441,8 @@ int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
44194441
}
44204442

44214443
/* set the external privkey */
4422-
if ((ret == 1) && (key->type == ECC_PRIVATEKEY) &&
4444+
if ((ret == 1) && ((key->type == ECC_PRIVATEKEY) ||
4445+
(key->type == ECC_PRIVATEKEY_ONLY)) &&
44234446
(wolfssl_bn_set_value(&eckey->priv_key,
44244447
wc_ecc_key_get_priv(key)) != 1)) {
44254448
WOLFSSL_MSG("ec priv key error");

‎src/ssl_api_pk.c‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2408,6 +2408,21 @@ int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr)
24082408
#ifndef SINGLE_THREADED
24092409
wc_UnLockMutex(&ssl->ctx->staticKELock);
24102410
#endif
2411+
2412+
#ifdef HAVE_ECC
2413+
/* SEC1 makes the public point optional, and the key share sends it.
2414+
* Derivation failure leaves the key private-only so the export fails the
2415+
* handshake. Returning that error would make the caller generate a key. */
2416+
if ((ret == 0) && (keyAlgo == WC_PK_TYPE_ECDH)) {
2417+
ecc_key* key = (ecc_key*)keyPtr;
2418+
2419+
ret = wc_ecc_derive_pub_if_needed(key, ssl->rng);
2420+
if (ret != 0) {
2421+
key->type = ECC_PRIVATEKEY_ONLY;
2422+
ret = 0;
2423+
}
2424+
}
2425+
#endif
24112426
return ret;
24122427
}
24132428

0 commit comments

Comments
 (0)