]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
initial openssl version splitting
authorAydın Mercan <aydin@isc.org>
Tue, 16 Sep 2025 11:43:52 +0000 (13:43 +0200)
committerAydın Mercan <aydin@isc.org>
Mon, 2 Feb 2026 08:12:53 +0000 (11:12 +0300)
Dealing with OpenSSL has been rapidly turning into an unwieldy situation
as post-3.0 changes turn the library into a different beast.

Start treating pre and post-3.0 versions differently for easier
maintenance.

.gitlab-ci.yml
lib/isc/crypto/meson.build [new file with mode: 0644]
lib/isc/crypto/ossl1_1.c [new file with mode: 0644]
lib/isc/crypto/ossl3.c [moved from lib/isc/crypto.c with 71% similarity]
lib/isc/crypto/ossl_common.c [new file with mode: 0644]
lib/isc/include/isc/crypto.h
lib/isc/meson.build
meson.build

index ba30f9e402e8468489cff5be0ce0a07110ccebd2..11ec9342073609347c4c794b49b992b1f2011172 100644 (file)
@@ -1389,15 +1389,13 @@ gcc:trixie:amd64cross32:
   <<: *debian_trixie_amd64cross32_image
   <<: *build_job
 
-# Jobs for strict OpenSSL 3.x (no deprecated) GCC builds on Debian "trixie" (amd64)
 # Run with pkcs11-provider tests
-
 gcc:ossl3:trixie:amd64:
   <<: *debian_trixie_amd64_image
   <<: *build_job
   variables:
     CC: gcc
-    CFLAGS: "${CFLAGS_COMMON} -DOPENSSL_NO_DEPRECATED=1 -DOPENSSL_API_COMPAT=30000"
+    CFLAGS: "${CFLAGS_COMMON}"
     # See https://gitlab.isc.org/isc-projects/bind9/-/issues/3444
     EXTRA_CONFIGURE: "-Doptimization=3 -Djemalloc=disabled -Dleak-detection=disabled"
     RUN_MESON_INSTALL: 1
