Skip to content

Commit b49b886

Browse files
committed
Feat: Allow for a wrapper for pem write privatekey & PUBKEY
1 parent 6074a2d commit b49b886

4 files changed

Lines changed: 228 additions & 0 deletions

File tree

src/pk.c

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6165,6 +6165,125 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
61656165
}
61666166
#endif /* !NO_BIO */
61676167

6168+
#ifndef NO_FILESYSTEM
6169+
/* Writes a public key to a file pointer encoded in PEM format.
6170+
*
6171+
* Mirrors wolfSSL_PEM_read_PUBKEY: convert the EVP_PKEY to public-key DER and
6172+
* write it with the generic PUBLIC KEY PEM type.
6173+
*
6174+
* @param [in] fp File pointer to write to.
6175+
* @param [in] key Public key to write in PEM format.
6176+
* @return 1 on success.
6177+
* @return 0 on failure.
6178+
*/
6179+
int wolfSSL_PEM_write_PUBKEY(XFILE fp, WOLFSSL_EVP_PKEY* key)
6180+
{
6181+
int ret = 0;
6182+
#if !defined(NO_ASN) && !defined(NO_PWDBASED)
6183+
unsigned char* der = NULL;
6184+
int derSz;
6185+
#endif
6186+
6187+
WOLFSSL_ENTER("wolfSSL_PEM_write_PUBKEY");
6188+
6189+
if ((fp == XBADFILE) || (key == NULL)) {
6190+
WOLFSSL_MSG("Bad Function Arguments");
6191+
return 0;
6192+
}
6193+
6194+
#if !defined(NO_ASN) && !defined(NO_PWDBASED)
6195+
derSz = wolfSSL_i2d_PUBKEY(key, &der);
6196+
if (derSz > 0) {
6197+
ret = der_write_to_file_as_pem(der, derSz, fp, PUBLICKEY_TYPE, NULL);
6198+
}
6199+
XFREE(der, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
6200+
#else
6201+
WOLFSSL_MSG("i2d_PUBKEY not supported in this build");
6202+
#endif
6203+
6204+
return ret;
6205+
}
6206+
6207+
/* Writes a private key to a file pointer encoded in PEM format.
6208+
*
6209+
* Mirrors wolfSSL_PEM_read_PrivateKey's key-type switch and writes the stored
6210+
* DER as the matching PEM private key type.
6211+
*
6212+
* @param [in] fp File pointer to write to.
6213+
* @param [in] key Private key to write in PEM format.
6214+
* @param [in] cipher Encryption cipher to use. May be NULL.
6215+
* @param [in] passwd Password to use when encrypting. May be NULL.
6216+
* @param [in] len Length of password.
6217+
* @param [in] cb Password callback.
6218+
* @param [in] arg Password callback argument.
6219+
* @return 1 on success.
6220+
* @return 0 on failure.
6221+
*/
6222+
int wolfSSL_PEM_write_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY* key,
6223+
const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int len,
6224+
wc_pem_password_cb* cb, void* arg)
6225+
{
6226+
int err = 0;
6227+
int type = 0;
6228+
6229+
WOLFSSL_ENTER("wolfSSL_PEM_write_PrivateKey");
6230+
6231+
/* Validate parameters. */
6232+
if ((fp == XBADFILE) || (key == NULL)) {
6233+
WOLFSSL_MSG("Bad Function Arguments");
6234+
err = 1;
6235+
}
6236+
6237+
if ((!err) && ((cipher != NULL) || (passwd != NULL) || (len != 0) ||
6238+
(cb != NULL) || (arg != NULL))) {
6239+
WOLFSSL_MSG("PEM private key encryption not supported here");
6240+
}
6241+
6242+
if (!err) {
6243+
/* Set PEM type based on key type, inverse of PEM_read_PrivateKey. */
6244+
switch (key->type) {
6245+
#ifndef NO_RSA
6246+
case WC_EVP_PKEY_RSA:
6247+
type = PRIVATEKEY_TYPE;
6248+
break;
6249+
#endif
6250+
#ifndef NO_DSA
6251+
case WC_EVP_PKEY_DSA:
6252+
type = DSA_PRIVATEKEY_TYPE;
6253+
break;
6254+
#endif
6255+
#ifdef HAVE_ECC
6256+
case WC_EVP_PKEY_EC:
6257+
type = ECC_PRIVATEKEY_TYPE;
6258+
break;
6259+
#endif
6260+
#ifndef NO_DH
6261+
case WC_EVP_PKEY_DH:
6262+
type = DH_PRIVATEKEY_TYPE;
6263+
break;
6264+
#endif
6265+
default:
6266+
type = WOLFSSL_FATAL_ERROR;
6267+
break;
6268+
}
6269+
}
6270+
6271+
if ((!err) && (type == WOLFSSL_FATAL_ERROR)) {
6272+
err = 1;
6273+
}
6274+
6275+
/* Write DER data as the selected PEM private key type. */
6276+
if ((!err) && (der_write_to_file_as_pem((byte*)key->pkey.ptr, key->pkey_sz,
6277+
fp, type, NULL) != 1)) {
6278+
err = 1;
6279+
}
6280+
6281+
WOLFSSL_LEAVE("wolfSSL_PEM_write_PrivateKey", err);
6282+
6283+
return !err;
6284+
}
6285+
#endif /* !NO_FILESYSTEM */
6286+
61686287
#ifndef NO_BIO
61696288
/* Create a private key object from the data in the BIO.
61706289
*

tests/api/test_ossl_pem.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,104 @@ int test_wolfSSL_PEM_PrivateKey(void)
755755
return EXPECT_RESULT();
756756
}
757757

758+
int test_wolfSSL_PEM_write_PrivateKey_PUBKEY(void)
759+
{
760+
EXPECT_DECLS;
761+
#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_RSA) && \
762+
!defined(NO_FILESYSTEM) && defined(USE_CERT_BUFFERS_2048) && \
763+
!defined(NO_ASN) && !defined(NO_PWDBASED)
764+
const char* privFile = "./test-pem-write-private-key.pem";
765+
const char* pubFile = "./test-pem-write-pubkey.pem";
766+
const unsigned char* serverKey =
767+
(const unsigned char*)server_key_der_2048;
768+
EVP_PKEY* pkey = NULL;
769+
EVP_PKEY* readPriv = NULL;
770+
EVP_PKEY* readPub = NULL;
771+
unsigned char* pubDer = NULL;
772+
unsigned char* readPubDer = NULL;
773+
XFILE fp = XBADFILE;
774+
long privSz = 0;
775+
long pubSz = 0;
776+
int pubDerSz = 0;
777+
int readPubDerSz = 0;
778+
779+
remove(privFile);
780+
remove(pubFile);
781+
782+
ExpectNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &serverKey,
783+
(long)sizeof_server_key_der_2048));
784+
785+
ExpectIntEQ(PEM_write_PrivateKey(XBADFILE, pkey, NULL, NULL, 0, NULL,
786+
NULL), 0);
787+
ExpectIntEQ(PEM_write_PrivateKey(stderr, NULL, NULL, NULL, 0, NULL,
788+
NULL), 0);
789+
ExpectIntEQ(PEM_write_PUBKEY(XBADFILE, pkey), 0);
790+
ExpectIntEQ(PEM_write_PUBKEY(stderr, NULL), 0);
791+
792+
ExpectTrue((fp = XFOPEN(privFile, "wb")) != XBADFILE);
793+
if (fp != XBADFILE) {
794+
ExpectIntEQ(PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL),
795+
1);
796+
XFCLOSE(fp);
797+
fp = XBADFILE;
798+
}
799+
800+
ExpectTrue((fp = XFOPEN(privFile, "rb")) != XBADFILE);
801+
if (fp != XBADFILE) {
802+
ExpectTrue(XFSEEK(fp, 0, XSEEK_END) == 0);
803+
ExpectIntGT(privSz = XFTELL(fp), 0);
804+
ExpectTrue(XFSEEK(fp, 0, XSEEK_SET) == 0);
805+
ExpectNotNull(readPriv = PEM_read_PrivateKey(fp, NULL, NULL, NULL));
806+
XFCLOSE(fp);
807+
fp = XBADFILE;
808+
}
809+
if ((pkey != NULL) && (readPriv != NULL) && (pkey->pkey.ptr != NULL) &&
810+
(readPriv->pkey.ptr != NULL)) {
811+
ExpectIntEQ(pkey->pkey_sz, readPriv->pkey_sz);
812+
ExpectIntEQ(XMEMCMP(pkey->pkey.ptr, readPriv->pkey.ptr,
813+
pkey->pkey_sz), 0);
814+
}
815+
816+
ExpectIntGT(pubDerSz = wolfSSL_i2d_PUBKEY(pkey, &pubDer), 0);
817+
ExpectTrue((fp = XFOPEN(pubFile, "wb")) != XBADFILE);
818+
if (fp != XBADFILE) {
819+
ExpectIntEQ(PEM_write_PUBKEY(fp, pkey), 1);
820+
XFCLOSE(fp);
821+
fp = XBADFILE;
822+
}
823+
824+
ExpectTrue((fp = XFOPEN(pubFile, "rb")) != XBADFILE);
825+
if (fp != XBADFILE) {
826+
ExpectTrue(XFSEEK(fp, 0, XSEEK_END) == 0);
827+
ExpectIntGT(pubSz = XFTELL(fp), 0);
828+
ExpectTrue(XFSEEK(fp, 0, XSEEK_SET) == 0);
829+
ExpectNotNull(readPub = PEM_read_PUBKEY(fp, NULL, NULL, NULL));
830+
XFCLOSE(fp);
831+
fp = XBADFILE;
832+
}
833+
ExpectIntGT(readPubDerSz = wolfSSL_i2d_PUBKEY(readPub, &readPubDer), 0);
834+
ExpectIntEQ(pubDerSz, readPubDerSz);
835+
if ((pubDer != NULL) && (readPubDer != NULL) && (pubDerSz > 0) &&
836+
(pubDerSz == readPubDerSz)) {
837+
ExpectIntEQ(XMEMCMP(pubDer, readPubDer, pubDerSz), 0);
838+
}
839+
840+
ExpectIntGT(privSz, pubSz);
841+
842+
XFREE(readPubDer, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
843+
XFREE(pubDer, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
844+
EVP_PKEY_free(readPub);
845+
EVP_PKEY_free(readPriv);
846+
EVP_PKEY_free(pkey);
847+
if (fp != XBADFILE) {
848+
XFCLOSE(fp);
849+
}
850+
remove(privFile);
851+
remove(pubFile);
852+
#endif
853+
return EXPECT_RESULT();
854+
}
855+
758856
int test_wolfSSL_PEM_file_RSAKey(void)
759857
{
760858
EXPECT_DECLS;

tests/api/test_ossl_pem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ int test_wolfSSL_PEM_PrivateKey_ecc(void);
3232
int test_wolfSSL_PEM_PrivateKey_dsa(void);
3333
int test_wolfSSL_PEM_PrivateKey_dh(void);
3434
int test_wolfSSL_PEM_PrivateKey(void);
35+
int test_wolfSSL_PEM_write_PrivateKey_PUBKEY(void);
3536
int test_wolfSSL_PEM_file_RSAKey(void);
3637
int test_wolfSSL_PEM_file_RSAPrivateKey(void);
3738
int test_wolfSSL_PEM_read_RSA_PUBKEY(void);
@@ -52,6 +53,7 @@ int test_wolfSSL_PEM_PUBKEY(void);
5253
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_PrivateKey_dsa), \
5354
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_PrivateKey_dh), \
5455
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_PrivateKey), \
56+
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_write_PrivateKey_PUBKEY), \
5557
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_file_RSAKey), \
5658
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_file_RSAPrivateKey), \
5759
TEST_DECL_GROUP("ossl_pem", test_wolfSSL_PEM_read_RSA_PUBKEY), \

wolfssl/openssl/pem.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,13 @@ WOLFSSL_API
231231
int wolfSSL_PEM_write_X509(XFILE fp, WOLFSSL_X509 *x);
232232
WOLFSSL_API
233233
int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh);
234+
WOLFSSL_API
235+
int wolfSSL_PEM_write_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY* key,
236+
const WOLFSSL_EVP_CIPHER* cipher,
237+
unsigned char* passwd, int len,
238+
wc_pem_password_cb* cb, void* arg);
239+
WOLFSSL_API
240+
int wolfSSL_PEM_write_PUBKEY(XFILE fp, WOLFSSL_EVP_PKEY* key);
234241
#endif /* NO_FILESYSTEM */
235242

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

245252
#define PEM_read_X509 wolfSSL_PEM_read_X509
246253
#define PEM_read_PrivateKey wolfSSL_PEM_read_PrivateKey
254+
#define PEM_write_PrivateKey wolfSSL_PEM_write_PrivateKey
247255
#define PEM_write_X509 wolfSSL_PEM_write_X509
248256
#define PEM_write_bio_PrivateKey wolfSSL_PEM_write_bio_PrivateKey
249257
#define PEM_write_bio_PKCS8PrivateKey wolfSSL_PEM_write_bio_PKCS8PrivateKey
@@ -287,6 +295,7 @@ int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh);
287295
#define PEM_read_PUBKEY wolfSSL_PEM_read_PUBKEY
288296
#define PEM_read_bio_PUBKEY wolfSSL_PEM_read_bio_PUBKEY
289297
#define PEM_write_bio_PUBKEY wolfSSL_PEM_write_bio_PUBKEY
298+
#define PEM_write_PUBKEY wolfSSL_PEM_write_PUBKEY
290299

291300
#define PEM_write_bio_PKCS8_PRIV_KEY_INFO wolfSSL_PEM_write_bio_PKCS8_PRIV_KEY_INFO
292301
#define PEM_read_bio_PKCS8_PRIV_KEY_INFO wolfSSL_PEM_read_bio_PKCS8_PRIV_KEY_INFO

0 commit comments

Comments
 (0)