STORE 'file' scheme loader: Add handler for encrypted PKCS#8 data
authorRichard Levitte <levitte@openssl.org>
Sat, 11 Feb 2017 00:18:29 +0000 (01:18 +0100)
committerRichard Levitte <levitte@openssl.org>
Thu, 29 Jun 2017 09:55:32 +0000 (11:55 +0200)
Add a separate handler for encrypted PKCS#8 data.  This uses the new
restart functionality.

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

crypto/err/openssl.txt
crypto/store/loader_file.c
crypto/store/store_err.c
include/openssl/storeerr.h

index d66ab4f..67e7d47 100644 (file)
@@ -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
index 472e819..0ec264b 100644 (file)
@@ -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,
     &params_handler,
index 57627eb..9117576 100644 (file)
@@ -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),
index c37e417..659355a 100644 (file)
@@ -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