summaryrefslogtreecommitdiffstats
path: root/crypto/pem
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-08-27 10:07:09 +0200
committerRichard Levitte <levitte@openssl.org>2020-09-08 16:45:11 +0200
commit4ce1025a8ac37d255f569147116dd776f9267cce (patch)
treeb89c84f89e808f6cfd6be703bf33e323507f5587 /crypto/pem
parent924663c36d47066d5307937da77fed7e872730c7 (diff)
PEM: Make PEM_write_bio_PrivateKey_traditional() handle provider-native keys
PEM_write_bio_PrivateKey_traditional() didn't handle provider-native keys very well. Originally, it would simply use the corresponding encoder, which is likely to output modern PEM (not "traditional"). PEM_write_bio_PrivateKey_traditional() is now changed to try and get a legacy copy of the input EVP_PKEY, and use that copy for traditional output, if it has such support. Internally, evp_pkey_copy_downgraded() is added, to be used when evp_pkey_downgrade() is too intrusive for what it's needed for. Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/12738)
Diffstat (limited to 'crypto/pem')
-rw-r--r--crypto/pem/pem_pkey.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c
index 8b9bfe101e..462010d2ac 100644
--- a/crypto/pem/pem_pkey.c
+++ b/crypto/pem/pem_pkey.c
@@ -165,20 +165,36 @@ PEM_write_cb_fnsig(PrivateKey, EVP_PKEY, BIO, write_bio)
return PEM_write_bio_PrivateKey_traditional(out, x, enc, kstr, klen, cb, u);
}
+/*
+ * Note: there is no way to tell a provided pkey encoder to use "traditional"
+ * encoding. Therefore, if the pkey is provided, we try to take a copy
+ * TODO: when #legacy keys are gone, this function will not be possible any
+ * more and should be removed.
+ */
int PEM_write_bio_PrivateKey_traditional(BIO *bp, const EVP_PKEY *x,
const EVP_CIPHER *enc,
const unsigned char *kstr, int klen,
pem_password_cb *cb, void *u)
{
char pem_str[80];
+ EVP_PKEY *copy = NULL;
+ int ret;
+
+ if (evp_pkey_is_assigned(x)
+ && evp_pkey_is_provided(x)
+ && evp_pkey_copy_downgraded(&copy, x))
+ x = copy;
if (x->ameth == NULL || x->ameth->old_priv_encode == NULL) {
ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return 0;
}
BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str);
- return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
- pem_str, bp, x, enc, kstr, klen, cb, u);
+ ret = PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
+ pem_str, bp, x, enc, kstr, klen, cb, u);
+
+ EVP_PKEY_free(copy);
+ return ret;
}
EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x,