]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
libkmod: move openssl-related functions to separate file
authorEmil Velikov <emil.l.velikov@gmail.com>
Mon, 1 Jun 2026 14:45:57 +0000 (15:45 +0100)
committerLucas De Marchi <demarchi@kernel.org>
Sat, 20 Jun 2026 16:13:26 +0000 (11:13 -0500)
Move openssl-related function to a separate file so it's easier to
isolate the dependency on each crypto library.

This will allow multiple implementations to co-exist in the same build.

As a nice side effect we fallback to the "dummy" implementation in the
(very likely) case that the openssl one fails.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
Link: https://github.com/kmod-project/kmod/pull/426
Signed-off-by: Lucas De Marchi <demarchi@kernel.org>
libkmod/docs/meson.build
libkmod/libkmod-internal-signature.h [new file with mode: 0644]
libkmod/libkmod-signature-openssl.c [new file with mode: 0644]
libkmod/libkmod-signature.c
meson.build

index eefec18d7f0732b88f367d9eb943ef6e68adff1b..5913ab2f722e411adc1e6cfe7eaaa4079cdd290e 100644 (file)
@@ -13,6 +13,7 @@ built_docs = gnome.gtkdoc(
     f'@project_source_root@/libkmod/libkmod-index.h',
     f'@project_source_root@/libkmod/libkmod-internal-file.h',
     f'@project_source_root@/libkmod/libkmod-internal.h',
+    f'@project_source_root@/libkmod/libkmod-internal-signature.h',
   ],
   scan_args : '--ignore-decorators="KMOD_EXPORT"',
   src_dir : f'@project_source_root@/libkmod/',
diff --git a/libkmod/libkmod-internal-signature.h b/libkmod/libkmod-internal-signature.h
new file mode 100644 (file)
index 0000000..b58193d
--- /dev/null
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2026 Emil Velikov <emil.l.velikov@gmail.com>
+
+#include <libkmod/libkmod-internal.h>
+
+#if ENABLE_OPENSSL
+bool kmod_fill_pkcs7_openssl(const char *mem, off_t size, size_t sig_len,
+                            struct kmod_signature_info **out_sig_info);
+#else
+static inline bool kmod_fill_pkcs7_openssl(const char *mem, off_t size, size_t sig_len,
+                                          struct kmod_signature_info **out_sig_info)
+{
+       return false;
+}
+#endif
diff --git a/libkmod/libkmod-signature-openssl.c b/libkmod/libkmod-signature-openssl.c
new file mode 100644 (file)
index 0000000..0af525e
--- /dev/null
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2013 Michal Marek, SUSE
+
+#define DLSYM_LOCALLY_ENABLED ENABLE_OPENSSL_DLOPEN
+
+#include <inttypes.h>
+#include <openssl/pkcs7.h>
+#include <openssl/ssl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <shared/elf-note.h>
+#include <shared/util.h>
+
+#include "libkmod-internal-signature.h"
+
+#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)
+{
+#if !DLSYM_LOCALLY_ENABLED
+       return 0;
+#else
+       static void *dl;
+
+       ELF_NOTE_DLOPEN("openssl", "Support for reading module signatures",
+                       ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED, "libcrypto.so.3");
+
+       return dlsym_many(&dl, "libcrypto.so.3", DL_SYMBOL_TABLE(DLSYM_ARG) NULL);
+#endif
+}
+
+static const char *x509_name_to_str(X509_NAME *name)
+{
+       int i;
+       X509_NAME_ENTRY *e;
+       ASN1_STRING *d;
+       ASN1_OBJECT *o;
+       int nid = -1;
+       const char *str;
+
+       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 = sym_X509_NAME_ENTRY_get_data(e);
+       str = (const char *)sym_ASN1_STRING_get0_data(d);
+
+       return str;
+}
+
+bool kmod_fill_pkcs7_openssl(const char *mem, off_t size, size_t sig_len,
+                            struct kmod_signature_info **out_sig_info)
+{
+       struct kmod_signature_info *sig_info;
+       char *p;
+       const char *pkcs7_raw;
+       PKCS7 *pkcs7;
+       STACK_OF(PKCS7_SIGNER_INFO) * sis;
+       PKCS7_SIGNER_INFO *si;
+       const PKCS7_ISSUER_AND_SERIAL *is;
+       const ASN1_OCTET_STRING *sig;
+       BIGNUM *sno_bn;
+       X509_ALGOR *dig_alg;
+       const ASN1_OBJECT *o;
+       BIO *in;
+       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 = sym_BIO_new_mem_buf(pkcs7_raw, sig_len);
+
+       pkcs7 = sym_d2i_PKCS7_bio(in, NULL);
+       sym_BIO_free(in);
+
+       if (pkcs7 == NULL)
+               goto err;
+
+       sis = sym_PKCS7_get_signer_info(pkcs7);
+       if (sis == NULL)
+               goto err;
+
+       si = sym_sk_PKCS7_SIGNER_INFO_value(sis, 0);
+       if (si == NULL || si->issuer_and_serial == NULL || si->enc_digest == NULL)
+               goto err;
+
+       is = si->issuer_and_serial;
+
+       /* Calculate the total length */
+       total_len = sizeof(struct kmod_signature_info);
+
+       /* signer */
+       issuer_str = x509_name_to_str(is->issuer);
+       if (issuer_str != NULL)
+               total_len += strlen(issuer_str);
+
+       /* key_id */
+       sno_bn = sym_ASN1_INTEGER_to_BN(is->serial, NULL);
+       if (sno_bn == NULL)
+               goto err;
+
+       total_len += sym_BN_num_bytes(sno_bn);
+
+       /* hash_algo */
+       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;
+
+       total_len += hash_algo_len + 1;
+
+       /* sig */
+       sig = si->enc_digest;
+       total_len += sym_ASN1_STRING_length(sig);
+
+       sig_info = calloc(1, total_len);
+       if (sig_info == NULL)
+               goto err1;
+
+       p = (char *)sig_info;
+
+       p += sizeof(struct kmod_signature_info);
+
+       /* signer */
+       if (issuer_str != NULL) {
+               sig_info->signer = p;
+               sig_info->signer_len = strlen(issuer_str);
+
+               memcpy(p, issuer_str, sig_info->signer_len);
+               p += sig_info->signer_len;
+       }
+
+       /* key_id */
+       sig_info->key_id = p;
+       sig_info->key_id_len = sym_BN_num_bytes(sno_bn);
+
+       sym_BN_bn2bin(sno_bn, (unsigned char *)p);
+       p += sig_info->key_id_len;
+
+       /* hash_algo */
+       sig_info->hash_algo = p;
+
+       hash_algo_len = sym_OBJ_obj2txt(p, hash_algo_len + 1, o, 0);
+       if (hash_algo_len < 0)
+               goto err2;
+       p += hash_algo_len;
+
+       *p = '\0';
+       p++;
+
+       /* sig */
+       sig_info->sig = p;
+       sig_info->sig_len = sym_ASN1_STRING_length(sig);
+
+       memcpy(p, sym_ASN1_STRING_get0_data(sig), sig_info->sig_len);
+
+       sym_BN_free(sno_bn);
+       sym_PKCS7_free(pkcs7);
+
+       *out_sig_info = sig_info;
+
+       return true;
+
+err2:
+       free(sig_info);
+err1:
+       sym_BN_free(sno_bn);
+err:
+       sym_PKCS7_free(pkcs7);
+       return false;
+}
index 04a29853f9eba3e374601de20d20b5c273f8de98..9f9181ee929861af5c185e63a5af07c5271caeda 100644 (file)
@@ -3,23 +3,15 @@
  * Copyright (C) 2013 Michal Marek, SUSE
  */
 
