diff options
author | Richard Levitte <levitte@openssl.org> | 2020-07-23 16:56:59 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-09-03 17:48:32 +0200 |
commit | 16feca71544681cabf873fecd3f860f9853bdf07 (patch) | |
tree | a1dce6397911d95de73f10208b65dbba04526ac6 | |
parent | bd7a6f16eb52c5c022b2555810efd99006db0a02 (diff) |
STORE: Move the built-in 'file:' loader to become an engine module
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, 504 insertions, 241 deletions
diff --git a/Configurations/unix-Makefile.tmpl b/Configurations/unix-Makefile.tmpl index 441f83c345..ff4803be74 100644 --- a/Configurations/unix-Makefile.tmpl +++ b/Configurations/unix-Makefile.tmpl @@ -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 diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c index 186e7ec413..249e6294c8 100644 --- a/crypto/asn1/a_d2i_fp.c +++ b/crypto/asn1/a_d2i_fp.c @@ -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 diff --git a/crypto/asn1/d2i_param.c b/crypto/asn1/d2i_param.c index bd6ef1ce51..f0217b47f6 100644 --- a/crypto/asn1/d2i_param.c +++ b/crypto/asn1/d2i_param.c @@ -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) diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c index a4d240e7c4..ba81782698 100644 --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/d2i_pr.c @@ -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; diff --git a/crypto/evp/evp_pkey.c b/crypto/evp/evp_pkey.c index cfe0544ed6..92ae3e5fe8 100644 --- a/crypto/evp/evp_pkey.c +++ b/crypto/evp/evp_pkey.c @@ -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 */ diff --git a/crypto/store/build.info b/crypto/store/build.info index 33b59f0fae..bd19237ba4 100644 --- a/crypto/store/build.info +++ b/crypto/store/build.info @@ -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 diff --git a/crypto/store/store_init.c b/crypto/store/store_init.c index b87730736d..4d434eb57b 100644 --- a/crypto/store/store_init.c +++ b/crypto/store/store_init.c @@ -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) diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c index d0fdb38cd8..1c718c589e 100644 --- a/crypto/store/store_lib.c +++ b/crypto/store/store_lib.c @@ -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, diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h index 619e547aae..cdd9f164b4 100644 --- a/crypto/store/store_local.h +++ b/crypto/store/store_local.h @@ -29,11 +29,6 @@ struct ossl_store_info_st { 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; } name; /* when type == OSSL_STORE_INFO_NAME */ @@ -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 diff --git a/crypto/store/store_result.c b/crypto/store/store_result.c index 74aeaf543b..9df29cec0a 100644 --- a/crypto/store/store_result.c +++ b/crypto/store/store_result.c @@ -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); } diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index a8ad292074..3e7dc42ef1 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -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" diff --git a/doc/man3/OSSL_STORE_INFO.pod b/doc/man3/OSSL_STORE_INFO.pod index bc965a77bd..8c811ec1f3 100644 --- a/doc/man3/OSSL_STORE_INFO.pod +++ b/doc/man3/OSSL_STORE_INFO.pod @@ -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. diff --git a/engines/build.info b/engines/build.info index 3bfe1dc057..4e83dbf9bc 100644 --- a/engines/build.info +++ b/engines/build.info @@ -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 diff --git a/crypto/store/loader_file.c b/engines/e_loader_attic.c index 25ce9ba92e..581bfb0285 100644 --- a/crypto/store/loader_file.c +++ b/engines/e_loader_attic.c @@ -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> @@ -21,25 +23,26 @@ #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, |