[openssl] master update

Richard Levitte levitte at openssl.org
Thu Aug 20 10:38:24 UTC 2020


The branch master has been updated
       via  5f2b7db09b6f9650ecf2b465ee9f737385623bd5 (commit)
       via  6e5ccd58c85f05f8d47a1682125a207dbc694768 (commit)
       via  2274d22d39fd65b83c9c969cba86c8f03b3e0bec (commit)
      from  6cc1dfca88c565ddacd9ea9aa8261ef9c0c37335 (commit)


- Log -----------------------------------------------------------------
commit 5f2b7db09b6f9650ecf2b465ee9f737385623bd5
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Aug 18 21:45:19 2020 +0200

    TEST: Use PEM_read_bio_PUBKEY_ex() and PEM_read_bio_PrivateKey_ex()
    
    test/evp_test.c and test/sslapitest.c are affected.  This allows them
    to decode keys found in stanza files via provider decoder implementations
    when a library context other than the default should be used.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12673)

commit 6e5ccd58c85f05f8d47a1682125a207dbc694768
Author: Richard Levitte <levitte at openssl.org>
Date:   Tue Aug 18 21:38:56 2020 +0200

    PEM: Add more library context aware PEM readers
    
    PEM_read_bio_PUBKEY_ex() and PEM_read_bio_Parameters_ex() are added to
    complete PEM_read_bio_PrivateKey_ex().  They are all refactored to be
    wrappers around the same internal function.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12673)

commit 2274d22d39fd65b83c9c969cba86c8f03b3e0bec
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Jul 30 10:09:43 2020 +0200

    STORE: Distinguish public keys from private keys
    
    While public keys and private keys use the same type (EVP_PKEY), just
    with different contents, callers still need to distinguish between the
    two to be able to know what functions to call with them (for example,
    to be able to choose between EVP_PKEY_print_private() and
    EVP_PKEY_print_public()).
    The OSSL_STORE backend knows what it loaded, so it has the capacity to
    inform.
    
    Note that the same as usual still applies, that a private key EVP_PKEY
    contains the public parts, but not necessarily the other way around.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12673)

-----------------------------------------------------------------------

Summary of changes:
 apps/include/apps.h                  |   3 +-
 apps/lib/apps.c                      |  30 +++++++--
 apps/storeutl.c                      |   7 ++
 crypto/err/openssl.txt               |   3 +-
 crypto/pem/pem_all.c                 |   1 -
 crypto/pem/pem_pkey.c                | 123 +++++++++++++++++++++++++----------
 crypto/store/loader_file.c           |   2 +-
 crypto/store/store_err.c             |   5 +-
 crypto/store/store_lib.c             |  31 ++++++++-
 crypto/store/store_local.h           |   1 +
 crypto/store/store_strings.c         |   1 +
 doc/man3/OSSL_STORE_INFO.pod         |  43 +++++++-----
 doc/man3/PEM_read_bio_PrivateKey.pod |  20 ++++--
 include/openssl/pem.h                |  22 +++++--
 include/openssl/store.h              |  10 ++-
 include/openssl/storeerr.h           |   3 +-
 test/evp_test.c                      |   2 +-
 test/sslapitest.c                    |   9 ++-
 util/libcrypto.num                   |   6 ++
 19 files changed, 240 insertions(+), 82 deletions(-)

