Commit c84affae0b for openssl.org
commit c84affae0b848b8194a045d26895f47d52199d8d
Author: Nikola Pajkovsky <nikolap@openssl.org>
Date: Mon May 11 11:43:28 2026 +0200
evp: avoid function-pointer-type UB in EVP_*_do_all_provided
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)
diff --git a/crypto/evp/asymcipher.c b/crypto/evp/asymcipher.c
index b76a144e8a..bdcb8b59dc 100644
--- a/crypto/evp/asymcipher.c
+++ b/crypto/evp/asymcipher.c
@@ -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);
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 43fa6b1256..b6c01daeee 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -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);
}
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 9c27b240bd..a23846fdf1 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -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);
}
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index fc01b71efc..d4a72b7527 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -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) */
diff --git a/crypto/evp/evp_rand.c b/crypto/evp/evp_rand.c
index 689243ef10..623b87135a 100644
--- a/crypto/evp/evp_rand.c
+++ b/crypto/evp/evp_rand.c
@@ -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);
}
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index a5eea9af1d..3928c08ec3 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -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);
diff --git a/crypto/evp/kdf_meth.c b/crypto/evp/kdf_meth.c
index 5ac6a94013..31680ee664 100644
--- a/crypto/evp/kdf_meth.c
+++ b/crypto/evp/kdf_meth.c
@@ -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);
}
diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c
index d0cf696b32..317db87b52 100644
--- a/crypto/evp/kem.c
+++ b/crypto/evp/kem.c
@@ -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);
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index d37ddcbaf8..e7f00d091f 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -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);
diff --git a/crypto/evp/mac_meth.c b/crypto/evp/mac_meth.c
index ee29f58b3e..ba47e95870 100644
--- a/crypto/evp/mac_meth.c
+++ b/crypto/evp/mac_meth.c
@@ -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);
}
diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c
index 4ca52810ee..51a5f0c4df 100644
--- a/crypto/evp/signature.c
+++ b/crypto/evp/signature.c
@@ -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);
diff --git a/crypto/evp/skeymgmt_meth.c b/crypto/evp/skeymgmt_meth.c
index 80e1abf883..75c4fef675 100644
--- a/crypto/evp/skeymgmt_meth.c
+++ b/crypto/evp/skeymgmt_meth.c
@@ -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);