STORE: Move the built-in 'file:' loader to become an engine module
authorRichard Levitte <levitte@openssl.org>
Thu, 23 Jul 2020 14:56:59 +0000 (16:56 +0200)
committerRichard Levitte <levitte@openssl.org>
Thu, 3 Sep 2020 15:48:32 +0000 (17:48 +0200)
From this point on, this engine must be specifically specified.

To replace the internal EMBEDDED hack with something unique for the
new module, functions to create application specific OSSL_STORE_INFO
types were added.

Furthermore, the following function had to be exported:

ossl_do_blob_header()
ossl_do_PVK_header()
asn1_d2i_read_bio()

Finally, evp_pkcs82pkey_int() has become public under a new name,
EVP_PKCS82PKEY_with_libctx()

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12587)

27 files changed:
Configurations/unix-Makefile.tmpl
crypto/asn1/a_d2i_fp.c
crypto/asn1/d2i_param.c
crypto/asn1/d2i_pr.c
crypto/evp/evp_pkey.c
crypto/store/build.info
crypto/store/store_init.c
crypto/store/store_lib.c
crypto/store/store_local.h
crypto/store/store_result.c
crypto/x509/x_all.c
doc/man3/OSSL_STORE_INFO.pod
engines/build.info
engines/e_loader_attic.c [moved from crypto/store/loader_file.c with 82% similarity]
engines/e_loader_attic.ec [new file with mode: 0644]
engines/e_loader_attic.txt [new file with mode: 0644]
engines/e_loader_attic_err.c [new file with mode: 0644]
engines/e_loader_attic_err.h [new file with mode: 0644]
include/crypto/asn1.h
include/crypto/evp.h
include/internal/asn1.h [new file with mode: 0644]
include/openssl/store.h
include/openssl/x509.h
providers/implementations/encode_decode/decode_common.c
util/libcrypto.num
util/missingcrypto-internal.txt
util/missingcrypto.txt

index 441f83c345b05e9b80a52fe3f93f0000992ada73..ff4803be747d570bf396b640ae1b2d7288aca71f 100644 (file)
@@ -1075,6 +1075,8 @@ errors:
            include/internal/o_dir.h
            include/internal/err.h
            include/internal/evp.h
+           include/internal/pem.h
+           include/internal/asn1.h
            include/internal/sslconf.h );
    our @cryptoskipheaders = ( @sslheaders,
        qw( include/openssl/conf_api.h
index 186e7ec4136e42735fb4f8e199da2a3e7cbeb8d8..249e6294c8b3a54b0ae270f177a925d96e904a3b 100644 (file)
@@ -13,6 +13,7 @@
 #include "internal/numbers.h"
 #include <openssl/buffer.h>
 #include <openssl/asn1.h>
+#include "internal/asn1.h"
 #include "crypto/asn1.h"
 
 #ifndef NO_OLD_ASN1
index bd6ef1ce51256701a388cd34f5294bcd70f268c0..f0217b47f607c10874f3b3e8476ec6d974d17c35 100644 (file)
@@ -11,8 +11,9 @@
 #include "internal/cryptlib.h"
 #include <openssl/evp.h>
 #include <openssl/asn1.h>
-#include "crypto/evp.h"
+#include "internal/asn1.h"
 #include "crypto/asn1.h"
+#include "crypto/evp.h"
 
 EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp,
                         long length)
index a4d240e7c4513c78e702e1083bbf688a7d25dd43..ba8178269880271fd5efd9ba2d28a42d8c3176df 100644 (file)
@@ -55,7 +55,7 @@ EVP_PKEY *d2i_PrivateKey_ex(int type, EVP_PKEY **a, const unsigned char **pp,
             p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
             if (p8 == NULL)
                 goto err;
-            tmp = evp_pkcs82pkey_int(p8, libctx, propq);
+            tmp = EVP_PKCS82PKEY_with_libctx(p8, libctx, propq);
             PKCS8_PRIV_KEY_INFO_free(p8);
             if (tmp == NULL)
                 goto err;
@@ -122,7 +122,7 @@ EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp,
             ASN1err(0, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
             return NULL;
         }
-        ret = evp_pkcs82pkey_int(p8, libctx, propq);
+        ret = EVP_PKCS82PKEY_with_libctx(p8, libctx, propq);
         PKCS8_PRIV_KEY_INFO_free(p8);
         if (ret == NULL)
             return NULL;
index cfe0544ed68f0936c96df82299f35a1900529604..92ae3e5fe8fc794f04ee68a8853ef1804b47624a 100644 (file)
@@ -18,8 +18,8 @@
 
 /* Extract a private key from a PKCS8 structure */
 
-EVP_PKEY *evp_pkcs82pkey_int(const PKCS8_PRIV_KEY_INFO *p8, OPENSSL_CTX *libctx,
-                             const char *propq)
+EVP_PKEY *EVP_PKCS82PKEY_with_libctx(const PKCS8_PRIV_KEY_INFO *p8,
+                                     OPENSSL_CTX *libctx, const char *propq)
 {
     EVP_PKEY *pkey = NULL;
     const ASN1_OBJECT *algoid;
@@ -64,7 +64,7 @@ EVP_PKEY *evp_pkcs82pkey_int(const PKCS8_PRIV_KEY_INFO *p8, OPENSSL_CTX *libctx,
 
 EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8)
 {
-    return evp_pkcs82pkey_int(p8, NULL, NULL);
+    return EVP_PKCS82PKEY_with_libctx(p8, NULL, NULL);
 }
 
 /* Turn a private key into a PKCS8 structure */
index 33b59f0faeb4b12425496b0baa9bc93c5d6ba966..bd19237ba49d158dfbc99d0fe4e8caa008857fa8 100644 (file)
@@ -1,4 +1,4 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=\
         store_err.c store_lib.c store_result.c store_strings.c store_meth.c \
-        store_init.c store_register.c loader_file.c
+        store_init.c store_register.c
index b87730736d2f5efb9c27b2f09442a50b82e9afc8..4d434eb57bcbf325a7dab8d742998f6c95216fdc 100644 (file)
@@ -14,8 +14,7 @@
 static CRYPTO_ONCE store_init = CRYPTO_ONCE_STATIC_INIT;
 DEFINE_RUN_ONCE_STATIC(do_store_init)
 {
-    return OPENSSL_init_crypto(0, NULL)
-        && ossl_store_file_loader_init();
+    return OPENSSL_init_crypto(0, NULL);
 }
 
 int ossl_store_init_once(void)
index d0fdb38cd88bb0ee92b75f98ef9f334aea1386ff..1c718c589e15f97089c95e42f4fd67d118e4c1ab 100644 (file)
@@ -474,7 +474,7 @@ int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
  * In all cases, ownership of the object is transferred to the OSSL_STORE_INFO
  * and will therefore be freed when the OSSL_STORE_INFO is freed.
  */
-static OSSL_STORE_INFO *store_info_new(int type, void *data)
+OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data)
 {
     OSSL_STORE_INFO *info = OPENSSL_zalloc(sizeof(*info));
 
@@ -488,7 +488,7 @@ static OSSL_STORE_INFO *store_info_new(int type, void *data)
 
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name)
 {
-    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_NAME, NULL);
+    OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_NAME, NULL);
 
     if (info == NULL) {
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
@@ -514,7 +514,7 @@ 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 *info = store_info_new(OSSL_STORE_INFO_PARAMS, params);
+    OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PARAMS, params);
 
     if (info == NULL)
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
@@ -523,7 +523,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params)
 
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pkey)
 {
-    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PUBKEY, pkey);
+    OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PUBKEY, pkey);
 
     if (info == NULL)
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
@@ -532,7 +532,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pkey)
 
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
 {
-    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_PKEY, pkey);
+    OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PKEY, pkey);
 
     if (info == NULL)
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
@@ -541,7 +541,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
 
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509)
 {
-    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CERT, x509);
+    OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CERT, x509);
 
     if (info == NULL)
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
@@ -550,7 +550,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509)
 
 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl)
 {
-    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_CRL, crl);
+    OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CRL, crl);
 
     if (info == NULL)
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
@@ -565,6 +565,13 @@ int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info)
     return info->type;
 }
 
