Move more general parts of internal/cryptlib.h to new internal/common.h
[openssl.git] / engines / e_loader_attic.c
index be01c557187772e6c4069d0f22e9e35a133f5298..59f19d329f8c604a2a24e8de5b13d6c9384afc05 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2021 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
@@ -9,10 +9,12 @@
 
 /* THIS ENGINE IS FOR TESTING PURPOSES ONLY. */
 
+/* This file has quite some overlap with providers/implementations/storemgmt/file_store.c */
+
 /* We need to use some engine deprecated APIs */
 #define OPENSSL_SUPPRESS_DEPRECATED
 
-/* #include "e_os.h" */
+#include "../e_os.h" /* for stat and strncasecmp */
 #include <string.h>
 #include <sys/stat.h>
 #include <ctype.h>
 #include <openssl/engine.h>
 #include <openssl/x509.h>        /* For the PKCS8 stuff o.O */
 #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/ctype.h"        /* For ossl_isdigit */
+#include "crypto/pem.h"          /* For PVK and "blob" PEM headers */
 
 #include "e_loader_attic_err.c"
 
 DEFINE_STACK_OF(OSSL_STORE_INFO)
 
-#ifdef _WIN32
-# define stat _stat
-# define strncasecmp _strnicmp
-#endif
-
 #ifndef S_ISDIR
 # define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
 #endif
@@ -199,6 +197,7 @@ static OSSL_STORE_INFO *new_EMBEDDED(const char *new_pem_name,
         return NULL;
     }
 
+    data->blob = embedded;
     data->pem_name =
         new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name);
 
@@ -207,7 +206,6 @@ static OSSL_STORE_INFO *new_EMBEDDED(const char *new_pem_name,
         store_info_free(info);
         info = NULL;
     }
-    data->blob = embedded;
 
     return info;
 }
@@ -262,7 +260,7 @@ typedef OSSL_STORE_INFO *(*file_try_decode_fn)(const char *pem_name,
                                                int *matchcount,
                                                const UI_METHOD *ui_method,
                                                void *ui_data, const char *uri,
-                                               OPENSSL_CTX *libctx,
+                                               OSSL_LIB_CTX *libctx,
                                                const char *propq);
 /*
  * The eof function should return 1 if there's no more data to be found
@@ -299,7 +297,7 @@ static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name,
                                           int *matchcount,
                                           const UI_METHOD *ui_method,
                                           void *ui_data, const char *uri,
-                                          OPENSSL_CTX *libctx,
+                                          OSSL_LIB_CTX *libctx,
                                           const char *propq)
 {
     OSSL_STORE_INFO *store_info = NULL;
@@ -322,12 +320,13 @@ static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name,
 
             *matchcount = 1;
 
-            if (PKCS12_verify_mac(p12, "", 0)
+            if (!PKCS12_mac_present(p12)
+                || 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 pass phrase", uri,
+                                          "PKCS12 import", uri,
                                           ui_data)) == NULL) {
                     ATTICerr(0, ATTIC_R_PASSPHRASE_CALLBACK_ERROR);
                     goto p12_end;
@@ -434,7 +433,7 @@ static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name,
                                                   const UI_METHOD *ui_method,
                                                   void *ui_data,
                                                   const char *uri,
-                                                  OPENSSL_CTX *libctx,
+                                                  OSSL_LIB_CTX *libctx,
                                                   const char *propq)
 {
     X509_SIG *p8 = NULL;
@@ -478,6 +477,7 @@ static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name,
     mem->data = (char *)new_data;
     mem->max = mem->length = (size_t)new_data_len;
     X509_SIG_free(p8);
+    p8 = NULL;
 
     store_info = new_EMBEDDED(PEM_STRING_PKCS8INF, mem);
     if (store_info == NULL) {
@@ -509,7 +509,7 @@ static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
                                               int *matchcount,
                                               const UI_METHOD *ui_method,
                                               void *ui_data, const char *uri,
-                                              OPENSSL_CTX *libctx,
+                                              OSSL_LIB_CTX *libctx,
                                               const char *propq)
 {
     OSSL_STORE_INFO *store_info = NULL;
@@ -523,7 +523,7 @@ static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name,
 
             *matchcount = 1;
             if (p8inf != NULL)
-                pkey = EVP_PKCS82PKEY_with_libctx(p8inf, libctx, propq);
+                pkey = EVP_PKCS82PKEY_ex(p8inf, libctx, propq);
             PKCS8_PRIV_KEY_INFO_free(p8inf);
         } else {
             int slen;
@@ -638,7 +638,7 @@ static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name,
                                           int *matchcount,
                                           const UI_METHOD *ui_method,
                                           void *ui_data, const char *uri,
-                                          OPENSSL_CTX *libctx,
+                                          OSSL_LIB_CTX *libctx,
                                           const char *propq)
 {
     OSSL_STORE_INFO *store_info = NULL;
@@ -674,7 +674,7 @@ static OSSL_STORE_INFO *try_decode_params(const char *pem_name,
                                           int *matchcount,
                                           const UI_METHOD *ui_method,
                                           void *ui_data, const char *uri,
-                                          OPENSSL_CTX *libctx,
+                                          OSSL_LIB_CTX *libctx,
                                           const char *propq)
 {
     OSSL_STORE_INFO *store_info = NULL;
@@ -752,7 +752,7 @@ static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name,
                                                    const UI_METHOD *ui_method,
                                                    void *ui_data,
                                                    const char *uri,
-                                                   OPENSSL_CTX *libctx,
+                                                   OSSL_LIB_CTX *libctx,
                                                    const char *propq)
 {
     OSSL_STORE_INFO *store_info = NULL;
@@ -777,7 +777,7 @@ static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name,
         *matchcount = 1;
     }
 
-    cert = X509_new_with_libctx(libctx, propq);
+    cert = X509_new_ex(libctx, propq);
     if (cert == NULL)
         return NULL;
 
@@ -808,7 +808,7 @@ static OSSL_STORE_INFO *try_decode_X509CRL(const char *pem_name,
                                            int *matchcount,
                                            const UI_METHOD *ui_method,
                                            void *ui_data, const char *uri,
-                                           OPENSSL_CTX *libctx,
+                                           OSSL_LIB_CTX *libctx,
                                            const char *propq)
 {
     OSSL_STORE_INFO *store_info = NULL;
@@ -902,7 +902,7 @@ struct ossl_store_loader_ctx_st {
     /* Expected object type.  May be unspecified */
     int expected_type;
 
-    OPENSSL_CTX *libctx;
+    OSSL_LIB_CTX *libctx;
     char *propq;
 };
 
@@ -940,9 +940,9 @@ static int file_find_type(OSSL_STORE_LOADER_CTX *ctx)
     return 1;
 }
 
-static OSSL_STORE_LOADER_CTX *file_open_with_libctx
+static OSSL_STORE_LOADER_CTX *file_open_ex
     (const OSSL_STORE_LOADER *loader, const char *uri,
-     OPENSSL_CTX *libctx, const char *propq,
+     OSSL_LIB_CTX *libctx, const char *propq,
      const UI_METHOD *ui_method, void *ui_data)
 {
     OSSL_STORE_LOADER_CTX *ctx = NULL;
@@ -952,7 +952,7 @@ static OSSL_STORE_LOADER_CTX *file_open_with_libctx
         unsigned int check_absolute:1;
     } path_data[2];
     size_t path_data_n = 0, i;
-    const char *path;
+    const char *path, *p = uri, *q;
 
     /*
      * First step, just take the URI as is.
@@ -961,20 +961,18 @@ static OSSL_STORE_LOADER_CTX *file_open_with_libctx
     path_data[path_data_n++].path = uri;
 
     /*
-     * Second step, if the URI appears to start with the 'file' scheme,
+     * Second step, if the URI appears to start with the "file" scheme,
      * extract the path and make that the second path to check.
      * There's a special case if the URI also contains an authority, then
      * the full URI shouldn't be used as a path anywhere.
      */
-    if (strncasecmp(uri, "file:", 5) == 0) {
-        const char *p = &uri[5];
-
-        if (strncmp(&uri[5], "//", 2) == 0) {
+    if (CHECK_AND_SKIP_CASE_PREFIX(p, "file:")) {
+        q = p;
+        if (CHECK_AND_SKIP_PREFIX(q, "//")) {
             path_data_n--;           /* Invalidate using the full URI */
-            if (strncasecmp(&uri[7], "localhost/", 10) == 0) {
-                p = &uri[16];
-            } else if (uri[7] == '/') {
-                p = &uri[7];
+            if (CHECK_AND_SKIP_CASE_PREFIX(q, "localhost/")
+                    || CHECK_AND_SKIP_PREFIX(q, "/")) {
+                p = q - 1;
             } else {
                 ATTICerr(0, ATTIC_R_URI_AUTHORITY_UNSUPPORTED);
                 return NULL;
@@ -983,7 +981,7 @@ static OSSL_STORE_LOADER_CTX *file_open_with_libctx
 
         path_data[path_data_n].check_absolute = 1;
 #ifdef _WIN32
-        /* Windows file: URIs with a drive letter start with a / */
+        /* Windows "file:" URIs with a drive letter start with a '/' */
         if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
             char c = tolower(p[1]);
 
@@ -1069,12 +1067,12 @@ static OSSL_STORE_LOADER_CTX *file_open
     (const OSSL_STORE_LOADER *loader, const char *uri,
      const UI_METHOD *ui_method, void *ui_data)
 {
-    return file_open_with_libctx(loader, uri, NULL, NULL, ui_method, ui_data);
+    return file_open_ex(loader, uri, NULL, NULL, ui_method, ui_data);
 }
 
 static OSSL_STORE_LOADER_CTX *file_attach
     (const OSSL_STORE_LOADER *loader, BIO *bp,
-     OPENSSL_CTX *libctx, const char *propq,
+     OSSL_LIB_CTX *libctx, const char *propq,
      const UI_METHOD *ui_method, void *ui_data)
 {
     OSSL_STORE_LOADER_CTX *ctx = NULL;
@@ -1154,7 +1152,8 @@ static int file_find(OSSL_STORE_LOADER_CTX *ctx,
             return 0;
         }
 
-        hash = X509_NAME_hash(OSSL_STORE_SEARCH_get0_name(search));
+        hash = X509_NAME_hash_ex(OSSL_STORE_SEARCH_get0_name(search),
+                                 NULL, NULL, NULL);
         BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name),
                      "%08lx", hash);
         return 1;
@@ -1232,10 +1231,13 @@ static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx,
                 }
                 if (result == NULL)
                     result = tmp_result;
+                if (result == NULL) /* e.g., PKCS#12 file decryption error */
+                    break;
             }
         }
 
-        if (*matchcount == 1 && matching_handlers[0]->repeatable) {
+        if (result != NULL
+                && *matchcount == 1 && matching_handlers[0]->repeatable) {
             ctx->_.file.last_handler = matching_handlers[0];
             ctx->_.file.last_handler_ctx = handler_ctx;
         }
@@ -1334,9 +1336,6 @@ static int file_read_pem(BIO *bp, char **pem_name, char **pem_header,
 
 static OSSL_STORE_INFO *file_try_read_msblob(BIO *bp, int *matchcount)
 {
-#ifdef OPENSSL_NO_DSA
-    return NULL;
-#else
     OSSL_STORE_INFO *result = NULL;
     int ispub = -1;
 
@@ -1368,16 +1367,12 @@ static OSSL_STORE_INFO *file_try_read_msblob(BIO *bp, int *matchcount)
     }
 
     return result;
-#endif
 }
 
 static OSSL_STORE_INFO *file_try_read_PVK(BIO *bp, const UI_METHOD *ui_method,
                                           void *ui_data, const char *uri,
                                           int *matchcount)
 {
-#if defined(OPENSSL_NO_DSA) || defined(OPENSSL_NO_RC4)
-    return NULL;
-#else
     OSSL_STORE_INFO *result = NULL;
 
     {
@@ -1407,7 +1402,6 @@ static OSSL_STORE_INFO *file_try_read_PVK(BIO *bp, const UI_METHOD *ui_method,
     }
 
     return result;
-#endif
 }
 
 static int file_read_asn1(BIO *bp, unsigned char **data, long *len)
@@ -1424,27 +1418,13 @@ static int file_read_asn1(BIO *bp, unsigned char **data, long *len)
     return 1;
 }
 
-static int ends_with_dirsep(const char *uri)
-{
-    if (*uri != '\0')
-        uri += strlen(uri) - 1;
-#if defined(__VMS)
-    if (*uri == ']' || *uri == '>' || *uri == ':')
-        return 1;
-#elif defined(_WIN32)
-    if (*uri == '\\')
-        return 1;
-#endif
-    return *uri == '/';
-}
-
 static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name,
                             char **data)
 {
     assert(name != NULL);
     assert(data != NULL);
     {
-        const char *pathsep = ends_with_dirsep(ctx->uri) ? "" : "/";
+        const char *pathsep = ossl_ends_with_dirsep(ctx->uri) ? "" : "/";
         long calculated_length = strlen(ctx->uri) + strlen(pathsep)
             + strlen(name) + 1 /* \0 */;
 
@@ -1464,6 +1444,7 @@ static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name,
 static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
 {
     const char *p = NULL;
+    size_t len = strlen(ctx->_.dir.search_name);
 
     /* If there are no search criteria, all names are accepted */
     if (ctx->_.dir.search_name[0] == '\0')
@@ -1478,11 +1459,9 @@ static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
     /*
      * First, check the basename
      */
-    if (strncasecmp(name, ctx->_.dir.search_name,
-                    sizeof(ctx->_.dir.search_name) - 1) != 0
-        || name[sizeof(ctx->_.dir.search_name) - 1] != '.')
+    if (strncasecmp(name, ctx->_.dir.search_name, len) != 0 || name[len] != '.')
         return 0;
-    p = &name[sizeof(ctx->_.dir.search_name)];
+    p = &name[len + 1];
 
     /*
      * Then, if the expected type is a CRL, check that the extension starts
@@ -1739,13 +1718,12 @@ static int loader_attic_destroy(ENGINE *e)
 static int bind_loader_attic(ENGINE *e)
 {
 
-    /* Ensure the ATTIC error handdling is set up on best effort basis */
+    /* Ensure the ATTIC error handling 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_ex(loader_attic, file_open_ex)
         || !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)