]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
evp: avoid function-pointer-type UB in EVP_*_do_all_provided
authorNikola Pajkovsky <nikolap@openssl.org>
Mon, 11 May 2026 09:43:28 +0000 (11:43 +0200)
committerNeil Horman <nhorman@openssl.org>
Wed, 20 May 2026 15:53:32 +0000 (11:53 -0400)
evp_generic_do_all() invokes its callback through a fixed pointer type
of the form "void (*)(void *method, void *arg)". The public
EVP_*_do_all_provided() wrappers were handing it user callbacks of type
for example:

   void (*)(EVP_MD *, void *)

cast to that generic shape:

    evp_generic_do_all(..., (void (*)(void *, void *))fn, arg, ...);

Calling a function through a pointer whose type does not match the
function's actual definition is undefined behavior in C and is flagged
by UBSan's -fsanitize=function.

Introduce a per-type thunk generated by EVP_DO_ALL_PROVIDED_THUNK that
has the exact signature evp_generic_do_all() expects. The thunk
receives the user's typed callback and arg in a small on-stack struct
and forwards them with the correct types, so every indirect call now
matches the pointee's real prototype.
No functional change intended.

Fixes: https://github.com/openssl/project/issues/1949
Signed-off-by: Nikola Pajkovsky <nikolap@openssl.org>
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
MergeDate: Wed May 20 15:53:38 2026
(Merged from https://github.com/openssl/openssl/pull/31151)

12 files changed:
crypto/evp/asymcipher.c
crypto/evp/digest.c
crypto/evp/evp_enc.c
crypto/evp/evp_local.h
crypto/evp/evp_rand.c
crypto/evp/exchange.c
crypto/evp/kdf_meth.c
crypto/evp/kem.c
crypto/evp/keymgmt_meth.c
crypto/evp/mac_meth.c
crypto/evp/signature.c
crypto/evp/skeymgmt_meth.c

index b76a144e8ac96ebb30f916da3927f7a277a8675b..bdcb8b59dc04d42f0cf6fd2ed054287d03329fcb 100644 (file)
@@ -513,8 +513,12 @@ void EVP_ASYM_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
         void *arg),
     void *arg)
 {
+    struct EVP_ASYM_CIPHER_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_ASYM_CIPHER,
-        (void (*)(void *, void *))fn, arg,
+        EVP_ASYM_CIPHER_do_all_provided_thunk, &t,
         evp_asym_cipher_from_algorithm,
         evp_asym_cipher_up_ref,
         evp_asym_cipher_free);
index 43fa6b1256b01e22c5c6e40b15576c46b87ea68f..b6c01daeee6171cd9a229e2aa5167ab30e791d6c 100644 (file)
@@ -1018,8 +1018,12 @@ void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx,
     void (*fn)(EVP_MD *mac, void *arg),
     void *arg)
 {
+    struct EVP_MD_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_DIGEST,
-        (void (*)(void *, void *))fn, arg,
+        EVP_MD_do_all_provided_thunk, &t,
         evp_md_from_algorithm, evp_md_up_ref, evp_md_free);
 }
 
index 9c27b240bd353c177f8efeb6b5c61d45e82a0fb8..a23846fdf13ca773fbf06dfe0f37d9fbed6e0d43 100644 (file)
@@ -1589,8 +1589,12 @@ void EVP_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
     void (*fn)(EVP_CIPHER *mac, void *arg),
     void *arg)
 {
+    struct EVP_CIPHER_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_CIPHER,
-        (void (*)(void *, void *))fn, arg,
+        EVP_CIPHER_do_all_provided_thunk, &t,
         evp_cipher_from_algorithm, evp_cipher_up_ref,
         evp_cipher_free);
 }
index fc01b71efc78d1474cdfc864db3c445da1a67cab..d4a72b7527cef0caedfca7dc12fcdecc5b025ca5 100644 (file)
@@ -398,4 +398,27 @@ int evp_names_do_all(OSSL_PROVIDER *prov, int number,
     void *data);
 int evp_cipher_cache_constants(EVP_CIPHER *cipher);
 
+#define EVP_DO_ALL_PROVIDED_THUNK(type)                                                       \
+    struct type##_do_all_provided_thunk {                                                     \
+        void (*fn)(type * method, void *arg);                                                 \
+        void *arg;                                                                            \
+    };                                                                                        \
+    static ossl_inline ossl_unused void type##_do_all_provided_thunk(void *method, void *arg) \
+    {                                                                                         \
+        struct type##_do_all_provided_thunk *t = arg;                                         \
+        (*t->fn)((type *)method, t->arg);                                                     \
+    }
+
+EVP_DO_ALL_PROVIDED_THUNK(EVP_ASYM_CIPHER)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_MD)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_CIPHER)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_RAND)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_KEYEXCH)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_KDF)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_KEM)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_KEYMGMT)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_MAC)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_SIGNATURE)
+EVP_DO_ALL_PROVIDED_THUNK(EVP_SKEYMGMT)
+
 #endif /* !defined(OSSL_LIBCRYPTO_EVP_EVP_LOCAL_H) */
