]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
libkmod: Allow to load libcrypto.so on demand
authorEmil Velikov <emil.l.velikov@gmail.com>
Sun, 8 Feb 2026 12:13:42 +0000 (12:13 +0000)
committerLucas De Marchi <demarchi@kernel.org>
Thu, 7 May 2026 05:57:56 +0000 (00:57 -0500)
Use dlfcn helpers to load libcrypto once it's needed.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
Link: https://github.com/kmod-project/kmod/pull/420
Signed-off-by: Lucas De Marchi <demarchi@kernel.org>
libkmod/libkmod-signature.c
meson.build
meson_options.txt

index 2af16ded7b095fb1485c3f4150dc7155bf0c3ef4..6bf25db5ae1eb9bb6ea881ef279d74d68ab3983b 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright (C) 2013 Michal Marek, SUSE
  */
 
+#define DLSYM_LOCALLY_ENABLED ENABLE_OPENSSL_DLOPEN
+
 #include <endian.h>
 #include <inttypes.h>
 #if ENABLE_OPENSSL
@@ -110,6 +112,48 @@ static bool fill_default(const char *mem, off_t size,
 
 #if ENABLE_OPENSSL
 
+#define DL_SYMBOL_TABLE(M)             \
+       M(ASN1_INTEGER_to_BN)          \
+       M(ASN1_STRING_get0_data)       \
+       M(ASN1_STRING_length)          \
+       M(BIO_free)                    \
+       M(BIO_new_mem_buf)             \
+       M(BN_bn2bin)                   \
+       M(BN_free)                     \
+       M(BN_num_bits)                 \
+       M(d2i_PKCS7_bio)               \
+       M(OBJ_obj2nid)                 \
+       M(OBJ_obj2txt)                 \
+       M(OPENSSL_sk_value)            \
+       M(PKCS7_free)                  \
+       M(PKCS7_get_signer_info)       \
+       M(PKCS7_SIGNER_INFO_get0_algs) \
+       M(X509_ALGOR_get0)             \
+       M(X509_NAME_entry_count)       \
+       M(X509_NAME_ENTRY_get_data)    \
+       M(X509_NAME_ENTRY_get_object)  \
+       M(X509_NAME_get_entry)
+
+DL_SYMBOL_TABLE(DECLARE_SYM)
+
+/* Portion of the libcrypto/openssl API is nested inline functions and/or macros. As such, we
+ * need to copy/paste a few so our forwarding works.
+ */
+#define sym_BN_num_bytes(a) ((sym_BN_num_bits(a) + 7) / 8)
+#define sym_sk_PKCS7_SIGNER_INFO_value(sk, idx)     \
+       ((PKCS7_SIGNER_INFO *)sym_OPENSSL_sk_value( \
+               ossl_check_const_PKCS7_SIGNER_INFO_sk_type(sk), (idx)))
+
+static int dlopen_crypto(void)
+{
+       static void *dl;
+
+       if (!DLSYM_LOCALLY_ENABLED)
+               return 0;
+
+       return dlsym_many(&dl, "libcrypto.so.3", DL_SYMBOL_TABLE(DLSYM_ARG) NULL);
+}
+
 static const char *x509_name_to_str(X509_NAME *name)
 {
        int i;
@@ -119,18 +163,18 @@ static const char *x509_name_to_str(X509_NAME *name)
        int nid = -1;
        const char *str;
 
-       for (i = 0; i < X509_NAME_entry_count(name); i++) {
-               e = X509_NAME_get_entry(name, i);
-               o = X509_NAME_ENTRY_get_object(e);
-               nid = OBJ_obj2nid(o);
+       for (i = 0; i < sym_X509_NAME_entry_count(name); i++) {
+               e = sym_X509_NAME_get_entry(name, i);
+               o = sym_X509_NAME_ENTRY_get_object(e);
+               nid = sym_OBJ_obj2nid(o);
                if (nid == NID_commonName)
                        break;
        }
        if (nid == -1)
                return NULL;
 
-       d = X509_NAME_ENTRY_get_data(e);
-       str = (const char *)ASN1_STRING_get0_data(d);
+       d = sym_X509_NAME_ENTRY_get_data(e);
+       str = (const char *)sym_ASN1_STRING_get0_data(d);
 
        return str;
 }
@@ -153,23 +197,28 @@ static bool fill_pkcs7(const char *mem, off_t size, size_t sig_len,
        const char *issuer_str;
        int hash_algo_len;
        size_t total_len;
+       int ret;
+
+       ret = dlopen_crypto();
+       if (ret < 0)
+               return false;
 
        size -= sig_len;
        pkcs7_raw = mem + size;
 
-       in = BIO_new_mem_buf(pkcs7_raw, sig_len);
+       in = sym_BIO_new_mem_buf(pkcs7_raw, sig_len);
 
-       pkcs7 = d2i_PKCS7_bio(in, NULL);
-       BIO_free(in);
+       pkcs7 = sym_d2i_PKCS7_bio(in, NULL);
+       sym_BIO_free(in);
 
        if (pkcs7 == NULL)
                goto err;
 
-       sis = PKCS7_get_signer_info(pkcs7);
+       sis = sym_PKCS7_get_signer_info(pkcs7);
        if (sis == NULL)
                goto err;
 
-       si = sk_PKCS7_SIGNER_INFO_value(sis, 0);
+       si = sym_sk_PKCS7_SIGNER_INFO_value(sis, 0);
        if (si == NULL || si->issuer_and_serial == NULL || si->enc_digest == NULL)
                goto err;
 
@@ -184,16 +233,16 @@ static bool fill_pkcs7(const char *mem, off_t size, size_t sig_len,
                total_len += strlen(issuer_str);
 
        /* key_id */
-       sno_bn = ASN1_INTEGER_to_BN(is->serial, NULL);
+       sno_bn = sym_ASN1_INTEGER_to_BN(is->serial, NULL);
        if (sno_bn == NULL)
                goto err;
 
-       total_len += BN_num_bytes(sno_bn);
+       total_len += sym_BN_num_bytes(sno_bn);
 
        /* hash_algo */
-       PKCS7_SIGNER_INFO_get0_algs(si, NULL, &dig_alg, NULL);
-       X509_ALGOR_get0(&o, NULL, NULL, dig_alg);
-       hash_algo_len = OBJ_obj2txt(NULL, 0, o, 0);
+       sym_PKCS7_SIGNER_INFO_get0_algs(si, NULL, &dig_alg, NULL);
+       sym_X509_ALGOR_get0(&o, NULL, NULL, dig_alg);
+       hash_algo_len = sym_OBJ_obj2txt(NULL, 0, o, 0);
        if (hash_algo_len < 0)
                goto err1;
 
@@ -201,7 +250,7 @@ static bool fill_pkcs7(const char *mem, off_t size, size_t sig_len,
 
        /* sig */
        sig = si->enc_digest;
-       total_len += ASN1_STRING_length(sig);
+       total_len += sym_ASN1_STRING_length(sig);
 
        sig_info = calloc(1, total_len);
        if (sig_info == NULL)
@@ -222,15 +271,15 @@ static bool fill_pkcs7(const char *mem, off_t size, size_t sig_len,
 
        /* key_id */
        sig_info->key_id = p;
-       sig_info->key_id_len = BN_num_bytes(sno_bn);
+       sig_info->key_id_len = sym_BN_num_bytes(sno_bn);
 
-       BN_bn2bin(sno_bn, (unsigned char *)p);
+       sym_BN_bn2bin(sno_bn, (unsigned char *)p);
        p += sig_info->key_id_len;
 
        /* hash_algo */
        sig_info->hash_algo = p;
 
-       hash_algo_len = OBJ_obj2txt(p, hash_algo_len + 1, o, 0);
+       hash_algo_len = sym_OBJ_obj2txt(p, hash_algo_len + 1, o, 0);
        if (hash_algo_len < 0)
                goto err2;
        p += hash_algo_len;
@@ -240,12 +289,12 @@ static bool fill_pkcs7(const char *mem, off_t size, size_t sig_len,
 
        /* sig */
        sig_info->sig = p;
-       sig_info->sig_len = ASN1_STRING_length(sig);
+       sig_info->sig_len = sym_ASN1_STRING_length(sig);
 
-       memcpy(p, ASN1_STRING_get0_data(sig), sig_info->sig_len);
+       memcpy(p, sym_ASN1_STRING_get0_data(sig), sig_info->sig_len);
 
-       BN_free(sno_bn);
-       PKCS7_free(pkcs7);
+       sym_BN_free(sno_bn);
+       sym_PKCS7_free(pkcs7);
 
        *out_sig_info = sig_info;
 
@@ -254,9 +303,9 @@ static bool fill_pkcs7(const char *mem, off_t size, size_t sig_len,
 err2:
        free(sig_info);
 err1:
-       BN_free(sno_bn);
+       sym_BN_free(sno_bn);
 err:
-       PKCS7_free(pkcs7);
+       sym_PKCS7_free(pkcs7);
        return false;
 }
 
index becd3c35b2f13ed2a834eb21c82655ab276b27bf..c2bf5adf0b7f4caa1e03ade4658f215fb732b6e4 100644 (file)
@@ -266,16 +266,17 @@ if bashcompletiondir != 'no'
 endif
 
 #-------------------------------------------------------------------------------
-# Compression support
+# Compression support and signed modules
 #-------------------------------------------------------------------------------
 
-_compression = [
-  ['zstd', 'libzstd', '>= 1.4.4'],
-  ['xz',   'liblzma', '>= 4.99'],
-  ['zlib', 'zlib',    '>= 0'],
+_moar_deps = [
+  ['zstd',    'libzstd',   '>= 1.4.4'],
+  ['xz',      'liblzma',   '>= 4.99'],
+  ['zlib',    'zlib',      '>= 0'],
+  ['openssl', 'libcrypto', '>= 3.0.0'],
 ]
 
-foreach tuple : _compression
+foreach tuple : _moar_deps
   opt = tuple[0]
   pkg_dep = tuple[1]
   pkg_dep_version = tuple[2]
@@ -294,7 +295,9 @@ foreach tuple : _compression
   cdata.set10('ENABLE_' + opt.to_upper(), have)
   cdata.set10('ENABLE_' + opt.to_upper() + '_DLOPEN', have and dlopen)
 
-  if have
+  if opt == 'openssl'
+    module_signatures = have ? 'PKCS7 legacy' : 'legacy'
+  elif have
     module_compressions += f'@opt@ '
   endif
 
@@ -302,23 +305,6 @@ foreach tuple : _compression
   dep_map += {opt : dep}
 endforeach
 
-#-------------------------------------------------------------------------------
-# Signed modules
-#-------------------------------------------------------------------------------
-
-opt = 'openssl'
-dep = dependency('libcrypto', version : '>= 3.0.0', required : get_option(opt))
-have = dep.found()
-
-if have
-  module_signatures = 'PKCS7 legacy'
-else
-  module_signatures = 'legacy'
-endif
-cdata.set10('ENABLE_' + opt.to_upper(), have)
-features += ['@0@@1@'.format(have ? '+' : '-', opt.to_upper())]
-dep_map += {opt : dep}
-
 #-------------------------------------------------------------------------------
 # Config output
 #-------------------------------------------------------------------------------
index 3d41fae2ec3afcae6e424cf0b3150f61a394fdfd..9fc5b56486f8b8e4c0b25d1e4b3a22230c645a3b 100644 (file)
@@ -70,7 +70,7 @@ option(
 option(
   'dlopen',
   type : 'array',
-  choices : ['zstd', 'xz', 'zlib', 'all'],
+  choices : ['zstd', 'xz', 'zlib', 'openssl', 'all'],
   value : [],
   description : 'Libraries to dlopen rather than linking. Use \'all\' to . Default: none',
 )