diff --git a/src/pk.c b/src/pk.c index aff129669..cb2c47f35 100644 --- a/src/pk.c +++ b/src/pk.c @@ -1568,6 +1568,42 @@ WOLFSSL_RSA *wolfSSL_PEM_read_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, return rsa; } +#ifndef NO_FILESYSTEM +/* Create an RSA public key by reading the PEM encoded data from the BIO. + * + * @param [in] fp File pointer to read from. + * @param [out] out RSA key created. + * @param [in] cb Password callback when PEM encrypted. + * @param [in] pass NUL terminated string for passphrase when PEM encrypted. + * @return RSA key on success. + * @return NULL on failure. + */ +WOLFSSL_RSA *wolfSSL_PEM_read_RSA_PUBKEY(XFILE fp, + WOLFSSL_RSA** out, wc_pem_password_cb* cb, void *pass) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_RSA* rsa = NULL; + + WOLFSSL_ENTER("wolfSSL_PEM_read_RSA_PUBKEY"); + + /* Read into a new EVP_PKEY. */ + pkey = wolfSSL_PEM_read_PUBKEY(fp, NULL, cb, pass); + if (pkey != NULL) { + /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PKEY + * the flag indicating that the WOLFSSL_RSA structure is owned should be + * FALSE to avoid having it free'd. */ + pkey->ownRsa = 0; + rsa = pkey->rsa; + if (out != NULL) { + *out = rsa; + } + + wolfSSL_EVP_PKEY_free(pkey); + } + + return rsa; +} +#endif /* NO_FILESYSTEM */ #endif /* !NO_BIO */ #if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) && \ diff --git a/src/ssl.c b/src/ssl.c index dc629deed..77f941f4f 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -28261,22 +28261,38 @@ WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio, return pkey; } -#endif /* !NO_BIO */ - #if !defined(NO_FILESYSTEM) WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, WOLFSSL_EVP_PKEY **x, wc_pem_password_cb *cb, void *u) { - (void)fp; - (void)x; - (void)cb; - (void)u; + int err = 0; + WOLFSSL_EVP_PKEY* ret = NULL; + WOLFSSL_BIO* bio = NULL; - WOLFSSL_MSG("wolfSSL_PEM_read_PUBKEY not implemented"); + WOLFSSL_ENTER("wolfSSL_PEM_read_PUBKEY"); - return NULL; + if (fp == XBADFILE) { + err = 1; + } + if (err == 0) { + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + err = bio == NULL; + } + if (err == 0) { + err = wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS; + } + if (err == 0) { + ret = wolfSSL_PEM_read_bio_PUBKEY(bio, x, cb, u); + } + + if (bio != NULL) { + wolfSSL_BIO_free(bio); + } + + return ret; } #endif /* NO_FILESYSTEM */ +#endif /* !NO_BIO */ #endif /* OPENSSL_EXTRA */ #ifdef WOLFSSL_ALT_CERT_CHAINS diff --git a/tests/api.c b/tests/api.c index e91cf04f9..d766b69e6 100644 --- a/tests/api.c +++ b/tests/api.c @@ -31986,6 +31986,29 @@ static int test_wolfSSL_PEM_read_PrivateKey(void) return 0; } +static int test_wolfSSL_PEM_read_PUBKEY(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) \ + && !defined(NO_FILESYSTEM) && !defined(NO_BIO) + XFILE file; + const char* fname = "./certs/client-keyPub.pem"; + EVP_PKEY* pkey; + + printf(testingFmt, "test_wolfSSL_PEM_read_PUBKEY()"); + + /* Check error case. */ + AssertNull(pkey = PEM_read_PUBKEY(NULL, NULL, NULL, NULL)); + + /* Read in an RSA key. */ + file = XFOPEN(fname, "rb"); + AssertTrue(file != XBADFILE); + AssertNotNull(pkey = PEM_read_PUBKEY(file, NULL, NULL, NULL)); + XFCLOSE(file); +#endif + + return 0; +} + static int test_wolfSSL_PEM_PrivateKey(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ @@ -32454,6 +32477,24 @@ static int test_wolfSSL_PEM_RSAPrivateKey(void) return 0; } +static int test_wolfSSL_PEM_read_RSA_PUBKEY(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + XFILE file; + const char* fname = "./certs/client-keyPub.pem"; + RSA *rsa; + + file = XFOPEN(fname, "rb"); + AssertTrue((file != XBADFILE)); + AssertNotNull((rsa = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL))); + AssertIntEQ(RSA_size(rsa), 256); + RSA_free(rsa); +#endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ + + return 0; +} + static int test_wolfSSL_PEM_bio_DSAKey(void) { #ifndef HAVE_SELFTEST @@ -57245,6 +57286,8 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_ASN1_GENERALIZEDTIME_free), TEST_DECL(test_wolfSSL_private_keys), TEST_DECL(test_wolfSSL_PEM_read_PrivateKey), + TEST_DECL(test_wolfSSL_PEM_read_RSA_PUBKEY), + TEST_DECL(test_wolfSSL_PEM_read_PUBKEY), TEST_DECL(test_wolfSSL_PEM_PrivateKey), #ifndef NO_BIO TEST_DECL(test_wolfSSL_PEM_bio_RSAKey), diff --git a/wolfssl/openssl/pem.h b/wolfssl/openssl/pem.h index 508405a5c..824f7f8d8 100644 --- a/wolfssl/openssl/pem.h +++ b/wolfssl/openssl/pem.h @@ -81,6 +81,10 @@ int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA* key); WOLFSSL_API int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA *x); + +WOLFSSL_API +WOLFSSL_RSA *wolfSSL_PEM_read_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA** rsa, + wc_pem_password_cb* cb, void *pass); #endif /* NO_FILESYSTEM */ /* DSA */ @@ -232,6 +236,7 @@ int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh); #define PEM_read_bio_ECPKParameters wolfSSL_PEM_read_bio_ECPKParameters #define PEM_write_RSAPrivateKey wolfSSL_PEM_write_RSAPrivateKey #define PEM_write_RSA_PUBKEY wolfSSL_PEM_write_RSA_PUBKEY +#define PEM_read_RSA_PUBKEY wolfSSL_PEM_read_RSA_PUBKEY #define PEM_write_RSAPublicKey wolfSSL_PEM_write_RSAPublicKey #define PEM_read_RSAPublicKey wolfSSL_PEM_read_RSAPublicKey /* DSA */