+void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info)
+{
+    if (info->type == type)
+        return info->_.data;
+    return NULL;
+}
+
 const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info)
 {
     if (info->type == OSSL_STORE_INFO_NAME)
@@ -698,10 +705,6 @@ void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
 {
     if (info != NULL) {
         switch (info->type) {
-        case OSSL_STORE_INFO_EMBEDDED:
-            BUF_MEM_free(info->_.embedded.blob);
-            OPENSSL_free(info->_.embedded.pem_name);
-            break;
         case OSSL_STORE_INFO_NAME:
             OPENSSL_free(info->_.name.name);
             OPENSSL_free(info->_.name.desc);
@@ -889,44 +892,6 @@ const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion)
     return criterion->digest;
 }
 
-/* Internal functions */
-OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name,
-                                              BUF_MEM *embedded)
-{
-    OSSL_STORE_INFO *info = store_info_new(OSSL_STORE_INFO_EMBEDDED, NULL);
-
-    if (info == NULL) {
-        ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
-        return NULL;
-    }
-
-    info->_.embedded.blob = embedded;
-    info->_.embedded.pem_name =
-        new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name);
-
-    if (new_pem_name != NULL && info->_.embedded.pem_name == NULL) {
-        ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
-        OSSL_STORE_INFO_free(info);
-        info = NULL;
-    }
-
-    return info;
-}
-
-BUF_MEM *ossl_store_info_get0_EMBEDDED_buffer(OSSL_STORE_INFO *info)
-{
-    if (info->type == OSSL_STORE_INFO_EMBEDDED)
-        return info->_.embedded.blob;
-    return NULL;
-}
-
-char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info)
-{
-    if (info->type == OSSL_STORE_INFO_EMBEDDED)
-        return info->_.embedded.pem_name;
-    return NULL;
-}
-
 OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
                                   OPENSSL_CTX *libctx, const char *propq,
                                   const UI_METHOD *ui_method, void *ui_data,
