Move stack of compression methods from libssl to OSSL_LIB_CTX

The compression methods are now a global variable in libssl.
This change moves it into OSSL library context.

It is necessary to eliminate atexit call from libssl.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/24414)
This commit is contained in:
sashan 2024-05-16 06:33:55 +02:00 committed by Tomas Mraz
parent 184d29dbab
commit da9342ed5e
19 changed files with 197 additions and 131 deletions

View File

@ -26,6 +26,7 @@ DEPEND[]=include/openssl/asn1.h \
include/openssl/cmp.h \
include/openssl/cms.h \
include/openssl/conf.h \
include/openssl/comp.h \
include/openssl/core_names.h \
include/openssl/crmf.h \
include/openssl/crypto.h \
@ -55,6 +56,7 @@ GENERATE[include/openssl/bio.h]=include/openssl/bio.h.in
GENERATE[include/openssl/cmp.h]=include/openssl/cmp.h.in
GENERATE[include/openssl/cms.h]=include/openssl/cms.h.in
GENERATE[include/openssl/conf.h]=include/openssl/conf.h.in
GENERATE[include/openssl/comp.h]=include/openssl/comp.h.in
# include/openssl/configuration.h is generated by configdata.pm
# We still need this information for the FIPS module checksum, but the attribute
# 'skip' ensures that nothing is actually done with it.

View File

@ -104,10 +104,10 @@ $UTIL_COMMON=\
SOURCE[../libcrypto]=$UTIL_COMMON \
mem.c mem_sec.c \
cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \
o_fopen.c getenv.c o_init.c init.c trace.c provider.c provider_child.c \
punycode.c passphrase.c sleep.c deterministic_nonce.c quic_vlint.c \
time.c
comp_methods.c cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c \
o_dir.c o_fopen.c getenv.c o_init.c init.c trace.c provider.c \
provider_child.c punycode.c passphrase.c sleep.c deterministic_nonce.c \
quic_vlint.c time.c
SOURCE[../providers/libfips.a]=$UTIL_COMMON
SOURCE[../libcrypto]=$UPLINKSRC

59
crypto/comp_methods.c Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/crypto.h>
#include <openssl/comp.h>
#include <openssl/obj_mac.h>
#include "internal/cryptlib.h"
#include "internal/comp.h"
#define SSL_COMP_NULL_IDX 0
#define SSL_COMP_ZLIB_IDX 1
#define SSL_COMP_NUM_IDX 2
#ifndef OPENSSL_NO_COMP
static int sk_comp_cmp(const SSL_COMP *const *a, const SSL_COMP *const *b)
{
return ((*a)->id - (*b)->id);
}
#endif
STACK_OF(SSL_COMP) *ossl_load_builtin_compressions(void)
{
STACK_OF(SSL_COMP) *comp_methods = NULL;
#ifndef OPENSSL_NO_COMP
SSL_COMP *comp = NULL;
COMP_METHOD *method = COMP_zlib();
comp_methods = sk_SSL_COMP_new(sk_comp_cmp);
if (COMP_get_type(method) != NID_undef && comp_methods != NULL) {
comp = OPENSSL_malloc(sizeof(*comp));
if (comp != NULL) {
comp->method = method;
comp->id = SSL_COMP_ZLIB_IDX;
comp->name = COMP_get_name(method);
if (!sk_SSL_COMP_push(comp_methods, comp))
OPENSSL_free(comp);
}
}
#endif
return comp_methods;
}
static void cmeth_free(SSL_COMP *cm)
{
OPENSSL_free(cm);
}
void ossl_free_compression_methods_int(STACK_OF(SSL_COMP) *methods)
{
sk_SSL_COMP_pop_free(methods, cmeth_free);
}

View File

