File 1321-crypto-Call-EVP_MAC_fetch-once-at-load-and-free-at-u.patch of Package erlang

From f2acfa01d99b70cb8bda79b7886b9a3262e3a2d4 Mon Sep 17 00:00:00 2001
From: William Yang <mscame@gmail.com>
Date: Wed, 27 Nov 2024 10:16:38 +0100
Subject: [PATCH] crypto: Call EVP_MAC_fetch once at load and free at unload

In the doc of EVP_MAC_fetch(), https://docs.openssl.org/3.0/man3/EVP_MAC
"The returned value must eventually be freed with EVP_MAC_free(3)."

Co-authored-by: Sverker Eriksson <sverker@erlang.org>
Co-authored-by: William Yang <mscame@gmail.com>
---
 lib/crypto/c_src/crypto.c |  1 +
 lib/crypto/c_src/mac.c    | 45 ++++++++++++++++++++++++++++++---------
 lib/crypto/c_src/mac.h    |  1 +
 3 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index f37bd14f45..ab69292ffd 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -393,6 +393,7 @@ static void unload(ErlNifEnv* env, void* priv_data)
         destroy_engine_mutex(env);
 
 #ifdef HAS_3_0_API
+        fini_mac_types();
 # ifdef FIPS_SUPPORT
         if (fips_provider) {
             OSSL_PROVIDER_unload(fips_provider);
diff --git a/lib/crypto/c_src/mac.c b/lib/crypto/c_src/mac.c
index 407501c367..83c9dbda36 100644
--- a/lib/crypto/c_src/mac.c
+++ b/lib/crypto/c_src/mac.c
@@ -41,6 +41,10 @@ struct mac_type_t {
     }alg;
     int type;
     size_t key_len;      /* != 0 to also match on key_len */
+#if defined(HAS_3_0_API)
+    const char* fetch_name;
+    EVP_MAC *evp_mac;
+#endif
 };
 
 /* masks in the flags field if mac_type_t */
@@ -59,6 +63,9 @@ static struct mac_type_t mac_types[] =
      {EVP_PKEY_POLY1305}, POLY1305_mac, 32
 #else
      {EVP_PKEY_NONE}, NO_mac, 0
+#endif
+#if defined(HAS_3_0_API)
+     ,"POLY1305"
 #endif
     },
 
@@ -68,6 +75,9 @@ static struct mac_type_t mac_types[] =
 #else
      /* HMAC is always supported, but possibly with low-level routines */
      {EVP_PKEY_NONE}, HMAC_mac, 0
+#endif
+#if defined(HAS_3_0_API)
+     ,"HMAC"
 #endif
     },
 
@@ -77,6 +87,9 @@ static struct mac_type_t mac_types[] =
      {EVP_PKEY_CMAC}, CMAC_mac, 0
 #else
      {EVP_PKEY_NONE}, NO_mac, 0
+#endif
+#if defined(HAS_3_0_API)
+     ,"CMAC"
 #endif
     },
 
@@ -114,10 +127,26 @@ void init_mac_types(ErlNifEnv* env)
 
     for (p = mac_types; p->name.str; p++) {
 	p->name.atom = enif_make_atom(env, p->name.str);
+#if defined(HAS_3_0_API)
+        p->evp_mac = EVP_MAC_fetch(NULL, p->fetch_name, NULL);
+#endif
     }
     p->name.atom = atom_false;  /* end marker */
 }
 
+void fini_mac_types(void)
+{
+#if defined(HAS_3_0_API)
+    struct mac_type_t* p = mac_types;
+
+    for (p = mac_types; p->name.str; p++) {
+        EVP_MAC_free(p->evp_mac);
+        p->evp_mac = NULL;
+    }
+#endif
+}
+
+
 
 ERL_NIF_TERM mac_types_as_list(ErlNifEnv* env)
 {
@@ -529,12 +558,13 @@ static void mac_context_dtor(ErlNifEnv* env, struct mac_context *obj)
     if (obj == NULL)
         return;
 
-    if (obj->ctx)
+    if (obj->ctx) {
 #if defined(HAS_3_0_API)
         EVP_MAC_CTX_free(obj->ctx);
 #else
         EVP_MD_CTX_free(obj->ctx);
 #endif
+    }
 }
 
 /*******************************************************************
@@ -560,10 +590,8 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
     ErlNifBinary key_bin;
     ERL_NIF_TERM return_term;
 # if defined(HAS_3_0_API)
-    const char *name = NULL;
     const char *digest = NULL;
     const char *cipher = NULL;
-    EVP_MAC *mac = NULL;
     OSSL_PARAM params[3];
     size_t params_n = 0;
 # else
@@ -623,7 +651,6 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
                     goto err;
                 }
 # if defined(HAS_3_0_API)
-            name = "HMAC";
             digest = digp->str_v3;
 # else
             if (digp->md.p == NULL)
@@ -675,7 +702,6 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
                 }
 
 #  if defined(HAS_3_0_API)
-            name = "CMAC";
             cipher = cipherp->str_v3;
 #  else
             /* Old style */
@@ -691,9 +717,7 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
          ************/
 # ifdef HAVE_POLY1305
     case POLY1305_mac:
-#  if defined(HAS_3_0_API)
-        name = "POLY1305";
-#  else
+#  if !defined(HAS_3_0_API)
         /* Old style */
         /* poly1305 implies that EVP_PKEY_new_raw_private_key exists */
         pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_POLY1305, /*engine*/ NULL, key_bin.data,  key_bin.size);
@@ -716,8 +740,9 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
     /*-----------------------------------------
       Common computations when we have 3.0 API
     */
-    if (!(mac = EVP_MAC_fetch(NULL, name, NULL)))
+    if (!macp->evp_mac) {
         assign_goto(return_term, err, EXCP_NOTSUP_N(env, 0, "Unsupported mac algorithm"));
+    }
 
     if (cipher != NULL)
         params[params_n++] =
@@ -730,7 +755,7 @@ ERL_NIF_TERM mac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
     if ((obj = enif_alloc_resource(mac_context_rtype, sizeof(struct mac_context))) == NULL)
         assign_goto(return_term, err, EXCP_ERROR(env, "Can't allocate mac_context_rtype"));
 
-    if (!(obj->ctx = EVP_MAC_CTX_new(mac)))
+    if (!(obj->ctx = EVP_MAC_CTX_new(macp->evp_mac)))
         assign_goto(return_term, err, EXCP_ERROR(env, "Can't create EVP_MAC_CTX"));
     
     if (!EVP_MAC_init(obj->ctx, key_bin.data, key_bin.size, params))
diff --git a/lib/crypto/c_src/mac.h b/lib/crypto/c_src/mac.h
index 5580d54d4c..a1d7183e87 100644
--- a/lib/crypto/c_src/mac.h
+++ b/lib/crypto/c_src/mac.h
@@ -26,6 +26,7 @@
 int init_mac_ctx(ErlNifEnv *env, ErlNifBinary* rt_buf);
 
 void init_mac_types(ErlNifEnv* env);
+void fini_mac_types(void);
 
 ERL_NIF_TERM mac_types_as_list(ErlNifEnv* env);
 
-- 
2.43.0

openSUSE Build Service is sponsored by