index 619e547aaee89fe9f6f99aa2f09520e58effd0f2..cdd9f164b418daff350597669889e9dbfef9de15 100644 (file)
@@ -28,11 +28,6 @@ struct ossl_store_info_st {
     union {
         void *data;              /* used internally as generic pointer */
 
-        struct {
-            BUF_MEM *blob;
-            char *pem_name;
-        } embedded;              /* when type == OSSL_STORE_INFO_EMBEDDED */
-
         struct {
             char *name;
             char *desc;
@@ -45,26 +40,8 @@ struct ossl_store_info_st {
         X509_CRL *crl;           /* when type == OSSL_STORE_INFO_CRL */
     } _;
 };
-
 DEFINE_STACK_OF(OSSL_STORE_INFO)
 
-/*
- * EMBEDDED is a special type of OSSL_STORE_INFO, specially for the file
- * handlers.  It should never reach a calling application or any engine.
- * However, it can be used by a FILE_HANDLER's try_decode function to signal
- * that it has decoded the incoming blob into a new blob, and that the
- * attempted decoding should be immediately restarted with the new blob, using
- * the new PEM name.
- */
-/*
- * Because this is an internal type, we don't make it public.
- */
-#define OSSL_STORE_INFO_EMBEDDED       -1
-OSSL_STORE_INFO *ossl_store_info_new_EMBEDDED(const char *new_pem_name,
-                                              BUF_MEM *embedded);
-BUF_MEM *ossl_store_info_get0_EMBEDDED_buffer(OSSL_STORE_INFO *info);
-char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info);
-
 /*-
  *  OSSL_STORE_SEARCH stuff
  *  -----------------------
@@ -174,7 +151,6 @@ struct ossl_store_ctx_st {
  */
 
 int ossl_store_init_once(void);
-int ossl_store_file_loader_init(void);
 
 /*-
  *  'file' scheme stuff
index 74aeaf543b70fca0dca710fd86918a814895e6b2..9df29cec0aa118ce2cffbd83aec07086f19a7981 100644 (file)
@@ -302,7 +302,7 @@ static EVP_PKEY *try_key_value_legacy(struct extracted_param_data_st *data,
             derp = der;
             p8info = d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, der_len);
             if (p8info != NULL) {
-                pk = evp_pkcs82pkey_int(p8info, libctx, propq);
+                pk = EVP_PKCS82PKEY_with_libctx(p8info, libctx, propq);
                 PKCS8_PRIV_KEY_INFO_free(p8info);
             }
 
index a8ad292074e0ad80d5ce56bc1aa5e1b91b53a33d..3e7dc42ef147699a87744c1b8e456fb215da0895 100644 (file)
@@ -23,7 +23,7 @@
 #include <openssl/rsa.h>
 #include <openssl/dsa.h>
 #include <openssl/x509v3.h>
-#include "crypto/asn1.h"
+#include "internal/asn1.h"
 #include "crypto/pkcs7.h"
 #include "crypto/x509.h"
 
index bc965a77bdeb483aacefc2881501785b89fcd91b..8c811ec1f31d20d6ae3f7c7a69f2e1f9aa46bf90 100644 (file)
@@ -12,7 +12,8 @@ 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_PUBKEY,
-OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT, OSSL_STORE_INFO_new_CRL
+OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT, OSSL_STORE_INFO_new_CRL,
+OSSL_STORE_INFO_new, OSSL_STORE_INFO_get0_data
 - Functions to manipulate OSSL_STORE_INFO objects
 
 =head1 SYNOPSIS
@@ -50,6 +51,9 @@ OSSL_STORE_INFO_new_PKEY, OSSL_STORE_INFO_new_CERT, OSSL_STORE_INFO_new_CRL
  OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509);
  OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
 
+ OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data);
+ void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info);
+
 =head1 DESCRIPTION
 
 These functions are primarily useful for applications to retrieve
@@ -110,6 +114,19 @@ description.
 This description is meant to be human readable and should be used for
 information printout.
 
+OSSL_STORE_INFO_new() creates a B<OSSL_STORE_INFO> with an arbitrary I<type>
+number and I<data> structure.  It's the responsibility of the caller to
+define type numbers other than the ones defined by F<< <openssl/store.h> >>,
+and to handle freeing the associated data structure on their own.
+I<Using type numbers that are defined by F<< <openssl/store.h> >> may cause
+undefined behaviours, including crashes>.
+
+OSSL_STORE_INFO_get0_data() returns the data pointer that was passed to
+OSSL_STORE_INFO_new() if I<type> matches the type number in I<info>.
+
+OSSL_STORE_INFO_new() and OSSL_STORE_INFO_get0_data() may be useful for
+applications that define their own STORE data, but must be used with care.
+
 =head1 SUPPORTED OBJECTS
 
 Currently supported object types are:
@@ -177,13 +194,13 @@ OSSL_STORE_INFO_get1_PARAMS(), OSSL_STORE_INFO_get1_PKEY(),
 OSSL_STORE_INFO_get1_CERT() and OSSL_STORE_INFO_get1_CRL() all return
 a pointer to a duplicate of the OpenSSL object on success, NULL otherwise.
 
-OSSL_STORE_INFO_type_string() returns a string on success, or B<NULL> on
+OSSL_STORE_INFO_type_string() returns a string on success, or NULL on
 failure.
 
 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() return a B<OSSL_STORE_INFO>
-pointer on success, or B<NULL> on failure.
+pointer on success, or NULL on failure.
 
 OSSL_STORE_INFO_set0_NAME_description() returns 1 on success, or 0 on
 failure.
index 3bfe1dc0572420f1c4ce017adfacdd7401462e41..4e83dbf9bcf325fb457a443d8b624c24e69a0c12 100644 (file)
@@ -70,7 +70,7 @@ IF[{- !$disabled{"engine"} -}]
       ENDIF
     ENDIF
 
-    MODULES{noinst,engine}=ossltest dasync
+    MODULES{noinst,engine}=ossltest dasync loader_attic
     SOURCE[dasync]=e_dasync.c
     DEPEND[dasync]=../libcrypto
     INCLUDE[dasync]=../include
@@ -86,6 +86,14 @@ IF[{- !$disabled{"engine"} -}]
       SOURCE[ossltest]=ossltest.ld
       GENERATE[ossltest.ld]=../util/engines.num
     ENDIF
+
+    SOURCE[loader_attic]=e_loader_attic.c
+    DEPEND[loader_attic]=../libcrypto
+    INCLUDE[loader_attic]=../include
+    IF[{- defined $target{shared_defflag} -}]
+      SOURCE[loader_attic]=loader_attic.ld
+      GENERATE[loader_attic.ld]=../util/engines.num
+    ENDIF
   ENDIF
   GENERATE[e_padlock-x86.s]=asm/e_padlock-x86.pl
   GENERATE[e_padlock-x86_64.s]=asm/e_padlock-x86_64.pl
similarity index 82%
rename from crypto/store/loader_file.c
rename to engines/e_loader_attic.c
index 25ce9ba92e006a478d2cc3d43510c40f375c9527..581bfb02853a64de2937604c42d84938f6c4d4a3 100644 (file)
@@ -7,10 +7,12 @@
  * https://www.openssl.org/source/license.html
  */
 
+/* THIS ENGINE IS FOR TESTING PURPOSES ONLY. */
+
 /* We need to use some engine deprecated APIs */
 #define OPENSSL_SUPPRESS_DEPRECATED
 
-#include "e_os.h"
+/* #include "e_os.h" */
 #include <string.h>
 #include <sys/stat.h>
 #include <ctype.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/pem.h>
-#include "internal/pem.h"
 #include <openssl/pkcs12.h>      /* For the PKCS8 stuff o.O */
 #include <openssl/rsa.h>         /* For d2i_RSAPrivateKey */
 #include <openssl/safestack.h>
 #include <openssl/store.h>
 #include <openssl/ui.h>
+#include <openssl/engine.h>
 #include <openssl/x509.h>        /* For the PKCS8 stuff o.O */
-#include "crypto/asn1.h"
-#include "crypto/ctype.h"
+#include "internal/asn1.h"       /* For asn1_d2i_read_bio */
+#include "internal/pem.h"        /* For PVK and "blob" PEM headers */
 #include "internal/o_dir.h"
 #include "internal/cryptlib.h"
-#include "crypto/store.h"
-#include "crypto/evp.h"
-#include "store_local.h"
+
+#include "e_loader_attic_err.c"
 
 DEFINE_STACK_OF(X509)
+DEFINE_STACK_OF(OSSL_STORE_INFO)
 
 #ifdef _WIN32
 # define stat _stat
+# define strncasecmp _strnicmp
 #endif
 
 #ifndef S_ISDIR
@@ -59,7 +62,7 @@ static char *file_get_pass(const UI_METHOD *ui_method, char *pass,
     char *prompt = NULL;
 
     if (ui == NULL) {
-        OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_MALLOC_FAILURE);
+        ATTICerr(0, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
@@ -68,21 +71,20 @@ static char *file_get_pass(const UI_METHOD *ui_method, char *pass,
     UI_add_user_data(ui, data);
 
     if ((prompt = UI_construct_prompt(ui, desc, info)) == NULL) {
-        OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_MALLOC_FAILURE);
+        ATTICerr(0, ERR_R_MALLOC_FAILURE);
         pass = NULL;
     } else if (!UI_add_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD,
                                     pass, 0, maxsize - 1)) {
-        OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_UI_LIB);
+        ATTICerr(0, ERR_R_UI_LIB);
         pass = NULL;
     } else {
         switch (UI_process(ui)) {
         case -2:
-            OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS,
-                          OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED);
+            ATTICerr(0, ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED);
             pass = NULL;
             break;
         case -1:
-            OSSL_STOREerr(OSSL_STORE_F_FILE_GET_PASS, ERR_R_UI_LIB);
+            ATTICerr(0, ERR_R_UI_LIB);
             pass = NULL;
             break;
         default:
@@ -126,6 +128,91 @@ static int file_get_pem_pass(char *buf, int num, int w, void *data)
     return pass == NULL ? 0 : strlen(pass);
 }
 
+/*
+ * Check if |str| ends with |suffix| preceded by a space, and if it does,
+ * return the index of that space.  If there is no such suffix in |str|,
+ * return -1.
+ * For |str| == "FOO BAR" and |suffix| == "BAR", the returned value is 3.
+ */
+static int check_suffix(const char *str, const char *suffix)
+{
+    int str_len = strlen(str);
+    int suffix_len = strlen(suffix) + 1;
+    const char *p = NULL;
+
+    if (suffix_len >= str_len)
+        return -1;
+    p = str + str_len - suffix_len;
+    if (*p != ' '
+        || strcmp(p + 1, suffix) != 0)
+        return -1;
+    return p - str;
+}
+
+/*
+ * EMBEDDED is a special type of OSSL_STORE_INFO, specially for the file
+ * handlers, so we define it internally.  This uses the possibility to
+ * create an OSSL_STORE_INFO with a generic data pointer and arbitrary
+ * type number.
+ *
+ * This is used by a FILE_HANDLER's try_decode function to signal that it
+ * has decoded the incoming blob into a new blob, and that the attempted
+ * decoding should be immediately restarted with the new blob, using the
+ * new PEM name.
+ */
+/* Negative numbers are never used for public OSSL_STORE_INFO types */
+#define STORE_INFO_EMBEDDED       -1
+
+/* This is the embedded data */
+struct embedded_st {
+    BUF_MEM *blob;
+    char *pem_name;
+};
+
+/* Helper functions */
+static struct embedded_st *get0_EMBEDDED(OSSL_STORE_INFO *info)
+{
+    return OSSL_STORE_INFO_get0_data(STORE_INFO_EMBEDDED, info);
+}
+
+static void store_info_free(OSSL_STORE_INFO *info)
+{
+    struct embedded_st *data;
+
+    if (info != NULL && (data = get0_EMBEDDED(info)) != NULL) {
+        BUF_MEM_free(data->blob);
+        OPENSSL_free(data->pem_name);
+        OPENSSL_free(data);
+    }
+    OSSL_STORE_INFO_free(info);
+}
+
+static OSSL_STORE_INFO *new_EMBEDDED(const char *new_pem_name,
+                                     BUF_MEM *embedded)
+{
+    OSSL_STORE_INFO *info = NULL;
+    struct embedded_st *data = NULL;
+
+    if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL
+        || (info = OSSL_STORE_INFO_new(STORE_INFO_EMBEDDED, data)) == NULL) {
+        ATTICerr(0, ERR_R_MALLOC_FAILURE);
+        OPENSSL_free(data);
+        return NULL;
+    }
+
+    data->pem_name =
+        new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name);
+
+    if (new_pem_name != NULL && data->pem_name == NULL) {
+        ATTICerr(0, ERR_R_MALLOC_FAILURE);
+        store_info_free(info);
+        info = NULL;
+    }
+    data->blob = embedded;
+
+    return info;
+}
+
 /*-
  *  The file scheme decoders
  *  ------------------------
@@ -243,13 +330,11 @@ static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name,
                 if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE,
                                           "PKCS12 import pass phrase", uri,
                                           ui_data)) == NULL) {
-                    OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12,
-                                  OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR);
+                    ATTICerr(0, ATTIC_R_PASSPHRASE_CALLBACK_ERROR);
                     goto p12_end;
                 }
                 if (!PKCS12_verify_mac(p12, pass, strlen(pass))) {
-                    OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12,
-                                  OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC);
+                    ATTICerr(0, ATTIC_R_ERROR_VERIFYING_PKCS12_MAC);
                     goto p12_end;
                 }
             }
@@ -293,11 +378,11 @@ static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name,
                 EVP_PKEY_free(pkey);
                 X509_free(cert);
                 sk_X509_pop_free(chain, X509_free);
-                OSSL_STORE_INFO_free(osi_pkey);
-                OSSL_STORE_INFO_free(osi_cert);
-                OSSL_STORE_INFO_free(osi_ca);
+                store_info_free(osi_pkey);
+                store_info_free(osi_cert);
+                store_info_free(osi_ca);
                 if (!ok) {
-                    sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free);
+                    sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free);
                     ctx = NULL;
                 }
                 *pctx = ctx;
@@ -325,7 +410,7 @@ static void destroy_ctx_PKCS12(void **pctx)
 {
     STACK_OF(OSSL_STORE_INFO) *ctx = *pctx;
 
-    sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free);
+    sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free);
     *pctx = NULL;
 }
 
@@ -375,16 +460,14 @@ static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name,
     *matchcount = 1;
 
     if ((mem = BUF_MEM_new()) == NULL) {
-        OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED,
-                      ERR_R_MALLOC_FAILURE);
+        ATTICerr(0, ERR_R_MALLOC_FAILURE);
         goto nop8;
     }
 
     if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE,
                               "PKCS8 decrypt pass phrase", uri,
                               ui_data)) == NULL) {
-        OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED,
-                      OSSL_STORE_R_BAD_PASSWORD_READ);
+        ATTICerr(0, ATTIC_R_BAD_PASSWORD_READ);
         goto nop8;
     }
 
@@ -397,10 +480,9 @@ static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name,
     mem->max = mem->length = (size_t)new_data_len;
     X509_SIG_free(p8);
 
-    store_info = ossl_store_info_new_EMBEDDED(PEM_STRING_PKCS8INF, mem);
+    store_info = new_EMBEDDED(PEM_STRING_PKCS8INF, mem);
     if (store_info == NULL) {
-        OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED,
-                      ERR_R_MALLOC_FAILURE);
+        ATTICerr(0, ERR_R_MALLOC_FAILURE);
         goto nop8;
     }
 
@@ -421,7 +503,6 @@ static FILE_HANDLER PKCS8Encrypted_handler = {
  * encoded ones and old style PEM ones (with the key type is encoded into
  * the PEM name).
  */
