Refactor TLS-PRF's kdf_tls1_prf_mkmacctx() to a provider utility
authorRichard Levitte <levitte@openssl.org>
Thu, 19 Sep 2019 09:47:46 +0000 (11:47 +0200)
committerRichard Levitte <levitte@openssl.org>
Fri, 20 Sep 2019 06:28:47 +0000 (08:28 +0200)
ossl_prov_macctx_load_from_params() creates a EVP_MAC_CTX *, or sets
new common parameters for an existing one.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9946)

include/openssl/core_names.h
providers/common/include/internal/provider_util.h
providers/common/kdfs/tls1_prf.c
providers/common/provider_util.c

index e1bc43d..ad4cf50 100644 (file)
@@ -47,6 +47,7 @@ extern "C" {
  */
 #define OSSL_ALG_PARAM_DIGEST       "digest"    /* utf8_string */
 #define OSSL_ALG_PARAM_CIPHER       "cipher"    /* utf8_string */
+#define OSSL_ALG_PARAM_MAC          "mac"       /* utf8_string */
 #define OSSL_ALG_PARAM_ENGINE       "engine"    /* utf8_string */
 #define OSSL_ALG_PARAM_PROPERTIES   "properties"/* utf8_string */
 
@@ -108,8 +109,8 @@ extern "C" {
 #define OSSL_KDF_PARAM_KEY          "key"       /* octet string */
 #define OSSL_KDF_PARAM_SALT         "salt"      /* octet string */
 #define OSSL_KDF_PARAM_PASSWORD     "pass"      /* octet string */
-#define OSSL_KDF_PARAM_DIGEST       OSSL_ALG_PARAM_DIGEST    /* utf8 string */
-#define OSSL_KDF_PARAM_MAC          "mac"       /* utf8 string */
+#define OSSL_KDF_PARAM_DIGEST       OSSL_ALG_PARAM_DIGEST     /* utf8 string */
+#define OSSL_KDF_PARAM_MAC          OSSL_ALG_PARAM_MAC        /* utf8 string */
 #define OSSL_KDF_PARAM_MAC_SIZE     "maclen"    /* size_t */
 #define OSSL_KDF_PARAM_ENGINE       OSSL_ALG_PARAM_ENGINE     /* utf8 string */
 #define OSSL_KDF_PARAM_PROPERTIES   OSSL_ALG_PARAM_PROPERTIES /* utf8 string */
index 9fe21c5..ad7e722 100644 (file)
@@ -85,3 +85,27 @@ int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src);
 const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd);
 ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd);
 const char *ossl_prov_digest_name(const PROV_DIGEST *pd);
+
+/* MAC functions */
+/*
+ * Load an EVP_MAC_CTX* from the specified parameters with the specified
+ * library context.
+ * The params "mac" and "properties" are used to determine the implementation
+ * used, and the parameters "digest", "cipher", "engine" and "properties" are
+ * passed to the MAC via the created MAC context if they are given.
+ * If there is already a created MAC context, it will be replaced if the "mac"
+ * parameter is found, otherwise it will simply be used as is, and passed the
+ * parameters to pilfer as it sees fit.
+ *
+ * As an option, a MAC name may be explicitly given, and if it is, the "mac"
+ * parameter will be ignored.
+ * Similarly, as an option, a cipher name or a digest name may be explicitly
+ * given, and if any of them is, the "digest" and "cipher" parameters are
+ * ignored.
+ */
+int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,
+                                      const OSSL_PARAM params[],
+                                      const char *macname,
+                                      const char *ciphername,
+                                      const char *mdname,
+                                      OPENSSL_CTX *ctx);
index 0acdcdf..3053b75 100644 (file)
@@ -145,51 +145,6 @@ static int kdf_tls1_prf_derive(void *vctx, unsigned char *key,
                         key, keylen);
 }
 
