From fceb55c3c9a558d9b21904d7a3e66cbbf81dc195 Mon Sep 17 00:00:00 2001 From: William Yang Date: Wed, 27 Nov 2024 10:16:38 +0100 Subject: [PATCH] crypto: Call EVP_MAC_fetch once at load and free at unload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: John Högberg Co-authored-by: William Yang --- 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 dc10b190f87a..03e85540100b 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -386,6 +386,7 @@ static void unload(ErlNifEnv* env, void* priv_data) destroy_engine_mutex(env); #ifdef HAS_3_0_API + fini_mac_types(); while (prov_cnt > 0) { OSSL_PROVIDER_unload(prov[--prov_cnt]); } diff --git a/lib/crypto/c_src/mac.c b/lib/crypto/c_src/mac.c index 407501c36785..83c9dbda360c 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 5580d54d4c3c..a1d7183e87ba 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);