-int pem_check_suffix(const char *pem_str, const char *suffix);
 static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
                                               const char *pem_header,
                                               const unsigned char *blob,
@@ -443,16 +524,19 @@ static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
 
             *matchcount = 1;
             if (p8inf != NULL)
-                pkey = evp_pkcs82pkey_int(p8inf, libctx, propq);
+                pkey = EVP_PKCS82PKEY_with_libctx(p8inf, libctx, propq);
             PKCS8_PRIV_KEY_INFO_free(p8inf);
         } else {
             int slen;
+            int pkey_id;
 
-            if ((slen = pem_check_suffix(pem_name, "PRIVATE KEY")) > 0
+            if ((slen = check_suffix(pem_name, "PRIVATE KEY")) > 0
                 && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name,
-                                                   slen)) != NULL) {
+                                                   slen)) != NULL
+                && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
+                                           ameth)) {
                 *matchcount = 1;
-                pkey = d2i_PrivateKey_ex(ameth->pkey_id, NULL, &blob, len,
+                pkey = d2i_PrivateKey_ex(pkey_id, NULL, &blob, len,
                                          libctx, propq);
             }
         }
@@ -473,17 +557,19 @@ static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
                     EVP_PKEY_ASN1_METHOD *ameth2 = NULL;
                     EVP_PKEY *tmp_pkey = NULL;
                     const unsigned char *tmp_blob = blob;
+                    int pkey_id, pkey_flags;
 
-                    if (!asn1meths(curengine, &ameth2, NULL, nids[i]))
-                        continue;
-                    if (ameth2 == NULL
-                        || ameth2->pkey_flags & ASN1_PKEY_ALIAS)
+                    if (!asn1meths(curengine, &ameth2, NULL, nids[i])
+                        || !EVP_PKEY_asn1_get0_info(&pkey_id, NULL,
+                                                    &pkey_flags, NULL, NULL,
+                                                    ameth2)
+                        || (pkey_flags & ASN1_PKEY_ALIAS) != 0)
                         continue;
 
                     ERR_set_mark(); /* prevent flooding error queue */
-                    tmp_pkey =
-                        d2i_PrivateKey_ex(ameth2->pkey_id, NULL,
-                                          &tmp_blob, len, libctx, propq);
+                    tmp_pkey = d2i_PrivateKey_ex(pkey_id, NULL,
+                                                 &tmp_blob, len,
+                                                 libctx, propq);
                     if (tmp_pkey != NULL) {
                         if (pkey != NULL)
                             EVP_PKEY_free(tmp_pkey);
@@ -501,13 +587,16 @@ static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
         for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
             EVP_PKEY *tmp_pkey = NULL;
             const unsigned char *tmp_blob = blob;
+            int pkey_id, pkey_flags;
 
             ameth = EVP_PKEY_asn1_get0(i);
-            if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
+            if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL,
+                                         NULL, ameth)
+                || (pkey_flags & ASN1_PKEY_ALIAS) != 0)
                 continue;
 
             ERR_set_mark(); /* prevent flooding error queue */
