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)
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 \
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.
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
--- /dev/null
+/*
+ * 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);
+}
#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"
void *thread_event_handler;
void *fips_prov;
#endif
+ STACK_OF(SSL_COMP) *comp_methods;
int ischild;
int conf_diagnostics;
if (!ossl_property_parse_init(ctx))
goto err;
+#ifndef FIPS_MODULE
+ ctx->comp_methods = ossl_load_builtin_compressions();
+#endif
+
return 1;
err:
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)
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);
=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
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
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
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.
* 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
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
# 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);
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
/*
- * 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
* https://www.openssl.org/source/license.html
*/
+{-
+use OpenSSL::stackhash qw(generate_stack_macros);
+-}
+
#ifndef OPENSSL_COMP_H
# define OPENSSL_COMP_H
# pragma once
# include <openssl/opensslconf.h>
-# ifndef OPENSSL_NO_COMP
# include <openssl/crypto.h>
# include <openssl/comperr.h>
# ifdef __cplusplus
+# 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);
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;
+
+{-
+ generate_stack_macros("SSL_COMP");
+-}
-# ifdef __cplusplus
+
+# ifdef __cplusplus
}
-# endif
# endif
#endif
void OSSL_sleep(uint64_t millis);
+
+void *OSSL_LIB_CTX_get_data(OSSL_LIB_CTX *ctx, int index);
+
# ifdef __cplusplus
}
# endif
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 {
* in VisualStudio 2015
*/
{-
- generate_const_stack_macros("SSL_CIPHER")
- .generate_stack_macros("SSL_COMP");
+ generate_const_stack_macros("SSL_CIPHER");
-}
/* compatibility */
#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)
{
#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 */
{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 */
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)
{
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))
ssl_get_algorithm2(s) >> TLS1_PRF_DGST_SHIFT);
}
+
#define ITEM_SEP(a) \
(((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ','))
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
#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;
- return old_meths;
-}
+ STACK_OF(SSL_COMP) **comp_methods;
+ STACK_OF(SSL_COMP) *old_meths;
-static void cmeth_free(SSL_COMP *cm)
-{
- OPENSSL_free(cm);
-}
+ 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;
+ }
-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);
+ return old_meths;
}
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;
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
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)
#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;
}
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,
# include "internal/ktls.h"
# include "internal/time.h"
# include "internal/ssl.h"
+# include "internal/cryptlib.h"
# include "record/record.h"
# ifdef OPENSSL_BUILD_SHLIBSSL
#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 */
#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)
{
#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);
#include <openssl/core_names.h>
#include <openssl/asn1t.h>
#include <openssl/comp.h>
+#include "internal/comp.h"
#define TICKET_NONCE_SIZE 8
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");
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: