Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 131 additions & 7 deletions src/pk.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,11 +291,7 @@ static int der_write_to_bio_as_pem(const unsigned char* der, int derSz,
#endif
#endif

#if defined(OPENSSL_EXTRA) && \
((!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)) || \
(!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)) || \
(defined(HAVE_ECC) && defined(WOLFSSL_KEY_GEN)))
#if !defined(NO_FILESYSTEM)
#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
/* Write the DER data as PEM into file pointer.
*
* @param [in] der Buffer containing DER data.
Expand Down Expand Up @@ -325,8 +321,7 @@ static int der_write_to_file_as_pem(const unsigned char* der, int derSz,
XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
#endif
#endif
#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */

#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_KEY_GEN) && \
defined(WOLFSSL_PEM_TO_DER)
Expand Down Expand Up @@ -6165,6 +6160,135 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
}
#endif /* !NO_BIO */

#ifndef NO_FILESYSTEM
#ifndef NO_CERTS
/* Writes a public key to a file pointer encoded in PEM format.
*
* @param [in] fp File pointer to write to.
* @param [in] key Public key to write in PEM format.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_PEM_write_PUBKEY(XFILE fp, WOLFSSL_EVP_PKEY* key)
{
int err = 0;
unsigned char* derBuf = NULL;
int derSz = 0;

WOLFSSL_ENTER("wolfSSL_PEM_write_PUBKEY");

/* Validate parameters. */
if ((fp == XBADFILE) || (key == NULL)) {
WOLFSSL_MSG("Bad Function Arguments");
err = 1;
}

/* Encode the public key as DER. */
if (!err) {
derSz = wolfSSL_i2d_PUBKEY(key, &derBuf);
if (derSz <= 0) {
WOLFSSL_MSG("Failed to convert key to DER");
err = 1;
}
}

/* Write DER buffer to file as PEM. */
if ((!err) && (der_write_to_file_as_pem(derBuf, derSz, fp,
PUBLICKEY_TYPE, NULL) != 1)) {
WOLFSSL_MSG("Failed to write DER to file as PEM");
err = 1;
}

/* Dispose of the DER encoding. */
XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);

WOLFSSL_LEAVE("wolfSSL_PEM_write_PUBKEY", err);
return !err;
}

/* Writes a private key to a file pointer encoded in PEM format.
*
* @param [in] fp File pointer to write to.
* @param [in] key Private key to write in PEM format.
* @param [in] cipher Encryption cipher to use. May be NULL.
* @param [in] passwd Password to use when encrypting. May be NULL.
* @param [in] len Length of password.
* @param [in] cb Password callback.
* @param [in] arg Password callback argument.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_PEM_write_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY* key,
const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int len,
wc_pem_password_cb* cb, void* arg)
{
int err = 0;
int type = 0;
unsigned char* derBuf = NULL;
int derSz = 0;

(void)cipher;
(void)passwd;
(void)len;
(void)cb;
(void)arg;

WOLFSSL_ENTER("wolfSSL_PEM_write_PrivateKey");

/* Validate parameters. */
if ((fp == XBADFILE) || (key == NULL)) {
WOLFSSL_MSG("Bad Function Arguments");
err = 1;
}

/* Determine PEM type from key type, mirroring wolfSSL_PEM_read_PrivateKey's
* keyFormat switch. */
if (!err) {
switch (key->type) {
case WC_EVP_PKEY_RSA:
type = PRIVATEKEY_TYPE;
break;
case WC_EVP_PKEY_DSA:
type = DSA_PRIVATEKEY_TYPE;
break;
case WC_EVP_PKEY_EC:
type = ECC_PRIVATEKEY_TYPE;
break;
case WC_EVP_PKEY_DH:
type = DH_PRIVATEKEY_TYPE;
break;
default:
WOLFSSL_MSG("Unknown key type");
err = 1;
break;
}
}

/* Encode the private key as DER. */
if (!err) {
derSz = wolfSSL_i2d_PrivateKey(key, &derBuf);
if (derSz <= 0) {
WOLFSSL_MSG("Error encoding private key as DER");
err = 1;
}
}

/* Write DER buffer to file as PEM. */
if ((!err) && (der_write_to_file_as_pem(derBuf, derSz, fp, type,
NULL) != 1)) {
WOLFSSL_MSG("Error writing DER to file as PEM");
err = 1;
}