diff --git a/apps/include/apps.h b/apps/include/apps.h
index 0ee8e070cd..0e734a528e 100644
--- a/apps/include/apps.h
+++ b/apps/include/apps.h
@@ -119,7 +119,8 @@ int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
               const char *pass, const char *desc);
 int load_key_cert_crl(const char *uri, int maybe_stdin,
                       const char *pass, const char *desc,
-                      EVP_PKEY **ppkey, X509 **pcert, X509_CRL **pcrl);
+                      EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+                      X509 **pcert, X509_CRL **pcrl);
 X509_STORE *setup_verify(const char *CAfile, int noCAfile,
                          const char *CApath, int noCApath,
                          const char *CAstore, int noCAstore);
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index e8592c4880..d19fdc2126 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -491,7 +491,8 @@ X509 *load_cert_pass(const char *uri, int maybe_stdin,
 
     if (desc == NULL)
         desc = "certificate";
-    (void)load_key_cert_crl(uri, maybe_stdin, pass, desc, NULL, &cert, NULL);
+    (void)load_key_cert_crl(uri, maybe_stdin, pass, desc,
+                            NULL, NULL, &cert, NULL);
     if (cert == NULL) {
         BIO_printf(bio_err, "Unable to load %s\n", desc);
         ERR_print_errors(bio_err);
@@ -512,7 +513,8 @@ X509_CRL *load_crl(const char *uri, int format, const char *desc)
 
     if (desc == NULL)
         desc = "CRL";
-    (void)load_key_cert_crl(uri, 0, NULL, desc, NULL, NULL, &crl);
+    (void)load_key_cert_crl(uri, 0, NULL, desc,
+                            NULL, NULL, NULL, &crl);
     if (crl == NULL) {
         BIO_printf(bio_err, "Unable to load %s\n", desc);
         ERR_print_errors(bio_err);
@@ -591,7 +593,8 @@ EVP_PKEY *load_key(const char *uri, int format, int may_stdin,
 #endif
         }
     } else {
-        (void)load_key_cert_crl(uri, may_stdin, pass, desc, &pkey, NULL, NULL);
+        (void)load_key_cert_crl(uri, may_stdin, pass, desc,
+                                &pkey, NULL, NULL, NULL);
     }
 
     if (pkey == NULL) {
@@ -629,8 +632,8 @@ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
 #endif
         }
     } else {
-        (void)load_key_cert_crl(uri, maybe_stdin, pass, desc, &pkey,
-                                NULL, NULL);
+        (void)load_key_cert_crl(uri, maybe_stdin, pass, desc,
+                                NULL, &pkey, NULL, NULL);
     }
     if (pkey == NULL) {
         BIO_printf(bio_err, "Unable to load %s\n", desc);
@@ -769,7 +772,8 @@ int load_crls(const char *file, STACK_OF(X509_CRL) **crls, int format,
  */
 int load_key_cert_crl(const char *uri, int maybe_stdin,
                       const char *pass, const char *desc,
-                      EVP_PKEY **ppkey, X509 **pcert, X509_CRL **pcrl)
+                      EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+                      X509 **pcert, X509_CRL **pcrl)
 {
     PW_CB_DATA uidata;
     OSSL_STORE_CTX *ctx = NULL;
@@ -780,6 +784,8 @@ int load_key_cert_crl(const char *uri, int maybe_stdin,
 
     if (ppkey != NULL)
         *ppkey = NULL;
+    if (ppubkey != NULL)
+        *ppubkey = NULL;
     if (pcert != NULL)
         *pcert = NULL;
     if (pcrl != NULL)
@@ -831,6 +837,18 @@ int load_key_cert_crl(const char *uri, int maybe_stdin,
         case OSSL_STORE_INFO_PKEY:
             if (ppkey != NULL && *ppkey == NULL)
                 err = ((*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL);
+
+            /*
+             * An EVP_PKEY with private parts also holds the public parts,
+             * so if the caller asked for a public key, and we got a private
+             * key, we can still pass it back.
+             */
+            if (ppubkey != NULL && *ppubkey == NULL)
+                err = ((*ppubkey = OSSL_STORE_INFO_get1_PKEY(info)) == NULL);
+            break;
+        case OSSL_STORE_INFO_PUBKEY:
+            if (ppubkey != NULL && *ppubkey == NULL)
+                err = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) == NULL);
             break;
         case OSSL_STORE_INFO_CERT:
             if (pcert != NULL && *pcert == NULL)
diff --git a/apps/storeutl.c b/apps/storeutl.c
index 66fd423ab0..3d9498dc46 100644
--- a/apps/storeutl.c
+++ b/apps/storeutl.c
@@ -450,6 +450,13 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
                 PEM_write_bio_Parameters(out,
                                          OSSL_STORE_INFO_get0_PARAMS(info));
             break;
+        case OSSL_STORE_INFO_PUBKEY:
+            if (text)
+                EVP_PKEY_print_public(out, OSSL_STORE_INFO_get0_PUBKEY(info),
+                                      0, NULL);
+            if (!noout)
+                PEM_write_bio_PUBKEY(out, OSSL_STORE_INFO_get0_PUBKEY(info));
+            break;
         case OSSL_STORE_INFO_PKEY:
             if (text)
                 EVP_PKEY_print_private(out, OSSL_STORE_INFO_get0_PKEY(info),
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 7431248d8f..e83f1013ec 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2717,8 +2717,9 @@ OSSL_STORE_R_LOADER_INCOMPLETE:116:loader incomplete
 OSSL_STORE_R_LOADING_STARTED:117:loading started
 OSSL_STORE_R_NOT_A_CERTIFICATE:100:not a certificate
 OSSL_STORE_R_NOT_A_CRL:101:not a crl
-OSSL_STORE_R_NOT_A_KEY:102:not a key
 OSSL_STORE_R_NOT_A_NAME:103:not a name
+OSSL_STORE_R_NOT_A_PRIVATE_KEY:102:not a private key
+OSSL_STORE_R_NOT_A_PUBLIC_KEY:122:not a public key
 OSSL_STORE_R_NOT_PARAMETERS:104:not parameters
 OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR:114:passphrase callback error
 OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE:108:path must be absolute
diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c
index 9b803082c6..bf7159a6ad 100644
--- a/crypto/pem/pem_all.c
+++ b/crypto/pem/pem_all.c
@@ -181,4 +181,3 @@ IMPLEMENT_PEM_write(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
 IMPLEMENT_PEM_write(DHxparams, DH, PEM_STRING_DHXPARAMS, DHxparams)
 #endif
 IMPLEMENT_PEM_provided_write(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
-IMPLEMENT_PEM_read(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c
index c60eed97c0..4ee5bb7009 100644
--- a/crypto/pem/pem_pkey.c
+++ b/crypto/pem/pem_pkey.c
@@ -27,23 +27,39 @@
 
 int pem_check_suffix(const char *pem_str, const char *suffix);
 
-EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
-                                     void *u, OPENSSL_CTX *libctx,
-                                     const char *propq)
+static EVP_PKEY *pem_read_bio_key(BIO *bp, EVP_PKEY **x,
+                                  pem_password_cb *cb, void *u,
+                                  OPENSSL_CTX *libctx, const char *propq,
+                                  int expected_store_info_type,
+                                  int try_secure)
 {
     EVP_PKEY *ret = NULL;
     OSSL_STORE_CTX *ctx = NULL;
     OSSL_STORE_INFO *info = NULL;
-    UI_METHOD *ui_method = NULL;
+    const UI_METHOD *ui_method = NULL;
+    UI_METHOD *allocated_ui_method = NULL;
 
-    if ((ui_method = UI_UTIL_wrap_read_pem_callback(cb, 0)) == NULL)
+    if (expected_store_info_type != OSSL_STORE_INFO_PKEY
+        && expected_store_info_type != OSSL_STORE_INFO_PUBKEY
+        && expected_store_info_type != OSSL_STORE_INFO_PARAMS) {
+        ERR_raise(ERR_LIB_PEM, ERR_R_PASSED_INVALID_ARGUMENT);
+        return NULL;
+    }
+
+    if (u != NULL && cb == NULL)
+        cb = PEM_def_callback;
+    if (cb == NULL)
+        ui_method = UI_null();
+    else
+        ui_method = allocated_ui_method = UI_UTIL_wrap_read_pem_callback(cb, 0);
+    if (ui_method == NULL)
         return NULL;
 
     if ((ctx = OSSL_STORE_attach(bp, "file", libctx, propq, ui_method, u,
                                  NULL, NULL)) == NULL)
         goto err;
 #ifndef OPENSSL_NO_SECURE_HEAP
-    {
+   if (try_secure) {
         int on = 1;
         if (!OSSL_STORE_ctrl(ctx, OSSL_STORE_C_USE_SECMEM, &on))
             goto err;
@@ -52,9 +68,18 @@ EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
 
     while (!OSSL_STORE_eof(ctx)
            && (info = OSSL_STORE_load(ctx)) != NULL) {
-        if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) {
-            ret = OSSL_STORE_INFO_get1_PKEY(info);
-            break;
+        if (OSSL_STORE_INFO_get_type(info) == expected_store_info_type) {
+            switch (expected_store_info_type) {
+            case OSSL_STORE_INFO_PKEY:
+                ret = OSSL_STORE_INFO_get1_PKEY(info);
+                break;
+            case OSSL_STORE_INFO_PUBKEY:
+                ret = OSSL_STORE_INFO_get1_PUBKEY(info);
+                break;
+            case OSSL_STORE_INFO_PARAMS:
+                ret = OSSL_STORE_INFO_get1_PARAMS(info);
+                break;
+            }
         }
         OSSL_STORE_INFO_free(info);
         info = NULL;
@@ -65,11 +90,57 @@ EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
 
  err:
     OSSL_STORE_close(ctx);
-    UI_destroy_method(ui_method);
+    UI_destroy_method(allocated_ui_method);
     OSSL_STORE_INFO_free(info);
     return ret;
 }
 
+EVP_PKEY *PEM_read_bio_PUBKEY_ex(BIO *bp, EVP_PKEY **x,
+                                 pem_password_cb *cb, void *u,
+                                 OPENSSL_CTX *libctx, const char *propq)
+{
+    return pem_read_bio_key(bp, x, cb, u, libctx, propq,
+                            OSSL_STORE_INFO_PUBKEY, 0);
+}
+
+EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
+                              void *u)
+{
+    return PEM_read_bio_PUBKEY_ex(bp, x, cb, u, NULL, NULL);
+}
+
+#ifndef OPENSSL_NO_STDIO
+EVP_PKEY *PEM_read_PUBKEY_ex(FILE *fp, EVP_PKEY **x,
+                             pem_password_cb *cb, void *u,
+                             OPENSSL_CTX *libctx, const char *propq)
+{
+    BIO *b;
+    EVP_PKEY *ret;
+
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        PEMerr(0, ERR_R_BUF_LIB);
+        return 0;
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = PEM_read_bio_PUBKEY_ex(b, x, cb, u, libctx, propq);
+    BIO_free(b);
+    return ret;
+}
+
+EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+{
+    return PEM_read_PUBKEY_ex(fp, x, cb, u, NULL, NULL);
+}
+#endif
+
+EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x,
+                                     pem_password_cb *cb, void *u,
+                                     OPENSSL_CTX *libctx, const char *propq)
+{
+    return pem_read_bio_key(bp, x, cb, u, libctx, propq,
+                            OSSL_STORE_INFO_PKEY, 1);
+}
+
 EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
                                   void *u)
 {
@@ -101,32 +172,16 @@ int PEM_write_bio_PrivateKey_traditional(BIO *bp, const EVP_PKEY *x,
                               pem_str, bp, x, enc, kstr, klen, cb, u);
 }
 
-EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x)
+EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x,
+                                     OPENSSL_CTX *libctx, const char *propq)
 {
-    EVP_PKEY *ret = NULL;
-    OSSL_STORE_CTX *ctx = NULL;
-    OSSL_STORE_INFO *info = NULL;
-
-    if ((ctx = OSSL_STORE_attach(bp, "file", NULL, NULL, UI_null(), NULL,
-                                 NULL, NULL)) == NULL)
-        goto err;
-
-    while (!OSSL_STORE_eof(ctx) && (info = OSSL_STORE_load(ctx)) != NULL) {
-        if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PARAMS) {
-            ret = OSSL_STORE_INFO_get1_PARAMS(info);
-            break;
-        }
-        OSSL_STORE_INFO_free(info);
-        info = NULL;
-    }
-
-    if (ret != NULL && x != NULL)
-        *x = ret;
+    return pem_read_bio_key(bp, x, NULL, NULL, libctx, propq,
+                            OSSL_STORE_INFO_PARAMS, 0);
+}
 
- err:
-    OSSL_STORE_close(ctx);
-    OSSL_STORE_INFO_free(info);
-    return ret;
+EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x)
+{
+    return PEM_read_bio_Parameters_ex(bp, x, NULL, NULL);
 }
 
 PEM_write_fnsig(Parameters, EVP_PKEY, BIO, write_bio)
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c
index 3b54ebbcd5..25ce9ba92e 100644
--- a/crypto/store/loader_file.c
+++ b/crypto/store/loader_file.c
@@ -565,7 +565,7 @@ static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name,
 
     if ((pkey = d2i_PUBKEY(NULL, &blob, len)) != NULL) {
         *matchcount = 1;
-        store_info = OSSL_STORE_INFO_new_PKEY(pkey);
+        store_info = OSSL_STORE_INFO_new_PUBKEY(pkey);
     }
 
     return store_info;
diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c
index 3abb50bb21..320934e6c6 100644
--- a/crypto/store/store_err.c
+++ b/crypto/store/store_err.c
@@ -32,8 +32,11 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = {
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CERTIFICATE),
     "not a certificate"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_CRL), "not a crl"},
-    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_KEY), "not a key"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_NAME), "not a name"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_PRIVATE_KEY),
+    "not a private key"},
+    {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_A_PUBLIC_KEY),
+    "not a public key"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_NOT_PARAMETERS),
     "not parameters"},
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR),
diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c
index 2878358245..2ff92b7984 100644
--- a/crypto/store/store_lib.c
+++ b/crypto/store/store_lib.c
@@ -307,6 +307,15 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params)
     return info;
 }
 
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pkey)
+{
+    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PUBKEY, pkey);
+
+    if (info == NULL)
+        ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
+    return info;
+}
+
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
 {
     OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PKEY, pkey);