-static EVP_MAC_CTX *kdf_tls1_prf_mkmacctx(OPENSSL_CTX *libctx,
-                                          const char *mdname,
-                                          const OSSL_PARAM params[])
-{
-    const OSSL_PARAM *p;
-    OSSL_PARAM mac_params[5], *mp = mac_params;
-    const char *properties = NULL;
-    /* TODO(3.0) rethink "flags", also see hmac.c in providers */
-    int mac_flags = EVP_MD_CTX_FLAG_NON_FIPS_ALLOW;
-    EVP_MAC_CTX *macctx = NULL;
-
-    *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
-                                             (char *)mdname, 0);
-#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ENGINE)) != NULL)
-        *mp++ = *p;
-#endif
-    if ((p = OSSL_PARAM_locate_const(params,
-                                     OSSL_KDF_PARAM_PROPERTIES)) != NULL) {
-        properties = p->data;
-        *mp++ = *p;
-    }
-    *mp++ = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_FLAGS, &mac_flags);
-    *mp = OSSL_PARAM_construct_end();
-
-    /* Implicit fetch */
-    {
-        EVP_MAC *mac = EVP_MAC_fetch(libctx, OSSL_MAC_NAME_HMAC, properties);
-
-        macctx = EVP_MAC_CTX_new(mac);
-        /* The context holds on to the MAC */
-        EVP_MAC_free(mac);
-        if (macctx == NULL)
-            goto err;
-    }
-
-    if (EVP_MAC_CTX_set_params(macctx, mac_params))
-        goto done;
- err:
-    EVP_MAC_CTX_free(macctx);
-    macctx = NULL;
- done:
-    return macctx;
-}
-
 static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 {
     const OSSL_PARAM *p;
@@ -197,13 +152,20 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
     OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
 
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
-        EVP_MAC_CTX_free(ctx->P_hash);
-        EVP_MAC_CTX_free(ctx->P_sha1);
         if (strcasecmp(p->data, SN_md5_sha1) == 0) {
-            ctx->P_hash = kdf_tls1_prf_mkmacctx(libctx, SN_md5, params);
-            ctx->P_sha1 = kdf_tls1_prf_mkmacctx(libctx, SN_sha1, params);
+            if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
+                                                   OSSL_MAC_NAME_HMAC,
+                                                   NULL, SN_md5, libctx)
+                || !ossl_prov_macctx_load_from_params(&ctx->P_sha1, params,
+                                                      OSSL_MAC_NAME_HMAC,
+                                                      NULL, SN_sha1, libctx))
+                return 0;
         } else {
-            ctx->P_hash = kdf_tls1_prf_mkmacctx(libctx, p->data, params);
+            EVP_MAC_CTX_free(ctx->P_sha1);
+            if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params,
+                                                   OSSL_MAC_NAME_HMAC,
+                                                   NULL, NULL, libctx))
+                return 0;
         }
     }
 
index 1995447..4056878 100644 (file)
@@ -165,3 +165,91 @@ const char *ossl_prov_digest_name(const PROV_DIGEST *pd)
 {
     return pd->name;
 }
+
+int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx,
+                                      const OSSL_PARAM params[],
+                                      const char *macname,
+                                      const char *ciphername,
+                                      const char *mdname,
+                                      OPENSSL_CTX *libctx)
+{
+    const OSSL_PARAM *p;
+    OSSL_PARAM mac_params[5], *mp = mac_params;
+    const char *properties = NULL;
+
+    if (macname == NULL
+        && (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) {
+        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+            return 0;
+        macname = p->data;
+    }
+    if ((p = OSSL_PARAM_locate_const(params,
+                                     OSSL_ALG_PARAM_PROPERTIES)) != NULL) {
+        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+            return 0;
+        properties = p->data;
+    }
+
+    /* If we got a new mac name, we make a new EVP_MAC_CTX */
+    if (macname != NULL) {
+        EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties);
+
+        EVP_MAC_CTX_free(*macctx);
+        *macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac);
+        /* The context holds on to the MAC */
+        EVP_MAC_free(mac);
+        if (*macctx == NULL)
+            return 0;
+    }
+
+    /*
+     * If there is no MAC yet (and therefore, no MAC context), we ignore
+     * all other parameters.
+     */
+    if (*macctx == NULL)
+        return 1;
+
+    if (mdname == NULL) {
+        if ((p = OSSL_PARAM_locate_const(params,
+                                         OSSL_ALG_PARAM_DIGEST)) != NULL) {
+            if (p->data_type != OSSL_PARAM_UTF8_STRING)
+                return 0;
+            mdname = p->data;
+        }
+    }
+    if (ciphername == NULL) {
+        if ((p = OSSL_PARAM_locate_const(params,
+                                         OSSL_ALG_PARAM_CIPHER)) != NULL) {
+            if (p->data_type != OSSL_PARAM_UTF8_STRING)
+                return 0;
+            ciphername = p->data;
+        }
+    }
+
+    if (mdname != NULL)
+        *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+                                                 (char *)mdname, 0);
+    if (ciphername != NULL)
+        *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+                                                 (char *)ciphername, 0);
+    if (properties != NULL)
+        *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES,
+                                                 (char *)properties, 0);
+
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE)) != NULL) {
+        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+            return 0;
+        *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
+                                                 p->data, p->data_size);
+    }
+#endif
+    *mp = OSSL_PARAM_construct_end();
+
+    if (EVP_MAC_CTX_set_params(*macctx, mac_params))
+        return 1;
+
+    EVP_MAC_CTX_free(*macctx);
+    *macctx = NULL;
+    return 0;
+}