From: Tomas Mraz Date: Wed, 26 Oct 2022 09:29:49 +0000 (+0200) Subject: When using PEM_read_bio_PrivateKey_ex() the public key is optional X-Git-Tag: openssl-3.2.0-alpha1~1663 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=adb408dc791e83f59f3a86bd90d8e804c814ac30;p=thirdparty%2Fopenssl.git When using PEM_read_bio_PrivateKey_ex() the public key is optional Fixes #19498 However the private key part is not optional which was mishandled by the legacy routine. Reviewed-by: Matt Caswell Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/19505) --- diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c index 8ffeed9d788..3e76852c67a 100644 --- a/crypto/pem/pem_pkey.c +++ b/crypto/pem/pem_pkey.c @@ -75,6 +75,10 @@ static EVP_PKEY *pem_read_bio_key_decoder(BIO *bp, EVP_PKEY **x, } ERR_pop_to_mark(); + /* if we were asked for private key, the public key is optional */ + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) + selection = selection & ~OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + if (!evp_keymgmt_util_has(pkey, selection)) { EVP_PKEY_free(pkey); pkey = NULL; @@ -106,7 +110,7 @@ static EVP_PKEY *pem_read_bio_key_legacy(BIO *bp, EVP_PKEY **x, EVP_PKEY *ret = NULL; ERR_set_mark(); /* not interested in PEM read errors */ - if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) { + if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { if (!PEM_bytes_read_bio_secmem(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u)) { @@ -116,7 +120,7 @@ static EVP_PKEY *pem_read_bio_key_legacy(BIO *bp, EVP_PKEY **x, } else { const char *pem_string = PEM_STRING_PARAMETERS; - if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) + if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) pem_string = PEM_STRING_PUBLIC; if (!PEM_bytes_read_bio(&data, &len, &nm, pem_string, @@ -174,9 +178,13 @@ static EVP_PKEY *pem_read_bio_key_legacy(BIO *bp, EVP_PKEY **x, goto p8err; ret = ossl_d2i_PrivateKey_legacy(ameth->pkey_id, x, &p, len, libctx, propq); - } else if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) { + } else if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0 + && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { + /* Trying legacy PUBKEY decoding only if we do not want private key. */ ret = ossl_d2i_PUBKEY_legacy(x, &p, len); - } else if ((slen = ossl_pem_check_suffix(nm, "PARAMETERS")) > 0) { + } else if ((selection & EVP_PKEY_KEYPAIR) == 0 + && (slen = ossl_pem_check_suffix(nm, "PARAMETERS")) > 0) { + /* Trying legacy params decoding only if we do not want a key. */ ret = EVP_PKEY_new(); if (ret == NULL) goto err; @@ -294,6 +302,7 @@ EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x, OSSL_LIB_CTX *libctx, const char *propq) { return pem_read_bio_key(bp, x, cb, u, libctx, propq, + /* we also want the public key, if available */ EVP_PKEY_KEYPAIR); }