-            tmp_pkey = d2i_PrivateKey_ex(ameth->pkey_id, NULL, &tmp_blob, len,
+            tmp_pkey = d2i_PrivateKey_ex(pkey_id, NULL, &tmp_blob, len,
                                          libctx, propq);
             if (tmp_pkey != NULL) {
                 if (pkey != NULL)
@@ -590,69 +679,58 @@ static OSSL_STORE_INFO *try_decode_params(const char *pem_name,
                                           const char *propq)
 {
     OSSL_STORE_INFO *store_info = NULL;
-    int slen = 0;
     EVP_PKEY *pkey = NULL;
     const EVP_PKEY_ASN1_METHOD *ameth = NULL;
-    int ok = 0;
 
     if (pem_name != NULL) {
-        if ((slen = pem_check_suffix(pem_name, "PARAMETERS")) == 0)
-            return NULL;
-        *matchcount = 1;
-    }
+        int slen;
+        int pkey_id;
 
-    if (slen > 0) {
-        if ((pkey = EVP_PKEY_new()) == NULL) {
-            OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PARAMS, ERR_R_EVP_LIB);
-            return NULL;
+        if ((slen = check_suffix(pem_name, "PARAMETERS")) > 0
+            && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, slen)) != NULL
+            && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL,
+                                       ameth)) {
+            *matchcount = 1;
+            pkey = d2i_KeyParams(pkey_id, NULL, &blob, len);
         }
-
-
-        if (EVP_PKEY_set_type_str(pkey, pem_name, slen)
-            && (ameth = EVP_PKEY_get0_asn1(pkey)) != NULL
-            && ameth->param_decode != NULL
-            && ameth->param_decode(pkey, &blob, len))
-            ok = 1;
     } else {
         int i;
-        EVP_PKEY *tmp_pkey = NULL;
 
         for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
+            EVP_PKEY *tmp_pkey = NULL;
             const unsigned char *tmp_blob = blob;
-
-            if (tmp_pkey == NULL && (tmp_pkey = EVP_PKEY_new()) == NULL) {
-                OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PARAMS, ERR_R_EVP_LIB);
-                break;
-            }
+            int pkey_id, pkey_flags;
 
             ameth = EVP_PKEY_asn1_get0(i);
-            if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
+            if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL,
+                                         NULL, ameth)
+                || (pkey_flags & ASN1_PKEY_ALIAS) != 0)
                 continue;
 
             ERR_set_mark(); /* prevent flooding error queue */
 
-            if (EVP_PKEY_set_type(tmp_pkey, ameth->pkey_id)
-                && (ameth = EVP_PKEY_get0_asn1(tmp_pkey)) != NULL
-                && ameth->param_decode != NULL
-                && ameth->param_decode(tmp_pkey, &tmp_blob, len)) {
+            tmp_pkey = d2i_KeyParams(pkey_id, NULL, &tmp_blob, len);
+
+            if (tmp_pkey != NULL) {
                 if (pkey != NULL)
                     EVP_PKEY_free(tmp_pkey);
                 else
                     pkey = tmp_pkey;
-                tmp_pkey = NULL;
                 (*matchcount)++;
             }
             ERR_pop_to_mark();
         }
 
-        EVP_PKEY_free(tmp_pkey);
-        if (*matchcount == 1) {
-            ok = 1;
+        if (*matchcount > 1) {
+            EVP_PKEY_free(pkey);
+            pkey = NULL;
         }
     }
+    if (pkey == NULL)
+        /* No match */
+        return NULL;
 
-    if (ok)
-        store_info = OSSL_STORE_INFO_new_PARAMS(pkey);
+    store_info = OSSL_STORE_INFO_new_PARAMS(pkey);
     if (store_info == NULL)
         EVP_PKEY_free(pkey);
 
@@ -824,6 +902,7 @@ struct ossl_store_loader_ctx_st {
 
     /* Expected object type.  May be unspecified */
     int expected_type;
+
     OPENSSL_CTX *libctx;
     char *propq;
 };
@@ -898,7 +977,7 @@ static OSSL_STORE_LOADER_CTX *file_open_with_libctx
             } else if (uri[7] == '/') {
                 p = &uri[7];
             } else {
-                OSSL_STOREerr(0, OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED);
+                ATTICerr(0, ATTIC_R_URI_AUTHORITY_UNSUPPORTED);
                 return NULL;
             }
         }
@@ -907,7 +986,7 @@ static OSSL_STORE_LOADER_CTX *file_open_with_libctx
 #ifdef _WIN32
         /* Windows file: URIs with a drive letter start with a / */
         if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