@@ -408,6 +417,23 @@ EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info)
     return NULL;
 }
 
+EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_PUBKEY)
+        return info->_.pubkey;
+    return NULL;
+}
+
+EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info)
+{
+    if (info->type == OSSL_STORE_INFO_PUBKEY) {
+        EVP_PKEY_up_ref(info->_.pubkey);
+        return info->_.pubkey;
+    }
+    OSSL_STOREerr(0, OSSL_STORE_R_NOT_A_PUBLIC_KEY);
+    return NULL;
+}
+
 EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info)
 {
     if (info->type == OSSL_STORE_INFO_PKEY)
@@ -422,7 +448,7 @@ EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info)
         return info->_.pkey;
     }
     OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_INFO_GET1_PKEY,
-                  OSSL_STORE_R_NOT_A_KEY);
+                  OSSL_STORE_R_NOT_A_PRIVATE_KEY);
     return NULL;
 }
 
@@ -480,6 +506,9 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
         case OSSL_STORE_INFO_PARAMS:
             EVP_PKEY_free(info->_.params);
             break;
+        case OSSL_STORE_INFO_PUBKEY:
+            EVP_PKEY_free(info->_.pubkey);
+            break;
         case OSSL_STORE_INFO_PKEY:
             EVP_PKEY_free(info->_.pkey);
             break;
diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h
index c9592c38ce..47cba87f86 100644
--- a/crypto/store/store_local.h
+++ b/crypto/store/store_local.h
@@ -36,6 +36,7 @@ struct ossl_store_info_st {
         } name;                  /* when type == OSSL_STORE_INFO_NAME */
 
         EVP_PKEY *params;        /* when type == OSSL_STORE_INFO_PARAMS */
+        EVP_PKEY *pubkey;        /* when type == OSSL_STORE_INFO_PUBKEY */
         EVP_PKEY *pkey;          /* when type == OSSL_STORE_INFO_PKEY */
         X509 *x509;              /* when type == OSSL_STORE_INFO_CERT */
         X509_CRL *crl;           /* when type == OSSL_STORE_INFO_CRL */
diff --git a/crypto/store/store_strings.c b/crypto/store/store_strings.c
index 84cfdcfe6b..97497c8a78 100644
--- a/crypto/store/store_strings.c
+++ b/crypto/store/store_strings.c
@@ -12,6 +12,7 @@
 static char *type_strings[] = {
     "Name",                      /* OSSL_STORE_INFO_NAME */
     "Parameters",                /* OSSL_STORE_INFO_PARAMS */
+    "Public key",                /* OSSL_STORE_INFO_PUBKEY */
     "Pkey",                      /* OSSL_STORE_INFO_PKEY */
     "Certificate",               /* OSSL_STORE_INFO_CERT */
     "CRL"                        /* OSSL_STORE_INFO_CRL */
diff --git a/doc/man3/OSSL_STORE_INFO.pod b/doc/man3/OSSL_STORE_INFO.pod
index c331677954..bc965a77bd 100644
--- a/doc/man3/OSSL_STORE_INFO.pod
+++ b/doc/man3/OSSL_STORE_INFO.pod
@@ -3,15 +3,17 @@
 =head1 NAME
 
 OSSL_STORE_INFO, OSSL_STORE_INFO_get_type, OSSL_STORE_INFO_get0_NAME,
-OSSL_STORE_INFO_get0_NAME_description, OSSL_STORE_INFO_get0_PARAMS,
+OSSL_STORE_INFO_get0_NAME_description,
+OSSL_STORE_INFO_get0_PARAMS, OSSL_STORE_INFO_get0_PUBKEY,
 OSSL_STORE_INFO_get0_PKEY, OSSL_STORE_INFO_get0_CERT, OSSL_STORE_INFO_get0_CRL,
 OSSL_STORE_INFO_get1_NAME, OSSL_STORE_INFO_get1_NAME_description,
-OSSL_STORE_INFO_get1_PARAMS, OSSL_STORE_INFO_get1_PKEY,
-OSSL_STORE_INFO_get1_CERT,
-OSSL_STORE_INFO_get1_CRL, OSSL_STORE_INFO_type_string, OSSL_STORE_INFO_free,
+OSSL_STORE_INFO_get1_PARAMS, OSSL_STORE_INFO_get1_PUBKEY,
+OSSL_STORE_INFO_get1_PKEY, OSSL_STORE_INFO_get1_CERT, OSSL_STORE_INFO_get1_CRL,
+OSSL_STORE_INFO_type_string, OSSL_STORE_INFO_free,
 OSSL_STORE_INFO_new_NAME, OSSL_STORE_INFO_set0_NAME_description,
-OSSL_STORE_INFO_new_PARAMS, OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT,
-OSSL_STORE_INFO_new_CRL - Functions to manipulate OSSL_STORE_INFO objects
+OSSL_STORE_INFO_new_PARAMS, OSSL_STORE_INFO_new_PUBKEY,
+OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT, OSSL_STORE_INFO_new_CRL
+- Functions to manipulate OSSL_STORE_INFO objects
 
 =head1 SYNOPSIS
 
@@ -27,6 +29,8 @@ OSSL_STORE_INFO_new_CRL - Functions to manipulate OSSL_STORE_INFO objects
  char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *store_info);
  EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *store_info);
  EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *store_info);
+ EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info);
+ EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info);
  EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *store_info);
  EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *store_info);
  X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *store_info);
@@ -41,6 +45,7 @@ OSSL_STORE_INFO_new_CRL - Functions to manipulate OSSL_STORE_INFO objects
  OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name);
  int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc);
  OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(DSA *dsa_params);
+ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pubkey);
  OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey);
  OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509);
  OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
@@ -76,23 +81,27 @@ STORE_INFO_get_type_string() takes a STORE type number and returns a
 short string describing it.
 
 OSSL_STORE_INFO_get0_NAME(), OSSL_STORE_INFO_get0_NAME_description(),
-OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PKEY(),
-OSSL_STORE_INFO_get0_CERT() and OSSL_STORE_INFO_get0_CRL() all take a
-B<OSSL_STORE_INFO> and return the held object of the appropriate OpenSSL
-type provided that's what's held.
+OSSL_STORE_INFO_get0_PARAMS(), OSSL_STORE_INFO_get0_PUBKEY(),
+OSSL_STORE_INFO_get0_PKEY(), OSSL_STORE_INFO_get0_CERT(),
+OSSL_STORE_INFO_get0_CRL()
+all take a B<OSSL_STORE_INFO> and return the object it holds if the
+B<OSSL_STORE_INFO> type (as returned by OSSL_STORE_INFO_get_type())
+matches the function, otherwise NULL.
 
 OSSL_STORE_INFO_get1_NAME(), OSSL_STORE_INFO_get1_NAME_description(),
-OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PKEY(),
-OSSL_STORE_INFO_get1_CERT() and OSSL_STORE_INFO_get1_CRL() all take a
-B<OSSL_STORE_INFO> and return a duplicate of the held object of the
-appropriate OpenSSL type provided that's what's held.
+OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PUBKEY(),
+OSSL_STORE_INFO_get1_PKEY(), OSSL_STORE_INFO_get1_CERT() and
+OSSL_STORE_INFO_get1_CRL()
+all take a B<OSSL_STORE_INFO> and return a duplicate the object it
+holds if the B<OSSL_STORE_INFO> type (as returned by
+OSSL_STORE_INFO_get_type()) matches the function, otherwise NULL.
 
 OSSL_STORE_INFO_free() frees a B<OSSL_STORE_INFO> and its contained type.
 
 OSSL_STORE_INFO_new_NAME() , OSSL_STORE_INFO_new_PARAMS(),
-OSSL_STORE_INFO_new_PKEY(), OSSL_STORE_INFO_new_CERT() and
-OSSL_STORE_INFO_new_CRL() create a B<OSSL_STORE_INFO>
-object to hold the given input object.
+, OSSL_STORE_INFO_new_PUBKEY(), OSSL_STORE_INFO_new_PKEY(),
+OSSL_STORE_INFO_new_CERT() and OSSL_STORE_INFO_new_CRL()
+create a B<OSSL_STORE_INFO> object to hold the given input object.
 On success the input object is consumed.
 
 Additionally, for B<OSSL_STORE_INFO_NAME>` objects,
diff --git a/doc/man3/PEM_read_bio_PrivateKey.pod b/doc/man3/PEM_read_bio_PrivateKey.pod
index 960a7df89e..26f03b5b0d 100644
--- a/doc/man3/PEM_read_bio_PrivateKey.pod
+++ b/doc/man3/PEM_read_bio_PrivateKey.pod
@@ -8,7 +8,8 @@ PEM_read_PrivateKey, PEM_write_bio_PrivateKey,
 PEM_write_bio_PrivateKey_traditional, PEM_write_PrivateKey,
 PEM_write_bio_PKCS8PrivateKey, PEM_write_PKCS8PrivateKey,
 PEM_write_bio_PKCS8PrivateKey_nid, PEM_write_PKCS8PrivateKey_nid,
-PEM_read_bio_PUBKEY, PEM_read_PUBKEY, PEM_write_bio_PUBKEY, PEM_write_PUBKEY,
+PEM_read_bio_PUBKEY_ex, PEM_read_bio_PUBKEY, PEM_read_PUBKEY_ex,
+PEM_read_PUBKEY, PEM_write_bio_PUBKEY, PEM_write_PUBKEY,
 PEM_read_bio_RSAPrivateKey, PEM_read_RSAPrivateKey,
 PEM_write_bio_RSAPrivateKey, PEM_write_RSAPrivateKey,
 PEM_read_bio_RSAPublicKey, PEM_read_RSAPublicKey, PEM_write_bio_RSAPublicKey,
@@ -16,8 +17,8 @@ PEM_write_RSAPublicKey, PEM_read_bio_RSA_PUBKEY, PEM_read_RSA_PUBKEY,
 PEM_write_bio_RSA_PUBKEY, PEM_write_RSA_PUBKEY, PEM_read_bio_DSAPrivateKey,
 PEM_read_DSAPrivateKey, PEM_write_bio_DSAPrivateKey, PEM_write_DSAPrivateKey,
 PEM_read_bio_DSA_PUBKEY, PEM_read_DSA_PUBKEY, PEM_write_bio_DSA_PUBKEY,
-PEM_write_DSA_PUBKEY, PEM_read_bio_Parameters, PEM_write_bio_Parameters,
-PEM_read_bio_DSAparams, PEM_read_DSAparams,
+PEM_write_DSA_PUBKEY, PEM_read_bio_Parameters_ex, PEM_read_bio_Parameters,
+PEM_write_bio_Parameters, PEM_read_bio_DSAparams, PEM_read_DSAparams,
 PEM_write_bio_DSAparams, PEM_write_DSAparams, PEM_read_bio_DHparams,
 PEM_read_DHparams, PEM_write_bio_DHparams, PEM_write_DHparams,
 PEM_read_bio_X509, PEM_read_X509, PEM_write_bio_X509, PEM_write_X509,
@@ -67,8 +68,14 @@ PEM_write_bio_PKCS7, PEM_write_PKCS7 - PEM routines
                                    char *kstr, int klen,
                                    pem_password_cb *cb, void *u);
 
+ EVP_PKEY *PEM_read_bio_PUBKEY_ex(BIO *bp, EVP_PKEY **x,
+                                  pem_password_cb *cb, void *u,
+                                  OPENSSL_CTX *libctx, const char *propq);
  EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x,
                                pem_password_cb *cb, void *u);
+ EVP_PKEY *PEM_read_PUBKEY_ex(FILE *fp, EVP_PKEY **x,
+                              pem_password_cb *cb, void *u,
+                              OPENSSL_CTX *libctx, const char *propq);
  EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x,
                            pem_password_cb *cb, void *u);
  int PEM_write_bio_PUBKEY(BIO *bp, EVP_PKEY *x);
@@ -117,6 +124,8 @@ PEM_write_bio_PKCS7, PEM_write_PKCS7 - PEM routines
  int PEM_write_bio_DSA_PUBKEY(BIO *bp, DSA *x);
  int PEM_write_DSA_PUBKEY(FILE *fp, DSA *x);
 
+ EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x,
+                                      OPENSSL_CTX *libctx, const char *propq);
  EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x);
  int PEM_write_bio_Parameters(BIO *bp, const EVP_PKEY *x);
 
@@ -506,8 +515,9 @@ The old Netscape certificate sequences were no longer documented
 in OpenSSL 1.1.0; applications should use the PKCS7 standard instead
 as they will be formally deprecated in a future releases.
 
-PEM_read_bio_PrivateKey_ex() and PEM_read_PrivateKey_ex() were introduced in
-OpenSSL 3.0.
+PEM_read_bio_PrivateKey_ex(), PEM_read_PrivateKey_ex(),
+PEM_read_bio_PUBKEY_ex(), PEM_read_PUBKEY_ex() and
+PEM_read_bio_Parameters_ex() were introduced in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/include/openssl/pem.h b/include/openssl/pem.h
index f4989e3987..6fbc28e0d3 100644
--- a/include/openssl/pem.h
+++ b/include/openssl/pem.h
@@ -356,15 +356,23 @@ DECLARE_PEM_rw(DHparams, DH)
 DECLARE_PEM_write(DHxparams, DH)
 # endif
 DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY)
-EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
-                                     void *u, OPENSSL_CTX *libctx,
-                                     const char *propq);
+EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x,
+                                     pem_password_cb *cb, void *u,
+                                     OPENSSL_CTX *libctx, const char *propq);
 # ifndef OPENSSL_NO_STDIO
-EVP_PKEY *PEM_read_PrivateKey_ex(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
-                                 void *u, OPENSSL_CTX *libctx,
-                                 const char *propq);
+EVP_PKEY *PEM_read_PrivateKey_ex(FILE *fp, EVP_PKEY **x,
+                                 pem_password_cb *cb, void *u,
+                                 OPENSSL_CTX *libctx, const char *propq);
 # endif
 DECLARE_PEM_rw(PUBKEY, EVP_PKEY)
+EVP_PKEY *PEM_read_bio_PUBKEY_ex(BIO *bp, EVP_PKEY **x,
+                                 pem_password_cb *cb, void *u,
+                                 OPENSSL_CTX *libctx, const char *propq);
+# ifndef OPENSSL_NO_STDIO
+EVP_PKEY *PEM_read_PUBKEY_ex(FILE *fp, EVP_PKEY **x,
+                             pem_password_cb *cb, void *u,
+                             OPENSSL_CTX *libctx, const char *propq);
+# endif
 
 int PEM_write_bio_PrivateKey_traditional(BIO *bp, const EVP_PKEY *x,
                                          const EVP_CIPHER *enc,
@@ -405,6 +413,8 @@ int PEM_write_PKCS8PrivateKey(FILE *fp, const EVP_PKEY *x, const EVP_CIPHER *enc
                               const char *kstr, int klen,
                               pem_password_cb *cd, void *u);
 # endif
+EVP_PKEY *PEM_read_bio_Parameters_ex(BIO *bp, EVP_PKEY **x,
+                                     OPENSSL_CTX *libctx, const char *propq);
 EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x);
 int PEM_write_bio_Parameters(BIO *bp, const EVP_PKEY *x);
 
diff --git a/include/openssl/store.h b/include/openssl/store.h
index d5e72a0963..b75c79868c 100644
--- a/include/openssl/store.h
+++ b/include/openssl/store.h
@@ -138,9 +138,10 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme,
  */
 # define OSSL_STORE_INFO_NAME           1   /* char * */
 # define OSSL_STORE_INFO_PARAMS         2   /* EVP_PKEY * */
-# define OSSL_STORE_INFO_PKEY           3   /* EVP_PKEY * */
-# define OSSL_STORE_INFO_CERT           4   /* X509 * */
-# define OSSL_STORE_INFO_CRL            5   /* X509_CRL * */
+# define OSSL_STORE_INFO_PUBKEY         3   /* EVP_PKEY * */
+# define OSSL_STORE_INFO_PKEY           4   /* EVP_PKEY * */
+# define OSSL_STORE_INFO_CERT           5   /* X509 * */
+# define OSSL_STORE_INFO_CRL            6   /* X509_CRL * */
 
 /*
  * Functions to generate OSSL_STORE_INFOs, one function for each type we
@@ -152,6 +153,7 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme,
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name);
 int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc);
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params);
+OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pubkey);
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey);
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509);
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
@@ -166,6 +168,8 @@ const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info);
 char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info);
 EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info);
 EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info);
+EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info);
+EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info);
 EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info);
 EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info);
 X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info);
diff --git a/include/openssl/storeerr.h b/include/openssl/storeerr.h
index ed8f7988fe..5213a0b33c 100644
--- a/include/openssl/storeerr.h
+++ b/include/openssl/storeerr.h
@@ -78,8 +78,9 @@ int ERR_load_OSSL_STORE_strings(void);
 # define OSSL_STORE_R_LOADING_STARTED                     117
 # define OSSL_STORE_R_NOT_A_CERTIFICATE                   100
 # define OSSL_STORE_R_NOT_A_CRL                           101
-# define OSSL_STORE_R_NOT_A_KEY                           102
 # define OSSL_STORE_R_NOT_A_NAME                          103
+# define OSSL_STORE_R_NOT_A_PRIVATE_KEY                   102
+# define OSSL_STORE_R_NOT_A_PUBLIC_KEY                    122
 # define OSSL_STORE_R_NOT_PARAMETERS                      104
 # define OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR           114
 # define OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE               108
diff --git a/test/evp_test.c b/test/evp_test.c
index cd6077e10d..958718b1ba 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -3342,7 +3342,7 @@ start:
         }
         klist = &private_keys;
     } else if (strcmp(pp->key, "PublicKey") == 0) {
-        pkey = PEM_read_bio_PUBKEY(t->s.key, NULL, 0, NULL);
+        pkey = PEM_read_bio_PUBKEY_ex(t->s.key, NULL, 0, NULL, libctx, NULL);
         if (pkey == NULL && !key_unsupported()) {
             EVP_PKEY_free(pkey);
             TEST_info("Can't read public key %s", pp->value);
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 6f4c11537b..cf9947ea0b 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -7511,7 +7511,9 @@ static int cert_cb(SSL *s, void *arg)
         BIO_free(in);
         if (!TEST_ptr(in = BIO_new(BIO_s_file()))
                 || !TEST_int_ge(BIO_read_filename(in, ecdsakey), 0)
-                || !TEST_ptr(pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL)))
+                || !TEST_ptr(pkey = PEM_read_bio_PrivateKey_ex(in, NULL,
+                                                               NULL, NULL,
+                                                               libctx, NULL)))
             goto out;
         rv = SSL_check_chain(s, x509, pkey, chain);
         /*
@@ -7656,8 +7658,9 @@ static int client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
     if (!TEST_ptr(xcert = X509_new_with_libctx(libctx, NULL))
             || !TEST_ptr(PEM_read_bio_X509(in, &xcert, NULL, NULL))
             || !TEST_ptr(priv_in = BIO_new_file(privkey, "r"))
-            || !TEST_ptr(privpkey = PEM_read_bio_PrivateKey(priv_in, NULL, NULL,
-                                                            NULL)))
+            || !TEST_ptr(privpkey = PEM_read_bio_PrivateKey_ex(priv_in, NULL,
+                                                               NULL, NULL,
+                                                               libctx, NULL)))
         goto err;
 
     *x509 = xcert;
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 6aa0109de3..a9b914839a 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5263,3 +5263,9 @@ EVP_SIGNATURE_settable_ctx_params       ?	3_0_0	EXIST::FUNCTION:
 EVP_KEYEXCH_gettable_ctx_params         ?	3_0_0	EXIST::FUNCTION:
 EVP_KEYEXCH_settable_ctx_params         ?	3_0_0	EXIST::FUNCTION:
 d2i_PUBKEY_ex                           ?	3_0_0	EXIST::FUNCTION:
+OSSL_STORE_INFO_new_PUBKEY              ?	3_0_0	EXIST::FUNCTION:
+OSSL_STORE_INFO_get0_PUBKEY             ?	3_0_0	EXIST::FUNCTION:
+OSSL_STORE_INFO_get1_PUBKEY             ?	3_0_0	EXIST::FUNCTION:
+PEM_read_bio_PUBKEY_ex                  ?	3_0_0	EXIST::FUNCTION:
+PEM_read_PUBKEY_ex                      ?	3_0_0	EXIST::FUNCTION:STDIO
+PEM_read_bio_Parameters_ex              ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list