diff --git a/src/ssl.c b/src/ssl.c index f20574976..f5dd3a554 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -6905,8 +6905,8 @@ WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY** out) { - const unsigned char* mem; - int memSz; + unsigned char* mem; + long memSz; WOLFSSL_EVP_PKEY* pkey = NULL; WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio()"); @@ -6916,76 +6916,29 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, } (void)out; - if ((memSz = wolfSSL_BIO_get_mem_data(bio, (void*)&mem)) < 0) { + memSz = wolfSSL_BIO_pending(bio); + if (memSz <= 0) { return NULL; } + + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); if (mem == NULL) { return NULL; } - #if !defined(NO_RSA) - { - RsaKey rsa; - word32 keyIdx = 0; - - /* test if RSA key */ - if (wc_InitRsaKey(&rsa, NULL) == 0 && - wc_RsaPublicKeyDecode(mem, &keyIdx, &rsa, memSz) == 0) { - wc_FreeRsaKey(&rsa); - pkey = wolfSSL_PKEY_new(); - if (pkey != NULL) { - pkey->pkey_sz = keyIdx; - pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, - DYNAMIC_TYPE_PUBLIC_KEY); - if (pkey->pkey.ptr == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - XMEMCPY(pkey->pkey.ptr, mem, keyIdx); - pkey->type = RSAk; - if (out != NULL) { - *out = pkey; - } - return pkey; - } + if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { + pkey = wolfSSL_d2i_PUBKEY(NULL, &mem, memSz); + if (out != NULL && pkey != NULL) { + *out = pkey; } - wc_FreeRsaKey(&rsa); } - #endif /* NO_RSA */ - #ifdef HAVE_ECC - { - word32 keyIdx = 0; - ecc_key ecc; - - if (wc_ecc_init(&ecc) == 0 && - wc_EccPublicKeyDecode(mem, &keyIdx, &ecc, memSz) == 0) { - wc_ecc_free(&ecc); - pkey = wolfSSL_PKEY_new(); - if (pkey != NULL) { - pkey->pkey_sz = keyIdx; - pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL, - DYNAMIC_TYPE_PUBLIC_KEY); - if (pkey->pkey.ptr == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - XMEMCPY(pkey->pkey.ptr, mem, keyIdx); - pkey->type = ECDSAk; - if (out != NULL) { - *out = pkey; - } - return pkey; - } - } - wc_ecc_free(&ecc); - } - #endif /* HAVE_ECC */ - - return NULL; + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return pkey; } + /* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure. * * out pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL @@ -6998,7 +6951,9 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, unsigned char** in, long inSz) { - WOLFSSL_EVP_PKEY* local; + WOLFSSL_EVP_PKEY* pkey = NULL; + const unsigned char* mem = *in; + long memSz = inSz; WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY"); @@ -7007,31 +6962,85 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, unsigned char** in, return NULL; } - local = wolfSSL_PKEY_new(); - if (local == NULL) { - return NULL; + #if !defined(NO_RSA) + { + RsaKey rsa; + word32 keyIdx = 0; + + /* test if RSA key */ + if (wc_InitRsaKey(&rsa, NULL) == 0 && + wc_RsaPublicKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) { + wc_FreeRsaKey(&rsa); + pkey = wolfSSL_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_RSA; + if (out != NULL) { + *out = pkey; + } + + pkey->ownRsa = 1; + pkey->rsa = wolfSSL_RSA_new(); + if (pkey->rsa == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(pkey->rsa, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_RSA_LOAD_PUBLIC) != 1) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; + } + } + wc_FreeRsaKey(&rsa); } + #endif /* NO_RSA */ - local->pkey_sz = (int)inSz; - local->pkey.ptr = (char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - if (local->pkey.ptr == NULL) { - wolfSSL_EVP_PKEY_free(local); - local = NULL; - } - else { - XMEMCPY(local->pkey.ptr, *in, inSz); + #ifdef HAVE_ECC + { + word32 keyIdx = 0; + ecc_key ecc; + + if (wc_ecc_init(&ecc) == 0 && + wc_EccPublicKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) { + wc_ecc_free(&ecc); + pkey = wolfSSL_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_EC; + if (out != NULL) { + *out = pkey; + } + return pkey; + } + } + wc_ecc_free(&ecc); } + #endif /* HAVE_ECC */ - if (out != NULL) { - *out = local; - } + return pkey; - /* creation of RSA and ECC struct here */ - - - return local; } + WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz) { diff --git a/tests/api.c b/tests/api.c index 0d7799977..ef4e47ca7 100644 --- a/tests/api.c +++ b/tests/api.c @@ -15503,6 +15503,41 @@ static void test_wolfSSL_BIO_gets(void) } +static void test_wolfSSL_d2i_PUBKEY(void) +{ + #if defined(OPENSSL_EXTRA) + BIO* bio; + EVP_PKEY* pkey; + + printf(testingFmt, "wolfSSL_d2i_PUBKEY()"); + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertNull(d2i_PUBKEY_bio(NULL, NULL)); + +#if defined(USE_CERT_BUFFERS_2048) && !defined(NO_RSA) + /* RSA PUBKEY test */ + AssertIntGT(BIO_write(bio, client_keypub_der_2048, + sizeof_client_keypub_der_2048), 0); + AssertNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); + EVP_PKEY_free(pkey); +#endif + +#if defined(USE_CERT_BUFFERS_256) && defined(HAVE_ECC) + /* ECC PUBKEY test */ + AssertIntGT(BIO_write(bio, ecc_clikeypub_der_256, + sizeof_ecc_clikeypub_der_256), 0); + AssertNotNull(pkey = d2i_PUBKEY_bio(bio, NULL)); + EVP_PKEY_free(pkey); +#endif + + BIO_free(bio); + + (void)pkey; + printf(resultFmt, passed); + #endif +} + + static void test_no_op_functions(void) { #if defined(OPENSSL_EXTRA) @@ -16308,6 +16343,7 @@ void ApiTest(void) test_wolfSSL_OBJ(); test_wolfSSL_X509_NAME_ENTRY(); test_wolfSSL_BIO_gets(); + test_wolfSSL_d2i_PUBKEY(); /* test the no op functions for compatibility */ test_no_op_functions();