diff --git a/lib/isc/crypto/meson.build b/lib/isc/crypto/meson.build
new file mode 100644 (file)
index 0000000..e610fbe
--- /dev/null
@@ -0,0 +1,16 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+isc_srcset.add(
+    when: 'HAVE_OPENSSL_3',
+    if_true: files('ossl3.c', 'ossl_common.c'),
+    if_false: files('ossl1_1.c', 'ossl_common.c'),
+)
diff --git a/lib/isc/crypto/ossl1_1.c b/lib/isc/crypto/ossl1_1.c
new file mode 100644 (file)
index 0000000..a8ac863
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+
+#include <isc/crypto.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/tls.h>
+#include <isc/util.h>
+
+static isc_mem_t *isc__crypto_mctx = NULL;
+
+#define md_register_algorithm(alg)                        \
+       {                                                 \
+               isc__crypto_##alg = UNCONST(EVP_##alg()); \
+               if (isc__crypto_##alg == NULL) {          \
+                       ERR_clear_error();                \
+               }                                         \
+       }
+
+static isc_result_t
+register_algorithms(void) {
+       if (!isc_crypto_fips_mode()) {
+               md_register_algorithm(md5);
+       }
+
+       md_register_algorithm(sha1);
+       md_register_algorithm(sha224);
+       md_register_algorithm(sha256);
+       md_register_algorithm(sha384);
+       md_register_algorithm(sha512);
+
+       return ISC_R_SUCCESS;
+}
+
+#undef md_unregister_algorithm
+
+#ifndef LIBRESSL_VERSION_NUMBER
+/*
+ * This was crippled with LibreSSL, so just skip it:
+ * https://cvsweb.openbsd.org/src/lib/libcrypto/Attic/mem.c
+ */
+
+#if ISC_MEM_TRACKLINES
+/*
+ * We use the internal isc__mem API here, so we can pass the file and line
+ * arguments passed from OpenSSL >= 1.1.0 to our memory functions for better
+ * tracking of the OpenSSL allocations.  Without this, we would always just see
+ * isc__crypto_{malloc,realloc,free} in the tracking output, but with this in
+ * place we get to see the places in the OpenSSL code where the allocations
+ * happen.
+ */
+
+static void *
+isc__crypto_malloc_ex(size_t size, const char *file, int line) {
+       return isc__mem_allocate(isc__crypto_mctx, size, 0, __func__, file,
+                                (unsigned int)line);
+}
+
+static void *
+isc__crypto_realloc_ex(void *ptr, size_t size, const char *file, int line) {
+       return isc__mem_reallocate(isc__crypto_mctx, ptr, size, 0, __func__,
+                                  file, (unsigned int)line);
+}
+
+static void
+isc__crypto_free_ex(void *ptr, const char *file, int line) {
+       if (ptr == NULL) {
+               return;
+       }
+       if (isc__crypto_mctx != NULL) {
+               isc__mem_free(isc__crypto_mctx, ptr, 0, __func__, file,
+                             (unsigned int)line);
+       }
+}
+
+#else /* ISC_MEM_TRACKLINES */
+
+static void *
+isc__crypto_malloc_ex(size_t size, const char *file, int line) {
+       UNUSED(file);
+       UNUSED(line);
+       return isc_mem_allocate(isc__crypto_mctx, size);
+}
+
+static void *
+isc__crypto_realloc_ex(void *ptr, size_t size, const char *file, int line) {
+       UNUSED(file);
+       UNUSED(line);
+       return isc_mem_reallocate(isc__crypto_mctx, ptr, size);
+}
+
+static void
+isc__crypto_free_ex(void *ptr, const char *file, int line) {
+       UNUSED(file);
+       UNUSED(line);
+       if (ptr == NULL) {
+               return;
+       }
+       if (isc__crypto_mctx != NULL) {
+               isc__mem_free(isc__crypto_mctx, ptr, 0);
+       }
+}
+
+#endif /* ISC_MEM_TRACKLINES */
+
+#endif /* !LIBRESSL_VERSION_NUMBER */
+
+#ifdef HAVE_FIPS_MODE
+bool
+isc_crypto_fips_mode(void) {
+       return FIPS_mode() != 0;
+}
+
+isc_result_t
+isc_crypto_fips_enable(void) {
+       if (isc_crypto_fips_mode()) {
+               return ISC_R_SUCCESS;
+       }
+
+       if (FIPS_mode_set(1) == 0) {
+               return isc_tlserr2result(ISC_LOGCATEGORY_GENERAL,
+                                        ISC_LOGMODULE_CRYPTO, "FIPS_mode_set",
+                                        ISC_R_CRYPTOFAILURE);
+       }
+
+       register_algorithms();
+
+       return ISC_R_SUCCESS;
+}
+#else
+bool
+isc_crypto_fips_mode(void) {
+       return false;
+}
+
+isc_result_t
+isc_crypto_fips_enable(void) {
+       return ISC_R_NOTIMPLEMENTED;
+}
+#endif
+
+void
+isc__crypto_setdestroycheck(bool check) {
+       isc_mem_setdestroycheck(isc__crypto_mctx, check);
+}
+
+void
+isc__crypto_initialize(void) {
+       uint64_t opts = OPENSSL_INIT_LOAD_CONFIG;
+
+       isc_mem_create("OpenSSL", &isc__crypto_mctx);
+       isc_mem_setdebugging(isc__crypto_mctx, 0);
+       isc_mem_setdestroycheck(isc__crypto_mctx, false);
+
+#ifndef LIBRESSL_VERSION_NUMBER
+       /*
+        * CRYPTO_set_mem_(_ex)_functions() returns 1 on success or 0 on
+        * failure, which means OpenSSL already allocated some memory.  There's
+        * nothing we can do about it.
+        */
+       (void)CRYPTO_set_mem_functions(isc__crypto_malloc_ex,
+                                      isc__crypto_realloc_ex,
+                                      isc__crypto_free_ex);
+#endif /* !LIBRESSL_VERSION_NUMBER */
+
+#if defined(OPENSSL_INIT_NO_ATEXIT)
+       /*
+        * We call OPENSSL_cleanup() manually, in a correct order, thus disable
+        * the automatic atexit() handler.
+        */
+       opts |= OPENSSL_INIT_NO_ATEXIT;
+#endif
+
+       RUNTIME_CHECK(OPENSSL_init_ssl(opts, NULL) == 1);
+
+       register_algorithms();
+
+#if defined(ENABLE_FIPS_MODE)
+       if (isc_crypto_fips_enable() != ISC_R_SUCCESS) {
+               ERR_clear_error();
+               FATAL_ERROR("Failed to toggle FIPS mode but is "
+                           "required for this build");
+       }
+#endif
+
+       /* Protect ourselves against unseeded PRNG */
+       if (RAND_status() != 1) {
+               isc_tlserr2result(ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO,
+                                 "RAND_status", ISC_R_CRYPTOFAILURE);
+               FATAL_ERROR("OpenSSL pseudorandom number generator "
+                           "cannot be initialized (see the `PRNG not "
+                           "seeded' message in the OpenSSL FAQ)");
+       }
+}
+
+void
+isc__crypto_shutdown(void) {
+       OPENSSL_cleanup();
+
+       isc_mem_detach(&isc__crypto_mctx);
+}
similarity index 71%
rename from lib/isc/crypto.c
rename to lib/isc/crypto/ossl3.c
index 9e4347794f7478ab3cfa8e6e4e3886e264ac0718..5f90df2bdda43ffe96206d0bb2bde6c515fd93a5 100644 (file)
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
+#include <openssl/provider.h>
 #include <openssl/rand.h>
 #include <openssl/ssl.h>
 
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-#include <openssl/provider.h>
-#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
-
 #include <isc/crypto.h>
 #include <isc/log.h>
 #include <isc/mem.h>
 
 static isc_mem_t *isc__crypto_mctx = NULL;
 
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
 static OSSL_PROVIDER *base = NULL, *fips = NULL;
