From: Emil Velikov Date: Sun, 8 Feb 2026 12:13:42 +0000 (+0000) Subject: libkmod: Allow to load libcrypto.so on demand X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4596bc6eb321a5129c27e64859c2600729814d56;p=thirdparty%2Fkmod.git libkmod: Allow to load libcrypto.so on demand Use dlfcn helpers to load libcrypto once it's needed. Signed-off-by: Emil Velikov Link: https://github.com/kmod-project/kmod/pull/420 Signed-off-by: Lucas De Marchi --- diff --git a/libkmod/libkmod-signature.c b/libkmod/libkmod-signature.c index 2af16ded..6bf25db5 100644 --- a/libkmod/libkmod-signature.c +++ b/libkmod/libkmod-signature.c @@ -3,6 +3,8 @@ * Copyright (C) 2013 Michal Marek, SUSE */ +#define DLSYM_LOCALLY_ENABLED ENABLE_OPENSSL_DLOPEN + #include #include #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; } diff --git a/meson.build b/meson.build index becd3c35..c2bf5adf 100644 --- a/meson.build +++ b/meson.build @@ -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 #------------------------------------------------------------------------------- diff --git a/meson_options.txt b/meson_options.txt index 3d41fae2..9fc5b564 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -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', )