-            char c = ossl_tolower(p[1]);
+            char c = tolower(p[1]);
 
             if (c >= 'a' && c <= 'z') {
                 p++;
@@ -926,7 +1005,7 @@ static OSSL_STORE_LOADER_CTX *file_open_with_libctx
          * be absolute.  So says RFC 8089
          */
         if (path_data[i].check_absolute && path_data[i].path[0] != '/') {
-            OSSL_STOREerr(0, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE);
+            ATTICerr(0, ATTIC_R_PATH_MUST_BE_ABSOLUTE);
             ERR_add_error_data(1, path_data[i].path);
             return NULL;
         }
@@ -947,12 +1026,12 @@ static OSSL_STORE_LOADER_CTX *file_open_with_libctx
 
     ctx = OPENSSL_zalloc(sizeof(*ctx));
     if (ctx == NULL) {
-        OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
+        ATTICerr(0, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     ctx->uri = OPENSSL_strdup(uri);
     if (ctx->uri == NULL) {
-        OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
+        ATTICerr(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -962,11 +1041,7 @@ static OSSL_STORE_LOADER_CTX *file_open_with_libctx
         ctx->_.dir.last_errno = errno;
         if (ctx->_.dir.last_entry == NULL) {
             if (ctx->_.dir.last_errno != 0) {
-                char errbuf[256];
-                OSSL_STOREerr(0, ERR_R_SYS_LIB);
-                errno = ctx->_.dir.last_errno;
-                if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
-                    ERR_add_error_data(1, errbuf);
+                ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
                 goto err;
             }
             ctx->_.dir.end_reached = 1;
@@ -979,7 +1054,7 @@ static OSSL_STORE_LOADER_CTX *file_open_with_libctx
     if (propq != NULL) {
         ctx->propq = OPENSSL_strdup(propq);
         if (ctx->propq == NULL) {
-            OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
+            ATTICerr(0, ERR_R_MALLOC_FAILURE);
             goto err;
         }
     }
@@ -1005,17 +1080,11 @@ static OSSL_STORE_LOADER_CTX *file_attach
 {
     OSSL_STORE_LOADER_CTX *ctx = NULL;
 
-    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
-        OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-
-    if (propq != NULL) {
-        ctx->propq = OPENSSL_strdup(propq);
-        if (ctx->propq == NULL) {
-            OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
-            goto err;
-        }
+    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL
+        || (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)) {
+        ATTICerr(0, ERR_R_MALLOC_FAILURE);
+        OSSL_STORE_LOADER_CTX_free(ctx);
+        return NULL;
     }
     ctx->libctx = libctx;
     ctx->flags |= FILE_FLAG_ATTACHED;
@@ -1048,7 +1117,7 @@ static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args)
                 ctx->flags |= FILE_FLAG_SECMEM;
                 break;
             default:
-                OSSL_STOREerr(0, ERR_R_PASSED_INVALID_ARGUMENT);
+                ATTICerr(0, ERR_R_PASSED_INVALID_ARGUMENT);
                 ret = 0;
                 break;
             }
@@ -1082,8 +1151,7 @@ static int file_find(OSSL_STORE_LOADER_CTX *ctx,
             return 1;
 
         if (ctx->type != is_dir) {
-            OSSL_STOREerr(OSSL_STORE_F_FILE_FIND,
-                          OSSL_STORE_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES);
+            ATTICerr(0, ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES);
             return 0;
         }
 
@@ -1094,8 +1162,7 @@ static int file_find(OSSL_STORE_LOADER_CTX *ctx,
     }
 
     if (ctx != NULL)
-        OSSL_STOREerr(OSSL_STORE_F_FILE_FIND,
-                      OSSL_STORE_R_UNSUPPORTED_SEARCH_TYPE);
+        ATTICerr(0, ATTIC_R_UNSUPPORTED_SEARCH_TYPE);
     return 0;
 }
 
@@ -1120,8 +1187,7 @@ static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx,
                            * OSSL_NELEM(file_handlers));
 
         if (matching_handlers == NULL) {
-            OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD_TRY_DECODE,
-                          ERR_R_MALLOC_FAILURE);
+            ATTICerr(0, ERR_R_MALLOC_FAILURE);
             goto err;
         }
 
@@ -1157,8 +1223,8 @@ static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx,
 
                 if ((*matchcount += try_matchcount) > 1) {
                     /* more than one match => ambiguous, kill any result */
-                    OSSL_STORE_INFO_free(result);
-                    OSSL_STORE_INFO_free(tmp_result);
+                    store_info_free(result);
+                    store_info_free(tmp_result);
                     if (handler->destroy_ctx != NULL)
                         handler->destroy_ctx(&handler_ctx);
                     handler_ctx = NULL;
@@ -1183,13 +1249,18 @@ static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx,
     BUF_MEM_free(new_mem);
 
     if (result != NULL
-        && (t = OSSL_STORE_INFO_get_type(result)) == OSSL_STORE_INFO_EMBEDDED) {
-        pem_name = new_pem_name =
-            ossl_store_info_get0_EMBEDDED_pem_name(result);
-        new_mem = ossl_store_info_get0_EMBEDDED_buffer(result);
+        && (t = OSSL_STORE_INFO_get_type(result)) == STORE_INFO_EMBEDDED) {
+        struct embedded_st *embedded = get0_EMBEDDED(result);
+
+        /* "steal" the embedded data */
+        pem_name = new_pem_name = embedded->pem_name;
+        new_mem = embedded->blob;
         data = (unsigned char *)new_mem->data;
         len = new_mem->length;
-        OPENSSL_free(result);
+        embedded->pem_name = NULL;
+        embedded->blob = NULL;
+
+        store_info_free(result);
         result = NULL;
         goto again;
     }
@@ -1380,7 +1451,7 @@ static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name,
 
         *data = OPENSSL_zalloc(calculated_length);
         if (*data == NULL) {
-            OSSL_STOREerr(OSSL_STORE_F_FILE_NAME_TO_URI, ERR_R_MALLOC_FAILURE);
+            ATTICerr(0, ERR_R_MALLOC_FAILURE);
             return 0;
         }
 
@@ -1431,9 +1502,9 @@ static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
      * Last, check that the rest of the extension is a decimal number, at
      * least one digit long.
      */
-    if (!ossl_isdigit(*p))
+    if (!isdigit(*p))
         return 0;
-    while (ossl_isdigit(*p))
+    while (isdigit(*p))
         p++;
 
 #ifdef __VMS
@@ -1469,13 +1540,9 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
 
             if (ctx->_.dir.last_entry == NULL) {
                 if (!ctx->_.dir.end_reached) {
-                    char errbuf[256];
                     assert(ctx->_.dir.last_errno != 0);
-                    OSSL_STOREerr(0, ERR_R_SYS_LIB);
-                    errno = ctx->_.dir.last_errno;
+                    ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno);
                     ctx->errcnt++;
-                    if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
-                        ERR_add_error_data(1, errbuf);
                 }
                 return NULL;
             }
@@ -1499,7 +1566,7 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
             if (newname != NULL
                 && (result = OSSL_STORE_INFO_new_NAME(newname)) == NULL) {
                 OPENSSL_free(newname);
-                OSSL_STOREerr(0, ERR_R_OSSL_STORE_LIB);
+                ATTICerr(0, ERR_R_OSSL_STORE_LIB);
                 return NULL;
             }
         } while (result == NULL && !file_eof(ctx));
@@ -1558,14 +1625,14 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
             }
 
             if (matchcount > 1) {
-                OSSL_STOREerr(0, OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE);
+                ATTICerr(0, ATTIC_R_AMBIGUOUS_CONTENT_TYPE);
             } else if (matchcount == 1) {
                 /*
                  * If there are other errors on the stack, they already show
                  * what the problem is.
                  */
                 if (ERR_peek_error() == 0) {
-                    OSSL_STOREerr(0, OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE);
+                    ATTICerr(0, ATTIC_R_UNSUPPORTED_CONTENT_TYPE);
                     if (pem_name != NULL)
                         ERR_add_error_data(3, "PEM type is '", pem_name, "'");
                 }
@@ -1581,14 +1648,14 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
 
         /* We bail out on ambiguity */
         if (matchcount > 1) {
-            OSSL_STORE_INFO_free(result);
+            store_info_free(result);
             return NULL;
         }
 
         if (result != NULL
             && ctx->expected_type != 0
             && ctx->expected_type != OSSL_STORE_INFO_get_type(result)) {
-            OSSL_STORE_INFO_free(result);
+            store_info_free(result);
             goto again;
         }
     }
@@ -1637,31 +1704,87 @@ static int file_close(OSSL_STORE_LOADER_CTX *ctx)
     return 1;
 }
 
-static OSSL_STORE_LOADER file_loader =
-    {
-        "file",
-        NULL,
-        file_open,
-        file_attach,
-        file_ctrl,
-        file_expect,
-        file_find,
-        file_load,
-        file_eof,
-        file_error,
-        file_close,
-        file_open_with_libctx,
-    };
-
-static void store_file_loader_deinit(void)
+/*-
+ * ENGINE management
+ */
+
+static const char *loader_attic_id = "loader_attic";
+static const char *loader_attic_name = "'file:' loader";
+
+static OSSL_STORE_LOADER *loader_attic = NULL;
+
+static int loader_attic_init(ENGINE *e)
 {
-    ossl_store_unregister_loader_int(file_loader.scheme);
+    return 1;
 }
 
-int ossl_store_file_loader_init(void)
+
+static int loader_attic_finish(ENGINE *e)
 {
-    int ret = ossl_store_register_loader_int(&file_loader);
+    return 1;
+}
 
-    OPENSSL_atexit(store_file_loader_deinit);
-    return ret;
+
+static int loader_attic_destroy(ENGINE *e)
+{
+    OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader("file");
+
+    if (loader == NULL)
+        return 0;
+
+    ERR_unload_ATTIC_strings();
+    OSSL_STORE_LOADER_free(loader);
+    return 1;
+}
+
+static int bind_loader_attic(ENGINE *e)
+{
+
+    /* Ensure the ATTIC error handdling is set up on best effort basis */
+    ERR_load_ATTIC_strings();
+
+    if (/* Create the OSSL_STORE_LOADER */
+        (loader_attic = OSSL_STORE_LOADER_new(e, "file")) == NULL
+        || !OSSL_STORE_LOADER_set_open_with_libctx(loader_attic,
+                                                   file_open_with_libctx)
+        || !OSSL_STORE_LOADER_set_open(loader_attic, file_open)
+        || !OSSL_STORE_LOADER_set_attach(loader_attic, file_attach)
+        || !OSSL_STORE_LOADER_set_ctrl(loader_attic, file_ctrl)
+        || !OSSL_STORE_LOADER_set_expect(loader_attic, file_expect)
+        || !OSSL_STORE_LOADER_set_find(loader_attic, file_find)
+        || !OSSL_STORE_LOADER_set_load(loader_attic, file_load)
+        || !OSSL_STORE_LOADER_set_eof(loader_attic, file_eof)
+        || !OSSL_STORE_LOADER_set_error(loader_attic, file_error)
+        || !OSSL_STORE_LOADER_set_close(loader_attic, file_close)
+        /* Init the engine itself */
+        || !ENGINE_set_id(e, loader_attic_id)
+        || !ENGINE_set_name(e, loader_attic_name)
+        || !ENGINE_set_destroy_function(e, loader_attic_destroy)
+        || !ENGINE_set_init_function(e, loader_attic_init)
+        || !ENGINE_set_finish_function(e, loader_attic_finish)
+        /* Finally, register the method with libcrypto */
+        || !OSSL_STORE_register_loader(loader_attic)) {
+        OSSL_STORE_LOADER_free(loader_attic);
+        loader_attic = NULL;
+        ATTICerr(0, ATTIC_R_INIT_FAILED);
+        return 0;
+    }
+
+    return 1;
+}
+
+#ifdef OPENSSL_NO_DYNAMIC_ENGINE
+# error "Only allowed as dynamically shared object"
+#endif
+
+static int bind_helper(ENGINE *e, const char *id)
+{
+    if (id && (strcmp(id, loader_attic_id) != 0))
+        return 0;
+    if (!bind_loader_attic(e))
+        return 0;
+    return 1;
 }
+
+IMPLEMENT_DYNAMIC_CHECK_FN()
+    IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
diff --git a/engines/e_loader_attic.ec b/engines/e_loader_attic.ec
new file mode 100644 (file)
index 0000000..525a689
--- /dev/null
@@ -0,0 +1,3 @@
+# The INPUT HEADER is scanned for declarations
+# LIBNAME       INPUT HEADER                    ERROR-TABLE FILE
+L ATTIC         e_loader_attic_err.h            e_loader_attic_err.c
diff --git a/engines/e_loader_attic.txt b/engines/e_loader_attic.txt
new file mode 100644 (file)
index 0000000..db1a996
--- /dev/null
@@ -0,0 +1,23 @@
+# Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# Function codes
+
+#Reason codes
+ATTIC_R_AMBIGUOUS_CONTENT_TYPE:100:ambiguous content type
+ATTIC_R_BAD_PASSWORD_READ:101:bad password read
+ATTIC_R_ERROR_VERIFYING_PKCS12_MAC:102:error verifying pkcs12 mac
+ATTIC_R_INIT_FAILED:103:init failed
+ATTIC_R_PASSPHRASE_CALLBACK_ERROR:104:passphrase callback error
+ATTIC_R_PATH_MUST_BE_ABSOLUTE:105:path must be absolute
+ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES:106:\
+       search only supported for directories
+ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED:107:\
+       ui process interrupted or cancelled
+ATTIC_R_UNSUPPORTED_CONTENT_TYPE:108:unsupported content type
+ATTIC_R_UNSUPPORTED_SEARCH_TYPE:109:unsupported search type
+ATTIC_R_URI_AUTHORITY_UNSUPPORTED:110:uri authority unsupported
diff --git a/engines/e_loader_attic_err.c b/engines/e_loader_attic_err.c
new file mode 100644 (file)
index 0000000..2bc4e85
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include "e_loader_attic_err.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static ERR_STRING_DATA ATTIC_str_reasons[] = {
+    {ERR_PACK(0, 0, ATTIC_R_AMBIGUOUS_CONTENT_TYPE), "ambiguous content type"},
+    {ERR_PACK(0, 0, ATTIC_R_BAD_PASSWORD_READ), "bad password read"},
+    {ERR_PACK(0, 0, ATTIC_R_ERROR_VERIFYING_PKCS12_MAC),
+    "error verifying pkcs12 mac"},
+    {ERR_PACK(0, 0, ATTIC_R_INIT_FAILED), "init failed"},
+    {ERR_PACK(0, 0, ATTIC_R_PASSPHRASE_CALLBACK_ERROR),
+    "passphrase callback error"},
+    {ERR_PACK(0, 0, ATTIC_R_PATH_MUST_BE_ABSOLUTE), "path must be absolute"},
+    {ERR_PACK(0, 0, ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES),
+    "search only supported for directories"},
+    {ERR_PACK(0, 0, ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED),
+    "ui process interrupted or cancelled"},
+    {ERR_PACK(0, 0, ATTIC_R_UNSUPPORTED_CONTENT_TYPE),
+    "unsupported content type"},
+    {ERR_PACK(0, 0, ATTIC_R_UNSUPPORTED_SEARCH_TYPE),
+    "unsupported search type"},
+    {ERR_PACK(0, 0, ATTIC_R_URI_AUTHORITY_UNSUPPORTED),
+    "uri authority unsupported"},
+    {0, NULL}
+};
+
+#endif
+
+static int lib_code = 0;
+static int error_loaded = 0;
+
+static int ERR_load_ATTIC_strings(void)
+{
+    if (lib_code == 0)
+        lib_code = ERR_get_next_error_library();
+
+    if (!error_loaded) {
+#ifndef OPENSSL_NO_ERR
+        ERR_load_strings(lib_code, ATTIC_str_reasons);
+#endif
+        error_loaded = 1;
+    }
+    return 1;
+}
+
+static void ERR_unload_ATTIC_strings(void)
+{
+    if (error_loaded) {
+#ifndef OPENSSL_NO_ERR
+        ERR_unload_strings(lib_code, ATTIC_str_reasons);
+#endif
+        error_loaded = 0;
+    }
+}
+
+static void ERR_ATTIC_error(int function, int reason, char *file, int line)
+{
+    if (lib_code == 0)
+        lib_code = ERR_get_next_error_library();
+    ERR_raise(lib_code, reason);
+    ERR_set_debug(file, line, NULL);
+}
diff --git a/engines/e_loader_attic_err.h b/engines/e_loader_attic_err.h
new file mode 100644 (file)
index 0000000..115e0ea
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_ATTICERR_H
+# define OPENSSL_ATTICERR_H
+# pragma once
+
+# include <openssl/opensslconf.h>
+# include <openssl/symhacks.h>
+
+
+# define ATTICerr(f, r) ERR_ATTIC_error(0, (r), OPENSSL_FILE, OPENSSL_LINE)
+
+
+/*
+ * ATTIC function codes.
+ */
+# ifndef OPENSSL_NO_DEPRECATED_3_0
+# endif
+
+/*
+ * ATTIC reason codes.
+ */
+# define ATTIC_R_AMBIGUOUS_CONTENT_TYPE                   100
+# define ATTIC_R_BAD_PASSWORD_READ                        101
+# define ATTIC_R_ERROR_VERIFYING_PKCS12_MAC               102
+# define ATTIC_R_INIT_FAILED                              103
+# define ATTIC_R_PASSPHRASE_CALLBACK_ERROR                104
+# define ATTIC_R_PATH_MUST_BE_ABSOLUTE                    105
+# define ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES    106
+# define ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED      107
+# define ATTIC_R_UNSUPPORTED_CONTENT_TYPE                 108
+# define ATTIC_R_UNSUPPORTED_SEARCH_TYPE                  109
+# define ATTIC_R_URI_AUTHORITY_UNSUPPORTED                110
+
+#endif
index 041642f022a0adac86fab6dda4e114709f4172a2..624df3cb055e13214a80f9b7ce501117539abc2f 100644 (file)
@@ -124,5 +124,3 @@ struct asn1_pctx_st {
     unsigned long oid_flags;
     unsigned long str_flags;
 } /* ASN1_PCTX */ ;