/* Dispose of the DER encoding. */
XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);

WOLFSSL_LEAVE("wolfSSL_PEM_write_PrivateKey", err);
return !err;
}
#endif /* !NO_CERTS */
#endif /* !NO_FILESYSTEM */

#ifndef NO_BIO
/* Create a private key object from the data in the BIO.
*
Expand Down
120 changes: 120 additions & 0 deletions tests/api/test_ossl_pem.c
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,126 @@ int test_wolfSSL_PEM_PrivateKey(void)
return EXPECT_RESULT();
}

int test_wolfSSL_PEM_write_PrivateKey(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_RSA) && \
!defined(NO_FILESYSTEM) && defined(USE_CERT_BUFFERS_2048) && \
!defined(NO_ASN) && !defined(NO_PWDBASED)
const char* privFile = "./test-pem-write-private-key.pem";
const unsigned char* serverKey =
(const unsigned char*)server_key_der_2048;
EVP_PKEY* pkey = NULL;
EVP_PKEY* readPriv = NULL;
XFILE fp = XBADFILE;

remove(privFile);

ExpectNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &serverKey,
(long)sizeof_server_key_der_2048));

/* Bad-argument checks. */
ExpectIntEQ(PEM_write_PrivateKey(XBADFILE, pkey, NULL, NULL, 0, NULL,
NULL), 0);
ExpectIntEQ(PEM_write_PrivateKey(stderr, NULL, NULL, NULL, 0, NULL,
NULL), 0);

/* Write private key to file. */
ExpectTrue((fp = XFOPEN(privFile, "wb")) != XBADFILE);
if (fp != XBADFILE) {
ExpectIntEQ(PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL),
1);
XFCLOSE(fp);
fp = XBADFILE;
}

/* Read it back and verify the DER content matches. */
ExpectTrue((fp = XFOPEN(privFile, "rb")) != XBADFILE);
if (fp != XBADFILE) {
ExpectNotNull(readPriv = PEM_read_PrivateKey(fp, NULL, NULL, NULL));
XFCLOSE(fp);
fp = XBADFILE;
}
if ((pkey != NULL) && (readPriv != NULL) && (pkey->pkey.ptr != NULL) &&
(readPriv->pkey.ptr != NULL)) {
ExpectIntEQ(pkey->pkey_sz, readPriv->pkey_sz);
ExpectIntEQ(XMEMCMP(pkey->pkey.ptr, readPriv->pkey.ptr,
pkey->pkey_sz), 0);
}

EVP_PKEY_free(readPriv);
EVP_PKEY_free(pkey);
if (fp != XBADFILE) {
XFCLOSE(fp);
}
remove(privFile);
#endif
return EXPECT_RESULT();
}

int test_wolfSSL_PEM_write_PUBKEY(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_RSA) && \
!defined(NO_FILESYSTEM) && defined(USE_CERT_BUFFERS_2048) && \
!defined(NO_ASN) && !defined(NO_PWDBASED)
const char* pubFile = "./test-pem-write-pubkey.pem";
const unsigned char* serverKey =
(const unsigned char*)server_key_der_2048;
EVP_PKEY* pkey = NULL;
EVP_PKEY* readPub = NULL;
unsigned char* pubDer = NULL;
unsigned char* readPubDer = NULL;
XFILE fp = XBADFILE;
int pubDerSz = 0;
int readPubDerSz = 0;

remove(pubFile);

ExpectNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &serverKey,
(long)sizeof_server_key_der_2048));

/* Bad-argument checks. */
ExpectIntEQ(PEM_write_PUBKEY(XBADFILE, pkey), 0);
ExpectIntEQ(PEM_write_PUBKEY(stderr, NULL), 0);

/* Capture the expected public-key DER for later comparison. */
ExpectIntGT(pubDerSz = wolfSSL_i2d_PUBKEY(pkey, &pubDer), 0);

/* Write public key to file. */
ExpectTrue((fp = XFOPEN(pubFile, "wb")) != XBADFILE);
if (fp != XBADFILE) {
ExpectIntEQ(PEM_write_PUBKEY(fp, pkey), 1);
XFCLOSE(fp);
fp = XBADFILE;
}

