Fix for KCAPI ECC KeyGen. Disable ECC consistency checks with KCAPI. Allow public AddSignature (used to be public). Fix KCAPI ECC SharedSecret output size.

This commit is contained in:
David Garske
2022-03-21 11:43:30 -07:00
parent 8bafa7f601
commit 6e550c8d75
4 changed files with 59 additions and 34 deletions

View File

@ -1250,12 +1250,14 @@ static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen
#if !defined(WOLFSSL_SP_MATH) && \ #if !defined(WOLFSSL_SP_MATH) && \
!defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
!defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_SE050) !defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_SILABS_SE_ACCEL) && \
!defined(WOLFSSL_SE050)
static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a,
mp_int* prime, mp_int* order); mp_int* prime, mp_int* order);
#endif #endif
static int _ecc_validate_public_key(ecc_key* key, int partial, int priv); static int _ecc_validate_public_key(ecc_key* key, int partial, int priv);
#if FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN) #if (FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN)) && \
!defined(WOLFSSL_KCAPI_ECC)
static int _ecc_pairwise_consistency_test(ecc_key* key, WC_RNG* rng); static int _ecc_pairwise_consistency_test(ecc_key* key, WC_RNG* rng);
#endif #endif
@ -5198,7 +5200,8 @@ int wc_ecc_make_key_ex2(WC_RNG* rng, int keysize, ecc_key* key, int curve_id,
err = _ecc_make_key_ex(rng, keysize, key, curve_id, flags); err = _ecc_make_key_ex(rng, keysize, key, curve_id, flags);
#if FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN) #if (FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN)) && \
!defined(WOLFSSL_KCAPI_ECC)
if (err == MP_OKAY) { if (err == MP_OKAY) {
err = _ecc_validate_public_key(key, 0, 0); err = _ecc_validate_public_key(key, 0, 0);
} }
@ -8670,9 +8673,11 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime)
#ifdef WOLFSSL_KCAPI_ECC #ifdef WOLFSSL_KCAPI_ECC
if (err == MP_OKAY) { if (err == MP_OKAY) {
word32 pubkey_sz = (word32)sizeof(key->pubkey_raw); word32 pubkey_sz = (word32)key->dp->size*2;
if (key->handle == NULL) {
err = KcapiEcc_LoadKey(key, key->pubkey_raw, &pubkey_sz, 1); /* if handle loaded, then pubkey_raw already populated */
err = KcapiEcc_LoadKey(key, key->pubkey_raw, &pubkey_sz, 1);
}
if (err == 0) { if (err == 0) {
err = mp_read_unsigned_bin(res->x, key->pubkey_raw, err = mp_read_unsigned_bin(res->x, key->pubkey_raw,
pubkey_sz/2); pubkey_sz/2);
@ -8721,7 +8726,8 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime)
#endif /* FIPS_VERSION_GE(5,0) || WOLFSSL_VALIDATE_ECC_KEYGEN || #endif /* FIPS_VERSION_GE(5,0) || WOLFSSL_VALIDATE_ECC_KEYGEN ||
* (!WOLFSSL_SP_MATH && WOLFSSL_VALIDATE_ECC_IMPORT) */ * (!WOLFSSL_SP_MATH && WOLFSSL_VALIDATE_ECC_IMPORT) */
#if FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN) #if (FIPS_VERSION_GE(5,0) || defined(WOLFSSL_VALIDATE_ECC_KEYGEN)) && \
!defined(WOLFSSL_KCAPI_ECC)
/* check privkey generator helper, creates prime needed */ /* check privkey generator helper, creates prime needed */
static int ecc_check_privkey_gen_helper(ecc_key* key) static int ecc_check_privkey_gen_helper(ecc_key* key)
@ -8740,6 +8746,9 @@ static int ecc_check_privkey_gen_helper(ecc_key* key)
#elif defined(WOLFSSL_SILABS_SE_ACCEL) #elif defined(WOLFSSL_SILABS_SE_ACCEL)
/* Hardware based private key, so this operation is not supported */ /* Hardware based private key, so this operation is not supported */
err = MP_OKAY; /* just report success */ err = MP_OKAY; /* just report success */
#elif defined(WOLFSSL_KCAPI_ECC)
/* Hardware based private key, so this operation is not supported */
err = MP_OKAY; /* just report success */
#else #else
err = MP_OKAY; err = MP_OKAY;
ALLOC_CURVE_SPECS(2, err); ALLOC_CURVE_SPECS(2, err);
@ -8822,7 +8831,7 @@ static int _ecc_pairwise_consistency_test(ecc_key* key, WC_RNG* rng)
return err; return err;
} }
#endif /* FIPS v5 or later || WOLFSSL_VALIDATE_ECC_KEYGEN */ #endif /* (FIPS v5 or later || WOLFSSL_VALIDATE_ECC_KEYGEN) &&!WOLFSSL_KCAPI_ECC */
#ifndef WOLFSSL_SP_MATH #ifndef WOLFSSL_SP_MATH
/* validate order * pubkey = point at infinity, 0 on success */ /* validate order * pubkey = point at infinity, 0 on success */
@ -9082,7 +9091,11 @@ static int _ecc_validate_public_key(ecc_key* key, int partial, int priv)
/* private keys must be in the range [1, n-1] */ /* private keys must be in the range [1, n-1] */
if ((err == MP_OKAY) && (key->type == ECC_PRIVATEKEY) && if ((err == MP_OKAY) && (key->type == ECC_PRIVATEKEY) &&
(mp_iszero(&key->k) || mp_isneg(&key->k) || (mp_iszero(&key->k) || mp_isneg(&key->k) ||
(mp_cmp(&key->k, curve->order) != MP_LT))) { (mp_cmp(&key->k, curve->order) != MP_LT))
#ifdef WOLFSSL_KCAPI_ECC
&& key->handle == NULL
#endif
) {
err = ECC_PRIV_KEY_E; err = ECC_PRIV_KEY_E;
} }
@ -9104,7 +9117,7 @@ static int _ecc_validate_public_key(ecc_key* key, int partial, int priv)
#endif #endif
FREE_CURVE_SPECS(); FREE_CURVE_SPECS();
#endif /* WOLFSSL_ATECC508A */ #endif /* HW Based Crypto */
#else #else
err = WC_KEY_SIZE_E; err = WC_KEY_SIZE_E;
#endif /* !WOLFSSL_SP_MATH */ #endif /* !WOLFSSL_SP_MATH */

View File

@ -88,6 +88,7 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz,
int ret = 0; int ret = 0;
word32 kcapiCurveId = 0; word32 kcapiCurveId = 0;
word32 keySz; word32 keySz;
int handleInit = 0;
if (key == NULL || key->dp == NULL) { if (key == NULL || key->dp == NULL) {
ret = BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
@ -102,6 +103,7 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz,
if (ret == 0 && key->handle == NULL) { if (ret == 0 && key->handle == NULL) {
ret = kcapi_kpp_init(&key->handle, WC_NAME_ECDH, 0); ret = kcapi_kpp_init(&key->handle, WC_NAME_ECDH, 0);
if (ret == 0) { if (ret == 0) {
handleInit = 1;
ret = kcapi_kpp_ecdh_setcurve(key->handle, kcapiCurveId); ret = kcapi_kpp_ecdh_setcurve(key->handle, kcapiCurveId);
if (ret >= 0) { if (ret >= 0) {
ret = 0; ret = 0;
@ -109,20 +111,26 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz,
} }
} }
/* if a private key value is set, load and use it. /* set the key */
* otherwise use existing key->handle */ if (ret == 0) {
if (ret == 0 && mp_iszero(&key->k) != MP_YES) { if (mp_iszero(&key->k) != MP_YES) {
byte priv[MAX_ECC_BYTES]; /* if a private key value is set, load and use it */
ret = wc_export_int(&key->k, priv, &keySz, keySz, WC_TYPE_UNSIGNED_BIN); byte priv[MAX_ECC_BYTES];
if (ret == 0) { ret = wc_export_int(&key->k, priv, &keySz, keySz, WC_TYPE_UNSIGNED_BIN);
ret = kcapi_kpp_setkey(key->handle, priv, keySz); if (ret == 0) {
if (ret >= 0) { ret = kcapi_kpp_setkey(key->handle, priv, keySz);
ret = 0;
} }
} }
else {
/* generate new ephemeral key */
ret = kcapi_kpp_setkey(key->handle, NULL, 0);
}
if (ret >= 0) {
ret = 0;
}
} }
/* optionally load public key */ /* optionally export public key */
if (ret == 0 && pubkey_raw != NULL && pubkey_sz != NULL) { if (ret == 0 && pubkey_raw != NULL && pubkey_sz != NULL) {
if (*pubkey_sz < keySz*2) { if (*pubkey_sz < keySz*2) {
ret = BUFFER_E; ret = BUFFER_E;
@ -137,7 +145,7 @@ int KcapiEcc_LoadKey(ecc_key* key, byte* pubkey_raw, word32* pubkey_sz,
} }
} }
if (release_handle && key != NULL && key->handle != NULL) { if (handleInit && release_handle && key != NULL && key->handle != NULL) {
kcapi_kpp_destroy(key->handle); kcapi_kpp_destroy(key->handle);
key->handle = NULL; key->handle = NULL;
} }
@ -170,6 +178,9 @@ int KcapiEcc_MakeKey(ecc_key* key, int keysize, int curve_id)
ret = mp_read_unsigned_bin(key->pubkey.y, ret = mp_read_unsigned_bin(key->pubkey.y,
key->pubkey_raw + pubkey_sz / 2, pubkey_sz / 2); key->pubkey_raw + pubkey_sz / 2, pubkey_sz / 2);
} }
if (ret == 0) {
ret = mp_set(key->pubkey.z, 1);
}
if (ret == 0) { if (ret == 0) {
key->type = ECC_PRIVATEKEY; key->type = ECC_PRIVATEKEY;
} }
@ -241,12 +252,6 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out,
} }
} }
} }
if (ret == 0) {
/* validate the output is large enough */
if (*outlen < keySz*2) {
ret = BUFFER_E;
}
}
if (ret == 0) { if (ret == 0) {
out_aligned = ((size_t)out % pageSz == 0) ? out : buf_aligned; out_aligned = ((size_t)out % pageSz == 0) ? out : buf_aligned;
if ((size_t)pub % pageSz == 0) { if ((size_t)pub % pageSz == 0) {
@ -262,9 +267,12 @@ int KcapiEcc_SharedSecret(ecc_key* private_key, ecc_key* public_key, byte* out,
if (ret >= 0) { if (ret >= 0) {
*outlen = ret / 2; *outlen = ret / 2;
if (out_aligned != out) { if (out_aligned != out) {
/* don't overflow out */
if (ret > (int)*outlen)
ret = (int)*outlen;
XMEMCPY(out, out_aligned, ret); XMEMCPY(out, out_aligned, ret);
} }
ret = 0; ret = 0; /* success */
} }
} }

View File

@ -21717,7 +21717,7 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount,
!defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A)
word32 y; word32 y;
#endif #endif
#ifdef HAVE_ECC_SIGN #if defined(HAVE_ECC_SIGN) && !defined(WOLFSSL_KCAPI_ECC)
WC_DECLARE_VAR(sig, byte, ECC_SIG_SIZE, HEAP_HINT); WC_DECLARE_VAR(sig, byte, ECC_SIG_SIZE, HEAP_HINT);
WC_DECLARE_VAR(digest, byte, ECC_DIGEST_SIZE, HEAP_HINT); WC_DECLARE_VAR(digest, byte, ECC_DIGEST_SIZE, HEAP_HINT);
int i; int i;
@ -21751,7 +21751,7 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount,
ERROR_OUT(-9901, done); ERROR_OUT(-9901, done);
#endif #endif
#ifdef HAVE_ECC_SIGN #if defined(HAVE_ECC_SIGN) && !defined(WOLFSSL_KCAPI_ECC)
if (sig == NULL || digest == NULL) if (sig == NULL || digest == NULL)
ERROR_OUT(-9902, done); ERROR_OUT(-9902, done);
#endif #endif
@ -21997,7 +21997,9 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount,
#endif /* HAVE_ECC_KEY_IMPORT */ #endif /* HAVE_ECC_KEY_IMPORT */
#endif /* HAVE_ECC_KEY_EXPORT */ #endif /* HAVE_ECC_KEY_EXPORT */
#if !defined(ECC_TIMING_RESISTANT) || (defined(ECC_TIMING_RESISTANT) && !defined(WC_NO_RNG)) /* For KCAPI cannot sign using generated ECDH key */
#if !defined(ECC_TIMING_RESISTANT) || (defined(ECC_TIMING_RESISTANT) && \
!defined(WC_NO_RNG) && !defined(WOLFSSL_KCAPI_ECC))
#ifdef HAVE_ECC_SIGN #ifdef HAVE_ECC_SIGN
/* ECC w/out Shamir has issue with all 0 digest */ /* ECC w/out Shamir has issue with all 0 digest */
/* WC_BIGINT doesn't have 0 len well on hardware */ /* WC_BIGINT doesn't have 0 len well on hardware */
@ -22079,10 +22081,12 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount,
} }
#endif /* HAVE_ECC_VERIFY */ #endif /* HAVE_ECC_VERIFY */
#endif /* HAVE_ECC_SIGN */ #endif /* HAVE_ECC_SIGN */
#endif /* !ECC_TIMING_RESISTANT || (ECC_TIMING_RESISTANT && !WC_NO_RNG) */ #endif /* !ECC_TIMING_RESISTANT || (ECC_TIMING_RESISTANT &&
* !WC_NO_RNG && !WOLFSSL_KCAPI_ECC) */
#if defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) && \ #if defined(HAVE_ECC_KEY_EXPORT) && !defined(WC_NO_RNG) && \
!defined(WOLFSSL_ATECC508) && !defined(WOLFSSL_ATECC608A) !defined(WOLFSSL_ATECC508) && !defined(WOLFSSL_ATECC608A) && \
!defined(WOLFSSL_KCAPI_ECC)
x = ECC_KEY_EXPORT_BUF_SIZE; x = ECC_KEY_EXPORT_BUF_SIZE;
ret = wc_ecc_export_private_only(userA, exportBuf, &x); ret = wc_ecc_export_private_only(userA, exportBuf, &x);
if (ret != 0) if (ret != 0)

View File

@ -1840,7 +1840,7 @@ WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz,
WOLFSSL_LOCAL int CheckCSRSignaturePubKey(const byte* cert, word32 certSz, WOLFSSL_LOCAL int CheckCSRSignaturePubKey(const byte* cert, word32 certSz,
void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID); void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID);
#endif /* WOLFSSL_CERT_REQ */ #endif /* WOLFSSL_CERT_REQ */
WOLFSSL_LOCAL int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz, WOLFSSL_ASN_API int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz,
int sigAlgoType); int sigAlgoType);
WOLFSSL_LOCAL int ParseCertRelative(DecodedCert* cert, int type, int verify, WOLFSSL_LOCAL int ParseCertRelative(DecodedCert* cert, int type, int verify,
void* cm); void* cm);