diff options
author | Richard Levitte <levitte@openssl.org> | 2020-08-27 10:07:09 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-09-08 16:45:11 +0200 |
commit | 4ce1025a8ac37d255f569147116dd776f9267cce (patch) | |
tree | b89c84f89e808f6cfd6be703bf33e323507f5587 /crypto/pem | |
parent | 924663c36d47066d5307937da77fed7e872730c7 (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.c | 20 |
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(©, 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, |