-#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
 
-const EVP_MD *isc__crypto_md5 = NULL;
-const EVP_MD *isc__crypto_sha1 = NULL;
-const EVP_MD *isc__crypto_sha224 = NULL;
-const EVP_MD *isc__crypto_sha256 = NULL;
-const EVP_MD *isc__crypto_sha384 = NULL;
-const EVP_MD *isc__crypto_sha512 = NULL;
-
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
 #define md_register_algorithm(alg, algname)                            \
        {                                                              \
                REQUIRE(isc__crypto_##alg == NULL);                    \
@@ -50,23 +37,13 @@ const EVP_MD *isc__crypto_sha512 = NULL;
                }                                                      \
        }
 
-#define md_unregister_algorithm(alg)                             \
-       {                                                        \
-               if (isc__crypto_##alg != NULL) {                 \
-                       EVP_MD_free(UNCONST(isc__crypto_##alg)); \
-                       isc__crypto_##alg = NULL;                \
-               }                                                \
-       }
-#else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
-#define md_register_algorithm(alg, algname)      \
-       {                                        \
-               isc__crypto_##alg = EVP_##alg(); \
-               if (isc__crypto_##alg == NULL) { \
-                       ERR_clear_error();       \
-               }                                \
+#define md_unregister_algorithm(alg)                    \
+       {                                               \
+               if (isc__crypto_##alg != NULL) {        \
+                       EVP_MD_free(isc__crypto_##alg); \
+                       isc__crypto_##alg = NULL;       \
+               }                                       \
        }
-#define md_unregister_algorithm(alg)
-#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
 
 static isc_result_t
 register_algorithms(void) {
@@ -96,12 +73,6 @@ unregister_algorithms(void) {
 #undef md_unregister_algorithm
 #undef md_register_algorithm
 
-#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
-/*
- * This was crippled with LibreSSL, so just skip it:
- * https://cvsweb.openbsd.org/src/lib/libcrypto/Attic/mem.c
- */
-
 #if ISC_MEM_TRACKLINES
 /*
  * We use the internal isc__mem API here, so we can pass the file and line
@@ -165,9 +136,6 @@ isc__crypto_free_ex(void *ptr, const char *file, int line) {
 
 #endif /* ISC_MEM_TRACKLINES */
 
-#endif /* !defined(LIBRESSL_VERSION_NUMBER) */
-
-#if defined(HAVE_EVP_DEFAULT_PROPERTIES_ENABLE_FIPS)
 bool
 isc_crypto_fips_mode(void) {
        return EVP_default_properties_is_fips_enabled(NULL) != 0;
@@ -208,40 +176,6 @@ isc_crypto_fips_enable(void) {
 
        return ISC_R_SUCCESS;
 }
-#elif defined(HAVE_FIPS_MODE)
-bool
-isc_crypto_fips_mode(void) {
-       return FIPS_mode() != 0;
-}
-
-isc_result_t
-isc_crypto_fips_enable(void) {
-       if (isc_crypto_fips_mode()) {
-               return ISC_R_SUCCESS;
-       }
-
-       if (FIPS_mode_set(1) == 0) {
-               return isc_tlserr2result(ISC_LOGCATEGORY_GENERAL,
-                                        ISC_LOGMODULE_CRYPTO, "FIPS_mode_set",
-                                        ISC_R_CRYPTOFAILURE);
-       }
-
-       unregister_algorithms();
-       register_algorithms();
-
-       return ISC_R_SUCCESS;
-}
-#else
-bool
-isc_crypto_fips_mode(void) {
-       return false;
-}
-
-isc_result_t
-isc_crypto_fips_enable(void) {
-       return ISC_R_NOTIMPLEMENTED;
-}
-#endif
 
 void
 isc__crypto_setdestroycheck(bool check) {
@@ -250,13 +184,16 @@ isc__crypto_setdestroycheck(bool check) {
 
 void
 isc__crypto_initialize(void) {
-       uint64_t opts = OPENSSL_INIT_LOAD_CONFIG;
+       /*
+        * We call OPENSSL_cleanup() manually, in a correct order, thus disable
+        * the automatic atexit() handler.
+        */
+       uint64_t opts = OPENSSL_INIT_LOAD_CONFIG | OPENSSL_INIT_NO_ATEXIT;
 
        isc_mem_create("OpenSSL", &isc__crypto_mctx);
        isc_mem_setdebugging(isc__crypto_mctx, 0);
        isc_mem_setdestroycheck(isc__crypto_mctx, false);
 
-#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
        /*
         * CRYPTO_set_mem_(_ex)_functions() returns 1 on success or 0 on
         * failure, which means OpenSSL already allocated some memory.  There's
@@ -265,16 +202,6 @@ isc__crypto_initialize(void) {
        (void)CRYPTO_set_mem_functions(isc__crypto_malloc_ex,
                                       isc__crypto_realloc_ex,
                                       isc__crypto_free_ex);
-#endif /* !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \
-         0x30000000L  */
-
-#if defined(OPENSSL_INIT_NO_ATEXIT)
-       /*
-        * We call OPENSSL_cleanup() manually, in a correct order, thus disable
-        * the automatic atexit() handler.
-        */
-       opts |= OPENSSL_INIT_NO_ATEXIT;
-#endif
 
        RUNTIME_CHECK(OPENSSL_init_ssl(opts, NULL) == 1);
 
@@ -302,7 +229,6 @@ void
 isc__crypto_shutdown(void) {
        unregister_algorithms();
 
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        if (base != NULL) {
                OSSL_PROVIDER_unload(base);
        }
@@ -310,7 +236,6 @@ isc__crypto_shutdown(void) {
        if (fips != NULL) {
                OSSL_PROVIDER_unload(fips);
        }
-#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
 
        OPENSSL_cleanup();
 
diff --git a/lib/isc/crypto/ossl_common.c b/lib/isc/crypto/ossl_common.c
new file mode 100644 (file)
index 0000000..1d940fa
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <openssl/evp.h>
+
+EVP_MD *isc__crypto_md5 = NULL;
+EVP_MD *isc__crypto_sha1 = NULL;
+EVP_MD *isc__crypto_sha224 = NULL;
+EVP_MD *isc__crypto_sha256 = NULL;
+EVP_MD *isc__crypto_sha384 = NULL;
+EVP_MD *isc__crypto_sha512 = NULL;
index 14bdd4693318cdbaeaf0decfbc574ce3fa624e41..a7dc9f45a4d12d2cc02f56a6a88107b4bbd35902 100644 (file)
 
 #include <isc/types.h>
 
-extern const EVP_MD *isc__crypto_md5;
-extern const EVP_MD *isc__crypto_sha1;
-extern const EVP_MD *isc__crypto_sha224;
-extern const EVP_MD *isc__crypto_sha256;
-extern const EVP_MD *isc__crypto_sha384;
-extern const EVP_MD *isc__crypto_sha512;
+extern EVP_MD *isc__crypto_md5;
+extern EVP_MD *isc__crypto_sha1;
+extern EVP_MD *isc__crypto_sha224;
+extern EVP_MD *isc__crypto_sha256;
+extern EVP_MD *isc__crypto_sha384;
+extern EVP_MD *isc__crypto_sha512;
 
 bool
 isc_crypto_fips_mode(void);
index d4db21672e3cb5d9e71a9409d5f9b3df80916fc8..645ff469cf527f816fb35dd6ad1cd9cbb1eb3679 100644 (file)
@@ -20,6 +20,7 @@ endif
 # isc_inc += include_directories('include')
 isc_inc_p += include_directories('.')
 
+subdir('crypto')
 subdir('netmgr')
 
 isc_srcset.add(
@@ -75,7 +76,6 @@ isc_srcset.add(
         'base64.c',
         'commandline.c',
         'counter.c',
-        'crypto.c',
         'dir.c',
         'errno.c',
         'errno2result.c',
index e979c790407dc35700ae4ccf1b4d0f122ddaba43..2529a0155b43c985f5cb8bc21aea5af9bb190c4c 100644 (file)
@@ -602,21 +602,37 @@ openssl_dep = [
     dependency('libssl', version: '>=1.1.1'),
 ]
 
-foreach fn, header : {
-    'EVP_default_properties_enable_fips': '#include <openssl/evp.h>',
-    'FIPS_mode': '#include <openssl/crypto.h>',
-}
-    if cc.has_function(fn, prefix: header, dependencies: openssl_dep)
-        config.set('HAVE_OPENSSL_FIPS_TOGGLE', 1)
-        config.set('HAVE_@0@'.format(fn.to_upper()), 1)
-    endif
-endforeach
-
-fips_opt.require(
-    config.has('HAVE_OPENSSL_FIPS_TOGGLE'),
-    error_message: 'OpenSSL FIPS mode requested but not available',
+# OpenSSL-forks usually set their own version number which can be greater than 3.0.0.
+# To understand if the library is pre or post-3.0, use the OPENSSL_VERSION_NUMBER value.
+openssl_version_number = cc.get_define(
+    'OPENSSL_VERSION_NUMBER',
+    dependencies: openssl_dep,
+    prefix: '#include <openssl/opensslv.h>',
 )
 
+config.set('OPENSSL_NO_DEPRECATED', true)
+if openssl_version_number.version_compare('>=3.0.0')
+    config.set('HAVE_OPENSSL_3', true)
+    config.set('OPENSSL_API_COMPAT', 30000)
+else
+    config.set('HAVE_OPENSSL_3', false)
+    config.set('OPENSSL_API_COMPAT', 10100)
+
+    config.set(
+        'HAVE_FIPS_MODE',
+        cc.has_function(
+            'FIPS_mode',
+            prefix: '#include <openssl/crypto.h>',
+            dependencies: openssl_dep,
+        ),
+    )
+
+    fips_opt.require(
+        config.get('HAVE_FIPS_MODE'),
+        error_message: 'OpenSSL FIPS mode requested but not available',
+    )
+endif
+
 # Hash and curve probe
 if cc.has_header_symbol('openssl/evp.h', 'NID_ED448', dependencies: openssl_dep)
     config.set('HAVE_OPENSSL_ED448', 1)