@ -11,6 +11,7 @@
#include <openssl/conf.h>
#include "internal/thread_once.h"
#include "internal/property.h"
#include "internal/cryptlib.h"
#include "internal/core.h"
#include "internal/bio.h"
#include "internal/provider.h"
@ -48,6 +49,7 @@ struct ossl_lib_ctx_st {
void *thread_event_handler;
void *fips_prov;
#endif
STACK_OF(SSL_COMP) *comp_methods;
int ischild;
int conf_diagnostics;
@ -204,6 +206,10 @@ static int context_init(OSSL_LIB_CTX *ctx)
if (!ossl_property_parse_init(ctx))
goto err;
#ifndef FIPS_MODULE
ctx->comp_methods = ossl_load_builtin_compressions();
#endif
return 1;
err:
@ -344,6 +350,14 @@ static void context_deinit_objs(OSSL_LIB_CTX *ctx)
ctx->child_provider = NULL;
}
#endif
#ifndef FIPS_MODULE
if (ctx->comp_methods != NULL) {
ossl_free_compression_methods_int(ctx->comp_methods);
ctx->comp_methods = NULL;
}
#endif
}
static int context_deinit(OSSL_LIB_CTX *ctx)
@ -634,11 +648,19 @@ void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index)
return ctx->fips_prov;
#endif
case OSSL_LIB_CTX_COMP_METHODS:
return (void *)&ctx->comp_methods;
default:
return NULL;
}
}
void *OSSL_LIB_CTX_get_data(OSSL_LIB_CTX *ctx, int index)
{
return ossl_lib_ctx_get_data(ctx, index);
}
OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx)
{
ctx = ossl_lib_ctx_get_concrete(ctx);

View File

@ -2,8 +2,9 @@
=head1 NAME
OSSL_LIB_CTX, OSSL_LIB_CTX_new, OSSL_LIB_CTX_new_from_dispatch,
OSSL_LIB_CTX_new_child, OSSL_LIB_CTX_free, OSSL_LIB_CTX_load_config,
OSSL_LIB_CTX, OSSL_LIB_CTX_get_data, OSSL_LIB_CTX_new,
OSSL_LIB_CTX_new_from_dispatch, OSSL_LIB_CTX_new_child,
OSSL_LIB_CTX_free, OSSL_LIB_CTX_load_config,
OSSL_LIB_CTX_get0_global_default, OSSL_LIB_CTX_set0_default
- OpenSSL library context
@ -22,6 +23,7 @@ OSSL_LIB_CTX_get0_global_default, OSSL_LIB_CTX_set0_default
void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx);
OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void);
OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *ctx);
void *OSSL_LIB_CTX_get_data(OSSL_LIB_CTX *ctx, int index);
=head1 DESCRIPTION
@ -111,6 +113,14 @@ in the mean time. This means that the calling thread must not free the
library context that was the default at the start of the async job before
that job has finished.
OSSL_LIB_CTX_get_data() returns a memory address whose interpretation depends
on the index. The index argument refers to a context member which is
to be retrieved. The values for index are all private to OpenSSL currently
and so applications should not typically call this function.
If ctx is NULL then the function operates on the default library context.
OSSL_LIB_CTX_get_data() returns a memory address whose interpretation
depends on the index.
=head1 RETURN VALUES
OSSL_LIB_CTX_new(), OSSL_LIB_CTX_get0_global_default() and
@ -121,10 +131,15 @@ OSSL_LIB_CTX_free() doesn't return any value.
OSSL_LIB_CTX_load_config() returns 1 on success, 0 on error.
OSSL_LIB_CTX_get_data() returns a memory address whose interpretation
depends on the index.
=head1 HISTORY
All of the functions described on this page were added in OpenSSL 3.0.
OSSL_LIB_CTX_get_data() was introduced in OpenSSL 3.4.
=head1 COPYRIGHT
Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.

View File

@ -6,9 +6,19 @@
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef _INTERNAL_COMP_H
#define _INTERNAL_COMP_H
#include <openssl/comp.h>
void ossl_comp_zlib_cleanup(void);
void ossl_comp_brotli_cleanup(void);
void ossl_comp_zstd_cleanup(void);
struct ssl_comp_st {
int id;
const char *name;
COMP_METHOD *method;
};
#endif

View File

@ -86,7 +86,6 @@ typedef struct ossl_ex_data_global_st {
EX_CALLBACKS ex_data[CRYPTO_EX_INDEX__COUNT];
} OSSL_EX_DATA_GLOBAL;
/* OSSL_LIB_CTX */
# define OSSL_LIB_CTX_PROVIDER_STORE_RUN_ONCE_INDEX 0
@ -117,7 +116,8 @@ typedef struct ossl_ex_data_global_st {
# define OSSL_LIB_CTX_CHILD_PROVIDER_INDEX 18
# define OSSL_LIB_CTX_THREAD_INDEX 19
# define OSSL_LIB_CTX_DECODER_CACHE_INDEX 20
# define OSSL_LIB_CTX_MAX_INDEXES 20
# define OSSL_LIB_CTX_COMP_METHODS 21
# define OSSL_LIB_CTX_MAX_INDEXES 21
OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx);
int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx);
@ -161,4 +161,7 @@ char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep);
unsigned char *ossl_hexstr2buf_sep(const char *str, long *buflen,
const char sep);
STACK_OF(SSL_COMP) *ossl_load_builtin_compressions(void);
void ossl_free_compression_methods_int(STACK_OF(SSL_COMP) *methods);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -7,6 +7,10 @@
* https://www.openssl.org/source/license.html
*/
{-
use OpenSSL::stackhash qw(generate_stack_macros);
-}
#ifndef OPENSSL_COMP_H
# define OPENSSL_COMP_H
# pragma once
@ -18,7 +22,6 @@
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_COMP
# include <openssl/crypto.h>
# include <openssl/comperr.h>
# ifdef __cplusplus
@ -27,6 +30,8 @@ extern "C" {
# ifndef OPENSSL_NO_COMP
COMP_CTX *COMP_CTX_new(COMP_METHOD *meth);
const COMP_METHOD *COMP_CTX_get_method(const COMP_CTX *ctx);
int COMP_CTX_get_type(const COMP_CTX* comp);
@ -46,19 +51,26 @@ COMP_METHOD *COMP_brotli_oneshot(void);
COMP_METHOD *COMP_zstd(void);
COMP_METHOD *COMP_zstd_oneshot(void);
#ifndef OPENSSL_NO_DEPRECATED_1_1_0
# define COMP_zlib_cleanup() while(0) continue
#endif
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
# define COMP_zlib_cleanup() while(0) continue
# endif
# ifdef OPENSSL_BIO_H
# ifdef OPENSSL_BIO_H
const BIO_METHOD *BIO_f_zlib(void);
const BIO_METHOD *BIO_f_brotli(void);
const BIO_METHOD *BIO_f_zstd(void);
# endif
# endif
typedef struct ssl_comp_st SSL_COMP;
# ifdef __cplusplus
{-
generate_stack_macros("SSL_COMP");
-}
# ifdef __cplusplus
}
# endif
# endif
#endif

View File

@ -541,6 +541,9 @@ void OSSL_LIB_CTX_set_conf_diagnostics(OSSL_LIB_CTX *ctx, int value);
void OSSL_sleep(uint64_t millis);
void *OSSL_LIB_CTX_get_data(OSSL_LIB_CTX *ctx, int index);
# ifdef __cplusplus
}
# endif

View File

