Use the right NID when putting a method in the store
authorMatt Caswell <matt@openssl.org>
Wed, 20 Mar 2019 17:51:29 +0000 (17:51 +0000)
committerMatt Caswell <matt@openssl.org>
Tue, 9 Apr 2019 09:24:43 +0000 (10:24 +0100)
When we attempt to fetch a method with a given NID we will ask the
providers for it if we don't already know about it. During that process
we may be told about other methods with a different NID. We need to
make sure we don't confuse the two.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8541)

crypto/core_fetch.c
crypto/evp/digest.c
crypto/evp/evp_fetch.c
crypto/evp/evp_locl.h
doc/internal/man3/evp_generic_fetch.pod
doc/internal/man3/ossl_method_construct.pod
include/internal/core.h

index d38e1325c6758f26707f355c582e58e39d8f62bb..2c4b0d71dea606b66cd74072e9708e0828f2ab89 100644 (file)
@@ -35,8 +35,9 @@ static int ossl_method_construct_this(OSSL_PROVIDER *provider, void *cbdata)
         const OSSL_ALGORITHM *thismap = map++;
         void *method = NULL;
 
-        if ((method = data->mcm->construct(thismap->implementation, provider,
-                                            data->mcm_data)) == NULL)
+        if ((method = data->mcm->construct(thismap->algorithm_name,
+                                           thismap->implementation, provider,
+                                           data->mcm_data)) == NULL)
             continue;
 
         /*
index b93a014564f2d871e262036badc07b985a5844e8..1af8d826586dbed979647d82c29c63b7af23b4ee 100644 (file)
@@ -585,10 +585,17 @@ static void evp_md_free(void *md)
     EVP_MD_meth_free(md);
 }
 
+static int evp_md_nid(void *vmd)
+{
+    EVP_MD *md = vmd;
+
+    return md->type;
+}
+
 EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
                      const char *properties)
 {
     return evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
                              evp_md_from_dispatch, evp_md_upref,
-                             evp_md_free);
+                             evp_md_free, evp_md_nid);
 }
index 329129d1330ed4175f076c8ff15a39907e31cc9b..012383f0989f1651535ea7c49bc32a815d5c7453 100644 (file)
@@ -62,6 +62,7 @@ struct method_data_st {
                                   OSSL_PROVIDER *);
     int (*refcnt_up_method)(void *method);
     void (*destruct_method)(void *method);
+    int (*nid_method)(void *method);
 };
 
 /*
@@ -106,29 +107,35 @@ static void *get_method_from_store(OPENSSL_CTX *libctx, void *store,
 }
 
 static int put_method_in_store(OPENSSL_CTX *libctx, void *store,
-                               const char *propdef, void *method,
-                               void *data)
+                               const char *propdef,
+                               void *method, void *data)
 {
     struct method_data_st *methdata = data;
+    int nid = methdata->nid_method(method);
+
+    if (nid == NID_undef)
+        return 0;
 
     if (store == NULL
         && (store = get_default_method_store(libctx)) == NULL)
         return 0;
 
     if (methdata->refcnt_up_method(method)
-        && ossl_method_store_add(store, methdata->nid, propdef, method,
+        && ossl_method_store_add(store, nid, propdef, method,
                                  methdata->destruct_method))
         return 1;
     return 0;
 }
 
-static void *construct_method(const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov,
+static void *construct_method(const char *algorithm_name,
+                              const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov,
                               void *data)
 {
     struct method_data_st *methdata = data;
     void *method = NULL;
+    int nid = OBJ_sn2nid(algorithm_name);
 
-    if (methdata->nid == NID_undef) {
+    if (nid == NID_undef) {
         /* Create a new NID for that name on the fly */
         ASN1_OBJECT tmpobj;
 
@@ -139,13 +146,13 @@ static void *construct_method(const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov,
         tmpobj.length = 0;
         tmpobj.data = NULL;
 
-        methdata->nid = OBJ_add_object(&tmpobj);
+        nid = OBJ_add_object(&tmpobj);
     }
 
-    if (methdata->nid == NID_undef)
+    if (nid == NID_undef)
         return NULL;
 
-    method = methdata->method_from_dispatch(methdata->nid, fns, prov);
+    method = methdata->method_from_dispatch(nid, fns, prov);
     if (method == NULL)
         return NULL;
     return method;
@@ -163,7 +170,8 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
                         void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
                                             OSSL_PROVIDER *prov),
                         int (*upref_method)(void *),
-                        void (*free_method)(void *))
+                        void (*free_method)(void *),
+                        int (*nid_method)(void *))
 {
     int nid = OBJ_sn2nid(algorithm);
     void *method = NULL;
@@ -186,6 +194,7 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
         mcmdata.destruct_method = free_method;
         mcmdata.refcnt_up_method = upref_method;
         mcmdata.destruct_method = free_method;
+        mcmdata.nid_method = nid_method;
         method = ossl_method_construct(libctx, operation_id, algorithm,
                                        properties, 0 /* !force_cache */,
                                        &mcm, &mcmdata);
index 2453effe1d0f786314bd1d90872c617bebb9fe6f..efa2db8f7518db6dfad4e52b2626fd22af69d625 100644 (file)
@@ -90,4 +90,5 @@ void *evp_generic_fetch(OPENSSL_CTX *ctx, int operation_id,
                         void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
                                             OSSL_PROVIDER *prov),
                         int (*upref_method)(void *),
-                        void (*free_method)(void *));
+                        void (*free_method)(void *),
+                        int (*nid_method)(void *));
index b871cd1fee1ef7e7b1907f0deaee9376b6f912c6..881aaf954a5bbf87519d50a0b56df0b1b6ddbce9 100644 (file)
@@ -14,7 +14,8 @@ evp_generic_fetch - generic algorithm fetcher and method creator for EVP
                          void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
                                              OSSL_PROVIDER *prov),
                          int (*upref_method)(void *),
-                         void (*free_method)(void *));
+                         void (*free_method)(void *),
+                         int (*nid_method)(void *));
 
 =head1 DESCRIPTION
 
@@ -41,6 +42,10 @@ one.
 
 frees the given method.
 
+=item nid_method()
+
+returns the nid associated with the given method.
+
 =back
 
 =head1 RETURN VALUES
index 36646354670b49d0e30bbf64ad5860cfae061ede..7b682dd0854f1494ec0155a4cff467faf9c66737 100644 (file)
@@ -21,8 +21,8 @@ OSSL_METHOD_CONSTRUCT_METHOD, ossl_method_construct
      int (*put)(OPENSSL_CTX *libctx, void *store, const char *propdef,
                 void *method, void *data);
      /* Construct a new method */
-     void *(*construct)(const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov,
-                        void *data);
+     void *(*construct)(const char *algorithm_name, const OSSL_DISPATCH *fns,
+                        OSSL_PROVIDER *prov, void *data);
      /* Destruct a method */
      void (*destruct)(void *method);
  };
@@ -107,7 +107,8 @@ This function is expected to increment the C<method>'s reference count.
 
 =item construct()
 
-Constructs a sub-system method given a dispatch table C<fns>.
+Constructs a sub-system method for the given C<algorithm_name> and the given
+dispatch table C<fns>.
 
 The associated I<provider object> C<prov> is passed as well, to make
 it possible for the sub-system constructor to keep a reference, which
index b395025eccd448faca7a9026957e3b1d790ca322..06a0775f85b35271c452ace7390e531d5bfbd118 100644 (file)
@@ -38,8 +38,8 @@ typedef struct ossl_method_construct_method_st {
     int (*put)(OPENSSL_CTX *libctx, void *store, const char *propdef,
                void *method, void *data);
     /* Construct a new method */
-    void *(*construct)(const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov,
-                       void *data);
+    void *(*construct)(const char *algorithm_name, const OSSL_DISPATCH *fns,
+                       OSSL_PROVIDER *prov, void *data);
     /* Destruct a method */
     void (*destruct)(void *method, void *data);
 } OSSL_METHOD_CONSTRUCT_METHOD;