diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index d66ab4f2ed674308e1f16431cb4fc5f4f11411d4..67e7d47d7671d9ca155e69b14eaa65c9d201437e 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -753,6 +753,7 @@ OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT:116:\ ossl_store_unregister_loader_int OSSL_STORE_F_TRY_DECODE_PARAMS:121:try_decode_params OSSL_STORE_F_TRY_DECODE_PKCS12:122:try_decode_PKCS12 +OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED:125:try_decode_PKCS8Encrypted PEM_F_B2I_DSS:127:b2i_dss PEM_F_B2I_PVK_BIO:128:b2i_PVK_bio PEM_F_B2I_RSA:129:b2i_rsa @@ -1980,6 +1981,7 @@ OCSP_R_UNKNOWN_MESSAGE_DIGEST:119:unknown message digest OCSP_R_UNKNOWN_NID:120:unknown nid OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE:129:unsupported requestorname type OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE:107:ambiguous content type +OSSL_STORE_R_BAD_PASSWORD_READ:115:bad password read OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC:113:error verifying pkcs12 mac OSSL_STORE_R_INVALID_SCHEME:106:invalid scheme OSSL_STORE_R_IS_NOT_A:112:is not a diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c index 472e8197f8f26e31fbadaa34ced5863fc8076e7a..0ec264bf1612e583b66ff6ca0a8b04415aa9c6c4 100644 --- a/crypto/store/loader_file.c +++ b/crypto/store/loader_file.c @@ -272,6 +272,69 @@ static FILE_HANDLER PKCS12_handler = { 1 /* repeatable */ }; +static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(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) +{ + X509_SIG *p8 = NULL; + char kbuf[PEM_BUFSIZE]; + char *pass = NULL; + const X509_ALGOR *dalg = NULL; + const ASN1_OCTET_STRING *doct = NULL; + OSSL_STORE_INFO *store_info = NULL; + BUF_MEM *mem = NULL; + unsigned char *new_data = NULL; + int new_data_len; + + if (pem_name != NULL && strcmp(pem_name, PEM_STRING_PKCS8) != 0) + return NULL; + + if ((p8 = d2i_X509_SIG(NULL, &blob, len)) == NULL) + return NULL; + + if ((mem = BUF_MEM_new()) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, + ERR_R_MALLOC_FAILURE); + goto nop8; + } + + if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE, + "PKCS8 decrypt password", ui_data)) == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, + OSSL_STORE_R_BAD_PASSWORD_READ); + goto nop8; + } + + X509_SIG_get0(p8, &dalg, &doct); + if (!PKCS12_pbe_crypt(dalg, pass, strlen(pass), doct->data, doct->length, + &new_data, &new_data_len, 0)) + goto nop8; + + mem->data = (char *)new_data; + mem->max = mem->length = (size_t)new_data_len; + X509_SIG_free(p8); + + store_info = ossl_store_info_new_EMBEDDED(PEM_STRING_PKCS8INF, mem); + if (store_info == NULL) { + OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, + ERR_R_MALLOC_FAILURE); + goto nop8; + } + + return store_info; + nop8: + X509_SIG_free(p8); + BUF_MEM_free(mem); + return NULL; +} +static FILE_HANDLER PKCS8Encrypted_handler = { + "PKCS8Encrypted", + try_decode_PKCS8Encrypted +}; + 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, @@ -285,11 +348,21 @@ static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name, const EVP_PKEY_ASN1_METHOD *ameth = NULL; if (pem_name != NULL) { - int slen; + if (strcmp(pem_name, PEM_STRING_PKCS8INF) == 0) { + PKCS8_PRIV_KEY_INFO *p8inf = + d2i_PKCS8_PRIV_KEY_INFO(NULL, &blob, len); - if ((slen = pem_check_suffix(pem_name, "PRIVATE KEY")) > 0 - && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, slen)) != NULL) - pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &blob, len); + if (p8inf != NULL) + pkey = EVP_PKCS82PKEY(p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + } else { + int slen; + + if ((slen = pem_check_suffix(pem_name, "PRIVATE KEY")) > 0 + && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, + slen)) != NULL) + pkey = d2i_PrivateKey(ameth->pkey_id, NULL, &blob, len); + } } else { int i; @@ -468,6 +541,7 @@ static FILE_HANDLER X509CRL_handler = { static const FILE_HANDLER *file_handlers[] = { &PKCS12_handler, + &PKCS8Encrypted_handler, &X509Certificate_handler, &X509CRL_handler, ¶ms_handler, diff --git a/crypto/store/store_err.c b/crypto/store/store_err.c index 57627ebdecb5736bebeae35fcce717ae884c4a73..9117576bd86c739c06ba683591bed2a30650bc81 100644 --- a/crypto/store/store_err.c +++ b/crypto/store/store_err.c @@ -63,12 +63,16 @@ static const ERR_STRING_DATA OSSL_STORE_str_functs[] = { "try_decode_params"}, {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PKCS12, 0), "try_decode_PKCS12"}, + {ERR_PACK(ERR_LIB_OSSL_STORE, OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, 0), + "try_decode_PKCS8Encrypted"}, {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_BAD_PASSWORD_READ), + "bad password read"}, {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), diff --git a/include/openssl/storeerr.h b/include/openssl/storeerr.h index c37e4170a9aeb1103609e0411611d524bc189cfc..659355a3d630a99db8c28a739abf84604d4c5b47 100644 --- a/include/openssl/storeerr.h +++ b/include/openssl/storeerr.h @@ -48,11 +48,13 @@ int ERR_load_OSSL_STORE_strings(void); # define OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT 116 # define OSSL_STORE_F_TRY_DECODE_PARAMS 121 # define OSSL_STORE_F_TRY_DECODE_PKCS12 122 +# define OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED 125 /* * OSSL_STORE reason codes. */ # define OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE 107 +# define OSSL_STORE_R_BAD_PASSWORD_READ 115 # define OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC 113 # define OSSL_STORE_R_INVALID_SCHEME 106 # define OSSL_STORE_R_IS_NOT_A 112