diff options
author | Richard Levitte <levitte@openssl.org> | 2017-02-11 01:16:07 +0100 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2017-06-29 11:55:31 +0200 |
commit | a09003ea22fd99511cc0153314c8751a84d95496 (patch) | |
tree | 2e078852c2ba40927e36f1f7bf84c79d9a62af99 /crypto/store | |
parent | e61ec2d9babf30da3a4d94554e576bf10c1fc92c (diff) | |
download | openssl-new-a09003ea22fd99511cc0153314c8751a84d95496.tar.gz |
STORE 'file' scheme loader: add support for the PKCS#12 container
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3542)
Diffstat (limited to 'crypto/store')
-rw-r--r-- | crypto/store/loader_file.c | 116 | ||||
-rw-r--r-- | crypto/store/store_err.c | 6 |
2 files changed, 122 insertions, 0 deletions
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c index 3a566c3289..558980a591 100644 --- a/crypto/store/loader_file.c +++ b/crypto/store/loader_file.c @@ -157,6 +157,121 @@ typedef struct file_handler_st { int repeatable; } FILE_HANDLER; +static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name, + const char *pem_header, + const unsigned char *blob, + size_t len, void **pctx, + const UI_METHOD *ui_method, + void *ui_data) +{ + OSSL_STORE_INFO *store_info = NULL; + STACK_OF(OSSL_STORE_INFO) *ctx = *pctx; + + if (ctx == NULL) { + /* Initial parsing */ + PKCS12 *p12; + int ok = 0; + + if (pem_name != NULL) + /* No match, there is no PEM PKCS12 tag */ + return NULL; + + if ((p12 = d2i_PKCS12(NULL, &blob, len)) != NULL) { + char *pass = NULL; + char tpass[PEM_BUFSIZE]; + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; + STACK_OF(X509) *chain = NULL; + + if (PKCS12_verify_mac(p12, "", 0) + || PKCS12_verify_mac(p12, NULL, 0)) { + pass = ""; + } else { + if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE, + "PKCS12 import password", + ui_data)) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12, + OSSL_STORE_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); + goto p12_end; + } + } + + if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) { + OSSL_STORE_INFO *si_pkey = NULL; + OSSL_STORE_INFO *si_cert = NULL; + OSSL_STORE_INFO *si_ca = NULL; + + if ((ctx = sk_OSSL_STORE_INFO_new_null()) != NULL + && (si_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL + && sk_OSSL_STORE_INFO_push(ctx, si_pkey) != 0 + && (si_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL + && sk_OSSL_STORE_INFO_push(ctx, si_cert) != 0) { + ok = 1; + si_pkey = NULL; + si_cert = NULL; + + while(sk_X509_num(chain) > 0) { + X509 *ca = sk_X509_value(chain, 0); + + if ((si_ca = OSSL_STORE_INFO_new_CERT(ca)) == NULL + || sk_OSSL_STORE_INFO_push(ctx, si_ca) == 0) { + ok = 0; + break; + } + si_ca = NULL; + (void)sk_X509_shift(chain); + } + } + if (!ok) { + OSSL_STORE_INFO_free(si_ca); + OSSL_STORE_INFO_free(si_cert); + OSSL_STORE_INFO_free(si_pkey); + sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free); + EVP_PKEY_free(pkey); + X509_free(cert); + sk_X509_pop_free(chain, X509_free); + ctx = NULL; + } + *pctx = ctx; + } + } + p12_end: + PKCS12_free(p12); + if (!ok) + return NULL; + } + + if (ctx != NULL) + store_info = sk_OSSL_STORE_INFO_shift(ctx); + + return store_info; +} +static int eof_PKCS12(void *ctx_) +{ + STACK_OF(OSSL_STORE_INFO) *ctx = ctx_; + + return ctx == NULL || sk_OSSL_STORE_INFO_num(ctx) == 0; +} +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); + *pctx = NULL; +} +static FILE_HANDLER PKCS12_handler = { + "PKCS12", + try_decode_PKCS12, + eof_PKCS12, + destroy_ctx_PKCS12, + 1 /* repeatable */ +}; + 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, @@ -352,6 +467,7 @@ static FILE_HANDLER X509CRL_handler = { }; static const FILE_HANDLER *file_handlers[] = { + &PKCS12_handler, &X509Certificate_handler, &X509CRL_handler, ¶ms_handler, diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c index d3dd382aef..ab8439cfeb 100644 --- a/crypto/store/store_err.c +++ b/crypto/store/store_err.c @@ -57,12 +57,16 @@ static const ERR_STRING_DATA OSSL_STORE_str_functs[] = { "ossl_store_unregister_loader_int"}, {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PARAMS, 0), "try_decode_params"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PKCS12, 0), + "try_decode_PKCS12"}, {0, NULL} }; static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = { {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE), "ambiguous content type"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC), + "error verifying pkcs12 mac"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_INVALID_SCHEME), "invalid scheme"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_IS_NOT_A), "is not a"}, @@ -73,6 +77,8 @@ static const ERR_STRING_DATA OSSL_STORE_str_reasons[] = { {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_PARAMETERS), "not parameters"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR), + "passphrase callback error"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE), "path must be absolute"}, {ERR_PACK(ERR_LIB_OSSL_STORE, 0, OSSL_STORE_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED), |