diff --git a/src/ssl.c b/src/ssl.c index 61ffe8c5d..d309a1ef8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -7927,7 +7927,7 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, } break; #endif /* HAVE_ECC */ -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) #ifndef NO_DSA case EVP_PKEY_DSA: local->ownDsa = 1; @@ -7962,7 +7962,7 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, break; #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ #endif /* HAVE_DH */ -#endif /* WOLFSSL_QT || OPENSSL_ALL */ +#endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */ default: WOLFSSL_MSG("Unsupported key type"); wolfSSL_EVP_PKEY_free(local); @@ -36902,8 +36902,12 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outlen, void *out, size_t *outlen)) { word32 len; - (void)KDF; - + ecc_key* key; + int ret; +#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \ + && !defined(HAVE_FIPS) + int setGlobalRNG = 0; +#endif (void)KDF; WOLFSSL_ENTER("wolfSSL_ECDH_compute_key"); @@ -36926,10 +36930,27 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outlen, } len = (word32)outlen; + key = (ecc_key*)ecdh->internal; - if (wc_ecc_shared_secret_ssh((ecc_key*)ecdh->internal, - (ecc_point*)pub_key->internal, - (byte *)out, &len) != MP_OKAY) { +#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \ + && !defined(HAVE_FIPS) + if (key->rng == NULL) { + if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("No RNG to use"); + return WOLFSSL_FATAL_ERROR; + } + key->rng = &globalRNG; + setGlobalRNG = 1; + } +#endif + ret = wc_ecc_shared_secret_ssh(key, (ecc_point*)pub_key->internal, + (byte *)out, &len); +#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \ + && !defined(HAVE_FIPS) + if (setGlobalRNG) + key->rng = NULL; +#endif + if (ret != MP_OKAY) { WOLFSSL_MSG("wc_ecc_shared_secret failed"); return WOLFSSL_FATAL_ERROR; } @@ -51829,35 +51850,11 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) if (cert == NULL || pkey == NULL) return WOLFSSL_FAILURE; - if (pkey->type == EVP_PKEY_RSA) - cert->pubKeyOID = RSAk; - else if (pkey->type == EVP_PKEY_EC) - cert->pubKeyOID = ECDSAk; - else if (pkey->type == EVP_PKEY_DSA) - cert->pubKeyOID = DSAk; - else - return WOLFSSL_FAILURE; - -#ifdef OPENSSL_EXTRA -#if !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) && \ - !defined(NO_RSA) && !defined(HAVE_USER_RSA) - if (pkey->type == EVP_PKEY_RSA) { - int pLen; - /* Public and private key formats differ. Make sure to put in the - * public key format in the cert. */ - if ((pLen = wolfSSL_i2d_RSAPublicKey(pkey->rsa, (const byte**)&p)) <= 0) { - WOLFSSL_MSG("wolfSSL_i2d_RSAPublicKey error"); - return WOLFSSL_FAILURE; - } - if (cert->pubKey.buffer != NULL) - XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); - cert->pubKey.buffer = p; - cert->pubKey.length = pLen; - } - else -#endif -#endif /* OPENSSL_EXTRA */ - { + if (pkey->type == EVP_PKEY_RSA +#ifndef NO_DSA + || pkey->type == EVP_PKEY_DSA +#endif /* !NO_DSA */ + ) { p = (byte*)XMALLOC(pkey->pkey_sz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (p == NULL) return WOLFSSL_FAILURE; @@ -51867,7 +51864,42 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) cert->pubKey.buffer = p; XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz); cert->pubKey.length = pkey->pkey_sz; +#ifndef NO_DSA + if (pkey->type == EVP_PKEY_DSA) + cert->pubKeyOID = DSAk; + else +#endif /* !NO_DSA */ + cert->pubKeyOID = RSAk; } +#ifdef HAVE_ECC + else if (pkey->type == EVP_PKEY_EC) { + /* Generate since pkey->pkey.ptr may contain private key */ + ecc_key* ecc; + int derSz; + + if (pkey->ecc == NULL || pkey->ecc->internal == NULL) + return WOLFSSL_FAILURE; + + ecc = (ecc_key*)pkey->ecc->internal; + derSz = wc_EccPublicKeyDerSize(ecc, 1); + if (derSz <= 0) + return WOLFSSL_FAILURE; + + p = (byte*)XMALLOC(derSz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (p == NULL) + return WOLFSSL_FAILURE; + + if ((derSz = wc_EccPublicKeyToDer(ecc, p, derSz, 1)) <= 0) { + XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_FAILURE; + } + cert->pubKey.buffer = p; + cert->pubKey.length = derSz; + cert->pubKeyOID = ECDSAk; + } +#endif /* HAVE_ECC */ + else + return WOLFSSL_FAILURE; return WOLFSSL_SUCCESS; } diff --git a/tests/api.c b/tests/api.c index 4c4956d2b..f9e14d433 100644 --- a/tests/api.c +++ b/tests/api.c @@ -33799,6 +33799,9 @@ static void test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY (void) /* Test wolfSSL_EVP_PKEY_set1_EC_KEY */ AssertIntEQ(wolfSSL_EVP_PKEY_set1_EC_KEY(NULL, ecKey), WOLFSSL_FAILURE); AssertIntEQ(wolfSSL_EVP_PKEY_set1_EC_KEY(pkey, NULL), WOLFSSL_FAILURE); + /* Should fail since ecKey is empty */ + AssertIntEQ(wolfSSL_EVP_PKEY_set1_EC_KEY(pkey, ecKey), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); AssertIntEQ(wolfSSL_EVP_PKEY_set1_EC_KEY(pkey, ecKey), WOLFSSL_SUCCESS); /* Test wolfSSL_EVP_PKEY_get1_EC_KEY */ @@ -34131,6 +34134,8 @@ static void test_wolfSSL_EVP_PKEY_assign(void) AssertIntEQ(wolfSSL_EVP_PKEY_assign(NULL,type,ecKey), WOLFSSL_FAILURE); AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,NULL), WOLFSSL_FAILURE); AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,-1,ecKey), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,ecKey), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); AssertIntEQ(wolfSSL_EVP_PKEY_assign(pkey,type,ecKey), WOLFSSL_SUCCESS); wolfSSL_EVP_PKEY_free(pkey); #endif /* HAVE_ECC */ @@ -36615,6 +36620,9 @@ static void test_EVP_PKEY_ec(void) AssertNotNull(pkey = wolfSSL_EVP_PKEY_new()); AssertIntEQ(EVP_PKEY_assign_EC_KEY(NULL, ecKey), WOLFSSL_FAILURE); AssertIntEQ(EVP_PKEY_assign_EC_KEY(pkey, NULL), WOLFSSL_FAILURE); + /* Should fail since ecKey is empty */ + AssertIntEQ(EVP_PKEY_assign_EC_KEY(pkey, ecKey), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); AssertIntEQ(EVP_PKEY_assign_EC_KEY(pkey, ecKey), WOLFSSL_SUCCESS); wolfSSL_EVP_PKEY_free(pkey); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index f1eb9022b..be73518e2 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -16607,13 +16607,15 @@ int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) } #ifdef HAVE_PKCS8 -/* Write only private ecc key to unencrypted PKCS#8 format. +/* Write only private ecc key or both private and public parts to unencrypted + * PKCS#8 format. * * If output is NULL, places required PKCS#8 buffer size in outLen and * returns LENGTH_ONLY_E. * * return length on success else < 0 */ -int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) +static int eccToPKCS8(ecc_key* key, byte* output, word32* outLen, + int includePublic) { int ret, tmpDerSz; int algoID = 0; @@ -16626,7 +16628,7 @@ int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) byte* tmpDer = NULL; #endif - if (key == NULL || outLen == NULL) + if (key == NULL || key->dp == NULL || outLen == NULL) return BAD_FUNC_ARG; /* set algoID, get curve OID */ @@ -16643,7 +16645,7 @@ int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) #endif XMEMSET(tmpDer, 0, ECC_BUFSIZE); - tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, 0); + tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, includePublic); if (tmpDerSz < 0) { #ifndef WOLFSSL_NO_MALLOC XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -16693,6 +16695,23 @@ int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) *outLen = ret; return ret; } + +/* Write only private ecc key to unencrypted PKCS#8 format. + * + * return length on success else < 0 */ +int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) +{ + return eccToPKCS8(key, output, outLen, 0); +} + +/* Write both private and public ecc keys to unencrypted PKCS#8 format. + * + * return length on success else < 0 */ +int wc_EccKeyToPKCS8(ecc_key* key, byte* output, + word32* outLen) +{ + return eccToPKCS8(key, output, outLen, 1); +} #endif /* HAVE_PKCS8 */ #endif /* HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */ #endif /* HAVE_ECC */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 4bc592a35..946979296 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -3845,6 +3845,7 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, #ifdef HAVE_ECC_CDH mp_int k_lcl; + WOLFSSL_ENTER("wc_ecc_shared_secret_gen_sync"); /* if cofactor flag has been set */ if (private_key->flags & WC_ECC_FLAG_COFACTOR) { mp_digit cofactor = (mp_digit)private_key->dp->cofactor; @@ -3861,6 +3862,8 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, } } } +#else + WOLFSSL_ENTER("wc_ecc_shared_secret_gen_sync"); #endif #ifdef WOLFSSL_HAVE_SP_ECC @@ -3945,6 +3948,8 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, mp_clear(k); #endif + WOLFSSL_LEAVE("wc_ecc_shared_secret_gen_sync", err); + return err; } @@ -4075,12 +4080,15 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, /* type valid? */ if (private_key->type != ECC_PRIVATEKEY && private_key->type != ECC_PRIVATEKEY_ONLY) { + WOLFSSL_MSG("ECC_BAD_ARG_E"); return ECC_BAD_ARG_E; } /* Verify domain params supplied */ - if (wc_ecc_is_valid_idx(private_key->idx) == 0) + if (wc_ecc_is_valid_idx(private_key->idx) == 0) { + WOLFSSL_MSG("wc_ecc_is_valid_idx failed"); return ECC_BAD_ARG_E; + } switch(private_key->state) { case ECC_STATE_NONE: @@ -4114,6 +4122,8 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, err = BAD_STATE_E; } /* switch */ + WOLFSSL_LEAVE("wc_ecc_shared_secret_ex", err); + /* if async pending then return and skip done cleanup below */ if (err == WC_PENDING_E) { private_key->state++; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index f93fe03af..e485315d7 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6201,29 +6201,29 @@ int wolfSSL_EVP_PKEY_assign(WOLFSSL_EVP_PKEY *pkey, int type, void *key) #if defined(HAVE_ECC) /* try and populate public pkey_sz and pkey.ptr */ -static void ECC_populate_EVP_PKEY(EVP_PKEY* pkey, ecc_key* ecc) +static int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, ecc_key* ecc) { - int ret; + word32 derSz = 0; if (!pkey || !ecc) - return; - if ((ret = wc_EccPublicKeyDerSize(ecc, 1)) > 0) { - int derSz = ret; - char* derBuf = (char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + if (wc_EccKeyToPKCS8(ecc, NULL, &derSz) == LENGTH_ONLY_E) { + byte* derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL); if (derBuf) { - ret = wc_EccPublicKeyToDer(ecc, (byte*)derBuf, derSz, 1); - if (ret >= 0) { + if (wc_EccKeyToPKCS8(ecc, derBuf, &derSz) >= 0) { if (pkey->pkey.ptr) { XFREE(pkey->pkey.ptr, NULL, DYNAMIC_TYPE_OPENSSL); } - pkey->pkey_sz = ret; - pkey->pkey.ptr = derBuf; + pkey->pkey_sz = (int)derSz; + pkey->pkey.ptr = (char*)derBuf; + return WOLFSSL_SUCCESS; } - else { /* failure - okay to ignore */ - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + else { + XFREE(derBuf, NULL, DYNAMIC_TYPE_OPENSSL); derBuf = NULL; } } } + return WOLFSSL_FAILURE; } WOLFSSL_API int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key) @@ -6255,8 +6255,7 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_ pkey->ecc = key; pkey->ownEcc = 0; /* pkey does not own EC key */ pkey->type = EVP_PKEY_EC; - ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); - return WOLFSSL_SUCCESS; + return ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); #else (void)pkey; (void)key; @@ -6292,9 +6291,7 @@ int wolfSSL_EVP_PKEY_assign_EC_KEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY* key) pkey->ownEcc = 1; /* try and populate public pkey_sz and pkey.ptr */ - ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); - - return WOLFSSL_SUCCESS; + return ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); } #endif /* HAVE_ECC */ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 480b64f64..d289547b2 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -517,6 +517,8 @@ WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); word32 inLen); WOLFSSL_API int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen); + WOLFSSL_API int wc_EccKeyToPKCS8(ecc_key* key, byte* output, + word32* outLen); /* public key helper */ WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*,