-
-int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
index 634eb86425976f5eb5230cad3d63da63ce3a5f95..b00634234c5ba522a54209fbeecad491224905c6 100644 (file)
@@ -763,8 +763,6 @@ int pkcs5_pbkdf2_hmac_with_libctx(const char *pass, int passlen,
 int evp_pkey_ctx_set_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params);
 int evp_pkey_ctx_get_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params);
 
-EVP_PKEY *evp_pkcs82pkey_int(const PKCS8_PRIV_KEY_INFO *p8, OPENSSL_CTX *libctx,
-                             const char *propq);
 EVP_MD_CTX *evp_md_ctx_new_with_libctx(EVP_PKEY *pkey,
                                        const ASN1_OCTET_STRING *id,
                                        OPENSSL_CTX *libctx, const char *propq);
diff --git a/include/internal/asn1.h b/include/internal/asn1.h
new file mode 100644 (file)
index 0000000..8448786
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_ASN1_H
+# define OSSL_INTERNAL_ASN1_H
+
+int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
+
+#endif
index 9a2b423371ae4e623df1c0bf552d650f81e4940b..b2201cacaadfc384bdfdc6860a6cd940fd7a284f 100644 (file)
@@ -151,6 +151,7 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme,
  * In all cases, ownership of the object is transferred to the OSSL_STORE_INFO
  * and will therefore be freed when the OSSL_STORE_INFO is freed.
  */
+OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data);
 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);
@@ -163,6 +164,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl);
  * Functions to try to extract data from a OSSL_STORE_INFO.
  */
 int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info);
+void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info);
 const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info);
 char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info);
 const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info);
index 9aef28c954b3625e8ad1da0b3fc986fe4dbe8645..d243fda94c409c3d4840a557e443709f93b6ff87 100644 (file)
@@ -1035,6 +1035,8 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
 DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
 
 EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8);
+EVP_PKEY *EVP_PKCS82PKEY_with_libctx(const PKCS8_PRIV_KEY_INFO *p8,
+                                     OPENSSL_CTX *libctx, const char *propq);
 PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(const EVP_PKEY *pkey);
 
 int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj,
index 2277c150c1ed7bf37db5eb4c231fc2ec24fdf844..798d8f10b29301dfe9ea6e758caaff843b7cdaf9 100644 (file)
@@ -15,7 +15,7 @@
 #include <openssl/pkcs12.h>
 #include "internal/pem.h"        /* For internal PVK and "blob" functions */
 #include "internal/cryptlib.h"
-#include "crypto/asn1.h"
+#include "internal/asn1.h"
 #include "internal/passphrase.h"
 #include "prov/bio.h"               /* ossl_prov_bio_printf() */
 #include "prov/providercommonerr.h" /* PROV_R_READ_KEY */
index 96f834500d9950918b2ec74ceff50f03b739e39b..a12d5272677af52d455150168d56b33b145a205e 100644 (file)
@@ -5286,3 +5286,11 @@ OSSL_PARAM_get_octet_string_ptr         ?        3_0_0   EXIST::FUNCTION:
 OSSL_DECODER_CTX_set_passphrase_cb      ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_CTX_set_mac_key                ?      3_0_0   EXIST::FUNCTION:
 EVP_PKEY_new_CMAC_key_with_libctx       ?      3_0_0   EXIST::FUNCTION:
+OSSL_STORE_INFO_new                     ?      3_0_0   EXIST::FUNCTION:
+OSSL_STORE_INFO_get0_data               ?      3_0_0   EXIST::FUNCTION:
+ossl_do_blob_header                     ?      3_0_0   EXIST::FUNCTION:DSA
+ossl_do_PVK_header                      ?      3_0_0   EXIST::FUNCTION:DSA,RC4
+asn1_d2i_read_bio                       ?      3_0_0   EXIST::FUNCTION:
+EVP_PKCS82PKEY_with_libctx              ?      3_0_0   EXIST::FUNCTION:
+ossl_b2i                                ?      3_0_0   EXIST::FUNCTION:DSA
+ossl_b2i_bio                            ?      3_0_0   EXIST::FUNCTION:DSA
index 4c908570355fdcd42efb6b0b7037667414f04ec6..54e1bc9ba7dd0407bfbfc59ceacbcf6e6e5c86ec 100644 (file)
@@ -1,3 +1,8 @@
 WPACKET(3)
 WPACKET_init_der(3)
 WPACKET_init_null_der(3)
+asn1_d2i_read_bio(3)
+ossl_do_PVK_header(3)
+ossl_do_blob_header(3)
+ossl_b2i(3)
+ossl_b2i_bio(3)
index 54ff9cc1b7f013a9a902d9b42ebab86e6a743158..783df1203f6552ee286e9b2add0a60f5beaadf1e 100644 (file)
@@ -673,6 +673,7 @@ EVP_PBE_find(3)
 EVP_PBE_get(3)
 EVP_PBE_scrypt(3)
 EVP_PKCS82PKEY(3)
+EVP_PKCS82PKEY_with_libctx(3)
 EVP_PKEY2PKCS8(3)
 EVP_PKEY_CTX_get0_peerkey(3)
 EVP_PKEY_CTX_get0_pkey(3)