mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 18:00:48 +02:00
Merge pull request #10317 from Roy-Carter/feature/pem_write_enhancement
Implementation for PEM_write_PrivateKey & PEM_write_PUBKEY
This commit is contained in:
@@ -292,11 +292,10 @@ 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(NO_FILESYSTEM) && \
|
||||
((defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN) && \
|
||||
!defined(NO_PWDBASED)) || \
|
||||
defined(WOLFSSL_DH_EXTRA))
|
||||
/* Write the DER data as PEM into file pointer.
|
||||
*
|
||||
* @param [in] der Buffer containing DER data.
|
||||
@@ -326,8 +325,9 @@ 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 /* !NO_FILESYSTEM &&
|
||||
* ((OPENSSL_EXTRA && !NO_CERTS && !NO_ASN && !NO_PWDBASED) ||
|
||||
* WOLFSSL_DH_EXTRA) */
|
||||
|
||||
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_KEY_GEN) && \
|
||||
defined(WOLFSSL_PEM_TO_DER)
|
||||
@@ -6282,6 +6282,166 @@ int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key,
|
||||
}
|
||||
#endif /* !NO_BIO */
|
||||
|
||||
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && \
|
||||
!defined(NO_ASN) && !defined(NO_PWDBASED)
|
||||
/* 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");
|
||||
|
||||
if ((fp == XBADFILE) || (key == NULL)) {
|
||||
WOLFSSL_MSG("Bad Function Arguments");
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
derSz = wolfSSL_i2d_PUBKEY(key, NULL);
|
||||
if (derSz <= 0) {
|
||||
WOLFSSL_MSG("Failed to get DER size for key");
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
unsigned char* tmp;
|
||||
derBuf = (unsigned char*)XMALLOC((size_t)derSz, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (derBuf == NULL) {
|
||||
WOLFSSL_MSG("Failed to allocate DER buffer");
|
||||
err = 1;
|
||||
}
|
||||
else {
|
||||
tmp = derBuf;
|
||||
if (wolfSSL_i2d_PUBKEY(key, &tmp) <= 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
derSz = wolfSSL_i2d_PrivateKey(key, NULL);
|
||||
if (derSz <= 0) {
|
||||
WOLFSSL_MSG("Failed to get DER size for private key");
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
unsigned char* tmp;
|
||||
derBuf = (unsigned char*)XMALLOC((size_t)derSz, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (derBuf == NULL) {
|
||||
WOLFSSL_MSG("Failed to allocate DER buffer");
|
||||
err = 1;
|
||||
}
|
||||
else {
|
||||
tmp = derBuf;
|
||||
if (wolfSSL_i2d_PrivateKey(key, &tmp) <= 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_FILESYSTEM && !NO_CERTS && OPENSSL_EXTRA && !NO_ASN &&
|
||||
* !NO_PWDBASED */
|
||||
|
||||
#ifndef NO_BIO
|
||||
/* Create a private key object from the data in the BIO.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
@@ -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), \
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user