@ -236,10 +236,8 @@ typedef struct ssl_cipher_st SSL_CIPHER;
typedef struct ssl_session_st SSL_SESSION;
typedef struct tls_sigalgs_st TLS_SIGALGS;
typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
typedef struct ssl_comp_st SSL_COMP;
STACK_OF(SSL_CIPHER);
STACK_OF(SSL_COMP);
/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/
typedef struct srtp_protection_profile_st {
@ -975,8 +973,7 @@ extern "C" {
* in VisualStudio 2015
*/
{-
generate_const_stack_macros("SSL_CIPHER")
.generate_stack_macros("SSL_COMP");
generate_const_stack_macros("SSL_CIPHER");
-}
/* compatibility */

View File

@ -19,6 +19,7 @@
#include <openssl/core_names.h>
#include "record_local.h"
#include "internal/packet.h"
#include "internal/comp.h"
void RECORD_LAYER_init(RECORD_LAYER *rl, SSL_CONNECTION *s)
{

View File

@ -21,6 +21,7 @@
#include "ssl_local.h"
#include "internal/thread_once.h"
#include "internal/cryptlib.h"
#include "internal/comp.h"
/* NB: make sure indices in these tables match values above */
@ -57,16 +58,6 @@ static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = {
{SSL_KUZNYECHIK, NID_kuznyechik_ctr_acpkm}, /* SSL_ENC_KUZNYECHIK_IDX */
};
#define SSL_COMP_NULL_IDX 0
#define SSL_COMP_ZLIB_IDX 1
#define SSL_COMP_NUM_IDX 2
static STACK_OF(SSL_COMP) *ssl_comp_methods = NULL;
#ifndef OPENSSL_NO_COMP
static CRYPTO_ONCE ssl_load_builtin_comp_once = CRYPTO_ONCE_STATIC_INIT;
#endif
/* NB: make sure indices in this table matches values above */
static const ssl_cipher_table ssl_cipher_table_mac[SSL_MD_NUM_IDX] = {
{SSL_MD5, NID_md5}, /* SSL_MD_MD5_IDX 0 */
@ -445,40 +436,6 @@ int ssl_load_ciphers(SSL_CTX *ctx)
return 1;
}
#ifndef OPENSSL_NO_COMP
static int sk_comp_cmp(const SSL_COMP *const *a, const SSL_COMP *const *b)
{
return ((*a)->id - (*b)->id);
}
DEFINE_RUN_ONCE_STATIC(do_load_builtin_compressions)
{
SSL_COMP *comp = NULL;
COMP_METHOD *method = COMP_zlib();
ssl_comp_methods = sk_SSL_COMP_new(sk_comp_cmp);
if (COMP_get_type(method) != NID_undef && ssl_comp_methods != NULL) {
comp = OPENSSL_malloc(sizeof(*comp));
if (comp != NULL) {
comp->method = method;
comp->id = SSL_COMP_ZLIB_IDX;
comp->name = COMP_get_name(method);
if (!sk_SSL_COMP_push(ssl_comp_methods, comp))
OPENSSL_free(comp);
sk_SSL_COMP_sort(ssl_comp_methods);
}
}
return 1;
}
static int load_builtin_compressions(void)
{
return RUN_ONCE(&ssl_load_builtin_comp_once, do_load_builtin_compressions);
}
#endif
int ssl_cipher_get_evp_cipher(SSL_CTX *ctx, const SSL_CIPHER *sslc,
const EVP_CIPHER **enc)
{
@ -549,20 +506,15 @@ int ssl_cipher_get_evp(SSL_CTX *ctx, const SSL_SESSION *s,
return 0;
if (comp != NULL) {
SSL_COMP ctmp;
#ifndef OPENSSL_NO_COMP
if (!load_builtin_compressions()) {
/*
* Currently don't care, since a failure only means that
* ssl_comp_methods is NULL, which is perfectly OK
*/
}
#endif
STACK_OF(SSL_COMP) *comp_methods;
*comp = NULL;
ctmp.id = s->compress_meth;
if (ssl_comp_methods != NULL) {
i = sk_SSL_COMP_find(ssl_comp_methods, &ctmp);
comp_methods = SSL_COMP_get_compression_methods();
if (comp_methods != NULL) {
i = sk_SSL_COMP_find(comp_methods, &ctmp);
if (i >= 0)
*comp = sk_SSL_COMP_value(ssl_comp_methods, i);
*comp = sk_SSL_COMP_value(comp_methods, i);
}
/* If were only interested in comp then return success */
if ((enc == NULL) && (md == NULL))
@ -649,6 +601,7 @@ const EVP_MD *ssl_prf_md(SSL_CONNECTION *s)
ssl_get_algorithm2(s) >> TLS1_PRF_DGST_SHIFT);
}
#define ITEM_SEP(a) \
(((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ','))
@ -1988,17 +1941,19 @@ uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c)
SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n)
{
SSL_COMP *ctmp;
int i, nn;
SSL_COMP srch_key;
int i;
if ((n == 0) || (sk == NULL))
return NULL;
nn = sk_SSL_COMP_num(sk);
for (i = 0; i < nn; i++) {
srch_key.id = n;
i = sk_SSL_COMP_find(sk, &srch_key);
if (i >= 0)
ctmp = sk_SSL_COMP_value(sk, i);
if (ctmp->id == n)
return ctmp;
}
return NULL;
else
ctmp = NULL;
return ctmp;
}
#ifdef OPENSSL_NO_COMP
@ -2021,34 +1976,44 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
#else
STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void)
{
load_builtin_compressions();
return ssl_comp_methods;
STACK_OF(SSL_COMP) **rv;
rv = (STACK_OF(SSL_COMP) **)OSSL_LIB_CTX_get_data(NULL,
OSSL_LIB_CTX_COMP_METHODS);
if (rv != NULL)
return *rv;
else
return NULL;
}
STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
*meths)
{
STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods;
ssl_comp_methods = meths;
STACK_OF(SSL_COMP) **comp_methods;
STACK_OF(SSL_COMP) *old_meths;
comp_methods = (STACK_OF(SSL_COMP) **)OSSL_LIB_CTX_get_data(NULL,
OSSL_LIB_CTX_COMP_METHODS);
if (comp_methods == NULL) {
old_meths = meths;
} else {
old_meths = *comp_methods;
*comp_methods = meths;
}
return old_meths;
}
static void cmeth_free(SSL_COMP *cm)
{
OPENSSL_free(cm);
}
void ssl_comp_free_compression_methods_int(void)
{
STACK_OF(SSL_COMP) *old_meths = ssl_comp_methods;
ssl_comp_methods = NULL;
sk_SSL_COMP_pop_free(old_meths, cmeth_free);
}
int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
{
STACK_OF(SSL_COMP) *comp_methods;
SSL_COMP *comp;
comp_methods = SSL_COMP_get_compression_methods();
if (comp_methods == NULL)
return 1;
if (cm == NULL || COMP_get_type(cm) == NID_undef)
return 1;
@ -2070,18 +2035,17 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm)
return 1;
comp->id = id;
comp->method = cm;
load_builtin_compressions();
if (ssl_comp_methods && sk_SSL_COMP_find(ssl_comp_methods, comp) >= 0) {
if (sk_SSL_COMP_find(comp_methods, comp) >= 0) {
OPENSSL_free(comp);
ERR_raise(ERR_LIB_SSL, SSL_R_DUPLICATE_COMPRESSION_ID);
return 1;
}
if (ssl_comp_methods == NULL || !sk_SSL_COMP_push(ssl_comp_methods, comp)) {
if (!sk_SSL_COMP_push(comp_methods, comp)) {
OPENSSL_free(comp);
ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
return 1;
}
return 0;
}
#endif

View File

@ -19,8 +19,6 @@
static int stopped;
static void ssl_library_stop(void);
static CRYPTO_ONCE ssl_base = CRYPTO_ONCE_STATIC_INIT;
static int ssl_base_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_ssl_base)
@ -36,11 +34,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_ssl_base)
#endif
ssl_sort_cipher_list();
OSSL_TRACE(INIT, "ossl_init_ssl_base: SSL_add_ssl_module()\n");
/*
* We ignore an error return here. Not much we can do - but not that bad
* either. We can still safely continue.
*/
OPENSSL_atexit(ssl_library_stop);
ssl_base_inited = 1;
return 1;
}
@ -67,22 +60,6 @@ DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_ssl_strings,
return 1;
}
static void ssl_library_stop(void)
{
/* Might be explicitly called and also by atexit */
if (stopped)
return;
stopped = 1;
if (ssl_base_inited) {
#ifndef OPENSSL_NO_COMP
OSSL_TRACE(INIT, "ssl_library_stop: "
"ssl_comp_free_compression_methods_int()\n");
ssl_comp_free_compression_methods_int();
#endif
}
}
/*
* If this function is called with a non NULL settings value then it must be
* called prior to any threads making calls to any OpenSSL functions,

View File

@ -37,6 +37,7 @@
# include "internal/ktls.h"
# include "internal/time.h"
# include "internal/ssl.h"
# include "internal/cryptlib.h"
# include "record/record.h"
# ifdef OPENSSL_BUILD_SHLIBSSL
@ -637,11 +638,6 @@ typedef enum {
#define MAX_COMPRESSIONS_SIZE 255
struct ssl_comp_st {
int id;
const char *name;
COMP_METHOD *method;
};
typedef struct raw_extension_st {
/* Raw packet data for the extension */