-#define DLSYM_LOCALLY_ENABLED ENABLE_OPENSSL_DLOPEN
-
 #include <endian.h>
 #include <inttypes.h>
-#if ENABLE_OPENSSL
-#include <openssl/pkcs7.h>
-#include <openssl/ssl.h>
-#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <shared/elf-note.h>
-#include <shared/missing.h>
 #include <shared/util.h>
 
-#include "libkmod-internal.h"
+#include "libkmod-internal-signature.h"
 
 /* These types and tables were copied from the 3.7 kernel sources.
  * As this is just description of the signature format, it should not be
@@ -111,213 +103,8 @@ static bool fill_default(const char *mem, off_t size,
        return true;
 }
 
-#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)
-{
-#if !DLSYM_LOCALLY_ENABLED
-       return 0;
-#else
-       static void *dl;
-
-       ELF_NOTE_DLOPEN("openssl", "Support for reading module signatures",
-                       ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED, "libcrypto.so.3");
-
-       return dlsym_many(&dl, "libcrypto.so.3", DL_SYMBOL_TABLE(DLSYM_ARG) NULL);
-#endif
-}
-
-static const char *x509_name_to_str(X509_NAME *name)
-{
-       int i;
-       X509_NAME_ENTRY *e;
-       ASN1_STRING *d;
-       ASN1_OBJECT *o;
-       int nid = -1;
-       const char *str;
-
-       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 = sym_X509_NAME_ENTRY_get_data(e);
-       str = (const char *)sym_ASN1_STRING_get0_data(d);
-
-       return str;
-}
-
-static bool fill_pkcs7(const char *mem, off_t size, size_t sig_len,
-                      struct kmod_signature_info **out_sig_info)
-{
-       struct kmod_signature_info *sig_info;
-       char *p;
-       const char *pkcs7_raw;
-       PKCS7 *pkcs7;
-       STACK_OF(PKCS7_SIGNER_INFO) * sis;
-       PKCS7_SIGNER_INFO *si;
-       const PKCS7_ISSUER_AND_SERIAL *is;
-       const ASN1_OCTET_STRING *sig;
-       BIGNUM *sno_bn;
-       X509_ALGOR *dig_alg;
-       const ASN1_OBJECT *o;
-       BIO *in;
-       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 = sym_BIO_new_mem_buf(pkcs7_raw, sig_len);
-
-       pkcs7 = sym_d2i_PKCS7_bio(in, NULL);
-       sym_BIO_free(in);
-
-       if (pkcs7 == NULL)
-               goto err;
-
-       sis = sym_PKCS7_get_signer_info(pkcs7);
-       if (sis == NULL)
-               goto err;
-
-       si = sym_sk_PKCS7_SIGNER_INFO_value(sis, 0);
-       if (si == NULL || si->issuer_and_serial == NULL || si->enc_digest == NULL)
-               goto err;
-
-       is = si->issuer_and_serial;
-
-       /* Calculate the total length */
-       total_len = sizeof(struct kmod_signature_info);
-
-       /* signer */
-       issuer_str = x509_name_to_str(is->issuer);
-       if (issuer_str != NULL)
-               total_len += strlen(issuer_str);
-
-       /* key_id */
-       sno_bn = sym_ASN1_INTEGER_to_BN(is->serial, NULL);
-       if (sno_bn == NULL)
-               goto err;
-
-       total_len += sym_BN_num_bytes(sno_bn);
-
-       /* hash_algo */
-       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;
-
-       total_len += hash_algo_len + 1;
-
-       /* sig */
-       sig = si->enc_digest;
-       total_len += sym_ASN1_STRING_length(sig);
-
-       sig_info = calloc(1, total_len);
-       if (sig_info == NULL)
-               goto err1;
-
-       p = (char *)sig_info;
-
-       p += sizeof(struct kmod_signature_info);
-
-       /* signer */
-       if (issuer_str != NULL) {
-               sig_info->signer = p;
-               sig_info->signer_len = strlen(issuer_str);
-
-               memcpy(p, issuer_str, sig_info->signer_len);
-               p += sig_info->signer_len;
-       }
-
-       /* key_id */
-       sig_info->key_id = p;
-       sig_info->key_id_len = sym_BN_num_bytes(sno_bn);
-
-       sym_BN_bn2bin(sno_bn, (unsigned char *)p);
-       p += sig_info->key_id_len;
-
-       /* hash_algo */
-       sig_info->hash_algo = p;
-
-       hash_algo_len = sym_OBJ_obj2txt(p, hash_algo_len + 1, o, 0);
-       if (hash_algo_len < 0)
-               goto err2;
-       p += hash_algo_len;
-
-       *p = '\0';
-       p++;
-
-       /* sig */
-       sig_info->sig = p;
-       sig_info->sig_len = sym_ASN1_STRING_length(sig);
-
-       memcpy(p, sym_ASN1_STRING_get0_data(sig), sig_info->sig_len);
-
-       sym_BN_free(sno_bn);
-       sym_PKCS7_free(pkcs7);
-
-       *out_sig_info = sig_info;
-
-       return true;
-
-err2:
-       free(sig_info);
-err1:
-       sym_BN_free(sno_bn);
-err:
-       sym_PKCS7_free(pkcs7);
-       return false;
-}
-
-#else
-
-static bool fill_pkcs7(const char *mem, off_t size, size_t sig_len,
-                      struct kmod_signature_info **out_sig_info)
+static bool kmod_fill_pkcs7_dummy(const char *mem, off_t size, size_t sig_len,
+                                 struct kmod_signature_info **out_sig_info)
 {
        struct kmod_signature_info *sig_info = calloc(1, sizeof(*sig_info));
        if (sig_info == NULL)
@@ -328,8 +115,6 @@ static bool fill_pkcs7(const char *mem, off_t size, size_t sig_len,
        return true;
 }
 
-#endif
-
 #define SIG_MAGIC "~Module signature appended~\n"
 
 /*
@@ -382,7 +167,9 @@ bool kmod_module_signature_info(const struct kmod_file *file,
 
        switch (modsig.id_type) {
        case PKEY_ID_PKCS7:
-               ret = fill_pkcs7(mem, size, sig_len, sig_info);
+               ret = kmod_fill_pkcs7_openssl(mem, size, sig_len, sig_info);
+               if (!ret)
+                       ret = kmod_fill_pkcs7_dummy(mem, size, sig_len, sig_info);
                break;
        default:
                ret = fill_default(mem, size, &modsig, sig_len, sig_info);
index 9fdf763467b92888435c13e6634c03a5add3384b..076c552beb2bcf0e63a50fabf44a34cc2bbfa261 100644 (file)
@@ -388,6 +388,7 @@ if dep_map.get('zlib').found()
 endif
 
 if dep_map.get('openssl').found()
+  libkmod_files += files('libkmod/libkmod-signature-openssl.c')
   libkmod_deps += dep_map['openssl']
 endif