index 689243ef10064d4b4341364227fb95d8f20c6c6c..623b87135afe19cf3ff6b6f880b8c785d0e1cdaf 100644 (file)
@@ -492,8 +492,12 @@ void EVP_RAND_do_all_provided(OSSL_LIB_CTX *libctx,
     void (*fn)(EVP_RAND *rand, void *arg),
     void *arg)
 {
+    struct EVP_RAND_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_RAND,
-        (void (*)(void *, void *))fn, arg,
+        EVP_RAND_do_all_provided_thunk, &t,
         evp_rand_from_algorithm, evp_rand_up_ref,
         evp_rand_free);
 }
index a5eea9af1d0768b33964052167b57f25b6df64c0..3928c08ec388984316544656cb5d9ec410d910c0 100644 (file)
@@ -591,8 +591,12 @@ void EVP_KEYEXCH_do_all_provided(OSSL_LIB_CTX *libctx,
     void (*fn)(EVP_KEYEXCH *keyexch, void *arg),
     void *arg)
 {
+    struct EVP_KEYEXCH_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_KEYEXCH,
-        (void (*)(void *, void *))fn, arg,
+        EVP_KEYEXCH_do_all_provided_thunk, &t,
         evp_keyexch_from_algorithm,
         evp_keyexch_up_ref,
         evp_keyexch_free);
index 5ac6a94013bb4c3378145542afac580099b521d6..31680ee664763c15c3d70e8b7aac3306d67ad74e 100644 (file)
@@ -235,7 +235,11 @@ void EVP_KDF_do_all_provided(OSSL_LIB_CTX *libctx,
     void (*fn)(EVP_KDF *kdf, void *arg),
     void *arg)
 {
+    struct EVP_KDF_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_KDF,
-        (void (*)(void *, void *))fn, arg,
+        EVP_KDF_do_all_provided_thunk, &t,
         evp_kdf_from_algorithm, evp_kdf_up_ref, evp_kdf_free);
 }
index d0cf696b32204871da6d89c321eeda068652f185..317db87b52ac2a042c918a4a85971c5d1d998a24 100644 (file)
@@ -499,7 +499,11 @@ void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
     void (*fn)(EVP_KEM *kem, void *arg),
     void *arg)
 {
-    evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg,
+    struct EVP_KEM_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
+    evp_generic_do_all(libctx, OSSL_OP_KEM, EVP_KEM_do_all_provided_thunk, &t,
         evp_kem_from_algorithm,
         evp_kem_up_ref,
         evp_kem_free);
index d37ddcbaf871fc814eb782f4a4029bdaed62317b..e7f00d091fc2a13425e20e870d26eeef42cb0e37 100644 (file)
@@ -350,8 +350,12 @@ void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
     void (*fn)(EVP_KEYMGMT *keymgmt, void *arg),
     void *arg)
 {
+    struct EVP_KEYMGMT_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_KEYMGMT,
-        (void (*)(void *, void *))fn, arg,
+        EVP_KEYMGMT_do_all_provided_thunk, &t,
         keymgmt_from_algorithm,
         evp_keymgmt_up_ref,
         evp_keymgmt_free);
index ee29f58b3e2234fc8ad50005b63243ae475ff1a8..ba47e9587032fa3f3bd38c02e271b4a2043277c5 100644 (file)
@@ -246,8 +246,12 @@ void EVP_MAC_do_all_provided(OSSL_LIB_CTX *libctx,
     void (*fn)(EVP_MAC *mac, void *arg),
     void *arg)
 {
+    struct EVP_MAC_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_MAC,
-        (void (*)(void *, void *))fn, arg,
+        EVP_MAC_do_all_provided_thunk, &t,
         evp_mac_from_algorithm, evp_mac_up_ref, evp_mac_free);
 }
 
index 4ca52810ee5ed04270b109f9c5e09823c67ca77b..51a5f0c4df5a29d81a1b403c3e3dedbec1624786 100644 (file)
@@ -532,8 +532,12 @@ void EVP_SIGNATURE_do_all_provided(OSSL_LIB_CTX *libctx,
         void *arg),
     void *arg)
 {
+    struct EVP_SIGNATURE_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_SIGNATURE,
-        (void (*)(void *, void *))fn, arg,
+        EVP_SIGNATURE_do_all_provided_thunk, &t,
         evp_signature_from_algorithm,
         evp_signature_up_ref,
         evp_signature_free);
index 80e1abf8836ffa062c7fae989c66e627331aaf59..75c4fef6751a01d87cccb831910f5df792db2db7 100644 (file)
@@ -207,8 +207,12 @@ void EVP_SKEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
     void (*fn)(EVP_SKEYMGMT *skeymgmt, void *arg),
     void *arg)
 {
+    struct EVP_SKEYMGMT_do_all_provided_thunk t;
+
+    t.fn = fn;
+    t.arg = arg;
     evp_generic_do_all(libctx, OSSL_OP_SKEYMGMT,
-        (void (*)(void *, void *))fn, arg,
+        EVP_SKEYMGMT_do_all_provided_thunk, &t,
         skeymgmt_from_algorithm,
         evp_skeymgmt_up_ref,
         evp_skeymgmt_free);