From 23a4d64caf11fb017b1d32ab09d77044eeca4526 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 24 Nov 2020 13:24:29 +0100 Subject: [PATCH] wolfSSL_EVP_PKEY_set1_EC_KEY should generate PKCS8 internal DER buffer This PKCS8 buffer should include both the private and the public parts of the key. --- src/ssl.c | 86 +++++++++++++++++++--------------- wolfcrypt/src/asn.c | 24 ++++++++-- wolfcrypt/src/ecc.c | 2 +- wolfcrypt/src/evp.c | 14 +++--- wolfssl/wolfcrypt/asn_public.h | 2 + 5 files changed, 78 insertions(+), 50 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 58df22565..7fd595708 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); @@ -36868,13 +36868,12 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outlen, void *out, size_t *outlen)) { word32 len; - (void)KDF; - - (void)KDF; ecc_key* key; -#ifdef ECC_TIMING_RESISTANT +#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \ + && !defined(HAVE_FIPS) int setGlobalRNG = 0; #endif + (void)KDF; WOLFSSL_ENTER("wolfSSL_ECDH_compute_key"); @@ -36898,7 +36897,8 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outlen, len = (word32)outlen; key = (ecc_key*)ecdh->internal; -#ifdef ECC_TIMING_RESISTANT +#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"); @@ -36916,7 +36916,8 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outlen, return WOLFSSL_FATAL_ERROR; } -#ifdef ECC_TIMING_RESISTANT +#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) \ + && !defined(HAVE_FIPS) if (setGlobalRNG) key->rng = NULL; #endif @@ -51813,35 +51814,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; @@ -51851,7 +51828,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/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 12ada17af..61d89027c 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -16598,13 +16598,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; @@ -16617,7 +16619,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 */ @@ -16634,7 +16636,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); @@ -16684,6 +16686,20 @@ 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); +} + +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 ae9c2cc1d..fbd542261 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -4072,7 +4072,7 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, #ifdef WOLFSSL_SMALL_STACK tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); if (tmpRNG == NULL) - return WOLFSSL_FAILURE; + return MEMORY_E; #endif if ((err = wc_InitRng(tmpRNG)) != MP_OKAY) { #ifdef WOLFSSL_SMALL_STACK diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 01844cc7e..254fd5204 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6178,20 +6178,18 @@ int wolfSSL_EVP_PKEY_assign(WOLFSSL_EVP_PKEY *pkey, int type, void *key) /* try and populate public pkey_sz and pkey.ptr */ static void 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); + if (wc_EccKeyToPKCS8(ecc, NULL, &derSz) == LENGTH_ONLY_E) { + byte* derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); 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; } else { /* failure - okay to ignore */ XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); 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*,