/* Read it back and verify the DER content matches. */
ExpectTrue((fp = XFOPEN(pubFile, "rb")) != XBADFILE);
if (fp != XBADFILE) {
ExpectNotNull(readPub = PEM_read_PUBKEY(fp, NULL, NULL, NULL));
XFCLOSE(fp);
fp = XBADFILE;
}
ExpectIntGT(readPubDerSz = wolfSSL_i2d_PUBKEY(readPub, &readPubDer), 0);
ExpectIntEQ(pubDerSz, readPubDerSz);
if ((pubDer != NULL) && (readPubDer != NULL) && (pubDerSz > 0) &&
(pubDerSz == readPubDerSz)) {
ExpectIntEQ(XMEMCMP(pubDer, readPubDer, pubDerSz), 0);
}

XFREE(readPubDer, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
XFREE(pubDer, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
EVP_PKEY_free(readPub);
EVP_PKEY_free(pkey);
if (fp != XBADFILE) {
XFCLOSE(fp);
}
remove(pubFile);
#endif
return EXPECT_RESULT();
}

int test_wolfSSL_PEM_file_RSAKey(void)
{
EXPECT_DECLS;
Expand Down
4 changes: 4 additions & 0 deletions tests/api/test_ossl_pem.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ int test_wolfSSL_PEM_PrivateKey_ecc(void);
int test_wolfSSL_PEM_PrivateKey_dsa(void);
int test_wolfSSL_PEM_PrivateKey_dh(void);
int test_wolfSSL_PEM_PrivateKey(void);
int test_wolfSSL_PEM_write_PrivateKey(void);
int test_wolfSSL_PEM_write_PUBKEY(void);
int test_wolfSSL_PEM_file_RSAKey(void);
int test_wolfSSL_PEM_file_RSAPrivateKey(void);
int test_wolfSSL_PEM_read_RSA_PUBKEY(void);
Expand All @@ -52,6 +54,8 @@ int test_wolfSSL_PEM_PUBKEY(void);
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_PrivateKey_dsa), \
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_PrivateKey_dh), \
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_PrivateKey), \
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_write_PrivateKey), \
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_write_PUBKEY), \
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_file_RSAKey), \
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_file_RSAPrivateKey), \
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_read_RSA_PUBKEY), \
Expand Down
9 changes: 9 additions & 0 deletions wolfssl/openssl/pem.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@ WOLFSSL_API
int wolfSSL_PEM_write_X509(XFILE fp, WOLFSSL_X509 *x);
WOLFSSL_API
int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh);
WOLFSSL_API
int wolfSSL_PEM_write_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY* key,
const WOLFSSL_EVP_CIPHER* cipher,
unsigned char* passwd, int len,
wc_pem_password_cb* cb, void* arg);
WOLFSSL_API
int wolfSSL_PEM_write_PUBKEY(XFILE fp, WOLFSSL_EVP_PKEY* key);
#endif /* NO_FILESYSTEM */

#ifndef OPENSSL_COEXIST
Expand All @@ -244,6 +251,7 @@ int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh);

#define PEM_read_X509 wolfSSL_PEM_read_X509
#define PEM_read_PrivateKey wolfSSL_PEM_read_PrivateKey
#define PEM_write_PrivateKey wolfSSL_PEM_write_PrivateKey
#define PEM_write_X509 wolfSSL_PEM_write_X509
#define PEM_write_bio_PrivateKey wolfSSL_PEM_write_bio_PrivateKey
#define PEM_write_bio_PKCS8PrivateKey wolfSSL_PEM_write_bio_PKCS8PrivateKey
Expand Down Expand Up @@ -287,6 +295,7 @@ int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh);
#define PEM_read_PUBKEY wolfSSL_PEM_read_PUBKEY
#define PEM_read_bio_PUBKEY wolfSSL_PEM_read_bio_PUBKEY
#define PEM_write_bio_PUBKEY wolfSSL_PEM_write_bio_PUBKEY
#define PEM_write_PUBKEY wolfSSL_PEM_write_PUBKEY

#define PEM_write_bio_PKCS8_PRIV_KEY_INFO wolfSSL_PEM_write_bio_PKCS8_PRIV_KEY_INFO
#define PEM_read_bio_PKCS8_PRIV_KEY_INFO wolfSSL_PEM_read_bio_PKCS8_PRIV_KEY_INFO
Expand Down