@@ -3717,6 +3717,76 @@ DataPointer Cipher::recover(const EVPKeyPointer& key,
37173717 key, params, in);
37183718}
37193719
3720+ namespace {
3721+ struct CipherCallbackContext {
3722+ Cipher::CipherNameCallback cb;
3723+ void operator ()(std::string_view name) {
3724+ cb (name);
3725+ }
3726+ };
3727+
3728+ #if OPENSSL_VERSION_MAJOR >= 3
3729+ template <class TypeName ,
3730+ TypeName* fetch_type (OSSL_LIB_CTX*, const char *, const char *),
3731+ void free_type(TypeName*),
3732+ const TypeName* getbyname(const char *),
3733+ const char* getname(const TypeName*)>
3734+ void array_push_back(const TypeName* evp_ref,
3735+ const char * from,
3736+ const char * to,
3737+ void * arg) {
3738+ if (from == nullptr ) return ;
3739+
3740+ const TypeName* real_instance = getbyname (from);
3741+ if (!real_instance) return ;
3742+
3743+ const char * real_name = getname (real_instance);
3744+ if (!real_name) return ;
3745+
3746+ // EVP_*_fetch() does not support alias names, so we need to pass it the
3747+ // real/original algorithm name.
3748+ // We use EVP_*_fetch() as a filter here because it will only return an
3749+ // instance if the algorithm is supported by the public OpenSSL APIs (some
3750+ // algorithms are used internally by OpenSSL and are also passed to this
3751+ // callback).
3752+ TypeName* fetched = fetch_type (nullptr , real_name, nullptr );
3753+ if (fetched == nullptr ) return ;
3754+
3755+ free_type (fetched);
3756+ auto & cb = *(static_cast <CipherCallbackContext*>(arg));
3757+ cb (from);
3758+ }
3759+ #else
3760+ template <class TypeName >
3761+ void array_push_back (const TypeName* evp_ref,
3762+ const char * from,
3763+ const char * to,
3764+ void * arg) {
3765+ if (!from) return ;
3766+ auto & cb = *(static_cast <CipherCallbackContext*>(arg));
3767+ cb (from);
3768+ }
3769+ #endif
3770+ } // namespace
3771+
3772+ void Cipher::ForEach (Cipher::CipherNameCallback callback) {
3773+ ClearErrorOnReturn clearErrorOnReturn;
3774+ CipherCallbackContext context;
3775+ context.cb = std::move (callback);
3776+
3777+ EVP_CIPHER_do_all_sorted (
3778+ #if OPENSSL_VERSION_MAJOR >= 3
3779+ array_push_back<EVP_CIPHER,
3780+ EVP_CIPHER_fetch,
3781+ EVP_CIPHER_free,
3782+ EVP_get_cipherbyname,
3783+ EVP_CIPHER_get0_name>,
3784+ #else
3785+ array_push_back<EVP_CIPHER>,
3786+ #endif
3787+ &context);
3788+ }
3789+
37203790// ============================================================================
37213791
37223792Ec::Ec () : ec_ (nullptr ) {}
0 commit comments