View File

@ -12,6 +12,8 @@
#include <openssl/buffer.h>
#include "ssl_local.h"
#include "internal/comp.h"
#ifndef OPENSSL_NO_STDIO
int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x)
{

View File

@ -27,6 +27,7 @@
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include "internal/cryptlib.h"
#include "internal/comp.h"
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL_CONNECTION *s,
PACKET *pkt);

View File

@ -27,6 +27,7 @@
#include <openssl/core_names.h>
#include <openssl/asn1t.h>
#include <openssl/comp.h>
#include "internal/comp.h"
#define TICKET_NONCE_SIZE 8

View File

@ -1346,7 +1346,7 @@ int main(int argc, char *argv[])
int j;
printf("Available compression methods:");
for (j = 0; j < n; j++) {
SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j);
const SSL_COMP *c = sk_SSL_COMP_value(ssl_comp_methods, j);
printf(" %s:%d", SSL_COMP_get0_name(c), SSL_COMP_get_id(c));
}
printf("\n");

View File

@ -5646,3 +5646,4 @@ OSSL_IETF_ATTR_SYNTAX_print ? 3_4_0 EXIST::FUNCTION:
X509_ACERT_add_attr_nconf ? 3_4_0 EXIST::FUNCTION:
OSSL_LIB_CTX_get_conf_diagnostics ? 3_4_0 EXIST::FUNCTION:
OSSL_LIB_CTX_set_conf_diagnostics ? 3_4_0 EXIST::FUNCTION:
OSSL_LIB_CTX_get_data ? 3_4_0 EXIST::FUNCTION: