Add OID for draft-ietf-opsawg-finding-geofeeds detached CMS signature
[openssl.git] / crypto / core_fetch.c
index ed50bb87d53c6c1d247a6371a0466fd525781aa0..0c30f985d6e26617500e00f3f23813f001647fa0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-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
@@ -16,7 +16,7 @@
 #include "internal/provider.h"
 
 struct construct_data_st {
-    OPENSSL_CTX *libctx;
+    OSSL_LIB_CTX *libctx;
     OSSL_METHOD_STORE *store;
     int operation_id;
     int force_store;
@@ -24,6 +24,42 @@ struct construct_data_st {
     void *mcm_data;
 };
 
+static int ossl_method_construct_precondition(OSSL_PROVIDER *provider,
+                                              int operation_id, void *cbdata,
+                                              int *result)
+{
+    if (!ossl_assert(result != NULL)) {
+        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    if (!ossl_provider_test_operation_bit(provider, operation_id, result))
+        return 0;
+
+    /*
+     * The result we get tells if methods have already been constructed.
+     * However, we want to tell whether construction should happen (true)
+     * or not (false), which is the opposite of what we got.
+     */
+    *result = !*result;
+
+    return 1;
+}
+
+static int ossl_method_construct_postcondition(OSSL_PROVIDER *provider,
+                                               int operation_id, int no_store,
+                                               void *cbdata, int *result)
+{
+    if (!ossl_assert(result != NULL)) {
+        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    *result = 1;
+    return no_store != 0
+        || ossl_provider_set_operation_bit(provider, operation_id);
+}
+
 static void ossl_method_construct_this(OSSL_PROVIDER *provider,
                                        const OSSL_ALGORITHM *algo,
                                        int no_store, void *cbdata)
@@ -31,9 +67,8 @@ static void ossl_method_construct_this(OSSL_PROVIDER *provider,
     struct construct_data_st *data = cbdata;
     void *method = NULL;
 
-    if ((method = data->mcm->construct(algo->algorithm_names,
-                                       algo->implementation, provider,
-                                       data->mcm_data)) == NULL)
+    if ((method = data->mcm->construct(algo, provider, data->mcm_data))
+        == NULL)
         return;
 
     /*
@@ -65,7 +100,7 @@ static void ossl_method_construct_this(OSSL_PROVIDER *provider,
     data->mcm->destruct(method, data->mcm_data);
 }
 
-void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
+void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id,
                             int force_store,
                             OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data)
 {
@@ -87,9 +122,22 @@ void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
         cbdata.mcm = mcm;
         cbdata.mcm_data = mcm_data;
         ossl_algorithm_do_all(libctx, operation_id, NULL,
-                              ossl_method_construct_this, &cbdata);
+                              ossl_method_construct_precondition,
+                              ossl_method_construct_this,
+                              ossl_method_construct_postcondition,
+                              &cbdata);
 
         method = mcm->get(libctx, cbdata.store, mcm_data);
+        if (method == NULL) {
+            /*
+             * If we get here then we did not construct the method that we
+             * attempted to construct. It's possible that another thread got
+             * there first and so we skipped construction (pre-condition
+             * failed). We check the global store again to see if it has
+             * appeared by now.
+             */
+            method = mcm->get(libctx, NULL, mcm_data);
+        }
         mcm->dealloc_tmp_store(cbdata.store);
     }