From 8c3f64e61fd42541f56c5de1b0f926f72f9d935e Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Mon, 20 Apr 2026 13:08:29 +0000 Subject: [PATCH] tree-wide: Load libcrypto and libssl via dlopen() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now OpenSSL was linked into every binary and library that needed cryptography, pulling libcrypto (and, for resolved, libssl) into the address space of services that never touch them at runtime. This commit moves all OpenSSL usage behind the same dlopen helper pattern that we already use for other optional libraries (libpam, libseccomp, libxz, …) so libcrypto/libssl are only loaded on demand. The bulk of the work lives in src/shared/crypto-util.{c,h} (libcrypto) and src/shared/ssl-util.{c,h} (libssl), which replace the previous src/shared/openssl-util.{c,h}: - crypto-util.{c,h} declares every libcrypto function we call via DLSYM_PROTOTYPE() and resolves them inside dlopen_libcrypto(). - ssl-util.{c,h} holds the libssl-specific DLSYM_PROTOTYPEs, dlopen_libssl(), and the SSL_freep cleanup helper, so translation units that only need libcrypto do not pull in libssl declarations. - Callers refer to the symbols through sym_* aliases rather than the original names. - Convenience macros that used to be provided by the OpenSSL headers (OPENSSL_free, BN_num_bytes, the sk_TYPE_* helpers, …) are reimplemented as sym_* wrappers so no code path needs to fall back to the linker-resolved symbols. - All _cleanup_ helpers are redefined in terms of the sym_* variants (EVP_PKEY_freep, X509_freep, BIO_freep, …) so cleanup attributes keep working without pulling in libcrypto symbols at link time. - The public crypto-util.c entry points (openssl_pubkey_from_pem, openssl_digest_many, openssl_hmac_many, openssl_cipher_many, kdf_ss_derive, kdf_kb_hmac_derive, rsa_* / ecc_* helpers, pubkey_fingerprint, digest_and_sign, pkcs7_new, x509_fingerprint, openssl_extract_public_key, pkey_generate_volume_keys, the load_* helpers, …) now call dlopen_libcrypto() at entry before touching any sym_* pointer. The call sites across the tree have been converted to call dlopen_libcrypto()/dlopen_libssl() at the appropriate entry point before their first sym_* use, and to use sym_* variants throughout: - bootctl, sbsign, measure, pcrlock, pcrextend, tpm2-setup, repart, cryptsetup, cryptenroll, homectl, homed, homework, keyutil, sysupdate, creds, import, dissect-image, pe-binary, pkcs11-util, pkcs7-util, tpm2-util, creds-util. resolved additionally dlopens libssl for DoT. The meson build files are updated to depend on libopenssl_cflags (a new partial dependency that exposes include paths and compile flags only, not the linker flags) instead of libopenssl for every target that previously linked against OpenSSL. Nothing links against libcrypto or libssl directly anymore. A new src/sbsign/authenticode.c hosts the Authenticode ASN.1 type definitions that used to live inline in sbsign.c. The OpenSSL ASN1_SEQUENCE / ASN1_CHOICE / IMPLEMENT_ASN1_FUNCTIONS macros expand to code that references libcrypto symbols directly, so to keep this translation unit unlinked from libcrypto we redirect ASN1_item_* to the sym_* variants via #define and wrap the ASN1_*_it() getters (which appear as constant function pointers in static initializers) in small trampoline functions that forward to the sym_* pointers at runtime. test-dlopen-so gains assertions for dlopen_libcrypto and dlopen_libssl so the dlopen contract is exercised in CI, and the openssl-specific test was renamed from test-openssl.c to test-crypto-util.c to match the new header naming. --- meson.build | 1 + src/basic/basic-forward.h | 10 + src/bootctl/bootctl-install.c | 35 +- src/bootctl/bootctl.c | 2 +- src/bootctl/meson.build | 2 +- src/creds/meson.build | 2 +- src/cryptenroll/cryptenroll-pkcs11.c | 2 +- src/cryptenroll/meson.build | 2 +- src/cryptsetup/cryptsetup.c | 9 +- src/cryptsetup/meson.build | 2 +- src/home/homectl-pkcs11.c | 2 +- src/home/homectl.c | 8 +- src/home/homed-manager-bus.c | 6 +- src/home/homed-manager.c | 30 +- src/home/homed-manager.h | 2 - src/home/homework-fscrypt.c | 56 +- src/home/homework-luks.c | 34 +- src/home/meson.build | 6 +- src/home/user-record-sign.c | 8 +- src/home/user-record-sign.h | 2 - src/import/meson.build | 2 +- src/import/pull-common.c | 1 + src/import/pull-job.c | 20 +- src/import/pull-job.h | 3 +- src/import/pull-oci.c | 1 + src/import/pull-raw.c | 1 + src/keyutil/keyutil.c | 26 +- src/keyutil/meson.build | 2 +- src/measure/measure-tool.c | 60 +- src/measure/meson.build | 2 +- src/pcrextend/meson.build | 2 +- src/pcrextend/pcrextend.c | 9 +- src/pcrlock/meson.build | 2 +- src/pcrlock/pcrlock-firmware.c | 7 +- src/pcrlock/pcrlock.c | 70 +- src/repart/meson.build | 4 +- src/repart/repart.c | 24 +- src/resolve/meson.build | 2 +- src/resolve/resolvectl.c | 2 +- src/resolve/resolved-dns-dnssec.c | 155 +-- src/resolve/resolved-dnstls.c | 105 +- src/resolve/resolved-dnstls.h | 2 - src/sbsign/authenticode.c | 125 ++ src/sbsign/authenticode.h | 65 +- src/sbsign/meson.build | 7 +- src/sbsign/sbsign.c | 131 +- src/shared/creds-util.c | 105 +- src/shared/{openssl-util.c => crypto-util.c} | 1166 ++++++++++++++--- src/shared/crypto-util.h | 406 ++++++ src/shared/dissect-image.c | 26 +- src/shared/meson.build | 5 +- src/shared/openssl-util.h | 196 --- src/shared/pe-binary.c | 33 +- src/shared/pe-binary.h | 1 - src/shared/pkcs11-util.c | 119 +- src/shared/pkcs11-util.h | 4 - src/shared/pkcs7-util.c | 22 +- src/shared/shared-forward.h | 1 + src/shared/ssl-util.c | 75 ++ src/shared/ssl-util.h | 46 + src/shared/tpm2-util.c | 80 +- src/shared/tpm2-util.h | 3 +- src/sysupdate/meson.build | 2 +- src/test/meson.build | 13 +- .../{test-openssl.c => test-crypto-util.c} | 47 +- src/test/test-cryptolib.c | 27 - src/test/test-dlopen-so.c | 4 + src/test/test-tpm2.c | 15 +- src/tpm2-setup/meson.build | 2 +- src/tpm2-setup/tpm2-setup.c | 11 +- 70 files changed, 2396 insertions(+), 1064 deletions(-) create mode 100644 src/sbsign/authenticode.c rename src/shared/{openssl-util.c => crypto-util.c} (51%) create mode 100644 src/shared/crypto-util.h delete mode 100644 src/shared/openssl-util.h create mode 100644 src/shared/ssl-util.c create mode 100644 src/shared/ssl-util.h rename src/test/{test-openssl.c => test-crypto-util.c} (93%) delete mode 100644 src/test/test-cryptolib.c diff --git a/meson.build b/meson.build index a902bc96aa..4f1a791bc7 100644 --- a/meson.build +++ b/meson.build @@ -1258,6 +1258,7 @@ libgnutls_cflags = libgnutls.partial_dependency(includes: true, compile_args: tr libopenssl = dependency('openssl', version : '>= 3.0.0', required : get_option('openssl')) +libopenssl_cflags = libopenssl.partial_dependency(includes: true, compile_args: true) conf.set10('HAVE_OPENSSL', libopenssl.found()) libp11kit = dependency('p11-kit-1', diff --git a/src/basic/basic-forward.h b/src/basic/basic-forward.h index 1ca9ecfeff..396056a8e5 100644 --- a/src/basic/basic-forward.h +++ b/src/basic/basic-forward.h @@ -69,6 +69,15 @@ struct fdisk_context; struct fdisk_table; struct crypt_device; +typedef struct buf_mem_st BUF_MEM; +typedef struct evp_pkey_st EVP_PKEY; +typedef struct evp_md_st EVP_MD; +typedef struct evp_md_ctx_st EVP_MD_CTX; +typedef struct ssl_st SSL; +typedef struct ssl_ctx_st SSL_CTX; +typedef struct ssl_session_st SSL_SESSION; +typedef struct x509_st X509; + /* basic/ forward declarations */ typedef void (*hash_func_t)(const void *p, struct siphash *state); @@ -111,6 +120,7 @@ typedef struct Set Set; typedef struct dual_timestamp dual_timestamp; typedef struct triple_timestamp triple_timestamp; +typedef struct Compressor Compressor; typedef struct ConfFile ConfFile; typedef struct LockFile LockFile; typedef struct PidRef PidRef; diff --git a/src/bootctl/bootctl-install.c b/src/bootctl/bootctl-install.c index a8ac742b9a..20958d0b0b 100644 --- a/src/bootctl/bootctl-install.c +++ b/src/bootctl/bootctl-install.c @@ -7,6 +7,7 @@ #include "sd-varlink.h" #include "alloc-util.h" +#include "ask-password-api.h" #include "blockdev-util.h" #include "boot-entry.h" #include "bootctl.h" @@ -15,6 +16,7 @@ #include "bootctl-util.h" #include "chase.h" #include "copy.h" +#include "crypto-util.h" #include "dirent-util.h" #include "efi-api.h" #include "efi-fundamental.h" @@ -31,7 +33,6 @@ #include "json-util.h" #include "kernel-config.h" #include "log.h" -#include "openssl-util.h" #include "parse-argument.h" #include "path-util.h" #include "pe-binary.h" @@ -117,11 +118,11 @@ static void install_context_done(InstallContext *c) { c->xbootldr_fd = safe_close(c->xbootldr_fd); #if HAVE_OPENSSL if (c->secure_boot_private_key) { - EVP_PKEY_free(c->secure_boot_private_key); + sym_EVP_PKEY_free(c->secure_boot_private_key); c->secure_boot_private_key = NULL; } if (c->secure_boot_certificate) { - X509_free(c->secure_boot_certificate); + sym_X509_free(c->secure_boot_certificate); c->secure_boot_certificate = NULL; } #endif @@ -1035,12 +1036,16 @@ static int install_secure_boot_auto_enroll(InstallContext *c) { if (!c->secure_boot_certificate || !c->secure_boot_private_key) return 0; + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_free_ uint8_t *dercert = NULL; int dercertsz; - dercertsz = i2d_X509(c->secure_boot_certificate, &dercert); + dercertsz = sym_i2d_X509(c->secure_boot_certificate, &dercert); if (dercertsz < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert X.509 certificate to DER: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); if (c->esp_fd < 0) return c->esp_fd; @@ -1087,7 +1092,7 @@ static int install_secure_boot_auto_enroll(InstallContext *c) { FOREACH_STRING(db, "PK", "KEK", "db") { _cleanup_(BIO_freep) BIO *bio = NULL; - bio = BIO_new(BIO_s_mem()); + bio = sym_BIO_new(sym_BIO_s_mem()); if (!bio) return log_oom(); @@ -1096,34 +1101,34 @@ static int install_secure_boot_auto_enroll(InstallContext *c) { return log_oom(); /* Don't count the trailing NUL terminator. */ - if (BIO_write(bio, db16, char16_strsize(db16) - sizeof(char16_t)) < 0) + if (sym_BIO_write(bio, db16, char16_strsize(db16) - sizeof(char16_t)) < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write variable name to bio"); EFI_GUID *guid = STR_IN_SET(db, "PK", "KEK") ? &(EFI_GUID) EFI_GLOBAL_VARIABLE : &(EFI_GUID) EFI_IMAGE_SECURITY_DATABASE_GUID; - if (BIO_write(bio, guid, sizeof(*guid)) < 0) + if (sym_BIO_write(bio, guid, sizeof(*guid)) < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write variable GUID to bio"); - if (BIO_write(bio, &attrs, sizeof(attrs)) < 0) + if (sym_BIO_write(bio, &attrs, sizeof(attrs)) < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write variable attributes to bio"); - if (BIO_write(bio, ×tamp, sizeof(timestamp)) < 0) + if (sym_BIO_write(bio, ×tamp, sizeof(timestamp)) < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write timestamp to bio"); - if (BIO_write(bio, siglist, siglistsz) < 0) + if (sym_BIO_write(bio, siglist, siglistsz) < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write signature list to bio"); _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL; - p7 = PKCS7_sign(c->secure_boot_certificate, c->secure_boot_private_key, /* certs= */ NULL, bio, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY|PKCS7_NOSMIMECAP); + p7 = sym_PKCS7_sign(c->secure_boot_certificate, c->secure_boot_private_key, /* certs= */ NULL, bio, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY|PKCS7_NOSMIMECAP); if (!p7) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to calculate PKCS7 signature: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); _cleanup_free_ uint8_t *sig = NULL; - int sigsz = i2d_PKCS7(p7, &sig); + int sigsz = sym_i2d_PKCS7(p7, &sig); if (sigsz < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert PKCS7 signature to DER: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); size_t authsz = offsetof(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo.CertData) + sigsz; _cleanup_free_ EFI_VARIABLE_AUTHENTICATION_2 *auth = malloc(authsz); diff --git a/src/bootctl/bootctl.c b/src/bootctl/bootctl.c index 59a93d07c3..942ef4d681 100644 --- a/src/bootctl/bootctl.c +++ b/src/bootctl/bootctl.c @@ -17,6 +17,7 @@ #include "bootctl-unlink.h" #include "bootctl-util.h" #include "build.h" +#include "crypto-util.h" #include "devnum-util.h" #include "dissect-image.h" #include "efi-loader.h" @@ -30,7 +31,6 @@ #include "loop-util.h" #include "main-func.h" #include "mount-util.h" -#include "openssl-util.h" #include "options.h" #include "pager.h" #include "parse-argument.h" diff --git a/src/bootctl/meson.build b/src/bootctl/meson.build index 8cfbb7c14a..f8349df716 100644 --- a/src/bootctl/meson.build +++ b/src/bootctl/meson.build @@ -23,6 +23,6 @@ executables += [ ], 'sources' : bootctl_sources, 'link_with' : boot_link_with, - 'dependencies' : [libopenssl], + 'dependencies' : [libopenssl_cflags], }, ] diff --git a/src/creds/meson.build b/src/creds/meson.build index a6e66495b6..dc4a5a28ae 100644 --- a/src/creds/meson.build +++ b/src/creds/meson.build @@ -11,7 +11,7 @@ executables += [ 'sources' : files('creds.c'), 'dependencies' : [ libmount_cflags, - libopenssl, + libopenssl_cflags, threads, ], }, diff --git a/src/cryptenroll/cryptenroll-pkcs11.c b/src/cryptenroll/cryptenroll-pkcs11.c index 51c2a5fa77..ae678f96e4 100644 --- a/src/cryptenroll/cryptenroll-pkcs11.c +++ b/src/cryptenroll/cryptenroll-pkcs11.c @@ -2,10 +2,10 @@ #include "alloc-util.h" #include "cryptenroll-pkcs11.h" +#include "crypto-util.h" #include "cryptsetup-util.h" #include "hexdecoct.h" #include "json-util.h" -#include "openssl-util.h" #include "pkcs11-util.h" #if HAVE_P11KIT && HAVE_OPENSSL diff --git a/src/cryptenroll/meson.build b/src/cryptenroll/meson.build index 2d882343d3..8213a0e672 100644 --- a/src/cryptenroll/meson.build +++ b/src/cryptenroll/meson.build @@ -24,7 +24,7 @@ executables += [ libcryptsetup_cflags, libdl, libfido2_cflags, - libopenssl, + libopenssl_cflags, libp11kit_cflags, ], }, diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 8e5161eba0..d772ba9a9a 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -12,6 +12,7 @@ #include "alloc-util.h" #include "ask-password-api.h" #include "build.h" +#include "crypto-util.h" #include "cryptsetup-fido2.h" #include "cryptsetup-keyfile.h" #include "cryptsetup-pkcs11.h" @@ -537,6 +538,10 @@ static int parse_one_option(const char *option) { #if HAVE_OPENSSL _cleanup_strv_free_ char **l = NULL; + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + l = strv_split(val, ":"); if (!l) return log_oom(); @@ -544,11 +549,11 @@ static int parse_one_option(const char *option) { STRV_FOREACH(i, l) { const EVP_MD *implementation; - implementation = EVP_get_digestbyname(*i); + implementation = sym_EVP_get_digestbyname(*i); if (!implementation) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown bank '%s', refusing.", val); - if (strv_extend(&arg_tpm2_measure_banks, EVP_MD_name(implementation)) < 0) + if (strv_extend(&arg_tpm2_measure_banks, sym_EVP_MD_get0_name(implementation)) < 0) return log_oom(); } #else diff --git a/src/cryptsetup/meson.build b/src/cryptsetup/meson.build index 9249f70177..9b7f3fa344 100644 --- a/src/cryptsetup/meson.build +++ b/src/cryptsetup/meson.build @@ -21,7 +21,7 @@ executables += [ libcryptsetup_cflags, libfido2_cflags, libmount_cflags, - libopenssl, + libopenssl_cflags, libp11kit_cflags, ], }, diff --git a/src/home/homectl-pkcs11.c b/src/home/homectl-pkcs11.c index a72aecf135..3ef1b80c22 100644 --- a/src/home/homectl-pkcs11.c +++ b/src/home/homectl-pkcs11.c @@ -2,12 +2,12 @@ #include "sd-json.h" +#include "crypto-util.h" #include "errno-util.h" #include "hexdecoct.h" #include "homectl-pkcs11.h" #include "libcrypt-util.h" #include "log.h" -#include "openssl-util.h" #include "pkcs11-util.h" #include "string-util.h" #include "strv.h" diff --git a/src/home/homectl.c b/src/home/homectl.c index 4ebf47ca9e..271e035875 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -18,6 +18,7 @@ #include "cgroup-util.h" #include "chase.h" #include "creds-util.h" +#include "crypto-util.h" #include "dirent-util.h" #include "dns-domain.h" #include "env-util.h" @@ -39,7 +40,6 @@ #include "libfido2-util.h" #include "locale-util.h" #include "main-func.h" -#include "openssl-util.h" #include "pager.h" #include "parse-argument.h" #include "parse-util.h" @@ -5316,13 +5316,17 @@ static int verb_list_signing_keys(int argc, char *argv[], uintptr_t _data, void /* Let's decode the PEM key to DER (so that we lose prefix/suffix), then truncate it * for display reasons. */ + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_(EVP_PKEY_freep) EVP_PKEY *key = NULL; r = openssl_pubkey_from_pem(pem, SIZE_MAX, &key); if (r < 0) return log_error_errno(r, "Failed to parse PEM: %m"); _cleanup_free_ void *der = NULL; - int n = i2d_PUBKEY(key, (unsigned char**) &der); + int n = sym_i2d_PUBKEY(key, (unsigned char**) &der); if (n < 0) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to encode key as DER."); diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c index f352685672..b8385c781e 100644 --- a/src/home/homed-manager-bus.c +++ b/src/home/homed-manager-bus.c @@ -12,6 +12,7 @@ #include "bus-message-util.h" #include "bus-object.h" #include "bus-polkit.h" +#include "crypto-util.h" #include "fileio.h" #include "format-util.h" #include "home-util.h" @@ -22,7 +23,6 @@ #include "homed-manager-bus.h" #include "homed-operation.h" #include "log.h" -#include "openssl-util.h" #include "path-util.h" #include "set.h" #include "string-util.h" @@ -936,14 +936,14 @@ static bool manager_has_public_key(Manager *m, EVP_PKEY *needle) { EVP_PKEY *pkey; HASHMAP_FOREACH(pkey, m->public_keys) { - r = EVP_PKEY_eq(pkey, needle); + r = sym_EVP_PKEY_eq(pkey, needle); if (r > 0) return true; /* EVP_PKEY_eq() returns -1 and -2 too under some conditions, which we'll all treat as "not the same" */ } - r = EVP_PKEY_eq(m->private_key, needle); + r = sym_EVP_PKEY_eq(m->private_key, needle); if (r > 0) return true; diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index 6c229abadc..fc6fe8a4b1 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -25,6 +24,7 @@ #include "clean-ipc.h" #include "common-signal.h" #include "conf-files.h" +#include "crypto-util.h" #include "device-util.h" #include "dirent-util.h" #include "errno-util.h" @@ -43,7 +43,6 @@ #include "homed-varlink.h" #include "mkdir.h" #include "notify-recv.h" -#include "openssl-util.h" #include "ordered-set.h" #include "quota-util.h" #include "random-util.h" @@ -313,7 +312,7 @@ Manager* manager_free(Manager *m) { m->homes_by_sysfs = hashmap_free(m->homes_by_sysfs); if (m->private_key) - EVP_PKEY_free(m->private_key); + sym_EVP_PKEY_free(m->private_key); hashmap_free(m->public_keys); @@ -1317,7 +1316,7 @@ static int manager_load_key_pair(Manager *m) { assert(m); if (m->private_key) { - EVP_PKEY_free(m->private_key); + sym_EVP_PKEY_free(m->private_key); m->private_key = NULL; } @@ -1337,7 +1336,7 @@ static int manager_load_key_pair(Manager *m) { if (st.st_uid != 0 || (st.st_mode & 0077) != 0) return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Private key file is readable by more than the root user"); - m->private_key = PEM_read_PrivateKey(f, NULL, NULL, NULL); + m->private_key = sym_PEM_read_PrivateKey(f, NULL, NULL, NULL); if (!m->private_key) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to load private key pair"); @@ -1353,20 +1352,20 @@ static int manager_generate_key_pair(Manager *m) { int r; if (m->private_key) { - EVP_PKEY_free(m->private_key); + sym_EVP_PKEY_free(m->private_key); m->private_key = NULL; } - ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL); + ctx = sym_EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL); if (!ctx) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to allocate Ed25519 key generation context."); - if (EVP_PKEY_keygen_init(ctx) <= 0) + if (sym_EVP_PKEY_keygen_init(ctx) <= 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to initialize Ed25519 key generation context."); log_info("Generating key pair for signing local user identity records."); - if (EVP_PKEY_keygen(ctx, &m->private_key) <= 0) + if (sym_EVP_PKEY_keygen(ctx, &m->private_key) <= 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate Ed25519 key pair"); log_info("Successfully created Ed25519 key pair."); @@ -1378,7 +1377,7 @@ static int manager_generate_key_pair(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to open key file for writing: %m"); - if (PEM_write_PUBKEY(fpublic, m->private_key) <= 0) + if (sym_PEM_write_PUBKEY(fpublic, m->private_key) <= 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key."); (void) fchmod(fileno(fpublic), 0444); /* Make public key world readable */ @@ -1394,7 +1393,7 @@ static int manager_generate_key_pair(Manager *m) { if (r < 0) return log_error_errno(r, "Failed to open key file for writing: %m"); - if (PEM_write_PrivateKey(fprivate, m->private_key, NULL, NULL, 0, NULL, NULL) <= 0) + if (sym_PEM_write_PrivateKey(fprivate, m->private_key, NULL, NULL, 0, NULL, NULL) <= 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write private key pair."); (void) fchmod(fileno(fprivate), 0400); /* Make private key root readable */ @@ -1459,7 +1458,8 @@ int manager_sign_user_record(Manager *m, UserRecord *u, UserRecord **ret, sd_bus return user_record_sign(u, m->private_key, ret); } -DEFINE_HASH_OPS_FULL(public_key_hash_ops, char, string_hash_func, string_compare_func, free, EVP_PKEY, EVP_PKEY_free); +/* dlopen_libcrypto() must have been called before populating this hashmap. */ +DEFINE_HASH_OPS_FULL(public_key_hash_ops, char, string_hash_func, string_compare_func, free, EVP_PKEY, sym_EVP_PKEY_free); static int manager_load_public_key_one(Manager *m, const char *path) { _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; @@ -1495,7 +1495,7 @@ static int manager_load_public_key_one(Manager *m, const char *path) { if (st.st_uid != 0 || (st.st_mode & 0022) != 0) return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Public key file %s is writable by more than the root user, refusing.", path); - pkey = PEM_read_PUBKEY(f, &pkey, NULL, NULL); + pkey = sym_PEM_read_PUBKEY(f, &pkey, NULL, NULL); if (!pkey) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse public key file %s.", path); @@ -1537,6 +1537,10 @@ int manager_startup(Manager *m) { assert(m); + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + r = manager_listen_notify(m); if (r < 0) return r; diff --git a/src/home/homed-manager.h b/src/home/homed-manager.h index fe1041e01e..a399c31bf8 100644 --- a/src/home/homed-manager.h +++ b/src/home/homed-manager.h @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include - #include "homed-forward.h" #include "user-record.h" diff --git a/src/home/homework-fscrypt.c b/src/home/homework-fscrypt.c index c2134142de..6f8ae4b8c9 100644 --- a/src/home/homework-fscrypt.c +++ b/src/home/homework-fscrypt.c @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include -#include -#include #include #include #include @@ -10,6 +8,7 @@ #include #include "alloc-util.h" +#include "crypto-util.h" #include "errno-util.h" #include "fd-util.h" #include "format-util.h" @@ -25,7 +24,6 @@ #include "mkdir.h" #include "mount-util.h" #include "nulstr-util.h" -#include "openssl-util.h" #include "parse-util.h" #include "process-util.h" #include "random-util.h" @@ -180,8 +178,8 @@ static void calculate_key_descriptor( /* Derive the key descriptor from the volume key via double SHA512, in order to be compatible with e4crypt */ - assert_se(SHA512(key, key_size, hashed) == hashed); - assert_se(SHA512(hashed, sizeof(hashed), hashed2) == hashed2); + assert_se(sym_SHA512(key, key_size, hashed) == hashed); + assert_se(sym_SHA512(hashed, sizeof(hashed), hashed2) == hashed2); assert_cc(sizeof(hashed2) >= FS_KEY_DESCRIPTOR_SIZE); @@ -211,6 +209,10 @@ static int fscrypt_slot_try_one( assert(encrypted_size > 0); assert(match_key_descriptor); + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + /* Our construction is like this: * * 1. In each key slot we store a salt value plus the encrypted volume key @@ -226,37 +228,37 @@ static int fscrypt_slot_try_one( CLEANUP_ERASE(derived); - if (PKCS5_PBKDF2_HMAC( + if (sym_PKCS5_PBKDF2_HMAC( password, strlen(password), salt, salt_size, - 0xFFFF, EVP_sha512(), + 0xFFFF, sym_EVP_sha512(), sizeof(derived), derived) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "PBKDF2 failed."); - context = EVP_CIPHER_CTX_new(); + context = sym_EVP_CIPHER_CTX_new(); if (!context) return log_oom(); /* We use AES256 in counter mode */ - assert_se(cc = EVP_aes_256_ctr()); + assert_se(cc = sym_EVP_aes_256_ctr()); /* We only use the first half of the derived key */ - assert(sizeof(derived) >= (size_t) EVP_CIPHER_key_length(cc)); + assert(sizeof(derived) >= (size_t) sym_EVP_CIPHER_get_key_length(cc)); - if (EVP_DecryptInit_ex(context, cc, NULL, derived, NULL) != 1) + if (sym_EVP_DecryptInit_ex(context, cc, NULL, derived, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize decryption context."); - decrypted_size = encrypted_size + EVP_CIPHER_key_length(cc) * 2; + decrypted_size = encrypted_size + sym_EVP_CIPHER_get_key_length(cc) * 2; decrypted = malloc(decrypted_size); if (!decrypted) return log_oom(); - if (EVP_DecryptUpdate(context, (uint8_t*) decrypted, &decrypted_size_out1, encrypted, encrypted_size) != 1) + if (sym_EVP_DecryptUpdate(context, (uint8_t*) decrypted, &decrypted_size_out1, encrypted, encrypted_size) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to decrypt volume key."); assert((size_t) decrypted_size_out1 <= decrypted_size); - if (EVP_DecryptFinal_ex(context, (uint8_t*) decrypted + decrypted_size_out1, &decrypted_size_out2) != 1) + if (sym_EVP_DecryptFinal_ex(context, (uint8_t*) decrypted + decrypted_size_out1, &decrypted_size_out2) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finish decryption of volume key."); assert((size_t) decrypted_size_out1 + (size_t) decrypted_size_out2 < decrypted_size); @@ -484,43 +486,47 @@ static int fscrypt_slot_set( size_t encrypted_size; ssize_t ss; + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + r = crypto_random_bytes(salt, sizeof(salt)); if (r < 0) return log_error_errno(r, "Failed to generate salt: %m"); CLEANUP_ERASE(derived); - if (PKCS5_PBKDF2_HMAC( + if (sym_PKCS5_PBKDF2_HMAC( password, strlen(password), salt, sizeof(salt), - 0xFFFF, EVP_sha512(), + 0xFFFF, sym_EVP_sha512(), sizeof(derived), derived) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "PBKDF2 failed"); - context = EVP_CIPHER_CTX_new(); + context = sym_EVP_CIPHER_CTX_new(); if (!context) return log_oom(); /* We use AES256 in counter mode */ - cc = EVP_aes_256_ctr(); + cc = sym_EVP_aes_256_ctr(); /* We only use the first half of the derived key */ - assert(sizeof(derived) >= (size_t) EVP_CIPHER_key_length(cc)); + assert(sizeof(derived) >= (size_t) sym_EVP_CIPHER_get_key_length(cc)); - if (EVP_EncryptInit_ex(context, cc, NULL, derived, NULL) != 1) + if (sym_EVP_EncryptInit_ex(context, cc, NULL, derived, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize encryption context."); - encrypted_size = volume_key_size + EVP_CIPHER_key_length(cc) * 2; + encrypted_size = volume_key_size + sym_EVP_CIPHER_get_key_length(cc) * 2; encrypted = malloc(encrypted_size); if (!encrypted) return log_oom(); - if (EVP_EncryptUpdate(context, (uint8_t*) encrypted, &encrypted_size_out1, volume_key, volume_key_size) != 1) + if (sym_EVP_EncryptUpdate(context, (uint8_t*) encrypted, &encrypted_size_out1, volume_key, volume_key_size) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to encrypt volume key."); assert((size_t) encrypted_size_out1 <= encrypted_size); - if (EVP_EncryptFinal_ex(context, (uint8_t*) encrypted + encrypted_size_out1, &encrypted_size_out2) != 1) + if (sym_EVP_EncryptFinal_ex(context, (uint8_t*) encrypted + encrypted_size_out1, &encrypted_size_out2) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finish encryption of volume key."); assert((size_t) encrypted_size_out1 + (size_t) encrypted_size_out2 < encrypted_size); @@ -569,6 +575,10 @@ int home_create_fscrypt( assert(setup); assert(ret_home); + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + assert_se(ip = user_record_image_path(h)); r = tempfn_random(ip, "homework", &d); diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index 96ac65a6fb..e85153d61d 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -21,6 +21,7 @@ #include "blockdev-util.h" #include "btrfs-util.h" #include "chattr-util.h" +#include "crypto-util.h" #include "cryptsetup-util.h" #include "device-util.h" #include "devnum-util.h" @@ -48,7 +49,6 @@ #include "memory-util.h" #include "mkdir.h" #include "mkfs-util.h" -#include "openssl-util.h" #include "parse-util.h" #include "path-util.h" #include "pidref.h" @@ -805,6 +805,10 @@ static int crypt_device_to_evp_cipher(struct crypt_device *cd, const EVP_CIPHER assert(cd); assert(ret); + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + /* Let's find the right OpenSSL EVP_CIPHER object that matches the encryption settings of the LUKS * device */ @@ -832,12 +836,12 @@ static int crypt_device_to_evp_cipher(struct crypt_device *cd, const EVP_CIPHER if (asprintf(&cipher_name, "%s-%zu-%s", cipher, key_bits, cipher_mode) < 0) return log_oom(); - cc = EVP_get_cipherbyname(cipher_name); + cc = sym_EVP_get_cipherbyname(cipher_name); if (!cc) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Selected cipher mode '%s' not supported, can't encrypt JSON record.", cipher_name); /* Verify that our key length calculations match what OpenSSL thinks */ - r = EVP_CIPHER_key_length(cc); + r = sym_EVP_CIPHER_get_key_length(cc); if (r < 0 || (uint64_t) r != key_size) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Key size of selected cipher doesn't meet our expectations."); @@ -909,27 +913,27 @@ static int luks_validate_home_record( r = crypt_device_to_evp_cipher(cd, &cc); if (r < 0) return r; - if (iv_size > INT_MAX || EVP_CIPHER_iv_length(cc) != (int) iv_size) + if (iv_size > INT_MAX || sym_EVP_CIPHER_get_iv_length(cc) != (int) iv_size) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "IV size doesn't match."); - context = EVP_CIPHER_CTX_new(); + context = sym_EVP_CIPHER_CTX_new(); if (!context) return log_oom(); - if (EVP_DecryptInit_ex(context, cc, NULL, volume_key, iv) != 1) + if (sym_EVP_DecryptInit_ex(context, cc, NULL, volume_key, iv) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize decryption context."); - decrypted_size = encrypted_size + EVP_CIPHER_key_length(cc) * 2; + decrypted_size = encrypted_size + sym_EVP_CIPHER_get_key_length(cc) * 2; decrypted = new(char, decrypted_size); if (!decrypted) return log_oom(); - if (EVP_DecryptUpdate(context, (uint8_t*) decrypted, &decrypted_size_out1, encrypted, encrypted_size) != 1) + if (sym_EVP_DecryptUpdate(context, (uint8_t*) decrypted, &decrypted_size_out1, encrypted, encrypted_size) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to decrypt JSON record."); assert((size_t) decrypted_size_out1 <= decrypted_size); - if (EVP_DecryptFinal_ex(context, (uint8_t*) decrypted + decrypted_size_out1, &decrypted_size_out2) != 1) + if (sym_EVP_DecryptFinal_ex(context, (uint8_t*) decrypted + decrypted_size_out1, &decrypted_size_out2) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finish decryption of JSON record."); assert((size_t) decrypted_size_out1 + (size_t) decrypted_size_out2 < decrypted_size); @@ -990,8 +994,8 @@ static int format_luks_token_text( if (r < 0) return r; - key_size = EVP_CIPHER_key_length(cc); - iv_size = EVP_CIPHER_iv_length(cc); + key_size = sym_EVP_CIPHER_get_key_length(cc); + iv_size = sym_EVP_CIPHER_get_iv_length(cc); if (iv_size > 0) { iv = malloc(iv_size); @@ -1003,11 +1007,11 @@ static int format_luks_token_text( return log_error_errno(r, "Failed to generate IV: %m"); } - context = EVP_CIPHER_CTX_new(); + context = sym_EVP_CIPHER_CTX_new(); if (!context) return log_oom(); - if (EVP_EncryptInit_ex(context, cc, NULL, volume_key, iv) != 1) + if (sym_EVP_EncryptInit_ex(context, cc, NULL, volume_key, iv) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize encryption context."); r = sd_json_variant_format(hr->json, 0, &text); @@ -1021,12 +1025,12 @@ static int format_luks_token_text( if (!encrypted) return log_oom(); - if (EVP_EncryptUpdate(context, encrypted, &encrypted_size_out1, (uint8_t*) text, text_length) != 1) + if (sym_EVP_EncryptUpdate(context, encrypted, &encrypted_size_out1, (uint8_t*) text, text_length) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to encrypt JSON record."); assert((size_t) encrypted_size_out1 <= encrypted_size); - if (EVP_EncryptFinal_ex(context, (uint8_t*) encrypted + encrypted_size_out1, &encrypted_size_out2) != 1) + if (sym_EVP_EncryptFinal_ex(context, (uint8_t*) encrypted + encrypted_size_out1, &encrypted_size_out2) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finish encryption of JSON record."); assert((size_t) encrypted_size_out1 + (size_t) encrypted_size_out2 <= encrypted_size); diff --git a/src/home/meson.build b/src/home/meson.build index b051bf580c..53c5675c83 100644 --- a/src/home/meson.build +++ b/src/home/meson.build @@ -65,7 +65,7 @@ executables += [ 'extract' : systemd_homed_extract_sources, 'dependencies' : [ libm, - libopenssl, + libopenssl_cflags, threads, ], }, @@ -76,7 +76,7 @@ executables += [ 'dependencies' : [ libblkid_cflags, libfdisk_cflags, - libopenssl, + libopenssl_cflags, libp11kit_cflags, threads, ], @@ -88,7 +88,7 @@ executables += [ 'objects' : ['systemd-homed'], 'dependencies' : [ libdl, - libopenssl, + libopenssl_cflags, libp11kit_cflags, threads, ], diff --git a/src/home/user-record-sign.c b/src/home/user-record-sign.c index 7a80ef1e7a..6bc97af27a 100644 --- a/src/home/user-record-sign.c +++ b/src/home/user-record-sign.c @@ -1,9 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "alloc-util.h" +#include "crypto-util.h" #include "json-util.h" #include "log.h" -#include "openssl-util.h" #include "user-record-sign.h" #include "user-record.h" @@ -118,14 +118,14 @@ int user_record_verify(UserRecord *ur, EVP_PKEY *public_key) { if (r < 0) return r; - md_ctx = EVP_MD_CTX_new(); + md_ctx = sym_EVP_MD_CTX_new(); if (!md_ctx) return -ENOMEM; - if (EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, public_key) <= 0) + if (sym_EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, public_key) <= 0) return -EIO; - if (EVP_DigestVerify(md_ctx, signature, signature_size, (uint8_t*) text, strlen(text)) <= 0) { + if (sym_EVP_DigestVerify(md_ctx, signature, signature_size, (uint8_t*) text, strlen(text)) <= 0) { n_bad++; continue; } diff --git a/src/home/user-record-sign.h b/src/home/user-record-sign.h index 3007d00b01..673c7b2b37 100644 --- a/src/home/user-record-sign.h +++ b/src/home/user-record-sign.h @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include - #include "shared-forward.h" int user_record_sign(UserRecord *ur, EVP_PKEY *private_key, UserRecord **ret); diff --git a/src/import/meson.build b/src/import/meson.build index 63e632a6cd..c2879c5d84 100644 --- a/src/import/meson.build +++ b/src/import/meson.build @@ -31,7 +31,7 @@ executables += [ 'pull-tar.c', ), 'objects' : ['systemd-importd'], - 'dependencies' : libopenssl, + 'dependencies' : libopenssl_cflags, }, libexec_template + { 'name' : 'systemd-import', diff --git a/src/import/pull-common.c b/src/import/pull-common.c index ac921addb2..49f87bcac4 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -10,6 +10,7 @@ #include "fd-util.h" #include "hexdecoct.h" #include "io-util.h" +#include "iovec-util.h" #include "log.h" #include "memory-util.h" #include "os-util.h" diff --git a/src/import/pull-job.c b/src/import/pull-job.c index 69346ff477..4c3fb05dd3 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -6,6 +6,8 @@ #include #include "alloc-util.h" +#include "compress.h" +#include "crypto-util.h" #include "curl-util.h" #include "fd-util.h" #include "format-util.h" @@ -57,7 +59,7 @@ PullJob* pull_job_unref(PullJob *j) { j->compress = compressor_free(j->compress); if (j->checksum_ctx) - EVP_MD_CTX_free(j->checksum_ctx); + sym_EVP_MD_CTX_free(j->checksum_ctx); free(j->url); free(j->etag); @@ -138,7 +140,7 @@ int pull_job_restart(PullJob *j, const char *new_url) { j->compress = compressor_free(j->compress); if (j->checksum_ctx) { - EVP_MD_CTX_free(j->checksum_ctx); + sym_EVP_MD_CTX_free(j->checksum_ctx); j->checksum_ctx = NULL; } @@ -279,7 +281,7 @@ void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) { goto finish; } - r = EVP_DigestFinal_ex(j->checksum_ctx, j->checksum.iov_base, &checksum_len); + r = sym_EVP_DigestFinal_ex(j->checksum_ctx, j->checksum.iov_base, &checksum_len); if (r == 0) { r = log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get checksum."); goto finish; @@ -294,7 +296,7 @@ void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) { goto finish; } - log_debug("%s of %s is %s.", EVP_MD_CTX_get0_name(j->checksum_ctx), pull_job_description(j), h); + log_debug("%s of %s is %s.", sym_EVP_MD_CTX_get0_name(j->checksum_ctx), pull_job_description(j), h); } if (iovec_is_set(&j->expected_checksum) && @@ -448,7 +450,7 @@ static int pull_job_write_compressed(PullJob *j, const struct iovec *data) { "Content length incorrect."); if (j->checksum_ctx) { - r = EVP_DigestUpdate(j->checksum_ctx, data->iov_base, data->iov_len); + r = sym_EVP_DigestUpdate(j->checksum_ctx, data->iov_base, data->iov_len); if (r == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Could not hash chunk."); @@ -485,11 +487,15 @@ static int pull_job_open_disk(PullJob *j) { } if (j->calc_checksum) { - j->checksum_ctx = EVP_MD_CTX_new(); + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + + j->checksum_ctx = sym_EVP_MD_CTX_new(); if (!j->checksum_ctx) return log_oom(); - r = EVP_DigestInit_ex(j->checksum_ctx, EVP_sha256(), NULL); + r = sym_EVP_DigestInit_ex(j->checksum_ctx, sym_EVP_sha256(), NULL); if (r == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to initialize hash context."); diff --git a/src/import/pull-job.h b/src/import/pull-job.h index 1daa006c1c..0b878292f0 100644 --- a/src/import/pull-job.h +++ b/src/import/pull-job.h @@ -3,9 +3,8 @@ #include #include +#include -#include "compress.h" -#include "openssl-util.h" #include "shared-forward.h" typedef struct CurlGlue CurlGlue; diff --git a/src/import/pull-oci.c b/src/import/pull-oci.c index f4878e3c87..acea93b09d 100644 --- a/src/import/pull-oci.c +++ b/src/import/pull-oci.c @@ -31,6 +31,7 @@ #include "pull-oci.h" #include "rm-rf.h" #include "set.h" +#include "sha256-fundamental.h" #include "signal-util.h" #include "stat-util.h" #include "string-util.h" diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index 6fde8c5f8b..0ddde7c091 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -13,6 +13,7 @@ #include "import-common.h" #include "import-util.h" #include "install-file.h" +#include "iovec-util.h" #include "log.h" #include "mkdir-label.h" #include "pull-common.h" diff --git a/src/keyutil/keyutil.c b/src/keyutil/keyutil.c index dcdd264226..01f27dcded 100644 --- a/src/keyutil/keyutil.c +++ b/src/keyutil/keyutil.c @@ -3,13 +3,13 @@ #include "alloc-util.h" #include "ask-password-api.h" #include "build.h" +#include "crypto-util.h" #include "fd-util.h" #include "fileio.h" #include "format-table.h" #include "fs-util.h" #include "log.h" #include "main-func.h" -#include "openssl-util.h" #include "options.h" #include "parse-argument.h" #include "pretty-print.h" @@ -240,6 +240,10 @@ static int verb_extract_public(int argc, char *argv[], uintptr_t _data, void *us return r; } + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + r = openssl_load_x509_certificate( arg_certificate_source_type, arg_certificate_source, @@ -248,7 +252,7 @@ static int verb_extract_public(int argc, char *argv[], uintptr_t _data, void *us if (r < 0) return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate); - public_key = X509_get_pubkey(certificate); + public_key = sym_X509_get_pubkey(certificate); if (!public_key) return log_error_errno( SYNTHETIC_ERRNO(EIO), @@ -288,7 +292,7 @@ static int verb_extract_public(int argc, char *argv[], uintptr_t _data, void *us } else return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "One of --certificate=, or --private-key= must be specified"); - if (PEM_write_PUBKEY(stdout, public_key) == 0) + if (sym_PEM_write_PUBKEY(stdout, public_key) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key to stdout"); return 0; @@ -317,7 +321,7 @@ static int verb_extract_certificate(int argc, char *argv[], uintptr_t _data, voi if (r < 0) return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate); - if (PEM_write_X509(stdout, certificate) == 0) + if (sym_PEM_write_X509(stdout, certificate) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write certificate to stdout."); return 0; @@ -376,18 +380,18 @@ static int verb_pkcs7(int argc, char *argv[], uintptr_t _data, void *userdata) { if (content_len == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Content file %s is empty", arg_content); - if (!PKCS7_content_new(pkcs7, NID_pkcs7_data)) + if (!sym_PKCS7_content_new(pkcs7, NID_pkcs7_data)) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Error creating new PKCS7 content field"); - ASN1_STRING_set0(pkcs7->d.sign->contents->d.data, TAKE_PTR(content), content_len); + sym_ASN1_STRING_set0(pkcs7->d.sign->contents->d.data, TAKE_PTR(content), content_len); } else - if (PKCS7_set_detached(pkcs7, true) == 0) + if (sym_PKCS7_set_detached(pkcs7, true) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS#7 detached attribute: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); /* Add PKCS1 signature to PKCS7_SIGNER_INFO */ - ASN1_STRING_set0(signer_info->enc_digest, TAKE_PTR(pkcs1), pkcs1_len); + sym_ASN1_STRING_set0(signer_info->enc_digest, TAKE_PTR(pkcs1), pkcs1_len); _cleanup_fclose_ FILE *output = NULL; _cleanup_(unlink_and_freep) char *tmp = NULL; @@ -395,9 +399,9 @@ static int verb_pkcs7(int argc, char *argv[], uintptr_t _data, void *userdata) { if (r < 0) return log_error_errno(r, "Failed to open temporary file: %m"); - if (!i2d_PKCS7_fp(output, pkcs7)) + if (!sym_i2d_PKCS7_fp(output, pkcs7)) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write PKCS#7 file: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); r = flink_tmpfile(output, tmp, arg_output, LINK_TMPFILE_REPLACE|LINK_TMPFILE_SYNC); if (r < 0) diff --git a/src/keyutil/meson.build b/src/keyutil/meson.build index 956f603989..ae3db9a276 100644 --- a/src/keyutil/meson.build +++ b/src/keyutil/meson.build @@ -7,6 +7,6 @@ executables += [ 'HAVE_OPENSSL', ], 'sources' : files('keyutil.c'), - 'dependencies' : libopenssl, + 'dependencies' : libopenssl_cflags, }, ] diff --git a/src/measure/measure-tool.c b/src/measure/measure-tool.c index 09c04d888c..44619cab7d 100644 --- a/src/measure/measure-tool.c +++ b/src/measure/measure-tool.c @@ -7,6 +7,7 @@ #include "alloc-util.h" #include "ask-password-api.h" #include "build.h" +#include "crypto-util.h" #include "efi-loader.h" #include "efivars.h" #include "fd-util.h" @@ -15,7 +16,6 @@ #include "hexdecoct.h" #include "log.h" #include "main-func.h" -#include "openssl-util.h" #include "options.h" #include "pager.h" #include "parse-argument.h" @@ -178,11 +178,15 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { "Select TPM bank (SHA1, SHA256, SHA384, SHA512)"): { const EVP_MD *implementation; - implementation = EVP_get_digestbyname(arg); + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + + implementation = sym_EVP_get_digestbyname(arg); if (!implementation) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown bank '%s', refusing.", arg); - if (strv_extend(&arg_banks, EVP_MD_name(implementation)) < 0) + if (strv_extend(&arg_banks, sym_EVP_MD_get0_name(implementation)) < 0) return log_oom(); break; @@ -529,7 +533,7 @@ static void evp_md_ctx_free_all(EVP_MD_CTX **md[]) { return; for (size_t i = 0; (*md)[i]; i++) - EVP_MD_CTX_free((*md)[i]); + sym_EVP_MD_CTX_free((*md)[i]); *md = mfree(*md); } @@ -546,22 +550,22 @@ static int pcr_state_extend(PcrState *pcr_state, const void *data, size_t sz) { /* Extends a (virtual) PCR by the given data */ - mc = EVP_MD_CTX_new(); + mc = sym_EVP_MD_CTX_new(); if (!mc) return log_oom(); - if (EVP_DigestInit_ex(mc, pcr_state->md, NULL) != 1) + if (sym_EVP_DigestInit_ex(mc, pcr_state->md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize %s context.", pcr_state->bank); /* First thing we do, is hash the old PCR value */ - if (EVP_DigestUpdate(mc, pcr_state->value, pcr_state->value_size) != 1) + if (sym_EVP_DigestUpdate(mc, pcr_state->value, pcr_state->value_size) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to run digest."); /* Then, we hash the new data */ - if (EVP_DigestUpdate(mc, data, sz) != 1) + if (sym_EVP_DigestUpdate(mc, data, sz) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to run digest."); - if (EVP_DigestFinal_ex(mc, pcr_state->value, &value_size) != 1) + if (sym_EVP_DigestFinal_ex(mc, pcr_state->value, &value_size) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finalize hash context."); assert(value_size == pcr_state->value_size); @@ -629,11 +633,11 @@ static int measure_kernel(PcrState *pcr_states, size_t n) { return log_oom(); for (size_t i = 0; i < n; i++) { - mdctx[i] = EVP_MD_CTX_new(); + mdctx[i] = sym_EVP_MD_CTX_new(); if (!mdctx[i]) return log_oom(); - if (EVP_DigestInit_ex(mdctx[i], pcr_states[i].md, NULL) != 1) + if (sym_EVP_DigestInit_ex(mdctx[i], pcr_states[i].md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize data %s context.", pcr_states[i].bank); } @@ -648,7 +652,7 @@ static int measure_kernel(PcrState *pcr_states, size_t n) { break; for (size_t i = 0; i < n; i++) - if (EVP_DigestUpdate(mdctx[i], buffer, sz) != 1) + if (sym_EVP_DigestUpdate(mdctx[i], buffer, sz) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to run digest."); m += sz; @@ -668,7 +672,7 @@ static int measure_kernel(PcrState *pcr_states, size_t n) { return log_oom(); /* Measure name of section */ - if (EVP_Digest(unified_sections[c], strlen(unified_sections[c]) + 1, data_hash, &data_hash_size, pcr_states[i].md, NULL) != 1) + if (sym_EVP_Digest(unified_sections[c], strlen(unified_sections[c]) + 1, data_hash, &data_hash_size, pcr_states[i].md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to hash section name with %s.", pcr_states[i].bank); assert(data_hash_size == (unsigned) pcr_states[i].value_size); @@ -678,7 +682,7 @@ static int measure_kernel(PcrState *pcr_states, size_t n) { return r; /* Retrieve hash of data and measure it */ - if (EVP_DigestFinal_ex(mdctx[i], data_hash, &data_hash_size) != 1) + if (sym_EVP_DigestFinal_ex(mdctx[i], data_hash, &data_hash_size) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finalize hash context."); assert(data_hash_size == (unsigned) pcr_states[i].value_size); @@ -719,7 +723,7 @@ static int measure_phase(PcrState *pcr_states, size_t n, const char *phase) { _cleanup_free_ void *b = NULL; int bsz; - bsz = EVP_MD_size(pcr_states[i].md); + bsz = sym_EVP_MD_get_size(pcr_states[i].md); assert(bsz > 0); b = malloc(bsz); @@ -727,7 +731,7 @@ static int measure_phase(PcrState *pcr_states, size_t n, const char *phase) { return log_oom(); /* First hash the word itself */ - if (EVP_Digest(*word, wl, b, NULL, pcr_states[i].md, NULL) != 1) + if (sym_EVP_Digest(*word, wl, b, NULL, pcr_states[i].md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash word '%s'.", *word); /* And then extend the PCR with the resulting hash */ @@ -757,13 +761,13 @@ static int pcr_states_allocate(PcrState **ret) { _cleanup_free_ char *b = NULL; int sz; - assert_se(implementation = EVP_get_digestbyname(*d)); /* Must work, we already checked while parsing command line */ + assert_se(implementation = sym_EVP_get_digestbyname(*d)); /* Must work, we already checked while parsing command line */ - b = strdup(EVP_MD_name(implementation)); + b = strdup(sym_EVP_MD_get0_name(implementation)); if (!b) return log_oom(); - sz = EVP_MD_size(implementation); + sz = sym_EVP_MD_get_size(implementation); if (sz <= 0 || sz >= INT_MAX) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unexpected digest size: %i", sz); @@ -986,11 +990,11 @@ static int build_policy_digest(bool sign) { if (!pubkeyf) return log_error_errno(errno, "Failed to open public key file '%s': %m", arg_public_key); - pubkey = PEM_read_PUBKEY(pubkeyf, NULL, NULL, NULL); + pubkey = sym_PEM_read_PUBKEY(pubkeyf, NULL, NULL, NULL); if (!pubkey) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse public key '%s'.", arg_public_key); } else if (certificate) { - pubkey = X509_get_pubkey(certificate); + pubkey = sym_X509_get_pubkey(certificate); if (!pubkey) return log_error_errno( SYNTHETIC_ERRNO(EIO), @@ -1026,7 +1030,7 @@ static int build_policy_digest(bool sign) { for (size_t i = 0; i < n; i++) { PcrState *p = pcr_states + i; - int tpmalg = tpm2_hash_alg_from_string(EVP_MD_name(p->md)); + int tpmalg = tpm2_hash_alg_from_string(sym_EVP_MD_get0_name(p->md)); if (tpmalg < 0) return log_error_errno(tpmalg, "Unsupported PCR bank"); @@ -1044,19 +1048,19 @@ static int build_policy_digest(bool sign) { size_t ss = 0; if (privkey) { /* We always use SHA256 for signing currently. Regardless of the bank. */ - const EVP_MD *sha256 = ASSERT_PTR(EVP_get_digestbyname("sha256")); + const EVP_MD *sha256 = ASSERT_PTR(sym_EVP_get_digestbyname("sha256")); r = digest_and_sign(sha256, privkey, pcr_policy_digest.buffer, pcr_policy_digest.size, &sig, &ss); if (r == -EADDRNOTAVAIL) - return log_error_errno(r, "Hash algorithm '%s' not available while signing. (Maybe OS security policy disables this algorithm?)", EVP_MD_name(p->md)); + return log_error_errno(r, "Hash algorithm '%s' not available while signing. (Maybe OS security policy disables this algorithm?)", sym_EVP_MD_get0_name(p->md)); if (r < 0) - return log_error_errno(r, "Failed to sign PCR policy with hash algorithm '%s': %m", EVP_MD_name(p->md)); + return log_error_errno(r, "Failed to sign PCR policy with hash algorithm '%s': %m", sym_EVP_MD_get0_name(p->md)); } _cleanup_free_ void *pubkey_fp = NULL; size_t pubkey_fp_size = 0; if (pubkey) { - r = pubkey_fingerprint(pubkey, EVP_sha256(), &pubkey_fp, &pubkey_fp_size); + r = pubkey_fingerprint(pubkey, sym_EVP_sha256(), &pubkey_fp, &pubkey_fp_size); if (r < 0) return r; } @@ -1121,6 +1125,10 @@ static int run(int argc, char *argv[]) { if (r <= 0) return r; + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + return dispatch_verb_with_args(args, NULL); } diff --git a/src/measure/meson.build b/src/measure/meson.build index e4e4f579df..ff777dc5d9 100644 --- a/src/measure/meson.build +++ b/src/measure/meson.build @@ -9,6 +9,6 @@ executables += [ 'HAVE_TPM2', ], 'sources' : files('measure-tool.c'), - 'dependencies' : libopenssl, + 'dependencies' : libopenssl_cflags, }, ] diff --git a/src/pcrextend/meson.build b/src/pcrextend/meson.build index 3a8824eaa8..f2f5f3b46e 100644 --- a/src/pcrextend/meson.build +++ b/src/pcrextend/meson.build @@ -11,7 +11,7 @@ executables += [ ], 'sources' : files('pcrextend.c'), 'dependencies' : [ - libopenssl, + libopenssl_cflags, tpm2, ], }, diff --git a/src/pcrextend/pcrextend.c b/src/pcrextend/pcrextend.c index 639331ba97..c92d3f9811 100644 --- a/src/pcrextend/pcrextend.c +++ b/src/pcrextend/pcrextend.c @@ -6,6 +6,7 @@ #include "alloc-util.h" #include "build.h" +#include "crypto-util.h" #include "efi-loader.h" #include "escape.h" #include "format-table.h" @@ -96,11 +97,15 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) { OPTION_LONG("bank", "DIGEST", "Select TPM PCR bank (SHA1, SHA256)"): { const EVP_MD *implementation; - implementation = EVP_get_digestbyname(arg); + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + + implementation = sym_EVP_get_digestbyname(arg); if (!implementation) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown bank '%s', refusing.", arg); - if (strv_extend(&arg_banks, EVP_MD_name(implementation)) < 0) + if (strv_extend(&arg_banks, sym_EVP_MD_get0_name(implementation)) < 0) return log_oom(); break; diff --git a/src/pcrlock/meson.build b/src/pcrlock/meson.build index c5b609ed4a..a80cd31947 100644 --- a/src/pcrlock/meson.build +++ b/src/pcrlock/meson.build @@ -13,7 +13,7 @@ executables += [ ), 'dependencies' : [ libm, - libopenssl, + libopenssl_cflags, tpm2, ], 'public' : true, diff --git a/src/pcrlock/pcrlock-firmware.c b/src/pcrlock/pcrlock-firmware.c index 81481dc168..5abf66077e 100644 --- a/src/pcrlock/pcrlock-firmware.c +++ b/src/pcrlock/pcrlock-firmware.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include - +#include "crypto-util.h" #include "log.h" #include "memory-util.h" #include "pcrlock-firmware.h" @@ -149,13 +148,13 @@ int validate_firmware_header( continue; } - implementation = EVP_get_digestbyname(a); + implementation = sym_EVP_get_digestbyname(a); if (!implementation) { log_notice("Event log advertises hash algorithm '%s' we don't implement, can't validate.", a); continue; } - if (EVP_MD_size(implementation) != id->digestSizes[i].digestSize) + if (sym_EVP_MD_get_size(implementation) != id->digestSizes[i].digestSize) return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Advertised digest size for '%s' is wrong, refusing.", a); } diff --git a/src/pcrlock/pcrlock.c b/src/pcrlock/pcrlock.c index 62a84a26cb..ecf7b18c35 100644 --- a/src/pcrlock/pcrlock.c +++ b/src/pcrlock/pcrlock.c @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include #include #include @@ -18,6 +17,7 @@ #include "color-util.h" #include "conf-files.h" #include "creds-util.h" +#include "crypto-util.h" #include "efi-api.h" #include "efivars.h" #include "env-util.h" @@ -1346,7 +1346,7 @@ static int event_log_calculate_pcrs(EventLog *el) { const char *a; assert_se(a = tpm2_hash_alg_to_string(el->algorithms[i])); - assert_se(md = EVP_get_digestbyname(a)); + assert_se(md = sym_EVP_get_digestbyname(a)); el->mds[i] = md; } @@ -1354,7 +1354,7 @@ static int event_log_calculate_pcrs(EventLog *el) { for (uint32_t pcr = 0; pcr < TPM2_PCRS_MAX; pcr++) for (size_t i = 0; i < el->n_algorithms; i++) { EventLogRegisterBank *b = el->registers[pcr].banks + i; - event_log_initial_pcr_state(el, pcr, EVP_MD_size(el->mds[i]), &b->calculated); + event_log_initial_pcr_state(el, pcr, sym_EVP_MD_get_size(el->mds[i]), &b->calculated); } FOREACH_ARRAY(rr, el->records, el->n_records) { @@ -1379,20 +1379,20 @@ static int event_log_calculate_pcrs(EventLog *el) { reg_b = reg->banks + i; - mc = EVP_MD_CTX_new(); + mc = sym_EVP_MD_CTX_new(); if (!mc) return log_oom(); - if (EVP_DigestInit_ex(mc, el->mds[i], NULL) != 1) + if (sym_EVP_DigestInit_ex(mc, el->mds[i], NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize %s message digest context.", n); - if (EVP_DigestUpdate(mc, reg_b->calculated.buffer, reg_b->calculated.size) != 1) + if (sym_EVP_DigestUpdate(mc, reg_b->calculated.buffer, reg_b->calculated.size) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to run digest."); - if (EVP_DigestUpdate(mc, rec_b->hash.buffer, rec_b->hash.size) != 1) + if (sym_EVP_DigestUpdate(mc, rec_b->hash.buffer, rec_b->hash.size) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to run digest."); - if (EVP_DigestFinal_ex(mc, reg_b->calculated.buffer, &sz) != 1) + if (sym_EVP_DigestFinal_ex(mc, reg_b->calculated.buffer, &sz) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finalize hash context."); assert(sz == reg_b->calculated.size); @@ -1481,7 +1481,7 @@ static int event_log_record_validate_hash_firmware( strict = false; } - int mdsz = EVP_MD_size(md); + int mdsz = sym_EVP_MD_get_size(md); assert(mdsz > 0); assert((size_t) mdsz <= sizeof_field(TPM2B_DIGEST, buffer)); @@ -1491,13 +1491,13 @@ static int event_log_record_validate_hash_firmware( unsigned dsz = mdsz; - if (EVP_Digest(hdata, hsz, payload_hash.buffer, &dsz, md, NULL) != 1) + if (sym_EVP_Digest(hdata, hsz, payload_hash.buffer, &dsz, md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to calculate event payload hash."); assert(dsz == (unsigned) mdsz); /* If this didn't match then let's try the alternative format here, if we have one, and check things then. */ if (memcmp_nn(bank->hash.buffer, bank->hash.size, payload_hash.buffer, payload_hash.size) != 0 && hdata_alternative) { - if (EVP_Digest(hdata_alternative, hsz_alternative, payload_hash.buffer, &dsz, md, NULL) != 1) + if (sym_EVP_Digest(hdata_alternative, hsz_alternative, payload_hash.buffer, &dsz, md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to calculate event payload hash."); assert(dsz == (unsigned) mdsz); } @@ -1541,7 +1541,7 @@ static int event_log_record_validate_hash_userspace( assert(sd_json_variant_is_string(js)); s = sd_json_variant_string(js); - mdsz = EVP_MD_size(md); + mdsz = sym_EVP_MD_get_size(md); assert(mdsz > 0); payload_hash_size = mdsz; @@ -1549,7 +1549,7 @@ static int event_log_record_validate_hash_userspace( if (!payload_hash) return log_oom(); - if (EVP_Digest(s, strlen(s), payload_hash, &payload_hash_size, md, NULL) != 1) + if (sym_EVP_Digest(s, strlen(s), payload_hash, &payload_hash_size, md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to calculate event payload hash."); assert((int) payload_hash_size == mdsz); @@ -1575,7 +1575,7 @@ static int event_log_validate_record_hashes(EventLog *el) { const char *a; assert_se(a = tpm2_hash_alg_to_string(bank->algorithm)); - assert_se(md = EVP_get_digestbyname(a)); + assert_se(md = sym_EVP_get_digestbyname(a)); r = event_log_record_validate_hash_firmware(*rr, bank, md); if (r < 0) @@ -2788,8 +2788,8 @@ static int make_pcrlock_record( const char *a; assert_se(a = tpm2_hash_alg_to_string(*pa)); - assert_se(md = EVP_get_digestbyname(a)); - hash_ssize = EVP_MD_size(md); + assert_se(md = sym_EVP_get_digestbyname(a)); + hash_ssize = sym_EVP_MD_get_size(md); assert(hash_ssize > 0); hash_usize = hash_ssize; @@ -2797,7 +2797,7 @@ static int make_pcrlock_record( if (!hash) return log_oom(); - if (EVP_Digest(data, data_size, hash, &hash_usize, md, NULL) != 1) + if (sym_EVP_Digest(data, data_size, hash, &hash_usize, md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data with algorithm '%s'.", a); r = sd_json_variant_append_arraybo( @@ -2821,7 +2821,7 @@ static void evp_md_ctx_free_all(EVP_MD_CTX *(*md)[TPM2_N_HASH_ALGORITHMS]) { assert(md); FOREACH_ARRAY(alg, *md, TPM2_N_HASH_ALGORITHMS) if (*alg) - EVP_MD_CTX_free(*alg); + sym_EVP_MD_CTX_free(*alg); } static int make_pcrlock_record_from_stream( @@ -2841,13 +2841,13 @@ static int make_pcrlock_record_from_stream( const EVP_MD *md; assert_se(a = tpm2_hash_alg_to_string(tpm2_hash_algorithms[i])); - assert_se(md = EVP_get_digestbyname(a)); + assert_se(md = sym_EVP_get_digestbyname(a)); - mdctx[i] = EVP_MD_CTX_new(); + mdctx[i] = sym_EVP_MD_CTX_new(); if (!mdctx[i]) return log_oom(); - if (EVP_DigestInit_ex(mdctx[i], md, NULL) != 1) + if (sym_EVP_DigestInit_ex(mdctx[i], md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to initialize message digest for %s.", a); } @@ -2863,7 +2863,7 @@ static int make_pcrlock_record_from_stream( break; for (size_t i = 0; i < TPM2_N_HASH_ALGORITHMS; i++) - if (EVP_DigestUpdate(mdctx[i], buffer, n) != 1) + if (sym_EVP_DigestUpdate(mdctx[i], buffer, n) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to hash data."); } @@ -2873,12 +2873,12 @@ static int make_pcrlock_record_from_stream( unsigned hash_usize; assert_se(a = tpm2_hash_alg_to_string(tpm2_hash_algorithms[i])); - hash_ssize = EVP_MD_CTX_size(mdctx[i]); + hash_ssize = sym_EVP_MD_CTX_get_size(mdctx[i]); assert(hash_ssize > 0 && hash_ssize <= EVP_MAX_MD_SIZE); hash_usize = hash_ssize; unsigned char hash[hash_usize]; - if (EVP_DigestFinal_ex(mdctx[i], hash, &hash_usize) != 1) + if (sym_EVP_DigestFinal_ex(mdctx[i], hash, &hash_usize) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to finalize hash context for algorithn '%s'.", a); @@ -3072,7 +3072,7 @@ static const EVP_MD* evp_from_tpm2_alg(uint16_t alg) { if (!name) return NULL; - return EVP_get_digestbyname(name); + return sym_EVP_get_digestbyname(name); } static int event_log_component_variant_calculate( @@ -3106,13 +3106,13 @@ static int event_log_component_variant_calculate( continue; } - md_ctx = EVP_MD_CTX_new(); + md_ctx = sym_EVP_MD_CTX_new(); if (!md_ctx) return log_oom(); const EVP_MD *md = ASSERT_PTR(evp_from_tpm2_alg(tpm2_hash_algorithms[i])); - int sz = EVP_MD_size(md); + int sz = sym_EVP_MD_get_size(md); assert(sz > 0); assert((size_t) sz <= sizeof_field(TPM2B_DIGEST, buffer)); @@ -3121,17 +3121,17 @@ static int event_log_component_variant_calculate( assert(result->hash[i].size == (size_t) sz); assert(b->hash.size == (size_t) sz); - if (EVP_DigestInit_ex(md_ctx, md, NULL) != 1) + if (sym_EVP_DigestInit_ex(md_ctx, md, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to initialize message digest."); - if (EVP_DigestUpdate(md_ctx, result->hash[i].buffer, sz) != 1) + if (sym_EVP_DigestUpdate(md_ctx, result->hash[i].buffer, sz) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash bank value."); - if (EVP_DigestUpdate(md_ctx, b->hash.buffer, sz) != 1) + if (sym_EVP_DigestUpdate(md_ctx, b->hash.buffer, sz) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data value."); unsigned l = (unsigned) sz; - if (EVP_DigestFinal_ex(md_ctx, result->hash[i].buffer, &l) != 1) + if (sym_EVP_DigestFinal_ex(md_ctx, result->hash[i].buffer, &l) != 1) return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to finalize message digest."); assert(l == (unsigned) sz); @@ -4749,7 +4749,7 @@ static int verb_lock_pe(int argc, char *argv[], uintptr_t _data, void *userdata) const char *a; assert_se(a = tpm2_hash_alg_to_string(*pa)); - assert_se(md = EVP_get_digestbyname(a)); + assert_se(md = sym_EVP_get_digestbyname(a)); r = pe_hash(fd < 0 ? STDIN_FILENO : fd, md, &hash, &hash_size); if (r < 0) @@ -4813,7 +4813,7 @@ static int verb_lock_uki(int argc, char *argv[], uintptr_t _data, void *userdata const char *a; assert_se(a = tpm2_hash_alg_to_string(tpm2_hash_algorithms[i])); - assert_se(md = EVP_get_digestbyname(a)); + assert_se(md = sym_EVP_get_digestbyname(a)); r = pe_hash(fd < 0 ? STDIN_FILENO : fd, md, &peh, hash_sizes + i); if (r < 0) @@ -5472,6 +5472,10 @@ static int run(int argc, char *argv[]) { if (r <= 0) return r; + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + if (arg_varlink) { _cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL; diff --git a/src/repart/meson.build b/src/repart/meson.build index b7c70be068..9b89f56f7a 100644 --- a/src/repart/meson.build +++ b/src/repart/meson.build @@ -16,7 +16,7 @@ executables += [ libblkid_cflags, libfdisk_cflags, libmount_cflags, - libopenssl, + libopenssl_cflags, threads, ], }, @@ -34,7 +34,7 @@ executables += [ libblkid_cflags, libfdisk_cflags, libmount_cflags, - libopenssl, + libopenssl_cflags, threads, ], }, diff --git a/src/repart/repart.c b/src/repart/repart.c index e585313713..0aab755d2c 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -24,6 +24,7 @@ #include "conf-parser.h" #include "constants.h" #include "copy.h" +#include "crypto-util.h" #include "cryptsetup-util.h" #include "device-util.h" #include "devnum-util.h" @@ -59,7 +60,6 @@ #include "mount-util.h" #include "mountpoint-util.h" #include "nulstr-util.h" -#include "openssl-util.h" #include "options.h" #include "parse-argument.h" #include "parse-helpers.h" @@ -985,9 +985,11 @@ static Context* context_free(Context *context) { free(context->node); #if HAVE_OPENSSL - X509_free(context->certificate); + if (context->certificate) + sym_X509_free(context->certificate); openssl_ask_password_ui_free(context->ui); - EVP_PKEY_free(context->private_key); + if (context->private_key) + sym_EVP_PKEY_free(context->private_key); #endif context->link = sd_varlink_unref(context->link); @@ -5826,7 +5828,7 @@ static int sign_verity_roothash( _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL; _cleanup_free_ char *hex = NULL; _cleanup_free_ uint8_t *sig = NULL; - int sigsz; + int sigsz, r; assert(context); assert(context->certificate); @@ -5835,23 +5837,27 @@ static int sign_verity_roothash( assert(iovec_is_set(roothash)); assert(ret_signature); + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + hex = hexmem(roothash->iov_base, roothash->iov_len); if (!hex) return log_oom(); - rb = BIO_new_mem_buf(hex, -1); + rb = sym_BIO_new_mem_buf(hex, -1); if (!rb) return log_oom(); - p7 = PKCS7_sign(context->certificate, context->private_key, NULL, rb, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY); + p7 = sym_PKCS7_sign(context->certificate, context->private_key, NULL, rb, PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY); if (!p7) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to calculate PKCS7 signature: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - sigsz = i2d_PKCS7(p7, &sig); + sigsz = sym_i2d_PKCS7(p7, &sig); if (sigsz < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert PKCS7 signature to DER: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); *ret_signature = IOVEC_MAKE(TAKE_PTR(sig), sigsz); diff --git a/src/resolve/meson.build b/src/resolve/meson.build index b9b2e24b18..5802889746 100644 --- a/src/resolve/meson.build +++ b/src/resolve/meson.build @@ -70,7 +70,7 @@ endif resolve_common_template = { 'dependencies' : [ libidn2_cflags, - libopenssl, + libopenssl_cflags, libm, threads, ], diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c index 8cc9e73f93..1452131b59 100644 --- a/src/resolve/resolvectl.c +++ b/src/resolve/resolvectl.c @@ -20,6 +20,7 @@ #include "bus-locator.h" #include "bus-message-util.h" #include "bus-util.h" +#include "crypto-util.h" #include "dns-configuration.h" #include "dns-domain.h" #include "dns-packet.h" @@ -34,7 +35,6 @@ #include "main-func.h" #include "missing-network.h" #include "netlink-util.h" -#include "openssl-util.h" #include "ordered-set.h" #include "pager.h" #include "parse-argument.h" diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 1a634810be..017c370b0e 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -2,6 +2,7 @@ #include "alloc-util.h" #include "bitmap.h" +#include "crypto-util.h" #include "dns-answer.h" #include "dns-domain.h" #include "dns-rr.h" @@ -10,19 +11,12 @@ #include "log.h" #include "memory-util.h" #include "memstream-util.h" -#include "openssl-util.h" #include "resolved-dns-dnssec.h" #include "sort-util.h" #include "string-table.h" #include "string-util.h" #include "time-util.h" -#if HAVE_OPENSSL -DISABLE_WARNING_DEPRECATED_DECLARATIONS; -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(RSA*, RSA_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY*, EC_KEY_free, NULL); -REENABLE_WARNING; -#endif #define VERIFY_RRS_MAX 256 #define MAX_KEY_SIZE (32*1024) @@ -84,49 +78,49 @@ static int dnssec_rsa_verify_raw( assert(hash_algorithm); - e = BN_bin2bn(exponent, exponent_size, NULL); + e = sym_BN_bin2bn(exponent, exponent_size, NULL); if (!e) return -EIO; - m = BN_bin2bn(modulus, modulus_size, NULL); + m = sym_BN_bin2bn(modulus, modulus_size, NULL); if (!m) return -EIO; - rpubkey = RSA_new(); + rpubkey = sym_RSA_new(); if (!rpubkey) return -ENOMEM; - if (RSA_set0_key(rpubkey, m, e, NULL) <= 0) + if (sym_RSA_set0_key(rpubkey, m, e, NULL) <= 0) return -EIO; e = m = NULL; - if ((size_t) RSA_size(rpubkey) != signature_size) + if ((size_t) sym_RSA_size(rpubkey) != signature_size) return -EINVAL; - epubkey = EVP_PKEY_new(); + epubkey = sym_EVP_PKEY_new(); if (!epubkey) return -ENOMEM; - if (EVP_PKEY_assign_RSA(epubkey, RSAPublicKey_dup(rpubkey)) <= 0) + if (sym_EVP_PKEY_assign_RSA(epubkey, sym_RSAPublicKey_dup(rpubkey)) <= 0) return -EIO; - ctx = EVP_PKEY_CTX_new(epubkey, NULL); + ctx = sym_EVP_PKEY_CTX_new(epubkey, NULL); if (!ctx) return -ENOMEM; - if (EVP_PKEY_verify_init(ctx) <= 0) + if (sym_EVP_PKEY_verify_init(ctx) <= 0) return -EIO; - if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) + if (sym_EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) return -EIO; - if (EVP_PKEY_CTX_set_signature_md(ctx, hash_algorithm) <= 0) + if (sym_EVP_PKEY_CTX_set_signature_md(ctx, hash_algorithm) <= 0) return -EIO; - r = EVP_PKEY_verify(ctx, signature, signature_size, data, data_size); + r = sym_EVP_PKEY_verify(ctx, signature, signature_size, data, data_size); if (r < 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), - "Signature verification failed: 0x%lx", ERR_get_error()); + "Signature verification failed: 0x%lx", sym_ERR_get_error()); REENABLE_WARNING; return r; @@ -207,58 +201,58 @@ static int dnssec_ecdsa_verify_raw( assert(hash_algorithm); - ec_group = EC_GROUP_new_by_curve_name(curve); + ec_group = sym_EC_GROUP_new_by_curve_name(curve); if (!ec_group) return -ENOMEM; - p = EC_POINT_new(ec_group); + p = sym_EC_POINT_new(ec_group); if (!p) return -ENOMEM; - bctx = BN_CTX_new(); + bctx = sym_BN_CTX_new(); if (!bctx) return -ENOMEM; - if (EC_POINT_oct2point(ec_group, p, key, key_size, bctx) <= 0) + if (sym_EC_POINT_oct2point(ec_group, p, key, key_size, bctx) <= 0) return -EIO; - eckey = EC_KEY_new(); + eckey = sym_EC_KEY_new(); if (!eckey) return -ENOMEM; - if (EC_KEY_set_group(eckey, ec_group) <= 0) + if (sym_EC_KEY_set_group(eckey, ec_group) <= 0) return -EIO; - if (EC_KEY_set_public_key(eckey, p) <= 0) + if (sym_EC_KEY_set_public_key(eckey, p) <= 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), - "EC_KEY_set_public_key failed: 0x%lx", ERR_get_error()); + "EC_KEY_set_public_key failed: 0x%lx", sym_ERR_get_error()); - if (EC_KEY_check_key(eckey) != 1) + if (sym_EC_KEY_check_key(eckey) != 1) return log_debug_errno(SYNTHETIC_ERRNO(EIO), - "EC_KEY_check_key failed: 0x%lx", ERR_get_error()); + "EC_KEY_check_key failed: 0x%lx", sym_ERR_get_error()); - r = BN_bin2bn(signature_r, signature_r_size, NULL); + r = sym_BN_bin2bn(signature_r, signature_r_size, NULL); if (!r) return -EIO; - s = BN_bin2bn(signature_s, signature_s_size, NULL); + s = sym_BN_bin2bn(signature_s, signature_s_size, NULL); if (!s) return -EIO; /* TODO: We should eventually use the EVP API once it supports ECDSA signature verification */ - sig = ECDSA_SIG_new(); + sig = sym_ECDSA_SIG_new(); if (!sig) return -ENOMEM; - if (ECDSA_SIG_set0(sig, r, s) <= 0) + if (sym_ECDSA_SIG_set0(sig, r, s) <= 0) return -EIO; r = s = NULL; - k = ECDSA_do_verify(data, data_size, sig, eckey); + k = sym_ECDSA_do_verify(data, data_size, sig, eckey); if (k < 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), - "Signature verification failed: 0x%lx", ERR_get_error()); + "Signature verification failed: 0x%lx", sym_ERR_get_error()); REENABLE_WARNING; return k; @@ -326,30 +320,30 @@ static int dnssec_eddsa_verify_raw( q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */ memcpy(q+1, signature, signature_size); - evkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, key, key_size); + evkey = sym_EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, key, key_size); if (!evkey) return log_debug_errno(SYNTHETIC_ERRNO(EIO), - "EVP_PKEY_new_raw_public_key failed: 0x%lx", ERR_get_error()); + "EVP_PKEY_new_raw_public_key failed: 0x%lx", sym_ERR_get_error()); - pctx = EVP_PKEY_CTX_new(evkey, NULL); + pctx = sym_EVP_PKEY_CTX_new(evkey, NULL); if (!pctx) return -ENOMEM; - ctx = EVP_MD_CTX_new(); + ctx = sym_EVP_MD_CTX_new(); if (!ctx) return -ENOMEM; /* This prevents EVP_DigestVerifyInit from managing pctx and complicating our free logic. */ - EVP_MD_CTX_set_pkey_ctx(ctx, pctx); + sym_EVP_MD_CTX_set_pkey_ctx(ctx, pctx); /* One might be tempted to use EVP_PKEY_verify_init, but see Ed25519(7ssl). */ - if (EVP_DigestVerifyInit(ctx, &pctx, NULL, NULL, evkey) <= 0) + if (sym_EVP_DigestVerifyInit(ctx, &pctx, NULL, NULL, evkey) <= 0) return -EIO; - r = EVP_DigestVerify(ctx, signature, signature_size, data, data_size); + r = sym_EVP_DigestVerify(ctx, signature, signature_size, data, data_size); if (r < 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), - "Signature verification failed: 0x%lx", ERR_get_error()); + "Signature verification failed: 0x%lx", sym_ERR_get_error()); return r; } @@ -382,12 +376,12 @@ static int dnssec_eddsa_verify( } static int md_add_uint8(EVP_MD_CTX *ctx, uint8_t v) { - return EVP_DigestUpdate(ctx, &v, sizeof(v)); + return sym_EVP_DigestUpdate(ctx, &v, sizeof(v)); } static int md_add_uint16(EVP_MD_CTX *ctx, uint16_t v) { v = htobe16(v); - return EVP_DigestUpdate(ctx, &v, sizeof(v)); + return sym_EVP_DigestUpdate(ctx, &v, sizeof(v)); } static void fwrite_uint8(FILE *fp, uint8_t v) { @@ -504,17 +498,17 @@ static const EVP_MD* algorithm_to_implementation_id(uint8_t algorithm) { case DNSSEC_ALGORITHM_RSASHA1: case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1: - return EVP_sha1(); + return sym_EVP_sha1(); case DNSSEC_ALGORITHM_RSASHA256: case DNSSEC_ALGORITHM_ECDSAP256SHA256: - return EVP_sha256(); + return sym_EVP_sha256(); case DNSSEC_ALGORITHM_ECDSAP384SHA384: - return EVP_sha384(); + return sym_EVP_sha384(); case DNSSEC_ALGORITHM_RSASHA512: - return EVP_sha512(); + return sym_EVP_sha512(); default: return NULL; @@ -645,19 +639,19 @@ static int dnssec_rrset_verify_sig( if (!md_algorithm) return -EOPNOTSUPP; - _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = sym_EVP_MD_CTX_new(); if (!ctx) return -ENOMEM; /* If the signature algorithm is supported by systemd-resolved but disabled by host policy, * also return -EOPNOTSUPP. */ - if (EVP_DigestInit_ex(ctx, md_algorithm, NULL) <= 0) + if (sym_EVP_DigestInit_ex(ctx, md_algorithm, NULL) <= 0) return -EOPNOTSUPP; - if (EVP_DigestUpdate(ctx, sig_data, sig_size) <= 0) + if (sym_EVP_DigestUpdate(ctx, sig_data, sig_size) <= 0) return -EIO; - if (EVP_DigestFinal_ex(ctx, hash, &hash_size) <= 0) + if (sym_EVP_DigestFinal_ex(ctx, hash, &hash_size) <= 0) return -EIO; assert(hash_size > 0); @@ -709,6 +703,11 @@ int dnssec_verify_rrset( assert(rrsig); assert(dnskey); assert(result); + + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + assert(rrsig->key->type == DNS_TYPE_RRSIG); assert(dnskey->key->type == DNS_TYPE_DNSKEY); @@ -1041,13 +1040,13 @@ static const EVP_MD* digest_to_hash_md(uint8_t algorithm) { switch (algorithm) { case DNSSEC_DIGEST_SHA1: - return EVP_sha1(); + return sym_EVP_sha1(); case DNSSEC_DIGEST_SHA256: - return EVP_sha256(); + return sym_EVP_sha256(); case DNSSEC_DIGEST_SHA384: - return EVP_sha384(); + return sym_EVP_sha384(); default: return NULL; @@ -1062,6 +1061,10 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, assert(dnskey); assert(ds); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */ if (dnskey->key->type != DNS_TYPE_DNSKEY) @@ -1092,22 +1095,22 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = NULL; uint8_t result[EVP_MAX_MD_SIZE]; - unsigned hash_size = EVP_MD_size(md_algorithm); + unsigned hash_size = sym_EVP_MD_get_size(md_algorithm); assert(hash_size > 0); if (ds->ds.digest_size != hash_size) return 0; - ctx = EVP_MD_CTX_new(); + ctx = sym_EVP_MD_CTX_new(); if (!ctx) return -ENOMEM; /* If the digest is supported by systemd-resolved but disabled by host policy, also return -EOPNOTSUPP */ - if (EVP_DigestInit_ex(ctx, md_algorithm, NULL) <= 0) + if (sym_EVP_DigestInit_ex(ctx, md_algorithm, NULL) <= 0) return -EOPNOTSUPP; - if (EVP_DigestUpdate(ctx, wire_format, encoded_length) <= 0) + if (sym_EVP_DigestUpdate(ctx, wire_format, encoded_length) <= 0) return -EIO; if (mask_revoke) @@ -1121,10 +1124,10 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, r = md_add_uint8(ctx, dnskey->dnskey.algorithm); if (r <= 0) return r; - if (EVP_DigestUpdate(ctx, dnskey->dnskey.key, dnskey->dnskey.key_size) <= 0) + if (sym_EVP_DigestUpdate(ctx, dnskey->dnskey.key, dnskey->dnskey.key_size) <= 0) return -EIO; - if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0) + if (sym_EVP_DigestFinal_ex(ctx, result, NULL) <= 0) return -EIO; return memcmp(result, ds->ds.digest, ds->ds.digest_size) == 0; @@ -1183,7 +1186,7 @@ static const EVP_MD* nsec3_hash_to_hash_md(uint8_t algorithm) { switch (algorithm) { case NSEC3_ALGORITHM_SHA1: - return EVP_sha1(); + return sym_EVP_sha1(); default: return NULL; @@ -1198,6 +1201,10 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) { assert(name); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + if (nsec3->key->type != DNS_TYPE_NSEC3) return -EINVAL; @@ -1210,41 +1217,41 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) { if (!algorithm) return -EOPNOTSUPP; - size_t hash_size = EVP_MD_size(algorithm); + size_t hash_size = sym_EVP_MD_get_size(algorithm); assert(hash_size > 0); if (nsec3->nsec3.next_hashed_name_size != hash_size) return -EINVAL; - _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = sym_EVP_MD_CTX_new(); if (!ctx) return -ENOMEM; - if (EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0) + if (sym_EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0) return -EOPNOTSUPP; r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true); if (r < 0) return r; - if (EVP_DigestUpdate(ctx, wire_format, r) <= 0) + if (sym_EVP_DigestUpdate(ctx, wire_format, r) <= 0) return -EIO; - if (EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0) + if (sym_EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0) return -EIO; uint8_t result[EVP_MAX_MD_SIZE]; - if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0) + if (sym_EVP_DigestFinal_ex(ctx, result, NULL) <= 0) return -EIO; for (unsigned k = 0; k < nsec3->nsec3.iterations; k++) { - if (EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0) + if (sym_EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0) return -EOPNOTSUPP; - if (EVP_DigestUpdate(ctx, result, hash_size) <= 0) + if (sym_EVP_DigestUpdate(ctx, result, hash_size) <= 0) return -EIO; - if (EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0) + if (sym_EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0) return -EIO; - if (EVP_DigestFinal_ex(ctx, result, NULL) <= 0) + if (sym_EVP_DigestFinal_ex(ctx, result, NULL) <= 0) return -EIO; } diff --git a/src/resolve/resolved-dnstls.c b/src/resolve/resolved-dnstls.c index 042077ab06..f59c2fa348 100644 --- a/src/resolve/resolved-dnstls.c +++ b/src/resolve/resolved-dnstls.c @@ -4,22 +4,21 @@ #error This source file requires DNS-over-TLS to be enabled and OpenSSL to be available. #endif -#include -#include #include #include "alloc-util.h" -#include "openssl-util.h" +#include "crypto-util.h" #include "log.h" #include "resolved-dns-server.h" #include "resolved-dns-stream.h" #include "resolved-dnstls.h" #include "resolved-manager.h" +#include "ssl-util.h" static char *dnstls_error_string(int ssl_error, char *buf, size_t count) { assert(buf || count == 0); if (ssl_error == SSL_ERROR_SSL) - ERR_error_string_n(ERR_get_error(), buf, count); + sym_ERR_error_string_n(sym_ERR_get_error(), buf, count); else snprintf(buf, count, "SSL_get_error()=%d", ssl_error); return buf; @@ -54,7 +53,7 @@ static int dnstls_flush_write_buffer(DnsStream *stream) { stream->dnstls_events |= EPOLLOUT; return -EAGAIN; } else { - BIO_reset(SSL_get_wbio(stream->dnstls_data.ssl)); + sym_BIO_reset(sym_SSL_get_wbio(stream->dnstls_data.ssl)); stream->dnstls_data.buffer_offset = 0; } } @@ -72,55 +71,55 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { assert(stream->manager); assert(server); - rb = BIO_new_socket(stream->fd, 0); + rb = sym_BIO_new_socket(stream->fd, 0); if (!rb) return -ENOMEM; - wb = BIO_new(BIO_s_mem()); + wb = sym_BIO_new(sym_BIO_s_mem()); if (!wb) return -ENOMEM; - BIO_get_mem_ptr(wb, &stream->dnstls_data.write_buffer); + sym_BIO_get_mem_ptr(wb, &stream->dnstls_data.write_buffer); stream->dnstls_data.buffer_offset = 0; - s = SSL_new(stream->manager->dnstls_data.ctx); + s = sym_SSL_new(stream->manager->dnstls_data.ctx); if (!s) return -ENOMEM; - SSL_set_connect_state(s); - r = SSL_set_session(s, server->dnstls_data.session); + sym_SSL_set_connect_state(s); + r = sym_SSL_set_session(s, server->dnstls_data.session); if (r == 0) return -EIO; - SSL_set_bio(s, TAKE_PTR(rb), TAKE_PTR(wb)); + sym_SSL_set_bio(s, TAKE_PTR(rb), TAKE_PTR(wb)); if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { X509_VERIFY_PARAM *v; - SSL_set_verify(s, SSL_VERIFY_PEER, NULL); - v = SSL_get0_param(s); + sym_SSL_set_verify(s, SSL_VERIFY_PEER, NULL); + v = sym_SSL_get0_param(s); if (server->server_name) { - X509_VERIFY_PARAM_set_hostflags(v, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); - if (X509_VERIFY_PARAM_set1_host(v, server->server_name, 0) == 0) + sym_X509_VERIFY_PARAM_set_hostflags(v, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + if (sym_X509_VERIFY_PARAM_set1_host(v, server->server_name, 0) == 0) return -ECONNREFUSED; } else { const unsigned char *ip; ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr; - if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0) + if (sym_X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0) return -ECONNREFUSED; } } if (server->server_name) { - r = SSL_set_tlsext_host_name(s, server->server_name); + r = sym_SSL_set_tlsext_host_name(s, server->server_name); if (r <= 0) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set server name: %s", DNSTLS_ERROR_STRING(SSL_ERROR_SSL)); } - ERR_clear_error(); - stream->dnstls_data.handshake = SSL_do_handshake(s); + sym_ERR_clear_error(); + stream->dnstls_data.handshake = sym_SSL_do_handshake(s); if (stream->dnstls_data.handshake <= 0) { - error = SSL_get_error(s, stream->dnstls_data.handshake); + error = sym_SSL_get_error(s, stream->dnstls_data.handshake); if (!IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED), "Failed to invoke SSL_do_handshake: %s", DNSTLS_ERROR_STRING(error)); @@ -131,7 +130,7 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { r = dnstls_flush_write_buffer(stream); if (r < 0 && r != -EAGAIN) { - SSL_free(TAKE_PTR(stream->dnstls_data.ssl)); + sym_SSL_free(TAKE_PTR(stream->dnstls_data.ssl)); return r; } @@ -143,7 +142,7 @@ void dnstls_stream_free(DnsStream *stream) { assert(stream->encrypted); if (stream->dnstls_data.ssl) - SSL_free(stream->dnstls_data.ssl); + sym_SSL_free(stream->dnstls_data.ssl); } int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) { @@ -161,8 +160,8 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) { } if (stream->dnstls_data.shutdown) { - ERR_clear_error(); - r = SSL_shutdown(stream->dnstls_data.ssl); + sym_ERR_clear_error(); + r = sym_SSL_shutdown(stream->dnstls_data.ssl); if (r == 0) { stream->dnstls_events = 0; @@ -172,7 +171,7 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) { return -EAGAIN; } else if (r < 0) { - error = SSL_get_error(stream->dnstls_data.ssl, r); + error = sym_SSL_get_error(stream->dnstls_data.ssl, r); if (IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { stream->dnstls_events = error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; @@ -198,10 +197,10 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) { dns_stream_unref(stream); return DNSTLS_STREAM_CLOSED; } else if (stream->dnstls_data.handshake <= 0) { - ERR_clear_error(); - stream->dnstls_data.handshake = SSL_do_handshake(stream->dnstls_data.ssl); + sym_ERR_clear_error(); + stream->dnstls_data.handshake = sym_SSL_do_handshake(stream->dnstls_data.ssl); if (stream->dnstls_data.handshake <= 0) { - error = SSL_get_error(stream->dnstls_data.ssl, stream->dnstls_data.handshake); + error = sym_SSL_get_error(stream->dnstls_data.ssl, stream->dnstls_data.handshake); if (IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { stream->dnstls_events = error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; r = dnstls_flush_write_buffer(stream); @@ -233,18 +232,18 @@ int dnstls_stream_shutdown(DnsStream *stream, int error) { assert(stream->dnstls_data.ssl); if (stream->server) { - s = SSL_get1_session(stream->dnstls_data.ssl); + s = sym_SSL_get1_session(stream->dnstls_data.ssl); if (s) { if (stream->server->dnstls_data.session) - SSL_SESSION_free(stream->server->dnstls_data.session); + sym_SSL_SESSION_free(stream->server->dnstls_data.session); stream->server->dnstls_data.session = s; } } if (error == ETIMEDOUT) { - ERR_clear_error(); - r = SSL_shutdown(stream->dnstls_data.ssl); + sym_ERR_clear_error(); + r = sym_SSL_shutdown(stream->dnstls_data.ssl); if (r == 0) { if (!stream->dnstls_data.shutdown) { stream->dnstls_data.shutdown = true; @@ -259,7 +258,7 @@ int dnstls_stream_shutdown(DnsStream *stream, int error) { return -EAGAIN; } else if (r < 0) { - ssl_error = SSL_get_error(stream->dnstls_data.ssl, r); + ssl_error = sym_SSL_get_error(stream->dnstls_data.ssl, r); if (IN_SET(ssl_error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { stream->dnstls_events = ssl_error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; r = dnstls_flush_write_buffer(stream); @@ -291,10 +290,10 @@ static ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t co int error, r; ssize_t ss; - ERR_clear_error(); - ss = r = SSL_write(stream->dnstls_data.ssl, buf, count); + sym_ERR_clear_error(); + ss = r = sym_SSL_write(stream->dnstls_data.ssl, buf, count); if (r <= 0) { - error = SSL_get_error(stream->dnstls_data.ssl, r); + error = sym_SSL_get_error(stream->dnstls_data.ssl, r); if (IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { stream->dnstls_events = error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; ss = -EAGAIN; @@ -352,10 +351,10 @@ ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) { assert(stream->dnstls_data.ssl); assert(buf); - ERR_clear_error(); - ss = r = SSL_read(stream->dnstls_data.ssl, buf, count); + sym_ERR_clear_error(); + ss = r = sym_SSL_read(stream->dnstls_data.ssl, buf, count); if (r <= 0) { - error = SSL_get_error(stream->dnstls_data.ssl, r); + error = sym_SSL_get_error(stream->dnstls_data.ssl, r); if (IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { /* If we receive SSL_ERROR_WANT_READ here, there are two possible scenarios: * OpenSSL needs to renegotiate (so we want to get an EPOLLIN event), or @@ -390,7 +389,7 @@ void dnstls_server_free(DnsServer *server) { assert(server); if (server->dnstls_data.session) - SSL_SESSION_free(server->dnstls_data.session); + sym_SSL_SESSION_free(server->dnstls_data.session); } int dnstls_manager_init(Manager *manager) { @@ -398,25 +397,33 @@ int dnstls_manager_init(Manager *manager) { assert(manager); - manager->dnstls_data.ctx = SSL_CTX_new(TLS_client_method()); + r = dlopen_libcrypto(LOG_WARNING); + if (r < 0) + return r; + + r = dlopen_libssl(LOG_WARNING); + if (r < 0) + return r; + + manager->dnstls_data.ctx = sym_SSL_CTX_new(sym_TLS_client_method()); if (!manager->dnstls_data.ctx) return log_warning_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to create SSL context: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - r = SSL_CTX_set_min_proto_version(manager->dnstls_data.ctx, TLS1_2_VERSION); + r = sym_SSL_CTX_set_min_proto_version(manager->dnstls_data.ctx, TLS1_2_VERSION); if (r == 0) return log_warning_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to set protocol version on SSL context: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - (void) SSL_CTX_set_options(manager->dnstls_data.ctx, SSL_OP_NO_COMPRESSION); + (void) sym_SSL_CTX_set_options(manager->dnstls_data.ctx, SSL_OP_NO_COMPRESSION); - r = SSL_CTX_set_default_verify_paths(manager->dnstls_data.ctx); + r = sym_SSL_CTX_set_default_verify_paths(manager->dnstls_data.ctx); if (r == 0) return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Failed to load system trust store: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); return 0; } @@ -424,5 +431,5 @@ void dnstls_manager_free(Manager *manager) { assert(manager); if (manager->dnstls_data.ctx) - SSL_CTX_free(manager->dnstls_data.ctx); + sym_SSL_CTX_free(manager->dnstls_data.ctx); } diff --git a/src/resolve/resolved-dnstls.h b/src/resolve/resolved-dnstls.h index 35a8d785de..b87b84a0d5 100644 --- a/src/resolve/resolved-dnstls.h +++ b/src/resolve/resolved-dnstls.h @@ -7,8 +7,6 @@ #error This source file requires OpenSSL to be available. #endif -#include - #include "resolved-forward.h" typedef struct DnsTlsManagerData { diff --git a/src/sbsign/authenticode.c b/src/sbsign/authenticode.c new file mode 100644 index 0000000000..9971cf9f26 --- /dev/null +++ b/src/sbsign/authenticode.c @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +#include "authenticode.h" +#include "crypto-util.h" + +/* OpenSSL's ASN1_SEQUENCE/ASN1_CHOICE/IMPLEMENT_ASN1_FUNCTIONS macros expand to code that references + * libcrypto symbols directly, which would force us to link this object against libcrypto and defeat the + * dlopen approach used everywhere else. We work around that in two different ways depending on where the + * reference appears in the macro expansion: + * + * - ASN1_item_new/ASN1_item_free/ASN1_item_d2i/ASN1_item_i2d are called from the bodies of the functions + * generated by IMPLEMENT_ASN1_FUNCTIONS. We can simply #define them to the matching sym_* variants, so + * the generated bodies end up calling our dlopen'd pointers. + * + * - ASN1_ANY_it/ASN1_BIT_STRING_it/... (the "_it" getters) are embedded as function pointers in the + * static const ASN1_ADB / ASN1_TEMPLATE tables emitted by the ASN1_SEQUENCE/ASN1_CHOICE macros. Static + * initializers can only contain constant expressions, so we can't point them at the sym_* variables + * (which are non-const globals filled in at dlopen time). Instead we define static trampoline + * functions (openssl_ASN1_*_it) whose addresses are constant, each forwarding to the corresponding + * sym_* pointer at runtime, and #define the OpenSSL names to our trampolines before the tables are + * emitted. + * + * Note that this file must only call these redefined macros indirectly, via the IMPLEMENT_ASN1_FUNCTIONS + * expansions, and callers of those generated wrappers (e.g. sbsign.c) must have dlopen_libcrypto() + * before invoking them, otherwise the sym_* pointers will still be NULL. */ + +static const ASN1_ITEM* openssl_ASN1_ANY_it(void) { + assert(sym_ASN1_ANY_it); + return sym_ASN1_ANY_it(); +} + +static const ASN1_ITEM* openssl_ASN1_BIT_STRING_it(void) { + assert(sym_ASN1_BIT_STRING_it); + return sym_ASN1_BIT_STRING_it(); +} + +static const ASN1_ITEM* openssl_ASN1_BMPSTRING_it(void) { + assert(sym_ASN1_BMPSTRING_it); + return sym_ASN1_BMPSTRING_it(); +} + +static const ASN1_ITEM* openssl_ASN1_IA5STRING_it(void) { + assert(sym_ASN1_IA5STRING_it); + return sym_ASN1_IA5STRING_it(); +} + +static const ASN1_ITEM* openssl_ASN1_OBJECT_it(void) { + assert(sym_ASN1_OBJECT_it); + return sym_ASN1_OBJECT_it(); +} + +static const ASN1_ITEM* openssl_ASN1_OCTET_STRING_it(void) { + assert(sym_ASN1_OCTET_STRING_it); + return sym_ASN1_OCTET_STRING_it(); +} + +#define ASN1_item_new sym_ASN1_item_new +#define ASN1_item_free sym_ASN1_item_free +#define ASN1_item_d2i sym_ASN1_item_d2i +#define ASN1_item_i2d sym_ASN1_item_i2d +#define ASN1_ANY_it openssl_ASN1_ANY_it +#define ASN1_BIT_STRING_it openssl_ASN1_BIT_STRING_it +#define ASN1_BMPSTRING_it openssl_ASN1_BMPSTRING_it +#define ASN1_IA5STRING_it openssl_ASN1_IA5STRING_it +#define ASN1_OBJECT_it openssl_ASN1_OBJECT_it +#define ASN1_OCTET_STRING_it openssl_ASN1_OCTET_STRING_it + +ASN1_SEQUENCE(SpcAttributeTypeAndOptionalValue) = { + ASN1_SIMPLE(SpcAttributeTypeAndOptionalValue, type, ASN1_OBJECT), + ASN1_OPT(SpcAttributeTypeAndOptionalValue, value, ASN1_ANY) +} ASN1_SEQUENCE_END(SpcAttributeTypeAndOptionalValue); + +IMPLEMENT_ASN1_FUNCTIONS(SpcAttributeTypeAndOptionalValue); + +ASN1_SEQUENCE(AlgorithmIdentifier) = { + ASN1_SIMPLE(AlgorithmIdentifier, algorithm, ASN1_OBJECT), + ASN1_OPT(AlgorithmIdentifier, parameters, ASN1_ANY) +} ASN1_SEQUENCE_END(AlgorithmIdentifier) + +IMPLEMENT_ASN1_FUNCTIONS(AlgorithmIdentifier); + +ASN1_SEQUENCE(DigestInfo) = { + ASN1_SIMPLE(DigestInfo, digestAlgorithm, AlgorithmIdentifier), + ASN1_SIMPLE(DigestInfo, digest, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(DigestInfo); + +IMPLEMENT_ASN1_FUNCTIONS(DigestInfo); + +ASN1_SEQUENCE(SpcIndirectDataContent) = { + ASN1_SIMPLE(SpcIndirectDataContent, data, SpcAttributeTypeAndOptionalValue), + ASN1_SIMPLE(SpcIndirectDataContent, messageDigest, DigestInfo) +} ASN1_SEQUENCE_END(SpcIndirectDataContent); + +IMPLEMENT_ASN1_FUNCTIONS(SpcIndirectDataContent); + +ASN1_CHOICE(SpcString) = { + ASN1_IMP_OPT(SpcString, value.unicode, ASN1_BMPSTRING, 0), + ASN1_IMP_OPT(SpcString, value.ascii, ASN1_IA5STRING, 1) +} ASN1_CHOICE_END(SpcString); + +IMPLEMENT_ASN1_FUNCTIONS(SpcString); + +ASN1_SEQUENCE(SpcSerializedObject) = { + ASN1_SIMPLE(SpcSerializedObject, classId, ASN1_OCTET_STRING), + ASN1_SIMPLE(SpcSerializedObject, serializedData, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(SpcSerializedObject); + +IMPLEMENT_ASN1_FUNCTIONS(SpcSerializedObject); + +ASN1_CHOICE(SpcLink) = { + ASN1_IMP_OPT(SpcLink, value.url, ASN1_IA5STRING, 0), + ASN1_IMP_OPT(SpcLink, value.moniker, SpcSerializedObject, 1), + ASN1_EXP_OPT(SpcLink, value.file, SpcString, 2) +} ASN1_CHOICE_END(SpcLink); + +IMPLEMENT_ASN1_FUNCTIONS(SpcLink); + +ASN1_SEQUENCE(SpcPeImageData) = { + ASN1_SIMPLE(SpcPeImageData, flags, ASN1_BIT_STRING), + ASN1_EXP_OPT(SpcPeImageData, file, SpcLink, 0) +} ASN1_SEQUENCE_END(SpcPeImageData) + +IMPLEMENT_ASN1_FUNCTIONS(SpcPeImageData); diff --git a/src/sbsign/authenticode.h b/src/sbsign/authenticode.h index 95d5499a8e..c076fe3624 100644 --- a/src/sbsign/authenticode.h +++ b/src/sbsign/authenticode.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include +#include #include "shared-forward.h" @@ -15,13 +15,6 @@ typedef struct { DECLARE_ASN1_FUNCTIONS(SpcAttributeTypeAndOptionalValue); -ASN1_SEQUENCE(SpcAttributeTypeAndOptionalValue) = { - ASN1_SIMPLE(SpcAttributeTypeAndOptionalValue, type, ASN1_OBJECT), - ASN1_OPT(SpcAttributeTypeAndOptionalValue, value, ASN1_ANY) -} ASN1_SEQUENCE_END(SpcAttributeTypeAndOptionalValue); - -IMPLEMENT_ASN1_FUNCTIONS(SpcAttributeTypeAndOptionalValue); - typedef struct { ASN1_OBJECT *algorithm; ASN1_TYPE *parameters; @@ -29,13 +22,6 @@ typedef struct { DECLARE_ASN1_FUNCTIONS(AlgorithmIdentifier); -ASN1_SEQUENCE(AlgorithmIdentifier) = { - ASN1_SIMPLE(AlgorithmIdentifier, algorithm, ASN1_OBJECT), - ASN1_OPT(AlgorithmIdentifier, parameters, ASN1_ANY) -} ASN1_SEQUENCE_END(AlgorithmIdentifier) - -IMPLEMENT_ASN1_FUNCTIONS(AlgorithmIdentifier); - typedef struct { AlgorithmIdentifier *digestAlgorithm; ASN1_OCTET_STRING *digest; @@ -43,13 +29,6 @@ typedef struct { DECLARE_ASN1_FUNCTIONS(DigestInfo); -ASN1_SEQUENCE(DigestInfo) = { - ASN1_SIMPLE(DigestInfo, digestAlgorithm, AlgorithmIdentifier), - ASN1_SIMPLE(DigestInfo, digest, ASN1_OCTET_STRING) -} ASN1_SEQUENCE_END(DigestInfo); - -IMPLEMENT_ASN1_FUNCTIONS(DigestInfo); - typedef struct { SpcAttributeTypeAndOptionalValue *data; DigestInfo *messageDigest; @@ -57,15 +36,6 @@ typedef struct { DECLARE_ASN1_FUNCTIONS(SpcIndirectDataContent); -ASN1_SEQUENCE(SpcIndirectDataContent) = { - ASN1_SIMPLE(SpcIndirectDataContent, data, SpcAttributeTypeAndOptionalValue), - ASN1_SIMPLE(SpcIndirectDataContent, messageDigest, DigestInfo) -} ASN1_SEQUENCE_END(SpcIndirectDataContent); - -IMPLEMENT_ASN1_FUNCTIONS(SpcIndirectDataContent); - -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SpcIndirectDataContent*, SpcIndirectDataContent_free, NULL); - typedef struct { int type; union { @@ -76,13 +46,6 @@ typedef struct { DECLARE_ASN1_FUNCTIONS(SpcString); -ASN1_CHOICE(SpcString) = { - ASN1_IMP_OPT(SpcString, value.unicode, ASN1_BMPSTRING, 0), - ASN1_IMP_OPT(SpcString, value.ascii, ASN1_IA5STRING, 1) -} ASN1_CHOICE_END(SpcString); - -IMPLEMENT_ASN1_FUNCTIONS(SpcString); - typedef struct { ASN1_OCTET_STRING *classId; ASN1_OCTET_STRING *serializedData; @@ -90,13 +53,6 @@ typedef struct { DECLARE_ASN1_FUNCTIONS(SpcSerializedObject); -ASN1_SEQUENCE(SpcSerializedObject) = { - ASN1_SIMPLE(SpcSerializedObject, classId, ASN1_OCTET_STRING), - ASN1_SIMPLE(SpcSerializedObject, serializedData, ASN1_OCTET_STRING) -} ASN1_SEQUENCE_END(SpcSerializedObject); - -IMPLEMENT_ASN1_FUNCTIONS(SpcSerializedObject); - typedef struct { int type; union { @@ -108,16 +64,6 @@ typedef struct { DECLARE_ASN1_FUNCTIONS(SpcLink); -ASN1_CHOICE(SpcLink) = { - ASN1_IMP_OPT(SpcLink, value.url, ASN1_IA5STRING, 0), - ASN1_IMP_OPT(SpcLink, value.moniker, SpcSerializedObject, 1), - ASN1_EXP_OPT(SpcLink, value.file, SpcString, 2) -} ASN1_CHOICE_END(SpcLink); - -IMPLEMENT_ASN1_FUNCTIONS(SpcLink); - -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SpcLink*, SpcLink_free, NULL); - typedef struct { ASN1_BIT_STRING *flags; SpcLink *file; @@ -125,11 +71,6 @@ typedef struct { DECLARE_ASN1_FUNCTIONS(SpcPeImageData); -ASN1_SEQUENCE(SpcPeImageData) = { - ASN1_SIMPLE(SpcPeImageData, flags, ASN1_BIT_STRING), - ASN1_EXP_OPT(SpcPeImageData, file, SpcLink, 0) -} ASN1_SEQUENCE_END(SpcPeImageData) - -IMPLEMENT_ASN1_FUNCTIONS(SpcPeImageData); - +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SpcIndirectDataContent*, SpcIndirectDataContent_free, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SpcLink*, SpcLink_free, NULL); DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SpcPeImageData*, SpcPeImageData_free, NULL); diff --git a/src/sbsign/meson.build b/src/sbsign/meson.build index b6e0dbcde9..f28d4648f9 100644 --- a/src/sbsign/meson.build +++ b/src/sbsign/meson.build @@ -6,7 +6,10 @@ executables += [ 'conditions' : [ 'HAVE_OPENSSL', ], - 'sources' : files('sbsign.c'), - 'dependencies' : libopenssl, + 'sources' : files( + 'sbsign.c', + 'authenticode.c', + ), + 'dependencies' : libopenssl_cflags, }, ] diff --git a/src/sbsign/sbsign.c b/src/sbsign/sbsign.c index a8c554ffcf..012f39dcc3 100644 --- a/src/sbsign/sbsign.c +++ b/src/sbsign/sbsign.c @@ -4,9 +4,11 @@ #include "alloc-util.h" #include "ansi-color.h" +#include "ask-password-api.h" #include "authenticode.h" #include "build.h" #include "copy.h" +#include "crypto-util.h" #include "efi-fundamental.h" #include "fd-util.h" #include "fileio.h" @@ -16,7 +18,6 @@ #include "io-util.h" #include "log.h" #include "main-func.h" -#include "openssl-util.h" #include "options.h" #include "parse-argument.h" #include "pe-binary.h" @@ -203,13 +204,13 @@ static int spc_indirect_data_content_new(const void *digest, size_t digestsz, ui return log_oom(); link->value.file->type = 0; - link->value.file->value.unicode = ASN1_BMPSTRING_new(); + link->value.file->value.unicode = sym_ASN1_BMPSTRING_new(); if (!link->value.file->value.unicode) return log_oom(); - if (ASN1_STRING_set(link->value.file->value.unicode, obsolete, sizeof(obsolete)) == 0) + if (sym_ASN1_STRING_set(link->value.file->value.unicode, obsolete, sizeof(obsolete)) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set ASN1 string: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); _cleanup_(SpcPeImageData_freep) SpcPeImageData *peid = SpcPeImageData_new(); if (!peid) @@ -221,46 +222,46 @@ static int spc_indirect_data_content_new(const void *digest, size_t digestsz, ui int peidrawsz = i2d_SpcPeImageData(peid, &peidraw); if (peidrawsz < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert SpcPeImageData to BER: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); _cleanup_(SpcIndirectDataContent_freep) SpcIndirectDataContent *idc = SpcIndirectDataContent_new(); - idc->data->value = ASN1_TYPE_new(); + idc->data->value = sym_ASN1_TYPE_new(); if (!idc->data->value) return log_oom(); idc->data->value->type = V_ASN1_SEQUENCE; - idc->data->value->value.sequence = ASN1_STRING_new(); + idc->data->value->value.sequence = sym_ASN1_STRING_new(); if (!idc->data->value->value.sequence) return log_oom(); - idc->data->type = OBJ_txt2obj(SPC_PE_IMAGE_DATA_OBJID, /* no_name= */ 1); + idc->data->type = sym_OBJ_txt2obj(SPC_PE_IMAGE_DATA_OBJID, /* no_name= */ 1); if (!idc->data->type) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get SpcPeImageData object: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (!ASN1_STRING_set(idc->data->value->value.sequence, peidraw, peidrawsz)) + if (!sym_ASN1_STRING_set(idc->data->value->value.sequence, peidraw, peidrawsz)) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set ASN1_STRING data."); - idc->messageDigest->digestAlgorithm->algorithm = OBJ_nid2obj(NID_sha256); + idc->messageDigest->digestAlgorithm->algorithm = sym_OBJ_nid2obj(NID_sha256); if (!idc->messageDigest->digestAlgorithm->algorithm) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get SHA256 object: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - idc->messageDigest->digestAlgorithm->parameters = ASN1_TYPE_new(); + idc->messageDigest->digestAlgorithm->parameters = sym_ASN1_TYPE_new(); if (!idc->messageDigest->digestAlgorithm->parameters) return log_oom(); idc->messageDigest->digestAlgorithm->parameters->type = V_ASN1_NULL; - if (ASN1_OCTET_STRING_set(idc->messageDigest->digest, digest, digestsz) == 0) + if (sym_ASN1_OCTET_STRING_set(idc->messageDigest->digest, digest, digestsz) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set digest: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); _cleanup_free_ uint8_t *idcraw = NULL; int idcrawsz = i2d_SpcIndirectDataContent(idc, &idcraw); if (idcrawsz < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert SpcIndirectDataContent to BER: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); *ret_idc = TAKE_PTR(idcraw); *ret_idcsz = (size_t) idcrawsz; @@ -276,12 +277,12 @@ static int asn1_timestamp(ASN1_TIME **ret) { usec_t epoch = parse_source_date_epoch(); if (epoch == USEC_INFINITY) { - time = X509_gmtime_adj(NULL, 0); + time = sym_X509_gmtime_adj(NULL, 0); if (!time) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get current time: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); } else { - time = ASN1_TIME_set(NULL, (time_t) (epoch / USEC_PER_SEC)); + time = sym_ASN1_TIME_set(NULL, (time_t) (epoch / USEC_PER_SEC)); if (!time) return log_oom(); } @@ -323,37 +324,37 @@ static int pkcs7_new_with_attributes( } /* Add an empty SMIMECAP attribute to indicate we don't have any SMIME capabilities. */ - _cleanup_(x509_algor_free_manyp) STACK_OF(X509_ALGOR) *smcap = sk_X509_ALGOR_new_null(); + _cleanup_(x509_algor_free_manyp) STACK_OF(X509_ALGOR) *smcap = (STACK_OF(X509_ALGOR)*) sym_OPENSSL_sk_new_null(); if (!smcap) return log_oom(); - if (PKCS7_add_attrib_smimecap(si, smcap) == 0) + if (sym_PKCS7_add_attrib_smimecap(si, smcap) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to add smimecap signed attribute to signer info: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (PKCS7_add_attrib_content_type(si, NULL) == 0) + if (sym_PKCS7_add_attrib_content_type(si, NULL) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to add content type signed attribute to signer info: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); _cleanup_(ASN1_TIME_freep) ASN1_TIME *time = NULL; r = asn1_timestamp(&time); if (r < 0) return r; - if (PKCS7_add0_attrib_signing_time(si, time) == 0) + if (sym_PKCS7_add0_attrib_signing_time(si, time) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to add signing time signed attribute to signer info: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); TAKE_PTR(time); - ASN1_OBJECT *idc = OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, /* no_name= */ true); + ASN1_OBJECT *idc = sym_OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, /* no_name= */ true); if (!idc) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get SpcIndirectDataContent object: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, V_ASN1_OBJECT, idc) == 0) + if (sym_PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, V_ASN1_OBJECT, idc) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to add signed attribute to pkcs7 signer info: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); *ret_p7 = TAKE_PTR(p7); *ret_si = TAKE_PTR(si); @@ -363,23 +364,23 @@ static int pkcs7_new_with_attributes( static int pkcs7_populate_data_bio(PKCS7* p7, const void *data, size_t size, BIO **ret) { assert(ret); - _cleanup_(BIO_free_allp) BIO *bio = PKCS7_dataInit(p7, NULL); + _cleanup_(BIO_free_allp) BIO *bio = sym_PKCS7_dataInit(p7, NULL); if (!bio) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to create PKCS7 data bio: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); int tag, class; long psz; const uint8_t *p = data; /* This function weirdly enough reports errors by setting the 0x80 bit in its return value. */ - if (ASN1_get_object(&p, &psz, &tag, &class, size) & 0x80) + if (sym_ASN1_get_object(&p, &psz, &tag, &class, size) & 0x80) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse ASN.1 object: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (BIO_write(bio, p, psz) < 0) + if (sym_BIO_write(bio, p, psz) < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write to PKCS7 data bio: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); *ret = TAKE_PTR(bio); @@ -391,26 +392,26 @@ static int pkcs7_add_digest_attribute(PKCS7 *p7, BIO *data, PKCS7_SIGNER_INFO *s assert(data); assert(si); - BIO *mdbio = BIO_find_type(data, BIO_TYPE_MD); + BIO *mdbio = sym_BIO_find_type(data, BIO_TYPE_MD); if (!mdbio) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to find digest bio: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); EVP_MD_CTX *mdc; - if (BIO_get_md_ctx(mdbio, &mdc) <= 0) + if (sym_BIO_get_md_ctx(mdbio, &mdc) <= 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get digest context from bio: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); unsigned char digest[EVP_MAX_MD_SIZE]; unsigned digestsz; - if (EVP_DigestFinal_ex(mdc, digest, &digestsz) == 0) + if (sym_EVP_DigestFinal_ex(mdc, digest, &digestsz) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get digest: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (PKCS7_add1_attrib_digest(si, digest, digestsz) == 0) + if (sym_PKCS7_add1_attrib_digest(si, digest, digestsz) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to add PKCS9 message digest signed attribute to signer info: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); return 0; } @@ -425,6 +426,10 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { _cleanup_(iovec_done) struct iovec signed_attributes_signature = {}; int r; + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + if (argc < 2) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No input file specified"); @@ -487,9 +492,9 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { return log_error_errno(r, "Failed to read signed attributes file '%s': %m", arg_signed_data); const uint8_t *p = content; - if (!ASN1_item_d2i((ASN1_VALUE **) &signed_attributes, &p, contentsz, ASN1_ITEM_rptr(PKCS7_ATTR_SIGN))) + if (!sym_ASN1_item_d2i((ASN1_VALUE **) &signed_attributes, &p, contentsz, sym_PKCS7_ATTR_SIGN_it())) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse signed attributes: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); } if (arg_signed_data_signature) { @@ -526,7 +531,7 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { _cleanup_free_ void *pehash = NULL; size_t pehashsz; - r = pe_hash(srcfd, EVP_sha256(), &pehash, &pehashsz); + r = pe_hash(srcfd, sym_EVP_sha256(), &pehash, &pehashsz); if (r < 0) return log_error_errno(r, "Failed to hash PE binary %s: %m", argv[0]); @@ -555,10 +560,10 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { return r; _cleanup_free_ unsigned char *abuf = NULL; - int alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf, ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); + int alen = sym_ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf, sym_PKCS7_ATTR_SIGN_it()); if (alen < 0 || !abuf) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert signed attributes ASN.1 to DER: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); r = loop_write(dstfd, abuf, alen); if (r < 0) @@ -573,51 +578,51 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { } if (iovec_is_set(&signed_attributes_signature)) - ASN1_STRING_set0(si->enc_digest, TAKE_PTR(signed_attributes_signature.iov_base), signed_attributes_signature.iov_len); + sym_ASN1_STRING_set0(si->enc_digest, TAKE_PTR(signed_attributes_signature.iov_base), signed_attributes_signature.iov_len); else { _cleanup_(BIO_free_allp) BIO *bio = NULL; r = pkcs7_populate_data_bio(p7, idcraw, idcrawsz, &bio); if (r < 0) return r; - if (PKCS7_dataFinal(p7, bio) == 0) + if (sym_PKCS7_dataFinal(p7, bio) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to sign data: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); } - _cleanup_(PKCS7_freep) PKCS7 *p7c = PKCS7_new(); + _cleanup_(PKCS7_freep) PKCS7 *p7c = sym_PKCS7_new(); if (!p7c) return log_oom(); - p7c->type = OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, /* no_name= */ true); + p7c->type = sym_OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, /* no_name= */ true); if (!p7c->type) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get SpcIndirectDataContent object: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - p7c->d.other = ASN1_TYPE_new(); + p7c->d.other = sym_ASN1_TYPE_new(); if (!p7c->d.other) return log_oom(); p7c->d.other->type = V_ASN1_SEQUENCE; - p7c->d.other->value.sequence = ASN1_STRING_new(); + p7c->d.other->value.sequence = sym_ASN1_STRING_new(); if (!p7c->d.other->value.sequence) return log_oom(); - if (ASN1_STRING_set(p7c->d.other->value.sequence, idcraw, idcrawsz) == 0) + if (sym_ASN1_STRING_set(p7c->d.other->value.sequence, idcraw, idcrawsz) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set ASN1 string: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (PKCS7_set_content(p7, p7c) == 0) + if (sym_PKCS7_set_content(p7, p7c) == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 data: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); TAKE_PTR(p7c); _cleanup_free_ uint8_t *sig = NULL; - int sigsz = i2d_PKCS7(p7, &sig); + int sigsz = sym_i2d_PKCS7(p7, &sig); if (sigsz < 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert PKCS7 signature to DER: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); _cleanup_free_ IMAGE_DOS_HEADER *dos_header = NULL; _cleanup_free_ PeHeader *pe_header = NULL; diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index d3383aebb6..dd2a93844d 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -6,10 +6,6 @@ #include "efivars.h" #include "time-util.h" -#if HAVE_OPENSSL -#include -#endif - #include "sd-id128.h" #include "sd-json.h" #include "sd-varlink.h" @@ -19,6 +15,7 @@ #include "chattr-util.h" #include "copy.h" #include "creds-util.h" +#include "crypto-util.h" #include "efi-api.h" #include "env-util.h" #include "errno-util.h" @@ -32,7 +29,6 @@ #include "log.h" #include "memory-util.h" #include "mkdir-label.h" -#include "openssl-util.h" #include "parse-util.h" #include "path-util.h" #include "random-util.h" @@ -734,6 +730,7 @@ static int sha256_hash_host_and_tpm2_key( _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *md = NULL; unsigned l; + int r; assert(iovec_is_valid(host_key)); assert(iovec_is_valid(tpm2_key)); @@ -741,22 +738,26 @@ static int sha256_hash_host_and_tpm2_key( /* Combines the host key and the TPM2 HMAC hash into a SHA256 hash value we'll use as symmetric encryption key. */ - md = EVP_MD_CTX_new(); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + md = sym_EVP_MD_CTX_new(); if (!md) return log_oom(); - if (EVP_DigestInit_ex(md, EVP_sha256(), NULL) != 1) + if (sym_EVP_DigestInit_ex(md, sym_EVP_sha256(), NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initial SHA256 context."); - if (iovec_is_set(host_key) && EVP_DigestUpdate(md, host_key->iov_base, host_key->iov_len) != 1) + if (iovec_is_set(host_key) && sym_EVP_DigestUpdate(md, host_key->iov_base, host_key->iov_len) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to hash host key."); - if (iovec_is_set(tpm2_key) && EVP_DigestUpdate(md, tpm2_key->iov_base, tpm2_key->iov_len) != 1) + if (iovec_is_set(tpm2_key) && sym_EVP_DigestUpdate(md, tpm2_key->iov_base, tpm2_key->iov_len) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to hash TPM2 key."); - assert(EVP_MD_CTX_size(md) == SHA256_DIGEST_LENGTH); + assert(sym_EVP_MD_CTX_get_size(md) == SHA256_DIGEST_LENGTH); - if (EVP_DigestFinal_ex(md, ret, &l) != 1) + if (sym_EVP_DigestFinal_ex(md, ret, &l) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finalize SHA256 hash."); assert(l == SHA256_DIGEST_LENGTH); @@ -1039,16 +1040,20 @@ int encrypt_credential_and_warn( return r; } - assert_se(cc = EVP_aes_256_gcm()); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; - ksz = EVP_CIPHER_key_length(cc); + assert_se(cc = sym_EVP_aes_256_gcm()); + + ksz = sym_EVP_CIPHER_get_key_length(cc); assert(ksz == sizeof(md)); - bsz = EVP_CIPHER_block_size(cc); + bsz = sym_EVP_CIPHER_get_block_size(cc); assert(bsz > 0); assert((size_t) bsz <= CREDENTIAL_FIELD_SIZE_MAX); - ivsz = EVP_CIPHER_iv_length(cc); + ivsz = sym_EVP_CIPHER_get_iv_length(cc); if (ivsz > 0) { assert((size_t) ivsz <= CREDENTIAL_FIELD_SIZE_MAX); @@ -1059,14 +1064,14 @@ int encrypt_credential_and_warn( tsz = 16; /* FIXME: On OpenSSL 3 there is EVP_CIPHER_CTX_get_tag_length(), until then let's hardcode this */ - context = EVP_CIPHER_CTX_new(); + context = sym_EVP_CIPHER_CTX_new(); if (!context) return log_error_errno(SYNTHETIC_ERRNO(ENOMEM), "Failed to allocate encryption object: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (EVP_EncryptInit_ex(context, cc, NULL, md, iv.iov_base) != 1) + if (sym_EVP_EncryptInit_ex(context, cc, NULL, md, iv.iov_base) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize encryption context: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); /* Just an upper estimate */ output.iov_len = @@ -1131,9 +1136,9 @@ int encrypt_credential_and_warn( } /* Pass the encrypted + TPM2 header + scoped header as AAD */ - if (EVP_EncryptUpdate(context, NULL, &added, output.iov_base, p) != 1) + if (sym_EVP_EncryptUpdate(context, NULL, &added, output.iov_base, p) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to write AAD data: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); /* Now construct the metadata header */ ml = strlen_ptr(name); @@ -1147,27 +1152,27 @@ int encrypt_credential_and_warn( memcpy_safe(m->name, name, ml); /* And encrypt the metadata header */ - if (EVP_EncryptUpdate(context, (uint8_t*) output.iov_base + p, &added, (const unsigned char*) m, ALIGN8(offsetof(struct metadata_credential_header, name) + ml)) != 1) + if (sym_EVP_EncryptUpdate(context, (uint8_t*) output.iov_base + p, &added, (const unsigned char*) m, ALIGN8(offsetof(struct metadata_credential_header, name) + ml)) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to encrypt metadata header: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); assert(added >= 0); assert((size_t) added <= output.iov_len - p); p += added; /* Then encrypt the plaintext */ - if (EVP_EncryptUpdate(context, (uint8_t*) output.iov_base + p, &added, input->iov_base, input->iov_len) != 1) + if (sym_EVP_EncryptUpdate(context, (uint8_t*) output.iov_base + p, &added, input->iov_base, input->iov_len) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to encrypt data: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); assert(added >= 0); assert((size_t) added <= output.iov_len - p); p += added; /* Finalize */ - if (EVP_EncryptFinal_ex(context, (uint8_t*) output.iov_base + p, &added) != 1) + if (sym_EVP_EncryptFinal_ex(context, (uint8_t*) output.iov_base + p, &added) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to finalize data encryption: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); assert(added >= 0); assert((size_t) added <= output.iov_len - p); @@ -1176,9 +1181,9 @@ int encrypt_credential_and_warn( assert(p <= output.iov_len - tsz); /* Append tag */ - if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_GET_TAG, tsz, (uint8_t*) output.iov_base + p) != 1) + if (sym_EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_GET_TAG, tsz, (uint8_t*) output.iov_base + p) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get tag: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); p += tsz; assert(p <= output.iov_len); @@ -1435,59 +1440,63 @@ int decrypt_credential_and_warn( return r; } - assert_se(cc = EVP_aes_256_gcm()); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + assert_se(cc = sym_EVP_aes_256_gcm()); /* Make sure cipher expectations match the header */ - if (EVP_CIPHER_key_length(cc) != (int) le32toh(h->key_size)) + if (sym_EVP_CIPHER_get_key_length(cc) != (int) le32toh(h->key_size)) return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected key size in header."); - if (EVP_CIPHER_block_size(cc) != (int) le32toh(h->block_size)) + if (sym_EVP_CIPHER_get_block_size(cc) != (int) le32toh(h->block_size)) return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Unexpected block size in header."); - context = EVP_CIPHER_CTX_new(); + context = sym_EVP_CIPHER_CTX_new(); if (!context) return log_error_errno(SYNTHETIC_ERRNO(ENOMEM), "Failed to allocate decryption object: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (EVP_DecryptInit_ex(context, cc, NULL, NULL, NULL) != 1) + if (sym_EVP_DecryptInit_ex(context, cc, NULL, NULL, NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize decryption context: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_IVLEN, le32toh(h->iv_size), NULL) != 1) + if (sym_EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_IVLEN, le32toh(h->iv_size), NULL) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set IV size on decryption context: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (EVP_DecryptInit_ex(context, NULL, NULL, md, h->iv) != 1) + if (sym_EVP_DecryptInit_ex(context, NULL, NULL, md, h->iv) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set IV and key: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (EVP_DecryptUpdate(context, NULL, &added, input->iov_base, p) != 1) + if (sym_EVP_DecryptUpdate(context, NULL, &added, input->iov_base, p) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to write AAD data: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); plaintext.iov_base = malloc(input->iov_len - p - le32toh(h->tag_size)); if (!plaintext.iov_base) return -ENOMEM; - if (EVP_DecryptUpdate( + if (sym_EVP_DecryptUpdate( context, plaintext.iov_base, &added, (uint8_t*) input->iov_base + p, input->iov_len - p - le32toh(h->tag_size)) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to decrypt data: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); assert(added >= 0); assert((size_t) added <= input->iov_len - p - le32toh(h->tag_size)); plaintext.iov_len = added; - if (EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_TAG, le32toh(h->tag_size), (uint8_t*) input->iov_base + input->iov_len - le32toh(h->tag_size)) != 1) + if (sym_EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_GCM_SET_TAG, le32toh(h->tag_size), (uint8_t*) input->iov_base + input->iov_len - le32toh(h->tag_size)) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set tag: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (EVP_DecryptFinal_ex(context, (uint8_t*) plaintext.iov_base + plaintext.iov_len, &added) != 1) + if (sym_EVP_DecryptFinal_ex(context, (uint8_t*) plaintext.iov_base + plaintext.iov_len, &added) != 1) return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Decryption failed (incorrect key?): %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); plaintext.iov_len += added; diff --git a/src/shared/openssl-util.c b/src/shared/crypto-util.c similarity index 51% rename from src/shared/openssl-util.c rename to src/shared/crypto-util.c index 18c6b06b17..bf770f2432 100644 --- a/src/shared/openssl-util.c +++ b/src/shared/crypto-util.c @@ -1,32 +1,633 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "sd-dlopen.h" + #include "alloc-util.h" #include "ask-password-api.h" +#include "crypto-util.h" +#include "dlfcn-util.h" #include "fd-util.h" #include "fileio.h" #include "hexdecoct.h" #include "log.h" #include "memory-util.h" #include "memstream-util.h" -#include "openssl-util.h" #include "random-util.h" #include "string-util.h" #include "strv.h" #if HAVE_OPENSSL -# include -# include +# include +# include +# include +# include # if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) # include -DISABLE_WARNING_DEPRECATED_DECLARATIONS; -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ENGINE*, ENGINE_free, NULL); -REENABLE_WARNING; # endif +# ifndef OPENSSL_NO_UI_CONSOLE +# include +# endif + +struct OpenSSLAskPasswordUI { + AskPasswordRequest request; #ifndef OPENSSL_NO_UI_CONSOLE -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(UI_METHOD*, UI_destroy_method, NULL); + UI_METHOD *method; #endif +}; + +static void *libcrypto_dl = NULL; + +static DLSYM_PROTOTYPE(ASN1_INTEGER_dup) = NULL; +static DLSYM_PROTOTYPE(ASN1_INTEGER_free) = NULL; +static DLSYM_PROTOTYPE(ASN1_INTEGER_set) = NULL; +DLSYM_PROTOTYPE(ASN1_ANY_it) = NULL; +DLSYM_PROTOTYPE(ASN1_BIT_STRING_it) = NULL; +DLSYM_PROTOTYPE(ASN1_BMPSTRING_it) = NULL; +DLSYM_PROTOTYPE(ASN1_BMPSTRING_new) = NULL; +DLSYM_PROTOTYPE(ASN1_IA5STRING_it) = NULL; +DLSYM_PROTOTYPE(ASN1_OBJECT_it) = NULL; +DLSYM_PROTOTYPE(ASN1_OCTET_STRING_free) = NULL; +DLSYM_PROTOTYPE(ASN1_OCTET_STRING_it) = NULL; +DLSYM_PROTOTYPE(ASN1_OCTET_STRING_set) = NULL; +DLSYM_PROTOTYPE(ASN1_STRING_get0_data) = NULL; +DLSYM_PROTOTYPE(ASN1_STRING_length) = NULL; +DLSYM_PROTOTYPE(ASN1_STRING_new) = NULL; +DLSYM_PROTOTYPE(ASN1_STRING_set) = NULL; +DLSYM_PROTOTYPE(ASN1_STRING_set0) = NULL; +DLSYM_PROTOTYPE(ASN1_TIME_free) = NULL; +DLSYM_PROTOTYPE(ASN1_TIME_set) = NULL; +DLSYM_PROTOTYPE(ASN1_TYPE_new) = NULL; +DLSYM_PROTOTYPE(ASN1_get_object) = NULL; +DLSYM_PROTOTYPE(ASN1_item_d2i) = NULL; +DLSYM_PROTOTYPE(ASN1_item_free) = NULL; +DLSYM_PROTOTYPE(ASN1_item_i2d) = NULL; +DLSYM_PROTOTYPE(ASN1_item_new) = NULL; +DLSYM_PROTOTYPE(BIO_ctrl) = NULL; +DLSYM_PROTOTYPE(BIO_find_type) = NULL; +DLSYM_PROTOTYPE(BIO_free) = NULL; +DLSYM_PROTOTYPE(BIO_free_all) = NULL; +DLSYM_PROTOTYPE(BIO_new) = NULL; +DLSYM_PROTOTYPE(BIO_new_mem_buf) = NULL; +DLSYM_PROTOTYPE(BIO_new_socket) = NULL; +DLSYM_PROTOTYPE(BIO_s_mem) = NULL; +DLSYM_PROTOTYPE(BIO_write) = NULL; +DLSYM_PROTOTYPE(BN_CTX_free) = NULL; +DLSYM_PROTOTYPE(BN_CTX_new) = NULL; +DLSYM_PROTOTYPE(BN_bin2bn) = NULL; +static DLSYM_PROTOTYPE(BN_bn2bin) = NULL; +DLSYM_PROTOTYPE(BN_bn2nativepad) = NULL; +DLSYM_PROTOTYPE(BN_free) = NULL; +DLSYM_PROTOTYPE(BN_new) = NULL; +DLSYM_PROTOTYPE(BN_num_bits) = NULL; +DLSYM_PROTOTYPE(CRYPTO_free) = NULL; +DLSYM_PROTOTYPE(ECDSA_SIG_free) = NULL; +DLSYM_PROTOTYPE(EC_GROUP_free) = NULL; +DLSYM_PROTOTYPE(EC_GROUP_get0_generator) = NULL; +DLSYM_PROTOTYPE(EC_GROUP_get0_order) = NULL; +DLSYM_PROTOTYPE(EC_GROUP_get_curve) = NULL; +DLSYM_PROTOTYPE(EC_GROUP_get_curve_name) = NULL; +DLSYM_PROTOTYPE(EC_GROUP_get_field_type) = NULL; +DLSYM_PROTOTYPE(EC_GROUP_new_by_curve_name) = NULL; +DLSYM_PROTOTYPE(EC_POINT_free) = NULL; +DLSYM_PROTOTYPE(EC_POINT_new) = NULL; +DLSYM_PROTOTYPE(EC_POINT_oct2point) = NULL; +static DLSYM_PROTOTYPE(EC_POINT_point2buf) = NULL; +DLSYM_PROTOTYPE(EC_POINT_point2oct) = NULL; +static DLSYM_PROTOTYPE(EC_POINT_set_affine_coordinates) = NULL; +DLSYM_PROTOTYPE(ERR_clear_error) = NULL; +DLSYM_PROTOTYPE(ERR_error_string) = NULL; +DLSYM_PROTOTYPE(ERR_error_string_n) = NULL; +DLSYM_PROTOTYPE(ERR_get_error) = NULL; +static DLSYM_PROTOTYPE(ERR_peek_last_error) = NULL; +DLSYM_PROTOTYPE(EVP_CIPHER_CTX_ctrl) = NULL; +DLSYM_PROTOTYPE(EVP_CIPHER_CTX_free) = NULL; +static DLSYM_PROTOTYPE(EVP_CIPHER_CTX_get_block_size) = NULL; +DLSYM_PROTOTYPE(EVP_CIPHER_CTX_new) = NULL; +static DLSYM_PROTOTYPE(EVP_CIPHER_fetch) = NULL; +DLSYM_PROTOTYPE(EVP_CIPHER_free) = NULL; +DLSYM_PROTOTYPE(EVP_CIPHER_get_block_size) = NULL; +DLSYM_PROTOTYPE(EVP_CIPHER_get_iv_length) = NULL; +DLSYM_PROTOTYPE(EVP_CIPHER_get_key_length) = NULL; +DLSYM_PROTOTYPE(EVP_DecryptFinal_ex) = NULL; +DLSYM_PROTOTYPE(EVP_DecryptInit_ex) = NULL; +DLSYM_PROTOTYPE(EVP_DecryptUpdate) = NULL; +DLSYM_PROTOTYPE(EVP_Digest) = NULL; +DLSYM_PROTOTYPE(EVP_DigestFinal_ex) = NULL; +DLSYM_PROTOTYPE(EVP_DigestInit_ex) = NULL; +static DLSYM_PROTOTYPE(EVP_DigestSign) = NULL; +static DLSYM_PROTOTYPE(EVP_DigestSignInit) = NULL; +DLSYM_PROTOTYPE(EVP_DigestUpdate) = NULL; +DLSYM_PROTOTYPE(EVP_DigestVerify) = NULL; +DLSYM_PROTOTYPE(EVP_DigestVerifyInit) = NULL; +DLSYM_PROTOTYPE(EVP_EncryptFinal_ex) = NULL; +static DLSYM_PROTOTYPE(EVP_EncryptInit) = NULL; +DLSYM_PROTOTYPE(EVP_EncryptInit_ex) = NULL; +DLSYM_PROTOTYPE(EVP_EncryptUpdate) = NULL; +static DLSYM_PROTOTYPE(EVP_KDF_CTX_free) = NULL; +static DLSYM_PROTOTYPE(EVP_KDF_CTX_new) = NULL; +static DLSYM_PROTOTYPE(EVP_KDF_derive) = NULL; +static DLSYM_PROTOTYPE(EVP_KDF_fetch) = NULL; +static DLSYM_PROTOTYPE(EVP_KDF_free) = NULL; +DLSYM_PROTOTYPE(EVP_MAC_CTX_free) = NULL; +static DLSYM_PROTOTYPE(EVP_MAC_CTX_get_mac_size) = NULL; +static DLSYM_PROTOTYPE(EVP_MAC_CTX_new) = NULL; +static DLSYM_PROTOTYPE(EVP_MAC_fetch) = NULL; +static DLSYM_PROTOTYPE(EVP_MAC_final) = NULL; +DLSYM_PROTOTYPE(EVP_MAC_free) = NULL; +static DLSYM_PROTOTYPE(EVP_MAC_init) = NULL; +static DLSYM_PROTOTYPE(EVP_MAC_update) = NULL; +DLSYM_PROTOTYPE(EVP_MD_CTX_free) = NULL; +DLSYM_PROTOTYPE(EVP_MD_CTX_get0_md) = NULL; +DLSYM_PROTOTYPE(EVP_MD_CTX_new) = NULL; +DLSYM_PROTOTYPE(EVP_MD_CTX_set_pkey_ctx) = NULL; +static DLSYM_PROTOTYPE(EVP_MD_fetch) = NULL; +DLSYM_PROTOTYPE(EVP_MD_free) = NULL; +DLSYM_PROTOTYPE(EVP_MD_get0_name) = NULL; +DLSYM_PROTOTYPE(EVP_MD_get_size) = NULL; +static DLSYM_PROTOTYPE(EVP_MD_get_type) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_CTX_free) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_CTX_new) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_CTX_new_from_name) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_CTX_new_id) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_CTX_set0_rsa_oaep_label) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_CTX_set_rsa_oaep_md) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_CTX_set_rsa_padding) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_CTX_set_signature_md) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_derive) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_derive_init) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_derive_set_peer) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_encrypt) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_encrypt_init) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_eq) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_free) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_fromdata) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_fromdata_init) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_get1_encoded_public_key) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_get_base_id) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_get_bits) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_get_bn_param) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_get_group_name) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_get_id) = NULL; +static DLSYM_PROTOTYPE(EVP_PKEY_get_utf8_string_param) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_keygen) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_keygen_init) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_new) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_new_raw_public_key) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_verify) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_verify_init) = NULL; +DLSYM_PROTOTYPE(EVP_aes_256_ctr) = NULL; +DLSYM_PROTOTYPE(EVP_aes_256_gcm) = NULL; +DLSYM_PROTOTYPE(EVP_get_cipherbyname) = NULL; +DLSYM_PROTOTYPE(EVP_get_digestbyname) = NULL; +DLSYM_PROTOTYPE(EVP_sha1) = NULL; +DLSYM_PROTOTYPE(EVP_sha256) = NULL; +DLSYM_PROTOTYPE(EVP_sha384) = NULL; +DLSYM_PROTOTYPE(EVP_sha512) = NULL; +DLSYM_PROTOTYPE(HMAC) = NULL; +DLSYM_PROTOTYPE(SHA1) = NULL; +DLSYM_PROTOTYPE(SHA512) = NULL; +DLSYM_PROTOTYPE(OBJ_nid2obj) = NULL; +DLSYM_PROTOTYPE(OBJ_nid2sn) = NULL; +DLSYM_PROTOTYPE(OBJ_sn2nid) = NULL; +DLSYM_PROTOTYPE(OBJ_txt2obj) = NULL; +DLSYM_PROTOTYPE(OPENSSL_sk_new_null) = NULL; +DLSYM_PROTOTYPE(OPENSSL_sk_num) = NULL; +DLSYM_PROTOTYPE(OPENSSL_sk_pop_free) = NULL; +DLSYM_PROTOTYPE(OPENSSL_sk_push) = NULL; +DLSYM_PROTOTYPE(OPENSSL_sk_value) = NULL; +DLSYM_PROTOTYPE(OSSL_EC_curve_nid2name) = NULL; +static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_new) = NULL; +static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_free) = NULL; +static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_push_octet_string) = NULL; +static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_push_utf8_string) = NULL; +static DLSYM_PROTOTYPE(OSSL_PARAM_BLD_to_param) = NULL; +DLSYM_PROTOTYPE(OSSL_PARAM_construct_BN) = NULL; +DLSYM_PROTOTYPE(OSSL_PARAM_construct_end) = NULL; +DLSYM_PROTOTYPE(OSSL_PARAM_construct_octet_string) = NULL; +DLSYM_PROTOTYPE(OSSL_PARAM_construct_utf8_string) = NULL; +DLSYM_PROTOTYPE(OSSL_PARAM_free) = NULL; +static DLSYM_PROTOTYPE(OSSL_PROVIDER_try_load) = NULL; +static DLSYM_PROTOTYPE(OSSL_STORE_INFO_free) = NULL; +static DLSYM_PROTOTYPE(OSSL_STORE_INFO_get1_CERT) = NULL; +static DLSYM_PROTOTYPE(OSSL_STORE_INFO_get1_PKEY) = NULL; +static DLSYM_PROTOTYPE(OSSL_STORE_close) = NULL; +static DLSYM_PROTOTYPE(OSSL_STORE_expect) = NULL; +static DLSYM_PROTOTYPE(OSSL_STORE_load) = NULL; +static DLSYM_PROTOTYPE(OSSL_STORE_open) = NULL; +DLSYM_PROTOTYPE(PEM_read_PUBKEY) = NULL; +DLSYM_PROTOTYPE(PEM_read_PrivateKey) = NULL; +DLSYM_PROTOTYPE(PEM_read_X509) = NULL; +static DLSYM_PROTOTYPE(PEM_read_bio_PrivateKey) = NULL; +static DLSYM_PROTOTYPE(PEM_read_bio_X509) = NULL; +DLSYM_PROTOTYPE(PKCS5_PBKDF2_HMAC) = NULL; +DLSYM_PROTOTYPE(PEM_write_PUBKEY) = NULL; +DLSYM_PROTOTYPE(PEM_write_PrivateKey) = NULL; +DLSYM_PROTOTYPE(PEM_write_X509) = NULL; +DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_free) = NULL; +DLSYM_PROTOTYPE(PKCS7_ATTR_SIGN_it) = NULL; +static DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_new) = NULL; +static DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_set) = NULL; +DLSYM_PROTOTYPE(PKCS7_add0_attrib_signing_time) = NULL; +DLSYM_PROTOTYPE(PKCS7_add1_attrib_digest) = NULL; +DLSYM_PROTOTYPE(PKCS7_add_attrib_content_type) = NULL; +DLSYM_PROTOTYPE(PKCS7_add_attrib_smimecap) = NULL; +static DLSYM_PROTOTYPE(PKCS7_add_certificate) = NULL; +DLSYM_PROTOTYPE(PKCS7_add_signed_attribute) = NULL; +static DLSYM_PROTOTYPE(PKCS7_add_signer) = NULL; +DLSYM_PROTOTYPE(PKCS7_content_new) = NULL; +DLSYM_PROTOTYPE(PKCS7_ctrl) = NULL; +DLSYM_PROTOTYPE(PKCS7_dataFinal) = NULL; +DLSYM_PROTOTYPE(PKCS7_dataInit) = NULL; +DLSYM_PROTOTYPE(PKCS7_free) = NULL; +DLSYM_PROTOTYPE(PKCS7_get_signer_info) = NULL; +DLSYM_PROTOTYPE(PKCS7_new) = NULL; +DLSYM_PROTOTYPE(PKCS7_set_content) = NULL; +static DLSYM_PROTOTYPE(PKCS7_set_type) = NULL; +DLSYM_PROTOTYPE(PKCS7_sign) = NULL; +DLSYM_PROTOTYPE(PKCS7_verify) = NULL; +static DLSYM_PROTOTYPE(X509_ALGOR_set0) = NULL; +DLSYM_PROTOTYPE(X509_NAME_free) = NULL; +DLSYM_PROTOTYPE(X509_ALGOR_free) = NULL; +DLSYM_PROTOTYPE(X509_ATTRIBUTE_free) = NULL; +DLSYM_PROTOTYPE(X509_NAME_oneline) = NULL; +static DLSYM_PROTOTYPE(X509_NAME_set) = NULL; +DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_host) = NULL; +DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_ip) = NULL; +DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set_hostflags) = NULL; +DLSYM_PROTOTYPE(X509_free) = NULL; +DLSYM_PROTOTYPE(X509_gmtime_adj) = NULL; +static DLSYM_PROTOTYPE(X509_get0_serialNumber) = NULL; +static DLSYM_PROTOTYPE(X509_get_issuer_name) = NULL; +DLSYM_PROTOTYPE(X509_get_pubkey) = NULL; +static DLSYM_PROTOTYPE(X509_get_signature_info) = NULL; +DLSYM_PROTOTYPE(X509_get_subject_name) = NULL; +DLSYM_PROTOTYPE(d2i_ASN1_OCTET_STRING) = NULL; +DLSYM_PROTOTYPE(d2i_ECPKParameters) = NULL; +DLSYM_PROTOTYPE(d2i_PKCS7) = NULL; +DLSYM_PROTOTYPE(d2i_PUBKEY) = NULL; +DLSYM_PROTOTYPE(d2i_X509) = NULL; +DLSYM_PROTOTYPE(i2d_ASN1_INTEGER) = NULL; +DLSYM_PROTOTYPE(i2d_PKCS7) = NULL; +DLSYM_PROTOTYPE(i2d_PKCS7_fp) = NULL; +DLSYM_PROTOTYPE(i2d_PUBKEY) = NULL; +static DLSYM_PROTOTYPE(i2d_PUBKEY_fp) = NULL; +static DLSYM_PROTOTYPE(i2d_PublicKey) = NULL; +DLSYM_PROTOTYPE(i2d_X509) = NULL; +DLSYM_PROTOTYPE(i2d_X509_NAME) = NULL; + +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(OSSL_PARAM_BLD*, sym_OSSL_PARAM_BLD_free, OSSL_PARAM_BLD_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(OSSL_STORE_CTX*, sym_OSSL_STORE_close, OSSL_STORE_closep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(OSSL_STORE_INFO*, sym_OSSL_STORE_INFO_free, OSSL_STORE_INFO_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_KDF*, sym_EVP_KDF_free, EVP_KDF_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_KDF_CTX*, sym_EVP_KDF_CTX_free, EVP_KDF_CTX_freep, NULL); + +#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) +DISABLE_WARNING_DEPRECATED_DECLARATIONS; +static DLSYM_PROTOTYPE(ENGINE_by_id) = NULL; +static DLSYM_PROTOTYPE(ENGINE_free) = NULL; +static DLSYM_PROTOTYPE(ENGINE_init) = NULL; +static DLSYM_PROTOTYPE(ENGINE_load_private_key) = NULL; +REENABLE_WARNING; + +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(ENGINE*, sym_ENGINE_free, ENGINE_freep, NULL); +#endif + +#if !defined(OPENSSL_NO_DEPRECATED_3_0) +DISABLE_WARNING_DEPRECATED_DECLARATIONS; +DLSYM_PROTOTYPE(ECDSA_SIG_new) = NULL; +DLSYM_PROTOTYPE(ECDSA_SIG_set0) = NULL; +DLSYM_PROTOTYPE(ECDSA_do_verify) = NULL; +DLSYM_PROTOTYPE(EC_KEY_check_key) = NULL; +DLSYM_PROTOTYPE(EC_KEY_free) = NULL; +DLSYM_PROTOTYPE(EC_KEY_new) = NULL; +DLSYM_PROTOTYPE(EC_KEY_set_group) = NULL; +DLSYM_PROTOTYPE(EC_KEY_set_public_key) = NULL; +DLSYM_PROTOTYPE(EVP_PKEY_assign) = NULL; +DLSYM_PROTOTYPE(RSA_free) = NULL; +DLSYM_PROTOTYPE(RSA_new) = NULL; +DLSYM_PROTOTYPE(RSA_set0_key) = NULL; +DLSYM_PROTOTYPE(RSA_size) = NULL; +DLSYM_PROTOTYPE(RSAPublicKey_dup) = NULL; +REENABLE_WARNING; +#endif + +#ifndef OPENSSL_NO_UI_CONSOLE +static DLSYM_PROTOTYPE(UI_OpenSSL) = NULL; +static DLSYM_PROTOTYPE(UI_create_method) = NULL; +static DLSYM_PROTOTYPE(UI_destroy_method) = NULL; +static DLSYM_PROTOTYPE(UI_get0_output_string) = NULL; +static DLSYM_PROTOTYPE(UI_get_default_method) = NULL; +static DLSYM_PROTOTYPE(UI_get_method) = NULL; +static DLSYM_PROTOTYPE(UI_get_string_type) = NULL; +static DLSYM_PROTOTYPE(UI_method_get_ex_data) = NULL; +static DLSYM_PROTOTYPE(UI_method_get_reader) = NULL; +static DLSYM_PROTOTYPE(UI_method_set_ex_data) = NULL; +static DLSYM_PROTOTYPE(UI_method_set_reader) = NULL; +static DLSYM_PROTOTYPE(UI_set_default_method) = NULL; +static DLSYM_PROTOTYPE(UI_set_result) = NULL; + +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(UI_METHOD*, sym_UI_destroy_method, UI_destroy_methodp, NULL); +#endif + +#endif + +int dlopen_libcrypto(int log_level) { +#if HAVE_OPENSSL + SD_ELF_NOTE_DLOPEN( + "libcrypto", + "Support for cryptographic operations", + SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED, + "libcrypto.so.3"); + + return dlopen_many_sym_or_warn( + &libcrypto_dl, + "libcrypto.so.3", + log_level, + DLSYM_ARG(ASN1_ANY_it), + DLSYM_ARG(ASN1_BIT_STRING_it), + DLSYM_ARG(ASN1_BMPSTRING_it), + DLSYM_ARG(ASN1_BMPSTRING_new), + DLSYM_ARG(ASN1_get_object), + DLSYM_ARG(ASN1_IA5STRING_it), + DLSYM_ARG(ASN1_INTEGER_dup), + DLSYM_ARG(ASN1_INTEGER_free), + DLSYM_ARG(ASN1_INTEGER_set), + DLSYM_ARG(ASN1_item_d2i), + DLSYM_ARG(ASN1_item_free), + DLSYM_ARG(ASN1_item_i2d), + DLSYM_ARG(ASN1_item_new), + DLSYM_ARG(ASN1_OBJECT_it), + DLSYM_ARG(ASN1_OCTET_STRING_free), + DLSYM_ARG(ASN1_OCTET_STRING_it), + DLSYM_ARG(ASN1_OCTET_STRING_set), + DLSYM_ARG(ASN1_STRING_get0_data), + DLSYM_ARG(ASN1_STRING_length), + DLSYM_ARG(ASN1_STRING_new), + DLSYM_ARG(ASN1_STRING_set), + DLSYM_ARG(ASN1_STRING_set0), + DLSYM_ARG(ASN1_TIME_free), + DLSYM_ARG(ASN1_TIME_set), + DLSYM_ARG(ASN1_TYPE_new), + DLSYM_ARG(BIO_ctrl), + DLSYM_ARG(BIO_find_type), + DLSYM_ARG(BIO_free_all), + DLSYM_ARG(BIO_free), + DLSYM_ARG(BIO_new_mem_buf), + DLSYM_ARG(BIO_new_socket), + DLSYM_ARG(BIO_new), + DLSYM_ARG(BIO_s_mem), + DLSYM_ARG(BIO_write), + DLSYM_ARG(BN_bin2bn), + DLSYM_ARG(BN_bn2bin), + DLSYM_ARG(BN_bn2nativepad), + DLSYM_ARG(BN_CTX_free), + DLSYM_ARG(BN_CTX_new), + DLSYM_ARG(BN_free), + DLSYM_ARG(BN_new), + DLSYM_ARG(BN_num_bits), + DLSYM_ARG(CRYPTO_free), + DLSYM_ARG(d2i_ASN1_OCTET_STRING), + DLSYM_ARG(d2i_ECPKParameters), + DLSYM_ARG(d2i_PKCS7), + DLSYM_ARG(d2i_PUBKEY), + DLSYM_ARG(d2i_X509), + DLSYM_ARG(EC_GROUP_free), + DLSYM_ARG(EC_GROUP_get_curve_name), + DLSYM_ARG(EC_GROUP_get_curve), + DLSYM_ARG(EC_GROUP_get_field_type), + DLSYM_ARG(EC_GROUP_get0_generator), + DLSYM_ARG(EC_GROUP_get0_order), + DLSYM_ARG(EC_GROUP_new_by_curve_name), + DLSYM_ARG(EC_POINT_free), + DLSYM_ARG(EC_POINT_new), + DLSYM_ARG(EC_POINT_oct2point), + DLSYM_ARG(EC_POINT_point2buf), + DLSYM_ARG(EC_POINT_point2oct), + DLSYM_ARG(EC_POINT_set_affine_coordinates), + DLSYM_ARG(ECDSA_SIG_free), +#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) + DLSYM_ARG_FORCE(ENGINE_by_id), + DLSYM_ARG_FORCE(ENGINE_free), + DLSYM_ARG_FORCE(ENGINE_init), + DLSYM_ARG_FORCE(ENGINE_load_private_key), +#endif +#if !defined(OPENSSL_NO_DEPRECATED_3_0) + DLSYM_ARG_FORCE(EC_KEY_check_key), + DLSYM_ARG_FORCE(EC_KEY_free), + DLSYM_ARG_FORCE(EC_KEY_new), + DLSYM_ARG_FORCE(EC_KEY_set_group), + DLSYM_ARG_FORCE(EC_KEY_set_public_key), + DLSYM_ARG_FORCE(ECDSA_do_verify), + DLSYM_ARG_FORCE(ECDSA_SIG_new), + DLSYM_ARG_FORCE(ECDSA_SIG_set0), + DLSYM_ARG_FORCE(EVP_PKEY_assign), + DLSYM_ARG_FORCE(RSA_free), + DLSYM_ARG_FORCE(RSA_new), + DLSYM_ARG_FORCE(RSA_set0_key), + DLSYM_ARG_FORCE(RSA_size), + DLSYM_ARG_FORCE(RSAPublicKey_dup), +#endif + DLSYM_ARG(ERR_clear_error), + DLSYM_ARG(ERR_error_string_n), + DLSYM_ARG(ERR_error_string), + DLSYM_ARG(ERR_get_error), + DLSYM_ARG(ERR_peek_last_error), + DLSYM_ARG(EVP_aes_256_ctr), + DLSYM_ARG(EVP_aes_256_gcm), + DLSYM_ARG(EVP_CIPHER_CTX_ctrl), + DLSYM_ARG(EVP_CIPHER_CTX_free), + DLSYM_ARG(EVP_CIPHER_CTX_get_block_size), + DLSYM_ARG(EVP_CIPHER_CTX_new), + DLSYM_ARG(EVP_CIPHER_fetch), + DLSYM_ARG(EVP_CIPHER_free), + DLSYM_ARG(EVP_CIPHER_get_block_size), + DLSYM_ARG(EVP_CIPHER_get_iv_length), + DLSYM_ARG(EVP_CIPHER_get_key_length), + DLSYM_ARG(EVP_DecryptFinal_ex), + DLSYM_ARG(EVP_DecryptInit_ex), + DLSYM_ARG(EVP_DecryptUpdate), + DLSYM_ARG(EVP_Digest), + DLSYM_ARG(EVP_DigestFinal_ex), + DLSYM_ARG(EVP_DigestInit_ex), + DLSYM_ARG(EVP_DigestSign), + DLSYM_ARG(EVP_DigestSignInit), + DLSYM_ARG(EVP_DigestUpdate), + DLSYM_ARG(EVP_DigestVerify), + DLSYM_ARG(EVP_DigestVerifyInit), + DLSYM_ARG(EVP_EncryptFinal_ex), + DLSYM_ARG(EVP_EncryptInit_ex), + DLSYM_ARG(EVP_EncryptInit), + DLSYM_ARG(EVP_EncryptUpdate), + DLSYM_ARG(EVP_get_cipherbyname), + DLSYM_ARG(EVP_get_digestbyname), + DLSYM_ARG(EVP_KDF_CTX_free), + DLSYM_ARG(EVP_KDF_CTX_new), + DLSYM_ARG(EVP_KDF_derive), + DLSYM_ARG(EVP_KDF_fetch), + DLSYM_ARG(EVP_KDF_free), + DLSYM_ARG(EVP_MAC_CTX_free), + DLSYM_ARG(EVP_MAC_CTX_get_mac_size), + DLSYM_ARG(EVP_MAC_CTX_new), + DLSYM_ARG(EVP_MAC_fetch), + DLSYM_ARG(EVP_MAC_final), + DLSYM_ARG(EVP_MAC_free), + DLSYM_ARG(EVP_MAC_init), + DLSYM_ARG(EVP_MAC_update), + DLSYM_ARG(EVP_MD_CTX_free), + DLSYM_ARG(EVP_MD_CTX_get0_md), + DLSYM_ARG(EVP_MD_CTX_new), + DLSYM_ARG(EVP_MD_CTX_set_pkey_ctx), + DLSYM_ARG(EVP_MD_fetch), + DLSYM_ARG(EVP_MD_free), + DLSYM_ARG(EVP_MD_get_size), + DLSYM_ARG(EVP_MD_get_type), + DLSYM_ARG(EVP_MD_get0_name), + DLSYM_ARG(EVP_PKEY_CTX_free), + DLSYM_ARG(EVP_PKEY_CTX_new_from_name), + DLSYM_ARG(EVP_PKEY_CTX_new_id), + DLSYM_ARG(EVP_PKEY_CTX_new), + DLSYM_ARG(EVP_PKEY_CTX_set_ec_paramgen_curve_nid), + DLSYM_ARG(EVP_PKEY_CTX_set_rsa_oaep_md), + DLSYM_ARG(EVP_PKEY_CTX_set_rsa_padding), + DLSYM_ARG(EVP_PKEY_CTX_set_signature_md), + DLSYM_ARG(EVP_PKEY_CTX_set0_rsa_oaep_label), + DLSYM_ARG(EVP_PKEY_derive_init), + DLSYM_ARG(EVP_PKEY_derive_set_peer), + DLSYM_ARG(EVP_PKEY_derive), + DLSYM_ARG(EVP_PKEY_encrypt_init), + DLSYM_ARG(EVP_PKEY_encrypt), + DLSYM_ARG(EVP_PKEY_eq), + DLSYM_ARG(EVP_PKEY_free), + DLSYM_ARG(EVP_PKEY_fromdata_init), + DLSYM_ARG(EVP_PKEY_fromdata), + DLSYM_ARG(EVP_PKEY_get_base_id), + DLSYM_ARG(EVP_PKEY_get_bits), + DLSYM_ARG(EVP_PKEY_get_bn_param), + DLSYM_ARG(EVP_PKEY_get_group_name), + DLSYM_ARG(EVP_PKEY_get_id), + DLSYM_ARG(EVP_PKEY_get_utf8_string_param), + DLSYM_ARG(EVP_PKEY_get1_encoded_public_key), + DLSYM_ARG(EVP_PKEY_keygen_init), + DLSYM_ARG(EVP_PKEY_keygen), + DLSYM_ARG(EVP_PKEY_new_raw_public_key), + DLSYM_ARG(EVP_PKEY_new), + DLSYM_ARG(EVP_PKEY_verify_init), + DLSYM_ARG(EVP_PKEY_verify), + DLSYM_ARG(EVP_sha1), + DLSYM_ARG(EVP_sha256), + DLSYM_ARG(EVP_sha384), + DLSYM_ARG(EVP_sha512), + DLSYM_ARG(HMAC), + DLSYM_ARG(i2d_ASN1_INTEGER), + DLSYM_ARG(i2d_PKCS7_fp), + DLSYM_ARG(i2d_PKCS7), + DLSYM_ARG(i2d_PUBKEY_fp), + DLSYM_ARG(i2d_PUBKEY), + DLSYM_ARG(i2d_PublicKey), + DLSYM_ARG(i2d_X509_NAME), + DLSYM_ARG(i2d_X509), + DLSYM_ARG(OBJ_nid2obj), + DLSYM_ARG(OBJ_nid2sn), + DLSYM_ARG(OBJ_sn2nid), + DLSYM_ARG(OBJ_txt2obj), + DLSYM_ARG(OPENSSL_sk_new_null), + DLSYM_ARG(OPENSSL_sk_num), + DLSYM_ARG(OPENSSL_sk_pop_free), + DLSYM_ARG(OPENSSL_sk_push), + DLSYM_ARG(OPENSSL_sk_value), + DLSYM_ARG(OSSL_EC_curve_nid2name), + DLSYM_ARG(OSSL_PARAM_BLD_free), + DLSYM_ARG(OSSL_PARAM_BLD_new), + DLSYM_ARG(OSSL_PARAM_BLD_push_octet_string), + DLSYM_ARG(OSSL_PARAM_BLD_push_utf8_string), + DLSYM_ARG(OSSL_PARAM_BLD_to_param), + DLSYM_ARG(OSSL_PARAM_construct_BN), + DLSYM_ARG(OSSL_PARAM_construct_end), + DLSYM_ARG(OSSL_PARAM_construct_octet_string), + DLSYM_ARG(OSSL_PARAM_construct_utf8_string), + DLSYM_ARG(OSSL_PARAM_free), + DLSYM_ARG(OSSL_PROVIDER_try_load), + DLSYM_ARG(OSSL_STORE_close), + DLSYM_ARG(OSSL_STORE_expect), + DLSYM_ARG(OSSL_STORE_INFO_free), + DLSYM_ARG(OSSL_STORE_INFO_get1_CERT), + DLSYM_ARG(OSSL_STORE_INFO_get1_PKEY), + DLSYM_ARG(OSSL_STORE_load), + DLSYM_ARG(OSSL_STORE_open), + DLSYM_ARG(PEM_read_bio_PrivateKey), + DLSYM_ARG(PEM_read_bio_X509), + DLSYM_ARG(PEM_read_PrivateKey), + DLSYM_ARG(PEM_read_PUBKEY), + DLSYM_ARG(PEM_read_X509), + DLSYM_ARG(PEM_write_PrivateKey), + DLSYM_ARG(PEM_write_PUBKEY), + DLSYM_ARG(PEM_write_X509), + DLSYM_ARG(PKCS5_PBKDF2_HMAC), + DLSYM_ARG(PKCS7_add_attrib_content_type), + DLSYM_ARG(PKCS7_add_attrib_smimecap), + DLSYM_ARG(PKCS7_add_certificate), + DLSYM_ARG(PKCS7_add_signed_attribute), + DLSYM_ARG(PKCS7_add_signer), + DLSYM_ARG(PKCS7_add0_attrib_signing_time), + DLSYM_ARG(PKCS7_add1_attrib_digest), + DLSYM_ARG(PKCS7_ATTR_SIGN_it), + DLSYM_ARG(PKCS7_content_new), + DLSYM_ARG(PKCS7_ctrl), + DLSYM_ARG(PKCS7_dataFinal), + DLSYM_ARG(PKCS7_dataInit), + DLSYM_ARG(PKCS7_free), + DLSYM_ARG(PKCS7_get_signer_info), + DLSYM_ARG(PKCS7_new), + DLSYM_ARG(PKCS7_set_content), + DLSYM_ARG(PKCS7_set_type), + DLSYM_ARG(PKCS7_sign), + DLSYM_ARG(PKCS7_SIGNER_INFO_free), + DLSYM_ARG(PKCS7_SIGNER_INFO_new), + DLSYM_ARG(PKCS7_SIGNER_INFO_set), + DLSYM_ARG(PKCS7_verify), + DLSYM_ARG(SHA1), + DLSYM_ARG(SHA512), +#ifndef OPENSSL_NO_UI_CONSOLE + DLSYM_ARG(UI_create_method), + DLSYM_ARG(UI_destroy_method), + DLSYM_ARG(UI_get_default_method), + DLSYM_ARG(UI_get_method), + DLSYM_ARG(UI_get_string_type), + DLSYM_ARG(UI_get0_output_string), + DLSYM_ARG(UI_method_get_ex_data), + DLSYM_ARG(UI_method_get_reader), + DLSYM_ARG(UI_method_set_ex_data), + DLSYM_ARG(UI_method_set_reader), + DLSYM_ARG(UI_OpenSSL), + DLSYM_ARG(UI_set_default_method), + DLSYM_ARG(UI_set_result), +#endif + DLSYM_ARG(X509_ALGOR_free), + DLSYM_ARG(X509_ALGOR_set0), + DLSYM_ARG(X509_ATTRIBUTE_free), + DLSYM_ARG(X509_free), + DLSYM_ARG(X509_get_issuer_name), + DLSYM_ARG(X509_get_pubkey), + DLSYM_ARG(X509_get_signature_info), + DLSYM_ARG(X509_get_subject_name), + DLSYM_ARG(X509_get0_serialNumber), + DLSYM_ARG(X509_gmtime_adj), + DLSYM_ARG(X509_NAME_free), + DLSYM_ARG(X509_NAME_oneline), + DLSYM_ARG(X509_NAME_set), + DLSYM_ARG(X509_VERIFY_PARAM_set_hostflags), + DLSYM_ARG(X509_VERIFY_PARAM_set1_host), + DLSYM_ARG(X509_VERIFY_PARAM_set1_ip)); +#else + return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP), + "libcrypto support is not compiled in."); +#endif +} + +#if HAVE_OPENSSL /* For each error in the OpenSSL thread error queue, log the provided message and the OpenSSL error * string. If there are no errors in the OpenSSL thread queue, this logs the message with "No OpenSSL @@ -45,19 +646,25 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(UI_METHOD*, UI_destroy_method, NULL); ({ \ int UNIQ_T(R, u) = 0; \ for (;;) { \ - unsigned long UNIQ_T(E, u) = ERR_get_error(); \ + unsigned long UNIQ_T(E, u) = sym_ERR_get_error(); \ if (UNIQ_T(E, u) == 0) \ break; \ - ERR_error_string_n(UNIQ_T(E, u), buf, max); \ + sym_ERR_error_string_n(UNIQ_T(E, u), buf, max); \ UNIQ_T(R, u) = log_debug_errno(SYNTHETIC_ERRNO(EIO), fmt ": %s", ##__VA_ARGS__, buf); \ } \ UNIQ_T(R, u); \ }) int openssl_pubkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret) { + int r; + assert(pem); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + if (pem_size == SIZE_MAX) pem_size = strlen(pem); @@ -66,7 +673,7 @@ int openssl_pubkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret) { if (!f) return log_oom_debug(); - _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = PEM_read_PUBKEY(f, /* x= */ NULL, /* pam_password_cb= */ NULL, /* userdata= */ NULL); + _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = sym_PEM_read_PUBKEY(f, /* x= */ NULL, /* pam_password_cb= */ NULL, /* userdata= */ NULL); if (!pkey) return log_openssl_errors("Failed to parse PEM"); @@ -75,15 +682,21 @@ int openssl_pubkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret) { } int openssl_pubkey_to_pem(EVP_PKEY *pkey, char **ret) { + int r; + assert(pkey); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_(memstream_done) MemStream m = {}; FILE *f = memstream_init(&m); if (!f) return -ENOMEM; - if (PEM_write_PUBKEY(f, pkey) <= 0) + if (sym_PEM_write_PUBKEY(f, pkey) <= 0) return -EIO; return memstream_finalize(&m, ret, /* ret_size= */ NULL); @@ -94,15 +707,21 @@ int openssl_pubkey_to_pem(EVP_PKEY *pkey, char **ret) { * e.g. shake128. Returns 0 on success, -EOPNOTSUPP if the algorithm is not supported, or < 0 for any other * error. */ int openssl_digest_size(const char *digest_alg, size_t *ret_digest_size) { + int r; + assert(digest_alg); assert(ret_digest_size); - _cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_MD_freep) EVP_MD *md = sym_EVP_MD_fetch(NULL, digest_alg, NULL); if (!md) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Digest algorithm '%s' not supported.", digest_alg); - size_t digest_size = EVP_MD_get_size(md); + size_t digest_size = sym_EVP_MD_get_size(md); if (digest_size == 0) return log_openssl_errors("Failed to get Digest size"); @@ -127,20 +746,24 @@ int openssl_digest_many( assert(ret_digest); /* ret_digest_size is optional, as caller may already know the digest size */ - _cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_MD_freep) EVP_MD *md = sym_EVP_MD_fetch(NULL, digest_alg, NULL); if (!md) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Digest algorithm '%s' not supported.", digest_alg); - _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX *ctx = sym_EVP_MD_CTX_new(); if (!ctx) return log_openssl_errors("Failed to create new EVP_MD_CTX"); - if (!EVP_DigestInit_ex(ctx, md, NULL)) + if (!sym_EVP_DigestInit_ex(ctx, md, NULL)) return log_openssl_errors("Failed to initialize EVP_MD_CTX"); for (size_t i = 0; i < n_data; i++) - if (!EVP_DigestUpdate(ctx, data[i].iov_base, data[i].iov_len)) + if (!sym_EVP_DigestUpdate(ctx, data[i].iov_base, data[i].iov_len)) return log_openssl_errors("Failed to update Digest"); size_t digest_size; @@ -153,7 +776,7 @@ int openssl_digest_many( return log_oom_debug(); unsigned size; - if (!EVP_DigestFinal_ex(ctx, buf, &size)) + if (!sym_EVP_DigestFinal_ex(ctx, buf, &size)) return log_openssl_errors("Failed to finalize Digest"); assert(size == digest_size); @@ -177,44 +800,50 @@ int openssl_hmac_many( void **ret_digest, size_t *ret_digest_size) { + int r; + assert(digest_alg); assert(key); assert(data || n_data == 0); assert(ret_digest); /* ret_digest_size is optional, as caller may already know the digest size */ - _cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_MD_freep) EVP_MD *md = sym_EVP_MD_fetch(NULL, digest_alg, NULL); if (!md) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Digest algorithm '%s' not supported.", digest_alg); - _cleanup_(EVP_MAC_freep) EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL); + _cleanup_(EVP_MAC_freep) EVP_MAC *mac = sym_EVP_MAC_fetch(NULL, "HMAC", NULL); if (!mac) return log_openssl_errors("Failed to create new EVP_MAC"); - _cleanup_(EVP_MAC_CTX_freep) EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(mac); + _cleanup_(EVP_MAC_CTX_freep) EVP_MAC_CTX *ctx = sym_EVP_MAC_CTX_new(mac); if (!ctx) return log_openssl_errors("Failed to create new EVP_MAC_CTX"); - _cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); + _cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = sym_OSSL_PARAM_BLD_new(); if (!bld) return log_openssl_errors("Failed to create new OSSL_PARAM_BLD"); - if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_MAC_PARAM_DIGEST, (char*) digest_alg, 0)) + if (!sym_OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_MAC_PARAM_DIGEST, (char*) digest_alg, 0)) return log_openssl_errors("Failed to set HMAC OSSL_MAC_PARAM_DIGEST"); - _cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld); + _cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = sym_OSSL_PARAM_BLD_to_param(bld); if (!params) return log_openssl_errors("Failed to build HMAC OSSL_PARAM"); - if (!EVP_MAC_init(ctx, key, key_size, params)) + if (!sym_EVP_MAC_init(ctx, key, key_size, params)) return log_openssl_errors("Failed to initialize EVP_MAC_CTX"); for (size_t i = 0; i < n_data; i++) - if (!EVP_MAC_update(ctx, data[i].iov_base, data[i].iov_len)) + if (!sym_EVP_MAC_update(ctx, data[i].iov_base, data[i].iov_len)) return log_openssl_errors("Failed to update HMAC"); - size_t digest_size = EVP_MAC_CTX_get_mac_size(ctx); + size_t digest_size = sym_EVP_MAC_CTX_get_mac_size(ctx); if (digest_size == 0) return log_openssl_errors("Failed to get HMAC digest size"); @@ -223,7 +852,7 @@ int openssl_hmac_many( return log_oom_debug(); size_t size; - if (!EVP_MAC_final(ctx, buf, &size, digest_size)) + if (!sym_EVP_MAC_final(ctx, buf, &size, digest_size)) return log_openssl_errors("Failed to finalize HMAC"); assert(size == digest_size); @@ -253,6 +882,8 @@ int openssl_cipher_many( void **ret, size_t *ret_size) { + int r; + assert(alg); assert(bits > 0); assert(mode); @@ -262,28 +893,32 @@ int openssl_cipher_many( assert(ret); assert(ret_size); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_free_ char *cipher_alg = NULL; if (asprintf(&cipher_alg, "%s-%zu-%s", alg, bits, mode) < 0) return log_oom_debug(); - _cleanup_(EVP_CIPHER_freep) EVP_CIPHER *cipher = EVP_CIPHER_fetch(NULL, cipher_alg, NULL); + _cleanup_(EVP_CIPHER_freep) EVP_CIPHER *cipher = sym_EVP_CIPHER_fetch(NULL, cipher_alg, NULL); if (!cipher) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Cipher algorithm '%s' not supported.", cipher_alg); - _cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + _cleanup_(EVP_CIPHER_CTX_freep) EVP_CIPHER_CTX *ctx = sym_EVP_CIPHER_CTX_new(); if (!ctx) return log_openssl_errors("Failed to create new EVP_CIPHER_CTX"); /* Verify enough key data was provided. */ - int cipher_key_length = EVP_CIPHER_key_length(cipher); + int cipher_key_length = sym_EVP_CIPHER_get_key_length(cipher); assert(cipher_key_length >= 0); if ((size_t) cipher_key_length > key_size) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Not enough key bytes provided, require %d", cipher_key_length); /* Verify enough IV data was provided or, if no IV was provided, use a zeroed buffer for IV data. */ - int cipher_iv_length = EVP_CIPHER_iv_length(cipher); + int cipher_iv_length = sym_EVP_CIPHER_get_iv_length(cipher); assert(cipher_iv_length >= 0); _cleanup_free_ void *zero_iv = NULL; if (iv_size == 0) { @@ -298,10 +933,10 @@ int openssl_cipher_many( return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Not enough IV bytes provided, require %d", cipher_iv_length); - if (!EVP_EncryptInit(ctx, cipher, key, iv)) + if (!sym_EVP_EncryptInit(ctx, cipher, key, iv)) return log_openssl_errors("Failed to initialize EVP_CIPHER_CTX."); - int cipher_block_size = EVP_CIPHER_CTX_block_size(ctx); + int cipher_block_size = sym_EVP_CIPHER_CTX_get_block_size(ctx); assert(cipher_block_size > 0); _cleanup_free_ uint8_t *buf = NULL; @@ -313,7 +948,7 @@ int openssl_cipher_many( return log_oom_debug(); int update_size; - if (!EVP_EncryptUpdate(ctx, &buf[size], &update_size, data[i].iov_base, data[i].iov_len)) + if (!sym_EVP_EncryptUpdate(ctx, &buf[size], &update_size, data[i].iov_base, data[i].iov_len)) return log_openssl_errors("Failed to update Cipher."); size += update_size; @@ -323,7 +958,7 @@ int openssl_cipher_many( return log_oom_debug(); int final_size; - if (!EVP_EncryptFinal_ex(ctx, &buf[size], &final_size)) + if (!sym_EVP_EncryptFinal_ex(ctx, &buf[size], &final_size)) return log_openssl_errors("Failed to finalize Cipher."); *ret = TAKE_PTR(buf); @@ -347,20 +982,26 @@ int kdf_ss_derive( size_t derive_size, void **ret) { + int r; + assert(digest); assert(key); assert(derive_size > 0); assert(ret); - _cleanup_(EVP_KDF_freep) EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_KDF_freep) EVP_KDF *kdf = sym_EVP_KDF_fetch(NULL, "SSKDF", NULL); if (!kdf) return log_openssl_errors("Failed to create new EVP_KDF"); - _cleanup_(EVP_KDF_CTX_freep) EVP_KDF_CTX *ctx = EVP_KDF_CTX_new(kdf); + _cleanup_(EVP_KDF_CTX_freep) EVP_KDF_CTX *ctx = sym_EVP_KDF_CTX_new(kdf); if (!ctx) return log_openssl_errors("Failed to create new EVP_KDF_CTX"); - _cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); + _cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = sym_OSSL_PARAM_BLD_new(); if (!bld) return log_openssl_errors("Failed to create new OSSL_PARAM_BLD"); @@ -368,25 +1009,25 @@ int kdf_ss_derive( if (!buf) return log_oom_debug(); - if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_DIGEST, (char*) digest, 0)) + if (!sym_OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_DIGEST, (char*) digest, 0)) return log_openssl_errors("Failed to add KDF-SS OSSL_KDF_PARAM_DIGEST"); - if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_KEY, (char*) key, key_size)) + if (!sym_OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_KEY, (char*) key, key_size)) return log_openssl_errors("Failed to add KDF-SS OSSL_KDF_PARAM_KEY"); if (salt) - if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_SALT, (char*) salt, salt_size)) + if (!sym_OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_SALT, (char*) salt, salt_size)) return log_openssl_errors("Failed to add KDF-SS OSSL_KDF_PARAM_SALT"); if (info) - if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_INFO, (char*) info, info_size)) + if (!sym_OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_INFO, (char*) info, info_size)) return log_openssl_errors("Failed to add KDF-SS OSSL_KDF_PARAM_INFO"); - _cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld); + _cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = sym_OSSL_PARAM_BLD_to_param(bld); if (!params) return log_openssl_errors("Failed to build KDF-SS OSSL_PARAM"); - if (EVP_KDF_derive(ctx, buf, derive_size, params) <= 0) + if (sym_EVP_KDF_derive(ctx, buf, derive_size, params) <= 0) return log_openssl_errors("OpenSSL KDF-SS derive failed"); *ret = TAKE_PTR(buf); @@ -413,6 +1054,8 @@ int kdf_kb_hmac_derive( size_t derive_size, void **ret) { + int r; + assert(mode); assert(strcaseeq(mode, "COUNTER") || strcaseeq(mode, "FEEDBACK")); assert(digest); @@ -423,44 +1066,48 @@ int kdf_kb_hmac_derive( assert(derive_size > 0); assert(ret); - _cleanup_(EVP_KDF_freep) EVP_KDF *kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_KDF_freep) EVP_KDF *kdf = sym_EVP_KDF_fetch(NULL, "KBKDF", NULL); if (!kdf) return log_openssl_errors("Failed to create new EVP_KDF"); - _cleanup_(EVP_KDF_CTX_freep) EVP_KDF_CTX *ctx = EVP_KDF_CTX_new(kdf); + _cleanup_(EVP_KDF_CTX_freep) EVP_KDF_CTX *ctx = sym_EVP_KDF_CTX_new(kdf); if (!ctx) return log_openssl_errors("Failed to create new EVP_KDF_CTX"); - _cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); + _cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = sym_OSSL_PARAM_BLD_new(); if (!bld) return log_openssl_errors("Failed to create new OSSL_PARAM_BLD"); - if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_MAC, (char*) "HMAC", 0)) + if (!sym_OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_MAC, (char*) "HMAC", 0)) return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_MAC"); - if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_MODE, (char*) mode, 0)) + if (!sym_OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_MODE, (char*) mode, 0)) return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_MODE"); - if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_DIGEST, (char*) digest, 0)) + if (!sym_OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_KDF_PARAM_DIGEST, (char*) digest, 0)) return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_DIGEST"); if (key) - if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_KEY, (char*) key, key_size)) + if (!sym_OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_KEY, (char*) key, key_size)) return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_KEY"); if (salt) - if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_SALT, (char*) salt, salt_size)) + if (!sym_OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_SALT, (char*) salt, salt_size)) return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_SALT"); if (info) - if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_INFO, (char*) info, info_size)) + if (!sym_OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_INFO, (char*) info, info_size)) return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_INFO"); if (seed) - if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_SEED, (char*) seed, seed_size)) + if (!sym_OSSL_PARAM_BLD_push_octet_string(bld, OSSL_KDF_PARAM_SEED, (char*) seed, seed_size)) return log_openssl_errors("Failed to add KDF-KB OSSL_KDF_PARAM_SEED"); - _cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld); + _cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = sym_OSSL_PARAM_BLD_to_param(bld); if (!params) return log_openssl_errors("Failed to build KDF-KB OSSL_PARAM"); @@ -468,7 +1115,7 @@ int kdf_kb_hmac_derive( if (!buf) return log_oom_debug(); - if (EVP_KDF_derive(ctx, buf, derive_size, params) <= 0) + if (sym_EVP_KDF_derive(ctx, buf, derive_size, params) <= 0) return log_openssl_errors("OpenSSL KDF-KB derive failed"); *ret = TAKE_PTR(buf); @@ -486,28 +1133,33 @@ int rsa_encrypt_bytes( _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = NULL; _cleanup_free_ void *b = NULL; size_t l; + int r; assert(ret_encrypt_key); assert(ret_encrypt_key_size); - ctx = EVP_PKEY_CTX_new(pkey, NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + ctx = sym_EVP_PKEY_CTX_new(pkey, NULL); if (!ctx) return log_openssl_errors("Failed to allocate public key context"); - if (EVP_PKEY_encrypt_init(ctx) <= 0) + if (sym_EVP_PKEY_encrypt_init(ctx) <= 0) return log_openssl_errors("Failed to initialize public key context"); - if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) + if (sym_EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) return log_openssl_errors("Failed to configure PKCS#1 padding"); - if (EVP_PKEY_encrypt(ctx, NULL, &l, decrypted_key, decrypted_key_size) <= 0) + if (sym_EVP_PKEY_encrypt(ctx, NULL, &l, decrypted_key, decrypted_key_size) <= 0) return log_openssl_errors("Failed to determine encrypted key size"); b = malloc(l); if (!b) return -ENOMEM; - if (EVP_PKEY_encrypt(ctx, b, &l, decrypted_key, decrypted_key_size) <= 0) + if (sym_EVP_PKEY_encrypt(ctx, b, &l, decrypted_key, decrypted_key_size) <= 0) return log_openssl_errors("Failed to determine encrypted key size"); *ret_encrypt_key = TAKE_PTR(b); @@ -526,6 +1178,8 @@ int rsa_oaep_encrypt_bytes( void **ret_encrypt_key, size_t *ret_encrypt_key_size) { + int r; + assert(pkey); assert(digest_alg); assert(label); @@ -534,42 +1188,46 @@ int rsa_oaep_encrypt_bytes( assert(ret_encrypt_key); assert(ret_encrypt_key_size); - _cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_MD_freep) EVP_MD *md = sym_EVP_MD_fetch(NULL, digest_alg, NULL); if (!md) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Digest algorithm '%s' not supported.", digest_alg); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new((EVP_PKEY*) pkey, NULL); + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = sym_EVP_PKEY_CTX_new((EVP_PKEY*) pkey, NULL); if (!ctx) return log_openssl_errors("Failed to create new EVP_PKEY_CTX"); - if (EVP_PKEY_encrypt_init(ctx) <= 0) + if (sym_EVP_PKEY_encrypt_init(ctx) <= 0) return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); - if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) + if (sym_EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) return log_openssl_errors("Failed to configure RSA-OAEP padding"); - if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) + if (sym_EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) return log_openssl_errors("Failed to configure RSA-OAEP MD"); _cleanup_free_ char *duplabel = strdup(label); if (!duplabel) return log_oom_debug(); - if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, duplabel, strlen(duplabel) + 1) <= 0) + if (sym_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, duplabel, strlen(duplabel) + 1) <= 0) return log_openssl_errors("Failed to configure RSA-OAEP label"); /* ctx owns this now, don't free */ TAKE_PTR(duplabel); size_t size = 0; - if (EVP_PKEY_encrypt(ctx, NULL, &size, decrypted_key, decrypted_key_size) <= 0) + if (sym_EVP_PKEY_encrypt(ctx, NULL, &size, decrypted_key, decrypted_key_size) <= 0) return log_openssl_errors("Failed to determine RSA-OAEP encrypted key size"); _cleanup_free_ void *buf = malloc(size); if (!buf) return log_oom_debug(); - if (EVP_PKEY_encrypt(ctx, buf, &size, decrypted_key, decrypted_key_size) <= 0) + if (sym_EVP_PKEY_encrypt(ctx, buf, &size, decrypted_key, decrypted_key_size) <= 0) return log_openssl_errors("Failed to RSA-OAEP encrypt"); *ret_encrypt_key = TAKE_PTR(buf); @@ -583,7 +1241,7 @@ int rsa_pkey_to_suitable_key_size( size_t *ret_suitable_key_size) { size_t suitable_key_size; - int bits; + int bits, r; assert(pkey); assert(ret_suitable_key_size); @@ -591,10 +1249,14 @@ int rsa_pkey_to_suitable_key_size( /* Analyzes the specified public key and that it is RSA. If so, will return a suitable size for a * disk encryption key to encrypt with RSA for use in PKCS#11 security token schemes. */ - if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + if (sym_EVP_PKEY_get_base_id(pkey) != EVP_PKEY_RSA) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "X.509 certificate does not refer to RSA key."); - bits = EVP_PKEY_bits(pkey); + bits = sym_EVP_PKEY_get_bits(pkey); log_debug("Bits in RSA key: %i", bits); /* We use PKCS#1 padding for the RSA cleartext, hence let's leave some extra space for it, hence only @@ -612,6 +1274,7 @@ int rsa_pkey_to_suitable_key_size( * in big-endian format, e.g. wrap it with htobe32() for uint32_t. */ int rsa_pkey_from_n_e(const void *n, size_t n_size, const void *e, size_t e_size, EVP_PKEY **ret) { _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; + int r; assert(n); assert(n_size != 0); @@ -619,18 +1282,22 @@ int rsa_pkey_from_n_e(const void *n, size_t n_size, const void *e, size_t e_size assert(e_size != 0); assert(ret); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = sym_EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); if (!ctx) return log_openssl_errors("Failed to create new EVP_PKEY_CTX"); - if (EVP_PKEY_fromdata_init(ctx) <= 0) + if (sym_EVP_PKEY_fromdata_init(ctx) <= 0) return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); OSSL_PARAM params[3]; #if __BYTE_ORDER == __BIG_ENDIAN - params[0] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N, (void*)n, n_size); - params[1] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_E, (void*)e, e_size); + params[0] = sym_OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N, (void*)n, n_size); + params[1] = sym_OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_E, (void*)e, e_size); #else _cleanup_free_ void *native_n = memdup_reverse(n, n_size); if (!native_n) @@ -640,12 +1307,12 @@ int rsa_pkey_from_n_e(const void *n, size_t n_size, const void *e, size_t e_size if (!native_e) return log_oom_debug(); - params[0] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N, native_n, n_size); - params[1] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_E, native_e, e_size); + params[0] = sym_OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_N, native_n, n_size); + params[1] = sym_OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_RSA_E, native_e, e_size); #endif - params[2] = OSSL_PARAM_construct_end(); + params[2] = sym_OSSL_PARAM_construct_end(); - if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) + if (sym_EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) return log_openssl_errors("Failed to create RSA EVP_PKEY"); *ret = TAKE_PTR(pkey); @@ -661,27 +1328,33 @@ int rsa_pkey_to_n_e( void **ret_e, size_t *ret_e_size) { + int r; + assert(pkey); assert(ret_n); assert(ret_n_size); assert(ret_e); assert(ret_e_size); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_(BN_freep) BIGNUM *bn_n = NULL; - if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn_n)) + if (!sym_EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn_n)) return log_openssl_errors("Failed to get RSA n"); _cleanup_(BN_freep) BIGNUM *bn_e = NULL; - if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn_e)) + if (!sym_EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn_e)) return log_openssl_errors("Failed to get RSA e"); - size_t n_size = BN_num_bytes(bn_n), e_size = BN_num_bytes(bn_e); + size_t n_size = sym_BN_num_bytes(bn_n), e_size = sym_BN_num_bytes(bn_e); _cleanup_free_ void *n = malloc(n_size), *e = malloc(e_size); if (!n || !e) return log_oom_debug(); - assert(BN_bn2bin(bn_n, n) == (int) n_size); - assert(BN_bn2bin(bn_e, e) == (int) e_size); + assert(sym_BN_bn2bin(bn_n, n) == (int) n_size); + assert(sym_BN_bn2bin(bn_e, e) == (int) e_size); *ret_n = TAKE_PTR(n); *ret_n_size = n_size; @@ -700,58 +1373,64 @@ int ecc_pkey_from_curve_x_y( size_t y_size, EVP_PKEY **ret) { + int r; + assert(x); assert(y); assert(ret); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = sym_EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (!ctx) return log_openssl_errors("Failed to create new EVP_PKEY_CTX"); - _cleanup_(BN_freep) BIGNUM *bn_x = BN_bin2bn(x, x_size, NULL); + _cleanup_(BN_freep) BIGNUM *bn_x = sym_BN_bin2bn(x, x_size, NULL); if (!bn_x) return log_openssl_errors("Failed to create BIGNUM x"); - _cleanup_(BN_freep) BIGNUM *bn_y = BN_bin2bn(y, y_size, NULL); + _cleanup_(BN_freep) BIGNUM *bn_y = sym_BN_bin2bn(y, y_size, NULL); if (!bn_y) return log_openssl_errors("Failed to create BIGNUM y"); - _cleanup_(EC_GROUP_freep) EC_GROUP *group = EC_GROUP_new_by_curve_name(curve_id); + _cleanup_(EC_GROUP_freep) EC_GROUP *group = sym_EC_GROUP_new_by_curve_name(curve_id); if (!group) return log_openssl_errors("ECC curve id %d not supported", curve_id); - _cleanup_(EC_POINT_freep) EC_POINT *point = EC_POINT_new(group); + _cleanup_(EC_POINT_freep) EC_POINT *point = sym_EC_POINT_new(group); if (!point) return log_openssl_errors("Failed to create new EC_POINT"); - if (!EC_POINT_set_affine_coordinates(group, point, bn_x, bn_y, NULL)) + if (!sym_EC_POINT_set_affine_coordinates(group, point, bn_x, bn_y, NULL)) return log_openssl_errors("Failed to set ECC coordinates"); - if (EVP_PKEY_fromdata_init(ctx) <= 0) + if (sym_EVP_PKEY_fromdata_init(ctx) <= 0) return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); - _cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); + _cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = sym_OSSL_PARAM_BLD_new(); if (!bld) return log_openssl_errors("Failed to create new OSSL_PARAM_BLD"); - if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, (char*) OSSL_EC_curve_nid2name(curve_id), 0)) + if (!sym_OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, (char*) sym_OSSL_EC_curve_nid2name(curve_id), 0)) return log_openssl_errors("Failed to add ECC OSSL_PKEY_PARAM_GROUP_NAME"); _cleanup_(OPENSSL_freep) void *pbuf = NULL; size_t pbuf_len = 0; - pbuf_len = EC_POINT_point2buf(group, point, POINT_CONVERSION_UNCOMPRESSED, (unsigned char**) &pbuf, NULL); + pbuf_len = sym_EC_POINT_point2buf(group, point, POINT_CONVERSION_UNCOMPRESSED, (unsigned char**) &pbuf, NULL); if (pbuf_len == 0) return log_openssl_errors("Failed to convert ECC point to buffer"); - if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pbuf, pbuf_len)) + if (!sym_OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pbuf, pbuf_len)) return log_openssl_errors("Failed to add ECC OSSL_PKEY_PARAM_PUB_KEY"); - _cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld); + _cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = sym_OSSL_PARAM_BLD_to_param(bld); if (!params) return log_openssl_errors("Failed to build ECC OSSL_PARAM"); _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; - if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) + if (sym_EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) return log_openssl_errors("Failed to create ECC EVP_PKEY"); *ret = TAKE_PTR(pkey); @@ -767,38 +1446,42 @@ int ecc_pkey_to_curve_x_y( size_t *ret_y_size) { _cleanup_(BN_freep) BIGNUM *bn_x = NULL, *bn_y = NULL; - int curve_id; + int curve_id, r; assert(pkey); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + size_t name_size; - if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0, &name_size)) + if (!sym_EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0, &name_size)) return log_openssl_errors("Failed to get ECC group name size"); _cleanup_free_ char *name = new(char, name_size + 1); if (!name) return log_oom_debug(); - if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, name, name_size + 1, NULL)) + if (!sym_EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, name, name_size + 1, NULL)) return log_openssl_errors("Failed to get ECC group name"); - curve_id = OBJ_sn2nid(name); + curve_id = sym_OBJ_sn2nid(name); if (curve_id == NID_undef) return log_openssl_errors("Failed to get ECC curve id"); - if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &bn_x)) + if (!sym_EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &bn_x)) return log_openssl_errors("Failed to get ECC point x"); - if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &bn_y)) + if (!sym_EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &bn_y)) return log_openssl_errors("Failed to get ECC point y"); - size_t x_size = BN_num_bytes(bn_x), y_size = BN_num_bytes(bn_y); + size_t x_size = sym_BN_num_bytes(bn_x), y_size = sym_BN_num_bytes(bn_y); _cleanup_free_ void *x = malloc(x_size), *y = malloc(y_size); if (!x || !y) return log_oom_debug(); - assert(BN_bn2bin(bn_x, x) == (int) x_size); - assert(BN_bn2bin(bn_y, y) == (int) y_size); + assert(sym_BN_bn2bin(bn_x, x) == (int) x_size); + assert(sym_BN_bn2bin(bn_y, y) == (int) y_size); if (ret_curve_id) *ret_curve_id = curve_id; @@ -816,20 +1499,26 @@ int ecc_pkey_to_curve_x_y( /* Generate a new ECC key for the specified ECC curve id. */ int ecc_pkey_new(int curve_id, EVP_PKEY **ret) { + int r; + assert(ret); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = sym_EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (!ctx) return log_openssl_errors("Failed to create new EVP_PKEY_CTX"); - if (EVP_PKEY_keygen_init(ctx) <= 0) + if (sym_EVP_PKEY_keygen_init(ctx) <= 0) return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); - if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, curve_id) <= 0) + if (sym_EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, curve_id) <= 0) return log_openssl_errors("Failed to set ECC curve %d", curve_id); _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; - if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + if (sym_EVP_PKEY_keygen(ctx, &pkey) <= 0) return log_openssl_errors("Failed to generate ECC key"); *ret = TAKE_PTR(pkey); @@ -847,30 +1536,36 @@ int ecc_ecdh(const EVP_PKEY *private_pkey, void **ret_shared_secret, size_t *ret_shared_secret_size) { + int r; + assert(private_pkey); assert(peer_pkey); assert(ret_shared_secret); assert(ret_shared_secret_size); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new((EVP_PKEY*) private_pkey, NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = sym_EVP_PKEY_CTX_new((EVP_PKEY*) private_pkey, NULL); if (!ctx) return log_openssl_errors("Failed to create new EVP_PKEY_CTX"); - if (EVP_PKEY_derive_init(ctx) <= 0) + if (sym_EVP_PKEY_derive_init(ctx) <= 0) return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); - if (EVP_PKEY_derive_set_peer(ctx, (EVP_PKEY*) peer_pkey) <= 0) + if (sym_EVP_PKEY_derive_set_peer(ctx, (EVP_PKEY*) peer_pkey) <= 0) return log_openssl_errors("Failed to set ECC derive peer"); size_t shared_secret_size; - if (EVP_PKEY_derive(ctx, NULL, &shared_secret_size) <= 0) + if (sym_EVP_PKEY_derive(ctx, NULL, &shared_secret_size) <= 0) return log_openssl_errors("Failed to get ECC shared secret size"); _cleanup_(erase_and_freep) void *shared_secret = malloc(shared_secret_size); if (!shared_secret) return log_oom_debug(); - if (EVP_PKEY_derive(ctx, (unsigned char*) shared_secret, &shared_secret_size) <= 0) + if (sym_EVP_PKEY_derive(ctx, (unsigned char*) shared_secret, &shared_secret_size) <= 0) return log_openssl_errors("Failed to derive ECC shared secret"); *ret_shared_secret = TAKE_PTR(shared_secret); @@ -885,6 +1580,7 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s int sz, lsz, msz; unsigned umsz; unsigned char *dd; + int r; /* Calculates a message digest of the DER encoded public key */ @@ -893,7 +1589,11 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s assert(ret); assert(ret_size); - sz = i2d_PublicKey(pk, NULL); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + sz = sym_i2d_PublicKey(pk, NULL); if (sz < 0) return log_openssl_errors("Unable to convert public key to DER format"); @@ -901,21 +1601,21 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s if (!d) return log_oom_debug(); - lsz = i2d_PublicKey(pk, &dd); + lsz = sym_i2d_PublicKey(pk, &dd); if (lsz < 0) return log_openssl_errors("Unable to convert public key to DER format"); - m = EVP_MD_CTX_new(); + m = sym_EVP_MD_CTX_new(); if (!m) return log_openssl_errors("Failed to create new EVP_MD_CTX"); - if (EVP_DigestInit_ex(m, md, NULL) != 1) - return log_openssl_errors("Failed to initialize %s context", EVP_MD_name(md)); + if (sym_EVP_DigestInit_ex(m, md, NULL) != 1) + return log_openssl_errors("Failed to initialize %s context", sym_EVP_MD_get0_name(md)); - if (EVP_DigestUpdate(m, d, lsz) != 1) - return log_openssl_errors("Failed to run %s context", EVP_MD_name(md)); + if (sym_EVP_DigestUpdate(m, d, lsz) != 1) + return log_openssl_errors("Failed to run %s context", sym_EVP_MD_get0_name(md)); - msz = EVP_MD_size(md); + msz = sym_EVP_MD_get_size(md); assert(msz > 0); h = malloc(msz); @@ -923,7 +1623,7 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s return log_oom_debug(); umsz = msz; - if (EVP_DigestFinal_ex(m, h, &umsz) != 1) + if (sym_EVP_DigestFinal_ex(m, h, &umsz) != 1) return log_openssl_errors("Failed to finalize hash context"); assert(umsz == (unsigned) msz); @@ -946,6 +1646,10 @@ int digest_and_sign( assert(ret); assert(ret_size); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + if (size == 0) data = ""; /* make sure to pass a valid pointer to OpenSSL */ else { @@ -955,28 +1659,28 @@ int digest_and_sign( size = strlen(data); } - _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX* mdctx = EVP_MD_CTX_new(); + _cleanup_(EVP_MD_CTX_freep) EVP_MD_CTX* mdctx = sym_EVP_MD_CTX_new(); if (!mdctx) return log_openssl_errors("Failed to create new EVP_MD_CTX"); - if (EVP_DigestSignInit(mdctx, NULL, md, NULL, privkey) != 1) { + if (sym_EVP_DigestSignInit(mdctx, NULL, md, NULL, privkey) != 1) { /* Distro security policies often disable support for SHA-1. Let's return a recognizable * error for that case. */ - bool invalid_digest = ERR_GET_REASON(ERR_peek_last_error()) == EVP_R_INVALID_DIGEST; + bool invalid_digest = ERR_GET_REASON(sym_ERR_peek_last_error()) == EVP_R_INVALID_DIGEST; r = log_openssl_errors("Failed to initialize signature context"); return invalid_digest ? -EADDRNOTAVAIL : r; } /* Determine signature size */ size_t ss; - if (EVP_DigestSign(mdctx, NULL, &ss, data, size) != 1) + if (sym_EVP_DigestSign(mdctx, NULL, &ss, data, size) != 1) return log_openssl_errors("Failed to determine size of signature"); _cleanup_free_ void *sig = malloc(ss); if (!sig) return log_oom_debug(); - if (EVP_DigestSign(mdctx, sig, &ss, data, size) != 1) + if (sym_EVP_DigestSign(mdctx, sig, &ss, data, size) != 1) return log_openssl_errors("Failed to sign data"); *ret = TAKE_PTR(sig); @@ -985,6 +1689,8 @@ int digest_and_sign( } int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorithm, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si) { + int r; + assert(certificate); assert(ret_p7); @@ -994,67 +1700,71 @@ int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorit * copied into the signer info's "enc_digest" field. If the signing hash algorithm is not provided, * SHA-256 is used. */ - _cleanup_(PKCS7_freep) PKCS7 *p7 = PKCS7_new(); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(PKCS7_freep) PKCS7 *p7 = sym_PKCS7_new(); if (!p7) return log_oom(); - if (PKCS7_set_type(p7, NID_pkcs7_signed) == 0) + if (sym_PKCS7_set_type(p7, NID_pkcs7_signed) == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 type: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (PKCS7_content_new(p7, NID_pkcs7_data) == 0) + if (sym_PKCS7_content_new(p7, NID_pkcs7_data) == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 content: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (PKCS7_add_certificate(p7, certificate) == 0) + if (sym_PKCS7_add_certificate(p7, certificate) == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 certificate: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); int x509_pknid = 0; - if (X509_get_signature_info(certificate, NULL, &x509_pknid, NULL, NULL) == 0) + if (sym_X509_get_signature_info(certificate, NULL, &x509_pknid, NULL, NULL) == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to get X509 digest NID: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - const EVP_MD *md = EVP_get_digestbyname(hash_algorithm ?: "SHA256"); + const EVP_MD *md = sym_EVP_get_digestbyname(hash_algorithm ?: "SHA256"); if (!md) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to get digest algorithm '%s'", hash_algorithm ?: "SHA256"); - _cleanup_(PKCS7_SIGNER_INFO_freep) PKCS7_SIGNER_INFO *si = PKCS7_SIGNER_INFO_new(); + _cleanup_(PKCS7_SIGNER_INFO_freep) PKCS7_SIGNER_INFO *si = sym_PKCS7_SIGNER_INFO_new(); if (!si) return log_oom(); if (private_key) { - if (PKCS7_SIGNER_INFO_set(si, certificate, private_key, md) <= 0) + if (sym_PKCS7_SIGNER_INFO_set(si, certificate, private_key, md) <= 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to configure signer info: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); } else { - if (ASN1_INTEGER_set(si->version, 1) == 0) + if (sym_ASN1_INTEGER_set(si->version, 1) == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set signer info version: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (X509_NAME_set(&si->issuer_and_serial->issuer, X509_get_issuer_name(certificate)) == 0) + if (sym_X509_NAME_set(&si->issuer_and_serial->issuer, sym_X509_get_issuer_name(certificate)) == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set signer info issuer: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - ASN1_INTEGER_free(si->issuer_and_serial->serial); - si->issuer_and_serial->serial = ASN1_INTEGER_dup(X509_get0_serialNumber(certificate)); + sym_ASN1_INTEGER_free(si->issuer_and_serial->serial); + si->issuer_and_serial->serial = sym_ASN1_INTEGER_dup(sym_X509_get0_serialNumber(certificate)); if (!si->issuer_and_serial->serial) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set signer info serial: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (X509_ALGOR_set0(si->digest_alg, OBJ_nid2obj(EVP_MD_type(md)), V_ASN1_NULL, NULL) == 0) + if (sym_X509_ALGOR_set0(si->digest_alg, sym_OBJ_nid2obj(sym_EVP_MD_get_type(md)), V_ASN1_NULL, NULL) == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set signer info digest algorithm: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); - if (X509_ALGOR_set0(si->digest_enc_alg, OBJ_nid2obj(x509_pknid), V_ASN1_NULL, NULL) == 0) + if (sym_X509_ALGOR_set0(si->digest_enc_alg, sym_OBJ_nid2obj(x509_pknid), V_ASN1_NULL, NULL) == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set signer info signing algorithm: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); } - if (PKCS7_add_signer(p7, si) == 0) + if (sym_PKCS7_add_signer(p7, si) == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 signer info: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); *ret_p7 = TAKE_PTR(p7); if (ret_si) @@ -1114,7 +1824,11 @@ static int ecc_pkey_generate_volume_keys( _cleanup_free_ char *curve_name = NULL; size_t len = 0; - if (EVP_PKEY_get_group_name(pkey, NULL, 0, &len) != 1 || len == 0) + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + if (sym_EVP_PKEY_get_group_name(pkey, NULL, 0, &len) != 1 || len == 0) return log_openssl_errors("Failed to determine PKEY group name length"); len++; @@ -1122,10 +1836,10 @@ static int ecc_pkey_generate_volume_keys( if (!curve_name) return log_oom_debug(); - if (EVP_PKEY_get_group_name(pkey, curve_name, len, &len) != 1) + if (sym_EVP_PKEY_get_group_name(pkey, curve_name, len, &len) != 1) return log_openssl_errors("Failed to get PKEY group name"); - r = ecc_pkey_new(OBJ_sn2nid(curve_name), &pkey_new); + r = ecc_pkey_new(sym_OBJ_sn2nid(curve_name), &pkey_new); if (r < 0) return log_debug_errno(r, "Failed to generate a new EC keypair: %m"); @@ -1135,7 +1849,7 @@ static int ecc_pkey_generate_volume_keys( /* EVP_PKEY_get1_encoded_public_key() always returns uncompressed format of EC points. See https://github.com/openssl/openssl/discussions/22835 */ - saved_key_size = EVP_PKEY_get1_encoded_public_key(pkey_new, &saved_key); + saved_key_size = sym_EVP_PKEY_get1_encoded_public_key(pkey_new, &saved_key); if (saved_key_size == 0) return log_openssl_errors("Failed to convert the generated public key to SEC1 format"); @@ -1195,13 +1909,19 @@ int pkey_generate_volume_keys( void **ret_saved_key, size_t *ret_saved_key_size) { + int r; + assert(pkey); assert(ret_decrypted_key); assert(ret_decrypted_key_size); assert(ret_saved_key); assert(ret_saved_key_size); - int type = EVP_PKEY_get_base_id(pkey); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + int type = sym_EVP_PKEY_get_base_id(pkey); switch (type) { case EVP_PKEY_RSA: @@ -1214,7 +1934,7 @@ int pkey_generate_volume_keys( return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine a type of public key."); default: - return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unsupported public key type: %s", OBJ_nid2sn(type)); + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unsupported public key type: %s", sym_OBJ_nid2sn(type)); } } @@ -1224,18 +1944,24 @@ static int load_key_from_provider( UI_METHOD *ui_method, EVP_PKEY **ret) { + int r; + assert(provider); assert(private_key_uri); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + /* Load the provider so that this can work without any custom written configuration in /etc/. * Also load the 'default' as that seems to be the recommendation. */ - if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true)) + if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true)) return log_openssl_errors("Failed to load OpenSSL provider '%s'", provider); - if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL, "default", /* retain_fallbacks= */ true)) + if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, "default", /* retain_fallbacks= */ true)) return log_openssl_errors("Failed to load OpenSSL provider 'default'"); - _cleanup_(OSSL_STORE_closep) OSSL_STORE_CTX *store = OSSL_STORE_open( + _cleanup_(OSSL_STORE_closep) OSSL_STORE_CTX *store = sym_OSSL_STORE_open( private_key_uri, ui_method, /* ui_data= */ NULL, @@ -1244,14 +1970,14 @@ static int load_key_from_provider( if (!store) return log_openssl_errors("Failed to open OpenSSL store via '%s'", private_key_uri); - if (OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY) == 0) + if (sym_OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY) == 0) return log_openssl_errors("Failed to filter store by private keys"); - _cleanup_(OSSL_STORE_INFO_freep) OSSL_STORE_INFO *info = OSSL_STORE_load(store); + _cleanup_(OSSL_STORE_INFO_freep) OSSL_STORE_INFO *info = sym_OSSL_STORE_load(store); if (!info) return log_openssl_errors("Failed to load OpenSSL store via '%s'", private_key_uri); - _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = OSSL_STORE_INFO_get1_PKEY(info); + _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = sym_OSSL_STORE_INFO_get1_PKEY(info); if (!private_key) return log_openssl_errors("Failed to load private key via '%s'", private_key_uri); @@ -1261,20 +1987,28 @@ static int load_key_from_provider( } static int load_key_from_engine(const char *engine, const char *private_key_uri, UI_METHOD *ui_method, EVP_PKEY **ret) { +#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) + int r; +#endif + assert(engine); assert(private_key_uri); assert(ret); #if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + DISABLE_WARNING_DEPRECATED_DECLARATIONS; - _cleanup_(ENGINE_freep) ENGINE *e = ENGINE_by_id(engine); + _cleanup_(ENGINE_freep) ENGINE *e = sym_ENGINE_by_id(engine); if (!e) return log_openssl_errors("Failed to load signing engine '%s'", engine); - if (ENGINE_init(e) == 0) + if (sym_ENGINE_init(e) == 0) return log_openssl_errors("Failed to initialize signing engine '%s'", engine); - _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = ENGINE_load_private_key(e, private_key_uri, ui_method, /* callback_data= */ NULL); + _cleanup_(EVP_PKEY_freep) EVP_PKEY *private_key = sym_ENGINE_load_private_key(e, private_key_uri, ui_method, /* callback_data= */ NULL); if (!private_key) return log_openssl_errors("Failed to load private key from '%s'", private_key_uri); REENABLE_WARNING; @@ -1291,14 +2025,14 @@ static int load_key_from_engine(const char *engine, const char *private_key_uri, static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) { int r; - switch(UI_get_string_type(uis)) { + switch(sym_UI_get_string_type(uis)) { case UIT_PROMPT: { /* If no ask password request was configured use the default openssl UI. */ - AskPasswordRequest *req = (AskPasswordRequest*) UI_method_get_ex_data(UI_get_method(ui), 0); + AskPasswordRequest *req = (AskPasswordRequest*) sym_UI_method_get_ex_data(sym_UI_get_method(ui), 0); if (!req) - return (UI_method_get_reader(UI_OpenSSL()))(ui, uis); + return (sym_UI_method_get_reader(sym_UI_OpenSSL()))(ui, uis); - req->message = UI_get0_output_string(uis); + req->message = sym_UI_get0_output_string(uis); _cleanup_strv_free_ char **l = NULL; r = ask_password_auto(req, ASK_PASSWORD_ACCEPT_CACHED|ASK_PASSWORD_PUSH_CACHE, &l); @@ -1312,7 +2046,7 @@ static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) { return 0; } - if (UI_set_result(ui, uis, *l) != 0) { + if (sym_UI_set_result(ui, uis, *l) != 0) { log_openssl_errors("Failed to set user interface result"); return 0; } @@ -1320,7 +2054,7 @@ static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) { return 1; } default: - return (UI_method_get_reader(UI_OpenSSL()))(ui, uis); + return (sym_UI_method_get_reader(sym_UI_OpenSSL()))(ui, uis); } } #endif @@ -1335,6 +2069,10 @@ static int openssl_load_private_key_from_file(const char *path, EVP_PKEY **ret) assert(path); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + r = read_full_file_full( AT_FDCWD, path, UINT64_MAX, SIZE_MAX, READ_FULL_FILE_SECURE|READ_FULL_FILE_WARN_WORLD_READABLE|READ_FULL_FILE_CONNECT_SOCKET, @@ -1343,14 +2081,14 @@ static int openssl_load_private_key_from_file(const char *path, EVP_PKEY **ret) if (r < 0) return log_debug_errno(r, "Failed to read key file '%s': %m", path); - kb = BIO_new_mem_buf(rawkey, rawkeysz); + kb = sym_BIO_new_mem_buf(rawkey, rawkeysz); if (!kb) return log_oom_debug(); - pk = PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL); + pk = sym_PEM_read_bio_PrivateKey(kb, NULL, NULL, NULL); if (!pk) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to parse PEM private key: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); *ret = TAKE_PTR(pk); @@ -1358,15 +2096,23 @@ static int openssl_load_private_key_from_file(const char *path, EVP_PKEY **ret) } static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSSLAskPasswordUI **ret) { +#ifndef OPENSSL_NO_UI_CONSOLE + int r; +#endif + assert(request); assert(ret); #ifndef OPENSSL_NO_UI_CONSOLE - _cleanup_(UI_destroy_methodp) UI_METHOD *method = UI_create_method("systemd-ask-password"); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + _cleanup_(UI_destroy_methodp) UI_METHOD *method = sym_UI_create_method("systemd-ask-password"); if (!method) return log_openssl_errors("Failed to initialize openssl user interface"); - if (UI_method_set_reader(method, openssl_ask_password_ui_read) != 0) + if (sym_UI_method_set_reader(method, openssl_ask_password_ui_read) != 0) return log_openssl_errors("Failed to set openssl user interface reader"); OpenSSLAskPasswordUI *ui = new(OpenSSLAskPasswordUI, 1); @@ -1378,9 +2124,9 @@ static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSS .request = *request, }; - UI_set_default_method(ui->method); + sym_UI_set_default_method(ui->method); - if (UI_method_set_ex_data(ui->method, 0, &ui->request) == 0) + if (sym_UI_method_set_ex_data(ui->method, 0, &ui->request) == 0) return log_openssl_errors("Failed to set extra data for UI method"); *ret = TAKE_PTR(ui); @@ -1400,6 +2146,10 @@ static int load_x509_certificate_from_file(const char *path, X509 **ret) { assert(path); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + r = read_full_file_full( AT_FDCWD, path, UINT64_MAX, SIZE_MAX, READ_FULL_FILE_CONNECT_SOCKET, @@ -1408,14 +2158,14 @@ static int load_x509_certificate_from_file(const char *path, X509 **ret) { if (r < 0) return log_debug_errno(r, "Failed to read certificate file '%s': %m", path); - cb = BIO_new_mem_buf(rawcert, rawcertsz); + cb = sym_BIO_new_mem_buf(rawcert, rawcertsz); if (!cb) return log_oom_debug(); - cert = PEM_read_bio_X509(cb, NULL, NULL, NULL); + cert = sym_PEM_read_bio_X509(cb, NULL, NULL, NULL); if (!cert) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse X.509 certificate: %s", - ERR_error_string(ERR_get_error(), NULL)); + sym_ERR_error_string(sym_ERR_get_error(), NULL)); *ret = TAKE_PTR(cert); @@ -1423,18 +2173,24 @@ static int load_x509_certificate_from_file(const char *path, X509 **ret) { } static int load_x509_certificate_from_provider(const char *provider, const char *certificate_uri, X509 **ret) { + int r; + assert(provider); assert(certificate_uri); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + /* Load the provider so that this can work without any custom written configuration in /etc/. * Also load the 'default' as that seems to be the recommendation. */ - if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true)) + if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true)) return log_openssl_errors("Failed to load OpenSSL provider '%s'", provider); - if (!OSSL_PROVIDER_try_load(/* ctx= */ NULL, "default", /* retain_fallbacks= */ true)) + if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, "default", /* retain_fallbacks= */ true)) return log_openssl_errors("Failed to load OpenSSL provider 'default'"); - _cleanup_(OSSL_STORE_closep) OSSL_STORE_CTX *store = OSSL_STORE_open( + _cleanup_(OSSL_STORE_closep) OSSL_STORE_CTX *store = sym_OSSL_STORE_open( certificate_uri, /* ui_method= */ NULL, /* ui_method= */ NULL, @@ -1443,14 +2199,14 @@ static int load_x509_certificate_from_provider(const char *provider, const char if (!store) return log_openssl_errors("Failed to open OpenSSL store via '%s'", certificate_uri); - if (OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) == 0) + if (sym_OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) == 0) return log_openssl_errors("Failed to filter store by X.509 certificates"); - _cleanup_(OSSL_STORE_INFO_freep) OSSL_STORE_INFO *info = OSSL_STORE_load(store); + _cleanup_(OSSL_STORE_INFO_freep) OSSL_STORE_INFO *info = sym_OSSL_STORE_load(store); if (!info) return log_openssl_errors("Failed to load OpenSSL store via '%s'", certificate_uri); - _cleanup_(X509_freep) X509 *cert = OSSL_STORE_INFO_get1_CERT(info); + _cleanup_(X509_freep) X509 *cert = sym_OSSL_STORE_INFO_get1_CERT(info); if (!cert) return log_openssl_errors("Failed to load certificate via '%s'", certificate_uri); @@ -1464,20 +2220,24 @@ OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) { return NULL; #ifndef OPENSSL_NO_UI_CONSOLE - assert(UI_get_default_method() == ui->method); - UI_set_default_method(UI_OpenSSL()); - UI_destroy_method(ui->method); + assert(sym_UI_get_default_method() == ui->method); + sym_UI_set_default_method(sym_UI_OpenSSL()); + sym_UI_destroy_method(ui->method); #endif return mfree(ui); } int x509_fingerprint(X509 *cert, uint8_t buffer[static SHA256_DIGEST_SIZE]) { _cleanup_free_ uint8_t *der = NULL; - int dersz; + int dersz, r; assert(cert); - dersz = i2d_X509(cert, &der); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + dersz = sym_i2d_X509(cert, &der); if (dersz < 0) return log_openssl_errors("Unable to convert PEM certificate to DER format"); @@ -1581,12 +2341,16 @@ int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret) { assert(private_key); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_(memstream_done) MemStream m = {}; FILE *tf = memstream_init(&m); if (!tf) return -ENOMEM; - if (i2d_PUBKEY_fp(tf, private_key) != 1) + if (sym_i2d_PUBKEY_fp(tf, private_key) != 1) return -EIO; _cleanup_(erase_and_freep) char *buf = NULL; @@ -1596,7 +2360,7 @@ int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret) { return r; const unsigned char *t = (const unsigned char*) buf; - if (!d2i_PUBKEY(ret, &t, len)) + if (!sym_d2i_PUBKEY(ret, &t, len)) return -EIO; return 0; diff --git a/src/shared/crypto-util.h b/src/shared/crypto-util.h new file mode 100644 index 0000000000..08c5e1ac85 --- /dev/null +++ b/src/shared/crypto-util.h @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "shared-forward.h" +#include "iovec-util.h" +#include "sha256.h" + +typedef enum CertificateSourceType { + OPENSSL_CERTIFICATE_SOURCE_FILE, + OPENSSL_CERTIFICATE_SOURCE_PROVIDER, + _OPENSSL_CERTIFICATE_SOURCE_MAX, + _OPENSSL_CERTIFICATE_SOURCE_INVALID = -EINVAL, +} CertificateSourceType; + +typedef enum KeySourceType { + OPENSSL_KEY_SOURCE_FILE, + OPENSSL_KEY_SOURCE_ENGINE, + OPENSSL_KEY_SOURCE_PROVIDER, + _OPENSSL_KEY_SOURCE_MAX, + _OPENSSL_KEY_SOURCE_INVALID = -EINVAL, +} KeySourceType; + +typedef struct OpenSSLAskPasswordUI OpenSSLAskPasswordUI; + +int parse_openssl_certificate_source_argument(const char *argument, char **certificate_source, CertificateSourceType *certificate_source_type); + +int parse_openssl_key_source_argument(const char *argument, char **private_key_source, KeySourceType *private_key_source_type); + +int dlopen_libcrypto(int log_level); + +#define X509_FINGERPRINT_SIZE SHA256_DIGEST_SIZE + +#if HAVE_OPENSSL +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ +# include /* IWYU pragma: export */ + +# include "dlfcn-util.h" + +extern DLSYM_PROTOTYPE(ASN1_ANY_it); +extern DLSYM_PROTOTYPE(ASN1_BIT_STRING_it); +extern DLSYM_PROTOTYPE(ASN1_BMPSTRING_it); +extern DLSYM_PROTOTYPE(ASN1_BMPSTRING_new); +extern DLSYM_PROTOTYPE(ASN1_get_object); +extern DLSYM_PROTOTYPE(ASN1_IA5STRING_it); +extern DLSYM_PROTOTYPE(ASN1_item_d2i); +extern DLSYM_PROTOTYPE(ASN1_item_free); +extern DLSYM_PROTOTYPE(ASN1_item_i2d); +extern DLSYM_PROTOTYPE(ASN1_item_new); +extern DLSYM_PROTOTYPE(ASN1_OBJECT_it); +extern DLSYM_PROTOTYPE(ASN1_OCTET_STRING_free); +extern DLSYM_PROTOTYPE(ASN1_OCTET_STRING_it); +extern DLSYM_PROTOTYPE(ASN1_OCTET_STRING_set); +extern DLSYM_PROTOTYPE(ASN1_STRING_get0_data); +extern DLSYM_PROTOTYPE(ASN1_STRING_length); +extern DLSYM_PROTOTYPE(ASN1_STRING_new); +extern DLSYM_PROTOTYPE(ASN1_STRING_set); +extern DLSYM_PROTOTYPE(ASN1_STRING_set0); +extern DLSYM_PROTOTYPE(ASN1_TIME_free); +extern DLSYM_PROTOTYPE(ASN1_TIME_set); +extern DLSYM_PROTOTYPE(ASN1_TYPE_new); +extern DLSYM_PROTOTYPE(BIO_ctrl); +extern DLSYM_PROTOTYPE(BIO_find_type); +extern DLSYM_PROTOTYPE(BIO_free_all); +extern DLSYM_PROTOTYPE(BIO_free); +extern DLSYM_PROTOTYPE(BIO_new_mem_buf); +extern DLSYM_PROTOTYPE(BIO_new_socket); +extern DLSYM_PROTOTYPE(BIO_new); +extern DLSYM_PROTOTYPE(BIO_s_mem); +extern DLSYM_PROTOTYPE(BIO_write); +extern DLSYM_PROTOTYPE(BN_bin2bn); +extern DLSYM_PROTOTYPE(BN_bn2nativepad); +extern DLSYM_PROTOTYPE(BN_CTX_free); +extern DLSYM_PROTOTYPE(BN_CTX_new); +extern DLSYM_PROTOTYPE(BN_free); +extern DLSYM_PROTOTYPE(BN_new); +extern DLSYM_PROTOTYPE(BN_num_bits); +extern DLSYM_PROTOTYPE(CRYPTO_free); +extern DLSYM_PROTOTYPE(d2i_ASN1_OCTET_STRING); +extern DLSYM_PROTOTYPE(d2i_ECPKParameters); +extern DLSYM_PROTOTYPE(d2i_PKCS7); +extern DLSYM_PROTOTYPE(d2i_PUBKEY); +extern DLSYM_PROTOTYPE(d2i_X509); +extern DLSYM_PROTOTYPE(EC_GROUP_free); +extern DLSYM_PROTOTYPE(EC_GROUP_get_curve_name); +extern DLSYM_PROTOTYPE(EC_GROUP_get_curve); +extern DLSYM_PROTOTYPE(EC_GROUP_get_field_type); +extern DLSYM_PROTOTYPE(EC_GROUP_get0_generator); +extern DLSYM_PROTOTYPE(EC_GROUP_get0_order); +extern DLSYM_PROTOTYPE(EC_GROUP_new_by_curve_name); +extern DLSYM_PROTOTYPE(EC_POINT_free); +extern DLSYM_PROTOTYPE(EC_POINT_new); +extern DLSYM_PROTOTYPE(EC_POINT_oct2point); +extern DLSYM_PROTOTYPE(EC_POINT_point2oct); +extern DLSYM_PROTOTYPE(ECDSA_SIG_free); +extern DLSYM_PROTOTYPE(ERR_clear_error); +extern DLSYM_PROTOTYPE(ERR_error_string_n); +extern DLSYM_PROTOTYPE(ERR_error_string); +extern DLSYM_PROTOTYPE(ERR_get_error); +extern DLSYM_PROTOTYPE(EVP_aes_256_ctr); +extern DLSYM_PROTOTYPE(EVP_aes_256_gcm); +extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_ctrl); +extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_free); +extern DLSYM_PROTOTYPE(EVP_CIPHER_CTX_new); +extern DLSYM_PROTOTYPE(EVP_CIPHER_free); +extern DLSYM_PROTOTYPE(EVP_CIPHER_get_block_size); +extern DLSYM_PROTOTYPE(EVP_CIPHER_get_iv_length); +extern DLSYM_PROTOTYPE(EVP_CIPHER_get_key_length); +extern DLSYM_PROTOTYPE(EVP_DecryptFinal_ex); +extern DLSYM_PROTOTYPE(EVP_DecryptInit_ex); +extern DLSYM_PROTOTYPE(EVP_DecryptUpdate); +extern DLSYM_PROTOTYPE(EVP_Digest); +extern DLSYM_PROTOTYPE(EVP_DigestFinal_ex); +extern DLSYM_PROTOTYPE(EVP_DigestInit_ex); +extern DLSYM_PROTOTYPE(EVP_DigestUpdate); +extern DLSYM_PROTOTYPE(EVP_DigestVerify); +extern DLSYM_PROTOTYPE(EVP_DigestVerifyInit); +extern DLSYM_PROTOTYPE(EVP_EncryptFinal_ex); +extern DLSYM_PROTOTYPE(EVP_EncryptInit_ex); +extern DLSYM_PROTOTYPE(EVP_EncryptUpdate); +extern DLSYM_PROTOTYPE(EVP_get_cipherbyname); +extern DLSYM_PROTOTYPE(EVP_get_digestbyname); +extern DLSYM_PROTOTYPE(EVP_MAC_CTX_free); +extern DLSYM_PROTOTYPE(EVP_MAC_free); +extern DLSYM_PROTOTYPE(EVP_MD_CTX_free); +extern DLSYM_PROTOTYPE(EVP_MD_CTX_get0_md); +extern DLSYM_PROTOTYPE(EVP_MD_CTX_new); +extern DLSYM_PROTOTYPE(EVP_MD_CTX_set_pkey_ctx); +extern DLSYM_PROTOTYPE(EVP_MD_free); +extern DLSYM_PROTOTYPE(EVP_MD_get_size); +extern DLSYM_PROTOTYPE(EVP_MD_get0_name); +extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_free); +extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_new_from_name); +extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_new_id); +extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_new); +extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_set_rsa_padding); +extern DLSYM_PROTOTYPE(EVP_PKEY_CTX_set_signature_md); +extern DLSYM_PROTOTYPE(EVP_PKEY_eq); +extern DLSYM_PROTOTYPE(EVP_PKEY_free); +extern DLSYM_PROTOTYPE(EVP_PKEY_fromdata_init); +extern DLSYM_PROTOTYPE(EVP_PKEY_fromdata); +extern DLSYM_PROTOTYPE(EVP_PKEY_get_id); +extern DLSYM_PROTOTYPE(EVP_PKEY_keygen_init); +extern DLSYM_PROTOTYPE(EVP_PKEY_keygen); +extern DLSYM_PROTOTYPE(EVP_PKEY_new_raw_public_key); +extern DLSYM_PROTOTYPE(EVP_PKEY_new); +extern DLSYM_PROTOTYPE(EVP_PKEY_verify_init); +extern DLSYM_PROTOTYPE(EVP_PKEY_verify); +extern DLSYM_PROTOTYPE(EVP_sha1); +extern DLSYM_PROTOTYPE(EVP_sha256); +extern DLSYM_PROTOTYPE(EVP_sha384); +extern DLSYM_PROTOTYPE(EVP_sha512); +extern DLSYM_PROTOTYPE(HMAC); +extern DLSYM_PROTOTYPE(i2d_ASN1_INTEGER); +extern DLSYM_PROTOTYPE(i2d_PKCS7_fp); +extern DLSYM_PROTOTYPE(i2d_PKCS7); +extern DLSYM_PROTOTYPE(i2d_PUBKEY); +extern DLSYM_PROTOTYPE(i2d_X509_NAME); +extern DLSYM_PROTOTYPE(i2d_X509); +extern DLSYM_PROTOTYPE(OBJ_nid2obj); +extern DLSYM_PROTOTYPE(OBJ_nid2sn); +extern DLSYM_PROTOTYPE(OBJ_sn2nid); +extern DLSYM_PROTOTYPE(OBJ_txt2obj); +extern DLSYM_PROTOTYPE(OPENSSL_sk_new_null); +extern DLSYM_PROTOTYPE(OPENSSL_sk_num); +extern DLSYM_PROTOTYPE(OPENSSL_sk_pop_free); +extern DLSYM_PROTOTYPE(OPENSSL_sk_push); +extern DLSYM_PROTOTYPE(OPENSSL_sk_value); +extern DLSYM_PROTOTYPE(OSSL_EC_curve_nid2name); +extern DLSYM_PROTOTYPE(OSSL_PARAM_construct_BN); +extern DLSYM_PROTOTYPE(OSSL_PARAM_construct_end); +extern DLSYM_PROTOTYPE(OSSL_PARAM_construct_octet_string); +extern DLSYM_PROTOTYPE(OSSL_PARAM_construct_utf8_string); +extern DLSYM_PROTOTYPE(OSSL_PARAM_free); +extern DLSYM_PROTOTYPE(PEM_read_PrivateKey); +extern DLSYM_PROTOTYPE(PEM_read_PUBKEY); +extern DLSYM_PROTOTYPE(PEM_read_X509); +extern DLSYM_PROTOTYPE(PEM_write_PrivateKey); +extern DLSYM_PROTOTYPE(PEM_write_PUBKEY); +extern DLSYM_PROTOTYPE(PEM_write_X509); +extern DLSYM_PROTOTYPE(PKCS5_PBKDF2_HMAC); +extern DLSYM_PROTOTYPE(PKCS7_add_attrib_content_type); +extern DLSYM_PROTOTYPE(PKCS7_add_attrib_smimecap); +extern DLSYM_PROTOTYPE(PKCS7_add_signed_attribute); +extern DLSYM_PROTOTYPE(PKCS7_add0_attrib_signing_time); +extern DLSYM_PROTOTYPE(PKCS7_add1_attrib_digest); +extern DLSYM_PROTOTYPE(PKCS7_ATTR_SIGN_it); +extern DLSYM_PROTOTYPE(PKCS7_content_new); +extern DLSYM_PROTOTYPE(PKCS7_ctrl); +extern DLSYM_PROTOTYPE(PKCS7_dataFinal); +extern DLSYM_PROTOTYPE(PKCS7_dataInit); +extern DLSYM_PROTOTYPE(PKCS7_free); +extern DLSYM_PROTOTYPE(PKCS7_get_signer_info); +extern DLSYM_PROTOTYPE(PKCS7_new); +extern DLSYM_PROTOTYPE(PKCS7_set_content); +extern DLSYM_PROTOTYPE(PKCS7_sign); +extern DLSYM_PROTOTYPE(PKCS7_SIGNER_INFO_free); +extern DLSYM_PROTOTYPE(PKCS7_verify); +extern DLSYM_PROTOTYPE(SHA1); +extern DLSYM_PROTOTYPE(SHA512); +extern DLSYM_PROTOTYPE(X509_ALGOR_free); +extern DLSYM_PROTOTYPE(X509_ATTRIBUTE_free); +extern DLSYM_PROTOTYPE(X509_free); +extern DLSYM_PROTOTYPE(X509_get_pubkey); +extern DLSYM_PROTOTYPE(X509_get_subject_name); +extern DLSYM_PROTOTYPE(X509_gmtime_adj); +extern DLSYM_PROTOTYPE(X509_NAME_free); +extern DLSYM_PROTOTYPE(X509_NAME_oneline); +extern DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set_hostflags); +extern DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_host); +extern DLSYM_PROTOTYPE(X509_VERIFY_PARAM_set1_ip); + +#if !defined(OPENSSL_NO_DEPRECATED_3_0) +DISABLE_WARNING_DEPRECATED_DECLARATIONS; +extern DLSYM_PROTOTYPE(ECDSA_SIG_new); +extern DLSYM_PROTOTYPE(ECDSA_SIG_set0); +extern DLSYM_PROTOTYPE(ECDSA_do_verify); +extern DLSYM_PROTOTYPE(EC_KEY_check_key); +extern DLSYM_PROTOTYPE(EC_KEY_free); +extern DLSYM_PROTOTYPE(EC_KEY_new); +extern DLSYM_PROTOTYPE(EC_KEY_set_group); +extern DLSYM_PROTOTYPE(EC_KEY_set_public_key); +extern DLSYM_PROTOTYPE(EVP_PKEY_assign); +extern DLSYM_PROTOTYPE(RSA_free); +extern DLSYM_PROTOTYPE(RSA_new); +extern DLSYM_PROTOTYPE(RSA_set0_key); +extern DLSYM_PROTOTYPE(RSA_size); +extern DLSYM_PROTOTYPE(RSAPublicKey_dup); +REENABLE_WARNING; + +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EC_KEY*, sym_EC_KEY_free, EC_KEY_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(RSA*, sym_RSA_free, RSA_freep, NULL); +#endif + +/* Mirrors of OpenSSL macros that go through our dlopen'd sym_* variants, so we don't end up linking against + * libcrypto just for these. */ +#define sym_BIO_get_md_ctx(b, mdcp) sym_BIO_ctrl((b), BIO_C_GET_MD_CTX, 0, (char*) (mdcp)) +#define sym_BIO_get_mem_ptr(b, pp) sym_BIO_ctrl((b), BIO_C_GET_BUF_MEM_PTR, 0, (char *) (pp)) +#define sym_BIO_reset(b) sym_BIO_ctrl((b), BIO_CTRL_RESET, 0, NULL) +#define sym_BN_num_bytes(a) ((sym_BN_num_bits(a) + 7) / 8) +#define sym_EVP_MD_CTX_get_size(ctx) sym_EVP_MD_get_size(sym_EVP_MD_CTX_get0_md(ctx)) +#define sym_EVP_MD_CTX_get0_name(ctx) sym_EVP_MD_get0_name(sym_EVP_MD_CTX_get0_md(ctx)) +#define sym_EVP_PKEY_assign_RSA(pkey, rsa) sym_EVP_PKEY_assign((pkey), EVP_PKEY_RSA, (rsa)) +#define sym_OPENSSL_free(addr) sym_CRYPTO_free((addr), OPENSSL_FILE, OPENSSL_LINE) +#define sym_PKCS7_set_detached(p, v) sym_PKCS7_ctrl((p), PKCS7_OP_SET_DETACHED_SIGNATURE, (v), NULL) + +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO_RENAME(void*, sym_OPENSSL_free, OPENSSL_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(ASN1_OCTET_STRING*, sym_ASN1_OCTET_STRING_free, ASN1_OCTET_STRING_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(ASN1_TIME*, sym_ASN1_TIME_free, ASN1_TIME_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(BIGNUM*, sym_BN_free, BN_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(BIO*, sym_BIO_free_all, BIO_free_allp, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(BIO*, sym_BIO_free, BIO_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(BN_CTX*, sym_BN_CTX_free, BN_CTX_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EC_GROUP*, sym_EC_GROUP_free, EC_GROUP_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EC_POINT*, sym_EC_POINT_free, EC_POINT_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(ECDSA_SIG*, sym_ECDSA_SIG_free, ECDSA_SIG_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_CIPHER_CTX*, sym_EVP_CIPHER_CTX_free, EVP_CIPHER_CTX_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_CIPHER*, sym_EVP_CIPHER_free, EVP_CIPHER_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_MAC_CTX*, sym_EVP_MAC_CTX_free, EVP_MAC_CTX_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_MAC*, sym_EVP_MAC_free, EVP_MAC_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_MD_CTX*, sym_EVP_MD_CTX_free, EVP_MD_CTX_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_MD*, sym_EVP_MD_free, EVP_MD_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_PKEY_CTX*, sym_EVP_PKEY_CTX_free, EVP_PKEY_CTX_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(EVP_PKEY*, sym_EVP_PKEY_free, EVP_PKEY_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(OSSL_PARAM*, sym_OSSL_PARAM_free, OSSL_PARAM_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(PKCS7_SIGNER_INFO*, sym_PKCS7_SIGNER_INFO_free, PKCS7_SIGNER_INFO_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(PKCS7*, sym_PKCS7_free, PKCS7_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(X509_NAME*, sym_X509_NAME_free, X509_NAME_freep, NULL); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(X509*, sym_X509_free, X509_freep, NULL); + +/* Stack-of macros that go through the dlopen'd sym_OPENSSL_sk_* variants, mirroring the sk_TYPE_OP() helpers + * from and friends. */ +#define sym_sk_X509_new_null() \ + ((STACK_OF(X509)*) sym_OPENSSL_sk_new_null()) +#define sym_sk_X509_push(sk, ptr) \ + sym_OPENSSL_sk_push(ossl_check_X509_sk_type(sk), ossl_check_X509_type(ptr)) +#define sym_sk_X509_pop_free(sk, freefunc) \ + sym_OPENSSL_sk_pop_free(ossl_check_X509_sk_type(sk), ossl_check_X509_freefunc_type(freefunc)) +#define sym_sk_X509_ALGOR_pop_free(sk, freefunc) \ + sym_OPENSSL_sk_pop_free(ossl_check_X509_ALGOR_sk_type(sk), ossl_check_X509_ALGOR_freefunc_type(freefunc)) +#define sym_sk_X509_ATTRIBUTE_pop_free(sk, freefunc) \ + sym_OPENSSL_sk_pop_free(ossl_check_X509_ATTRIBUTE_sk_type(sk), ossl_check_X509_ATTRIBUTE_freefunc_type(freefunc)) +#define sym_sk_PKCS7_SIGNER_INFO_num(sk) \ + sym_OPENSSL_sk_num(ossl_check_const_PKCS7_SIGNER_INFO_sk_type(sk)) +#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 inline STACK_OF(X509_ALGOR) *x509_algor_free_many(STACK_OF(X509_ALGOR) *attrs) { + if (!attrs) + return NULL; + + sym_sk_X509_ALGOR_pop_free(attrs, sym_X509_ALGOR_free); + return NULL; +} + +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(STACK_OF(X509_ALGOR)*, x509_algor_free_many, NULL); + +static inline STACK_OF(X509_ATTRIBUTE) *x509_attribute_free_many(STACK_OF(X509_ATTRIBUTE) *attrs) { + if (!attrs) + return NULL; + + sym_sk_X509_ATTRIBUTE_pop_free(attrs, sym_X509_ATTRIBUTE_free); + return NULL; +} + +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(STACK_OF(X509_ATTRIBUTE)*, x509_attribute_free_many, NULL); + +static inline void sk_X509_free_allp(STACK_OF(X509) **sk) { + if (!sk || !*sk) + return; + + sym_sk_X509_pop_free(*sk, sym_X509_free); +} + +int openssl_pubkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret); +int openssl_pubkey_to_pem(EVP_PKEY *pkey, char **ret); + +int openssl_digest_size(const char *digest_alg, size_t *ret_digest_size); + +int openssl_digest_many(const char *digest_alg, const struct iovec data[], size_t n_data, void **ret_digest, size_t *ret_digest_size); + +static inline int openssl_digest(const char *digest_alg, const void *buf, size_t len, void **ret_digest, size_t *ret_digest_size) { + return openssl_digest_many(digest_alg, &IOVEC_MAKE((void*) buf, len), 1, ret_digest, ret_digest_size); +} + +int openssl_hmac_many(const char *digest_alg, const void *key, size_t key_size, const struct iovec data[], size_t n_data, void **ret_digest, size_t *ret_digest_size); + +static inline int openssl_hmac(const char *digest_alg, const void *key, size_t key_size, const void *buf, size_t len, void **ret_digest, size_t *ret_digest_size) { + return openssl_hmac_many(digest_alg, key, key_size, &IOVEC_MAKE((void*) buf, len), 1, ret_digest, ret_digest_size); +} + +int openssl_cipher_many(const char *alg, size_t bits, const char *mode, const void *key, size_t key_size, const void *iv, size_t iv_size, const struct iovec data[], size_t n_data, void **ret, size_t *ret_size); + +static inline int openssl_cipher(const char *alg, size_t bits, const char *mode, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *buf, size_t len, void **ret, size_t *ret_size) { + return openssl_cipher_many(alg, bits, mode, key, key_size, iv, iv_size, &IOVEC_MAKE((void*) buf, len), 1, ret, ret_size); +} + +int kdf_ss_derive(const char *digest, const void *key, size_t key_size, const void *salt, size_t salt_size, const void *info, size_t info_size, size_t derive_size, void **ret); + +int kdf_kb_hmac_derive(const char *mode, const char *digest, const void *key, size_t key_size, const void *salt, size_t salt_size, const void *info, size_t info_size, const void *seed, size_t seed_size, size_t derive_size, void **ret); + +int rsa_encrypt_bytes(EVP_PKEY *pkey, const void *decrypted_key, size_t decrypted_key_size, void **ret_encrypt_key, size_t *ret_encrypt_key_size); + +int rsa_oaep_encrypt_bytes(const EVP_PKEY *pkey, const char *digest_alg, const char *label, const void *decrypted_key, size_t decrypted_key_size, void **ret_encrypt_key, size_t *ret_encrypt_key_size); + +int rsa_pkey_to_suitable_key_size(EVP_PKEY *pkey, size_t *ret_suitable_key_size); + +int rsa_pkey_from_n_e(const void *n, size_t n_size, const void *e, size_t e_size, EVP_PKEY **ret); + +int rsa_pkey_to_n_e(const EVP_PKEY *pkey, void **ret_n, size_t *ret_n_size, void **ret_e, size_t *ret_e_size); + +int ecc_pkey_from_curve_x_y(int curve_id, const void *x, size_t x_size, const void *y, size_t y_size, EVP_PKEY **ret); + +int ecc_pkey_to_curve_x_y(const EVP_PKEY *pkey, int *ret_curve_id, void **ret_x, size_t *ret_x_size, void **ret_y, size_t *ret_y_size); + +int ecc_pkey_new(int curve_id, EVP_PKEY **ret); + +int ecc_ecdh(const EVP_PKEY *private_pkey, const EVP_PKEY *peer_pkey, void **ret_shared_secret, size_t *ret_shared_secret_size); + +int pkey_generate_volume_keys(EVP_PKEY *pkey, void **ret_decrypted_key, size_t *ret_decrypted_key_size, void **ret_saved_key, size_t *ret_saved_key_size); + +int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_size); + +int digest_and_sign(const EVP_MD *md, EVP_PKEY *privkey, const void *data, size_t size, void **ret, size_t *ret_size); + +int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorithm, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si); + +int string_hashsum(const char *s, size_t len, const char *md_algorithm, char **ret); +static inline int string_hashsum_sha224(const char *s, size_t len, char **ret) { + return string_hashsum(s, len, "SHA224", ret); +} +static inline int string_hashsum_sha256(const char *s, size_t len, char **ret) { + return string_hashsum(s, len, "SHA256", ret); +} + +int x509_fingerprint(X509 *cert, uint8_t buffer[static X509_FINGERPRINT_SIZE]); + +int openssl_load_x509_certificate( + CertificateSourceType certificate_source_type, + const char *certificate_source, + const char *certificate, + X509 **ret); + +int openssl_load_private_key( + KeySourceType private_key_source_type, + const char *private_key_source, + const char *private_key, + const AskPasswordRequest *request, + EVP_PKEY **ret_private_key, + OpenSSLAskPasswordUI **ret_user_interface); + +int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret); + +OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui); +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OpenSSLAskPasswordUI*, openssl_ask_password_ui_free, NULL); + +#endif diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 7252278768..662739ea0f 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -6,12 +6,6 @@ #include #include -#if HAVE_OPENSSL -#include -#include -#include -#endif - #include "sd-device.h" #include "sd-id128.h" #include "sd-json.h" @@ -26,6 +20,7 @@ #include "conf-files.h" #include "constants.h" #include "copy.h" +#include "crypto-util.h" #include "cryptsetup-util.h" #include "device-private.h" #include "devnum-util.h" @@ -57,7 +52,6 @@ #include "mountpoint-util.h" #include "namespace-util.h" #include "nulstr-util.h" -#include "openssl-util.h" #include "os-util.h" #include "path-util.h" #include "pcrextend-util.h" @@ -3087,6 +3081,10 @@ static int validate_signature_userspace(const VeritySettings *verity, const char assert(iovec_is_set(&verity->root_hash)); assert(iovec_is_set(&verity->root_hash_sig)); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + /* Because installing a signature certificate into the kernel chain is so messy, let's optionally do * userspace validation. */ @@ -3099,7 +3097,7 @@ static int validate_signature_userspace(const VeritySettings *verity, const char } const unsigned char *d = verity->root_hash_sig.iov_base; - p7 = d2i_PKCS7(NULL, &d, (long) verity->root_hash_sig.iov_len); + p7 = sym_d2i_PKCS7(NULL, &d, (long) verity->root_hash_sig.iov_len); if (!p7) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PKCS7 DER signature data."); @@ -3107,11 +3105,11 @@ static int validate_signature_userspace(const VeritySettings *verity, const char if (!s) return log_oom_debug(); - bio = BIO_new_mem_buf(s, strlen(s)); + bio = sym_BIO_new_mem_buf(s, strlen(s)); if (!bio) return log_oom_debug(); - sk = sk_X509_new_null(); + sk = sym_sk_X509_new_null(); if (!sk) return log_oom_debug(); @@ -3125,23 +3123,23 @@ static int validate_signature_userspace(const VeritySettings *verity, const char continue; } - c = PEM_read_X509(f, NULL, NULL, NULL); + c = sym_PEM_read_X509(f, NULL, NULL, NULL); if (!c) { log_debug("Failed to load X509 certificate '%s', ignoring.", *i); continue; } - if (sk_X509_push(sk, c) == 0) + if (sym_sk_X509_push(sk, c) == 0) return log_oom_debug(); TAKE_PTR(c); } - r = PKCS7_verify(p7, sk, NULL, bio, NULL, PKCS7_NOINTERN|PKCS7_NOVERIFY); + r = sym_PKCS7_verify(p7, sk, NULL, bio, NULL, PKCS7_NOINTERN|PKCS7_NOVERIFY); if (r) log_debug("Userspace PKCS#7 validation succeeded."); else - log_debug("Userspace PKCS#7 validation failed: %s", ERR_error_string(ERR_get_error(), NULL)); + log_debug("Userspace PKCS#7 validation failed: %s", sym_ERR_error_string(sym_ERR_get_error(), NULL)); return r; #else diff --git a/src/shared/meson.build b/src/shared/meson.build index 1ab14a5c92..741dbb60a4 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -51,6 +51,7 @@ shared_sources = files( 'coredump-util.c', 'cpu-set-util.c', 'creds-util.c', + 'crypto-util.c', 'cryptsetup-fido2.c', 'cryptsetup-tpm2.c', 'cryptsetup-util.c', @@ -151,7 +152,6 @@ shared_sources = files( 'nsresource.c', 'numa-util.c', 'open-file.c', - 'openssl-util.c', 'options.c', 'osc-context.c', 'output-mode.c', @@ -197,6 +197,7 @@ shared_sources = files( 'socket-label.c', 'socket-netlink.c', 'specifier.c', + 'ssl-util.c', 'switch-root.c', 'swtpm-util.c', 'tar-util.c', @@ -400,7 +401,7 @@ libshared_deps = [threads, libkmod_cflags, libmicrohttpd_cflags, libmount_cflags, - libopenssl, + libopenssl_cflags, libp11kit_cflags, libpam_cflags, libpcre2_cflags, diff --git a/src/shared/openssl-util.h b/src/shared/openssl-util.h deleted file mode 100644 index 218641e06f..0000000000 --- a/src/shared/openssl-util.h +++ /dev/null @@ -1,196 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "ask-password-api.h" -#include "shared-forward.h" -#include "iovec-util.h" -#include "sha256.h" - -typedef enum CertificateSourceType { - OPENSSL_CERTIFICATE_SOURCE_FILE, - OPENSSL_CERTIFICATE_SOURCE_PROVIDER, - _OPENSSL_CERTIFICATE_SOURCE_MAX, - _OPENSSL_CERTIFICATE_SOURCE_INVALID = -EINVAL, -} CertificateSourceType; - -typedef enum KeySourceType { - OPENSSL_KEY_SOURCE_FILE, - OPENSSL_KEY_SOURCE_ENGINE, - OPENSSL_KEY_SOURCE_PROVIDER, - _OPENSSL_KEY_SOURCE_MAX, - _OPENSSL_KEY_SOURCE_INVALID = -EINVAL, -} KeySourceType; - -typedef struct OpenSSLAskPasswordUI OpenSSLAskPasswordUI; - -int parse_openssl_certificate_source_argument(const char *argument, char **certificate_source, CertificateSourceType *certificate_source_type); - -int parse_openssl_key_source_argument(const char *argument, char **private_key_source, KeySourceType *private_key_source_type); - -#define X509_FINGERPRINT_SIZE SHA256_DIGEST_SIZE - -#if HAVE_OPENSSL -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# include /* IWYU pragma: export */ -# ifndef OPENSSL_NO_UI_CONSOLE -# include /* IWYU pragma: export */ -# endif -# include /* IWYU pragma: export */ - -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_MACRO(void*, OPENSSL_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ASN1_OCTET_STRING*, ASN1_OCTET_STRING_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ASN1_TIME*, ASN1_TIME_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIO*, BIO_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIO*, BIO_free_all, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIGNUM*, BN_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BN_CTX*, BN_CTX_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_GROUP*, EC_GROUP_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_POINT*, EC_POINT_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ECDSA_SIG*, ECDSA_SIG_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_CIPHER*, EVP_CIPHER_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_CIPHER_CTX*, EVP_CIPHER_CTX_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_KDF*, EVP_KDF_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_KDF_CTX*, EVP_KDF_CTX_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC*, EVP_MAC_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC_CTX*, EVP_MAC_CTX_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD*, EVP_MD_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY*, EVP_PKEY_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY_CTX*, EVP_PKEY_CTX_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM*, OSSL_PARAM_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM_BLD*, OSSL_PARAM_BLD_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_STORE_CTX*, OSSL_STORE_close, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_STORE_INFO*, OSSL_STORE_INFO_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7*, PKCS7_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(PKCS7_SIGNER_INFO*, PKCS7_SIGNER_INFO_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SSL*, SSL_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509*, X509_free, NULL); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(X509_NAME*, X509_NAME_free, NULL); - -static inline STACK_OF(X509_ALGOR) *x509_algor_free_many(STACK_OF(X509_ALGOR) *attrs) { - if (!attrs) - return NULL; - - sk_X509_ALGOR_pop_free(attrs, X509_ALGOR_free); - return NULL; -} - -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(STACK_OF(X509_ALGOR)*, x509_algor_free_many, NULL); - -static inline STACK_OF(X509_ATTRIBUTE) *x509_attribute_free_many(STACK_OF(X509_ATTRIBUTE) *attrs) { - if (!attrs) - return NULL; - - sk_X509_ATTRIBUTE_pop_free(attrs, X509_ATTRIBUTE_free); - return NULL; -} - -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(STACK_OF(X509_ATTRIBUTE)*, x509_attribute_free_many, NULL); - -static inline void sk_X509_free_allp(STACK_OF(X509) **sk) { - if (!sk || !*sk) - return; - - sk_X509_pop_free(*sk, X509_free); -} - -int openssl_pubkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret); -int openssl_pubkey_to_pem(EVP_PKEY *pkey, char **ret); - -int openssl_digest_size(const char *digest_alg, size_t *ret_digest_size); - -int openssl_digest_many(const char *digest_alg, const struct iovec data[], size_t n_data, void **ret_digest, size_t *ret_digest_size); - -static inline int openssl_digest(const char *digest_alg, const void *buf, size_t len, void **ret_digest, size_t *ret_digest_size) { - return openssl_digest_many(digest_alg, &IOVEC_MAKE((void*) buf, len), 1, ret_digest, ret_digest_size); -} - -int openssl_hmac_many(const char *digest_alg, const void *key, size_t key_size, const struct iovec data[], size_t n_data, void **ret_digest, size_t *ret_digest_size); - -static inline int openssl_hmac(const char *digest_alg, const void *key, size_t key_size, const void *buf, size_t len, void **ret_digest, size_t *ret_digest_size) { - return openssl_hmac_many(digest_alg, key, key_size, &IOVEC_MAKE((void*) buf, len), 1, ret_digest, ret_digest_size); -} - -int openssl_cipher_many(const char *alg, size_t bits, const char *mode, const void *key, size_t key_size, const void *iv, size_t iv_size, const struct iovec data[], size_t n_data, void **ret, size_t *ret_size); - -static inline int openssl_cipher(const char *alg, size_t bits, const char *mode, const void *key, size_t key_size, const void *iv, size_t iv_size, const void *buf, size_t len, void **ret, size_t *ret_size) { - return openssl_cipher_many(alg, bits, mode, key, key_size, iv, iv_size, &IOVEC_MAKE((void*) buf, len), 1, ret, ret_size); -} - -int kdf_ss_derive(const char *digest, const void *key, size_t key_size, const void *salt, size_t salt_size, const void *info, size_t info_size, size_t derive_size, void **ret); - -int kdf_kb_hmac_derive(const char *mode, const char *digest, const void *key, size_t key_size, const void *salt, size_t salt_size, const void *info, size_t info_size, const void *seed, size_t seed_size, size_t derive_size, void **ret); - -int rsa_encrypt_bytes(EVP_PKEY *pkey, const void *decrypted_key, size_t decrypted_key_size, void **ret_encrypt_key, size_t *ret_encrypt_key_size); - -int rsa_oaep_encrypt_bytes(const EVP_PKEY *pkey, const char *digest_alg, const char *label, const void *decrypted_key, size_t decrypted_key_size, void **ret_encrypt_key, size_t *ret_encrypt_key_size); - -int rsa_pkey_to_suitable_key_size(EVP_PKEY *pkey, size_t *ret_suitable_key_size); - -int rsa_pkey_from_n_e(const void *n, size_t n_size, const void *e, size_t e_size, EVP_PKEY **ret); - -int rsa_pkey_to_n_e(const EVP_PKEY *pkey, void **ret_n, size_t *ret_n_size, void **ret_e, size_t *ret_e_size); - -int ecc_pkey_from_curve_x_y(int curve_id, const void *x, size_t x_size, const void *y, size_t y_size, EVP_PKEY **ret); - -int ecc_pkey_to_curve_x_y(const EVP_PKEY *pkey, int *ret_curve_id, void **ret_x, size_t *ret_x_size, void **ret_y, size_t *ret_y_size); - -int ecc_pkey_new(int curve_id, EVP_PKEY **ret); - -int ecc_ecdh(const EVP_PKEY *private_pkey, const EVP_PKEY *peer_pkey, void **ret_shared_secret, size_t *ret_shared_secret_size); - -int pkey_generate_volume_keys(EVP_PKEY *pkey, void **ret_decrypted_key, size_t *ret_decrypted_key_size, void **ret_saved_key, size_t *ret_saved_key_size); - -int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_size); - -int digest_and_sign(const EVP_MD *md, EVP_PKEY *privkey, const void *data, size_t size, void **ret, size_t *ret_size); - -int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorithm, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si); - -int string_hashsum(const char *s, size_t len, const char *md_algorithm, char **ret); -static inline int string_hashsum_sha224(const char *s, size_t len, char **ret) { - return string_hashsum(s, len, "SHA224", ret); -} -static inline int string_hashsum_sha256(const char *s, size_t len, char **ret) { - return string_hashsum(s, len, "SHA256", ret); -} - -int x509_fingerprint(X509 *cert, uint8_t buffer[static X509_FINGERPRINT_SIZE]); - -int openssl_load_x509_certificate( - CertificateSourceType certificate_source_type, - const char *certificate_source, - const char *certificate, - X509 **ret); - -int openssl_load_private_key( - KeySourceType private_key_source_type, - const char *private_key_source, - const char *private_key, - const AskPasswordRequest *request, - EVP_PKEY **ret_private_key, - OpenSSLAskPasswordUI **ret_user_interface); - -int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret); - -struct OpenSSLAskPasswordUI { - AskPasswordRequest request; -#ifndef OPENSSL_NO_UI_CONSOLE - UI_METHOD *method; -#endif -}; - -OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui); -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OpenSSLAskPasswordUI*, openssl_ask_password_ui_free, NULL); -#endif diff --git a/src/shared/pe-binary.c b/src/shared/pe-binary.c index da54428306..b4b180d701 100644 --- a/src/shared/pe-binary.c +++ b/src/shared/pe-binary.c @@ -4,6 +4,7 @@ #include #include "alloc-util.h" +#include "crypto-util.h" #include "hexdecoct.h" #include "log.h" #include "pe-binary.h" @@ -325,7 +326,7 @@ static int hash_file(int fd, EVP_MD_CTX *md_ctx, uint64_t offset, uint64_t size) if ((size_t) n != m) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Short read while hashing."); - if (EVP_DigestUpdate(md_ctx, buffer, m) != 1) + if (sym_EVP_DigestUpdate(md_ctx, buffer, m) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to hash data."); offset += m; @@ -358,6 +359,10 @@ int pe_hash(int fd, assert(ret_hash_size); assert(ret_hash); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + if (fstat(fd, &st) < 0) return log_debug_errno(errno, "Failed to stat file: %m"); r = stat_verify_regular(&st); @@ -376,11 +381,11 @@ int pe_hash(int fd, if (!certificate_table) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "File lacks certificate table."); - mdctx = EVP_MD_CTX_new(); + mdctx = sym_EVP_MD_CTX_new(); if (!mdctx) return log_oom_debug(); - if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) + if (sym_EVP_DigestInit_ex(mdctx, md, NULL) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to allocate message digest."); /* Everything from beginning of file to CheckSum field in PE header */ @@ -428,11 +433,11 @@ int pe_hash(int fd, return r; /* If the file size is not a multiple of 8 bytes, pad the hash with zero bytes. */ - if (st.st_size % 8 != 0 && EVP_DigestUpdate(mdctx, (const uint8_t[8]) {}, 8 - (st.st_size % 8)) != 1) + if (st.st_size % 8 != 0 && sym_EVP_DigestUpdate(mdctx, (const uint8_t[8]) {}, 8 - (st.st_size % 8)) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to hash data."); } - int hsz = EVP_MD_CTX_size(mdctx); + int hsz = sym_EVP_MD_CTX_get_size(mdctx); if (hsz < 0) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to get hash size."); @@ -441,7 +446,7 @@ int pe_hash(int fd, if (!hash) return log_oom_debug(); - if (EVP_DigestFinal_ex(mdctx, hash, &hash_size) != 1) + if (sym_EVP_DigestFinal_ex(mdctx, hash, &hash_size) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to finalize hash function."); assert(hash_size == (unsigned) hsz); @@ -525,6 +530,10 @@ int uki_hash(int fd, assert(ret_hashes); assert(ret_hash_size); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + r = pe_load_headers(fd, &dos_header, &pe_header); if (r < 0) return r; @@ -533,7 +542,7 @@ int uki_hash(int fd, if (r < 0) return r; - int hsz = EVP_MD_size(md); + int hsz = sym_EVP_MD_get_size(md); if (hsz < 0) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to get hash size."); @@ -553,11 +562,11 @@ int uki_hash(int fd, if (hashes[i]) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Duplicate section"); - mdctx = EVP_MD_CTX_new(); + mdctx = sym_EVP_MD_CTX_new(); if (!mdctx) return log_oom_debug(); - if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) + if (sym_EVP_DigestInit_ex(mdctx, md, NULL) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to allocate message digest."); r = hash_file(fd, mdctx, le32toh(section->PointerToRawData), MIN(le32toh(section->VirtualSize), le32toh(section->SizeOfRawData))); @@ -571,7 +580,7 @@ int uki_hash(int fd, while (remaining > 0) { size_t sz = MIN(sizeof(zeroes), remaining); - if (EVP_DigestUpdate(mdctx, zeroes, sz) != 1) + if (sym_EVP_DigestUpdate(mdctx, zeroes, sz) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to hash data."); remaining -= sz; @@ -583,7 +592,7 @@ int uki_hash(int fd, return log_oom_debug(); unsigned hash_size = (unsigned) hsz; - if (EVP_DigestFinal_ex(mdctx, hashes[i], &hash_size) != 1) + if (sym_EVP_DigestFinal_ex(mdctx, hashes[i], &hash_size) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to finalize hash function."); assert(hash_size == (unsigned) hsz); @@ -592,7 +601,7 @@ int uki_hash(int fd, _cleanup_free_ char *hs = NULL; hs = hexmem(hashes[i], hsz); - log_debug("Section %s with %s is %s.", n, EVP_MD_name(md), strna(hs)); + log_debug("Section %s with %s is %s.", n, sym_EVP_MD_get0_name(md), strna(hs)); } } diff --git a/src/shared/pe-binary.h b/src/shared/pe-binary.h index 0f748a87d7..4b5dc243fe 100644 --- a/src/shared/pe-binary.h +++ b/src/shared/pe-binary.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#include "openssl-util.h" #include "sparse-endian.h" #include "uki.h" diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c index eea7fec893..a4c5bb83f7 100644 --- a/src/shared/pkcs11-util.c +++ b/src/shared/pkcs11-util.c @@ -1,16 +1,20 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#if HAVE_OPENSSL +# include +#endif + #include "sd-dlopen.h" #include "alloc-util.h" #include "ask-password-api.h" +#include "crypto-util.h" #include "dlfcn-util.h" #include "env-util.h" #include "escape.h" #include "format-table.h" #include "log.h" #include "memory-util.h" -#include "openssl-util.h" #include "pkcs11-util.h" #include "random-util.h" #include "string-util.h" @@ -429,7 +433,7 @@ static int read_public_key_info( "Failed to read CKA_PUBLIC_KEY_INFO: %s", sym_p11_kit_strerror(rv)); const unsigned char *value = attribute.pValue; - pkey = d2i_PUBKEY(NULL, &value, attribute.ulValueLen); + pkey = sym_d2i_PUBKEY(NULL, &value, attribute.ulValueLen); if (!pkey) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse CKA_PUBLIC_KEY_INFO"); @@ -449,6 +453,10 @@ int pkcs11_token_read_public_key( assert(ret_pkey); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + r = read_public_key_info(m, session, object, &pkey); if (r >= 0) { *ret_pkey = TAKE_PTR(pkey); @@ -543,67 +551,67 @@ int pkcs11_token_read_public_key( _cleanup_(ASN1_OCTET_STRING_freep) ASN1_OCTET_STRING *os = NULL; const unsigned char *ec_params_value = ec_attributes[0].pValue; - group = d2i_ECPKParameters(NULL, &ec_params_value, ec_attributes[0].ulValueLen); + group = sym_d2i_ECPKParameters(NULL, &ec_params_value, ec_attributes[0].ulValueLen); if (!group) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unable to decode CKA_EC_PARAMS."); const unsigned char *ec_point_value = ec_attributes[1].pValue; - os = d2i_ASN1_OCTET_STRING(NULL, &ec_point_value, ec_attributes[1].ulValueLen); + os = sym_d2i_ASN1_OCTET_STRING(NULL, &ec_point_value, ec_attributes[1].ulValueLen); if (!os) return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unable to decode CKA_EC_POINT."); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = sym_EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); if (!ctx) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to create an EVP_PKEY_CTX for EC."); - if (EVP_PKEY_fromdata_init(ctx) != 1) + if (sym_EVP_PKEY_fromdata_init(ctx) != 1) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to init an EVP_PKEY_CTX for EC."); OSSL_PARAM ec_params[8] = { /* We need to drop the const from the data param, because ec_params is * modified below. But we'll not modify ec_params[0]. */ OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, - (unsigned char *) ASN1_STRING_get0_data(os), - ASN1_STRING_length(os)), + (unsigned char *) sym_ASN1_STRING_get0_data(os), + sym_ASN1_STRING_length(os)), }; _cleanup_free_ void *order = NULL, *p = NULL, *a = NULL, *b = NULL, *generator = NULL; size_t order_size, p_size, a_size, b_size, generator_size; - int nid = EC_GROUP_get_curve_name(group); + int nid = sym_EC_GROUP_get_curve_name(group); if (nid != NID_undef) { - const char* name = OSSL_EC_curve_nid2name(nid); - ec_params[1] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char*)name, strlen(name)); - ec_params[2] = OSSL_PARAM_construct_end(); + const char* name = sym_OSSL_EC_curve_nid2name(nid); + ec_params[1] = sym_OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char*)name, strlen(name)); + ec_params[2] = sym_OSSL_PARAM_construct_end(); } else { - const char *field_type = EC_GROUP_get_field_type(group) == NID_X9_62_prime_field ? + const char *field_type = sym_EC_GROUP_get_field_type(group) == NID_X9_62_prime_field ? "prime-field" : "characteristic-two-field"; - const BIGNUM *bn_order = EC_GROUP_get0_order(group); + const BIGNUM *bn_order = sym_EC_GROUP_get0_order(group); - _cleanup_(BN_CTX_freep) BN_CTX *bnctx = BN_CTX_new(); + _cleanup_(BN_CTX_freep) BN_CTX *bnctx = sym_BN_CTX_new(); if (!bnctx) return log_oom_debug(); - _cleanup_(BN_freep) BIGNUM *bn_p = BN_new(); + _cleanup_(BN_freep) BIGNUM *bn_p = sym_BN_new(); if (!bn_p) return log_oom_debug(); - _cleanup_(BN_freep) BIGNUM *bn_a = BN_new(); + _cleanup_(BN_freep) BIGNUM *bn_a = sym_BN_new(); if (!bn_a) return log_oom_debug(); - _cleanup_(BN_freep) BIGNUM *bn_b = BN_new(); + _cleanup_(BN_freep) BIGNUM *bn_b = sym_BN_new(); if (!bn_b) return log_oom_debug(); - if (EC_GROUP_get_curve(group, bn_p, bn_a, bn_b, bnctx) != 1) + if (sym_EC_GROUP_get_curve(group, bn_p, bn_a, bn_b, bnctx) != 1) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to extract EC parameters from EC_GROUP."); - order_size = BN_num_bytes(bn_order); - p_size = BN_num_bytes(bn_p); - a_size = BN_num_bytes(bn_a); - b_size = BN_num_bytes(bn_b); + order_size = sym_BN_num_bytes(bn_order); + p_size = sym_BN_num_bytes(bn_p); + a_size = sym_BN_num_bytes(bn_a); + b_size = sym_BN_num_bytes(bn_b); order = malloc(order_size); if (!order) @@ -621,14 +629,14 @@ int pkcs11_token_read_public_key( if (!b) return log_oom_debug(); - if (BN_bn2nativepad(bn_order, order, order_size) <= 0 || - BN_bn2nativepad(bn_p, p, p_size) <= 0 || - BN_bn2nativepad(bn_a, a, a_size) <= 0 || - BN_bn2nativepad(bn_b, b, b_size) <= 0 ) + if (sym_BN_bn2nativepad(bn_order, order, order_size) <= 0 || + sym_BN_bn2nativepad(bn_p, p, p_size) <= 0 || + sym_BN_bn2nativepad(bn_a, a, a_size) <= 0 || + sym_BN_bn2nativepad(bn_b, b, b_size) <= 0 ) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to store EC parameters in native byte order."); - const EC_POINT *point_gen = EC_GROUP_get0_generator(group); - generator_size = EC_POINT_point2oct(group, point_gen, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bnctx); + const EC_POINT *point_gen = sym_EC_GROUP_get0_generator(group); + generator_size = sym_EC_POINT_point2oct(group, point_gen, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bnctx); if (generator_size == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to determine size of a EC generator."); @@ -636,20 +644,20 @@ int pkcs11_token_read_public_key( if (!generator) return log_oom_debug(); - generator_size = EC_POINT_point2oct(group, point_gen, POINT_CONVERSION_UNCOMPRESSED, generator, generator_size, bnctx); + generator_size = sym_EC_POINT_point2oct(group, point_gen, POINT_CONVERSION_UNCOMPRESSED, generator, generator_size, bnctx); if (generator_size == 0) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert a EC generator to octet string."); - ec_params[1] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, (char*)field_type, strlen(field_type)); - ec_params[2] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, generator, generator_size); - ec_params[3] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_EC_ORDER, order, order_size); - ec_params[4] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_EC_P, p, p_size); - ec_params[5] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_EC_A, a, a_size); - ec_params[6] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_EC_B, b, b_size); - ec_params[7] = OSSL_PARAM_construct_end(); + ec_params[1] = sym_OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_FIELD_TYPE, (char*)field_type, strlen(field_type)); + ec_params[2] = sym_OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_EC_GENERATOR, generator, generator_size); + ec_params[3] = sym_OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_EC_ORDER, order, order_size); + ec_params[4] = sym_OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_EC_P, p, p_size); + ec_params[5] = sym_OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_EC_A, a, a_size); + ec_params[6] = sym_OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_EC_B, b, b_size); + ec_params[7] = sym_OSSL_PARAM_construct_end(); } - if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, ec_params) != 1) + if (sym_EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, ec_params) != 1) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to create EVP_PKEY from EC parameters."); break; } @@ -695,16 +703,20 @@ int pkcs11_token_read_x509_certificate( return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to read X.509 certificate data off token: %s", sym_p11_kit_strerror(rv)); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + const unsigned char *p = attribute.pValue; - _cleanup_(X509_freep) X509 *x509 = d2i_X509(NULL, &p, attribute.ulValueLen); + _cleanup_(X509_freep) X509 *x509 = sym_d2i_X509(NULL, &p, attribute.ulValueLen); if (!x509) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse X.509 certificate."); - const X509_NAME *name = X509_get_subject_name(x509); + const X509_NAME *name = sym_X509_get_subject_name(x509); if (!name) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to acquire X.509 subject name."); - _cleanup_free_ char *t = X509_NAME_oneline(name, NULL, 0); + _cleanup_free_ char *t = sym_X509_NAME_oneline(name, NULL, 0); if (!t) return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to format X.509 subject name as string."); @@ -1009,23 +1021,27 @@ static int ecc_convert_to_compressed( _cleanup_free_ void *compressed_point = NULL; size_t compressed_point_size; + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + const unsigned char *ec_params_value = ec_params_attr.pValue; - group = d2i_ECPKParameters(NULL, &ec_params_value, ec_params_attr.ulValueLen); + group = sym_d2i_ECPKParameters(NULL, &ec_params_value, ec_params_attr.ulValueLen); if (!group) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unable to decode CKA_EC_PARAMS"); - point = EC_POINT_new(group); + point = sym_EC_POINT_new(group); if (!point) return log_oom(); - bnctx = BN_CTX_new(); + bnctx = sym_BN_CTX_new(); if (!bnctx) return log_oom(); - if (EC_POINT_oct2point(group, point, uncompressed_point, uncompressed_point_size, bnctx) != 1) + if (sym_EC_POINT_oct2point(group, point, uncompressed_point, uncompressed_point_size, bnctx) != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unable to decode an uncompressed EC point"); - compressed_point_size = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, NULL, 0, bnctx); + compressed_point_size = sym_EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, NULL, 0, bnctx); if (compressed_point_size == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to determine size of a compressed EC point"); @@ -1033,7 +1049,7 @@ static int ecc_convert_to_compressed( if (!compressed_point) return log_oom(); - compressed_point_size = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, compressed_point, compressed_point_size, bnctx); + compressed_point_size = sym_EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, compressed_point, compressed_point_size, bnctx); if (compressed_point_size == 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert a EC point to compressed format"); @@ -1521,7 +1537,8 @@ struct pkcs11_acquire_public_key_callback_data { static void pkcs11_acquire_public_key_callback_data_release(struct pkcs11_acquire_public_key_callback_data *data) { erase_and_free(data->pin_used); - EVP_PKEY_free(data->pkey); + if (data->pkey) + sym_EVP_PKEY_free(data->pkey); } static int pkcs11_acquire_public_key_callback( @@ -1673,7 +1690,11 @@ static int pkcs11_acquire_public_key_callback( if (r < 0) return log_error_errno(r, "Failed to read a found X.509 certificate."); - pkey = X509_get_pubkey(cert); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + + pkey = sym_X509_get_pubkey(cert); if (!pkey) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to extract public key from X.509 certificate."); } diff --git a/src/shared/pkcs11-util.h b/src/shared/pkcs11-util.h index 92d850b6e5..7864598180 100644 --- a/src/shared/pkcs11-util.h +++ b/src/shared/pkcs11-util.h @@ -1,10 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once -#if HAVE_OPENSSL -# include -#endif - #if HAVE_P11KIT # include /* IWYU pragma: export */ # include /* IWYU pragma: export */ diff --git a/src/shared/pkcs7-util.c b/src/shared/pkcs7-util.c index 0a0e102adf..4d22d90421 100644 --- a/src/shared/pkcs7-util.c +++ b/src/shared/pkcs7-util.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "alloc-util.h" -#include "openssl-util.h" +#include "crypto-util.h" #include "pkcs7-util.h" #include "log.h" @@ -28,6 +28,10 @@ int pkcs7_extract_signers( Signer **ret_signers, size_t *ret_n_signers) { +#if HAVE_OPENSSL + int r; +#endif + assert(ret_signers); assert(ret_n_signers); @@ -35,16 +39,20 @@ int pkcs7_extract_signers( return -EBADMSG; #if HAVE_OPENSSL + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + const unsigned char *d = sig->iov_base; _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL; - p7 = d2i_PKCS7(/* a= */ NULL, &d, (long) sig->iov_len); + p7 = sym_d2i_PKCS7(/* a= */ NULL, &d, (long) sig->iov_len); if (!p7) return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse PKCS7 DER signature data."); - STACK_OF(PKCS7_SIGNER_INFO) *sinfos = PKCS7_get_signer_info(p7); + STACK_OF(PKCS7_SIGNER_INFO) *sinfos = sym_PKCS7_get_signer_info(p7); if (!sinfos) return log_debug_errno(SYNTHETIC_ERRNO(ENODATA), "No signature information in PKCS7 signature?"); - int n = sk_PKCS7_SIGNER_INFO_num(sinfos); + int n = sym_sk_PKCS7_SIGNER_INFO_num(sinfos); if (n == 0) return log_debug_errno(SYNTHETIC_ERRNO(ENODATA), "No signatures in PKCS7 signature, refusing."); if (n > SIGNERS_MAX) /* safety net, in case people send us weirdly complex signatures */ @@ -59,17 +67,17 @@ int pkcs7_extract_signers( CLEANUP_ARRAY(signers, n_signers, signer_free_many); for (int i = 0; i < n; i++) { - PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(PKCS7_get_signer_info(p7), i); + PKCS7_SIGNER_INFO *si = sym_sk_PKCS7_SIGNER_INFO_value(sym_PKCS7_get_signer_info(p7), i); if (!si) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to get signer information."); _cleanup_(signer_done) Signer signer = {}; _cleanup_free_ unsigned char *p = NULL; - int len = i2d_X509_NAME(si->issuer_and_serial->issuer, &p); + int len = sym_i2d_X509_NAME(si->issuer_and_serial->issuer, &p); signer.issuer = IOVEC_MAKE(TAKE_PTR(p), len); - len = i2d_ASN1_INTEGER(si->issuer_and_serial->serial, &p); + len = sym_i2d_ASN1_INTEGER(si->issuer_and_serial->serial, &p); signer.serial = IOVEC_MAKE(TAKE_PTR(p), len); signers[n_signers++] = TAKE_STRUCT(signer); diff --git a/src/shared/shared-forward.h b/src/shared/shared-forward.h index 38349d9dbb..1a19b42499 100644 --- a/src/shared/shared-forward.h +++ b/src/shared/shared-forward.h @@ -45,6 +45,7 @@ typedef enum UserDBFlags UserDBFlags; typedef enum UserRecordLoadFlags UserRecordLoadFlags; typedef enum UserStorage UserStorage; +typedef struct AskPasswordRequest AskPasswordRequest; typedef struct Bitmap Bitmap; typedef struct BootConfig BootConfig; typedef struct BPFProgram BPFProgram; diff --git a/src/shared/ssl-util.c b/src/shared/ssl-util.c new file mode 100644 index 0000000000..82ed54d037 --- /dev/null +++ b/src/shared/ssl-util.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "sd-dlopen.h" + +#include "log.h" /* IWYU pragma: keep */ +#include "ssl-util.h" + +#if HAVE_OPENSSL + +static void *libssl_dl = NULL; + +DLSYM_PROTOTYPE(SSL_ctrl) = NULL; +DLSYM_PROTOTYPE(SSL_CTX_ctrl) = NULL; +DLSYM_PROTOTYPE(SSL_CTX_free) = NULL; +DLSYM_PROTOTYPE(SSL_CTX_new) = NULL; +DLSYM_PROTOTYPE(SSL_CTX_set_default_verify_paths) = NULL; +DLSYM_PROTOTYPE(SSL_CTX_set_options) = NULL; +DLSYM_PROTOTYPE(SSL_do_handshake) = NULL; +DLSYM_PROTOTYPE(SSL_free) = NULL; +DLSYM_PROTOTYPE(SSL_get_error) = NULL; +DLSYM_PROTOTYPE(SSL_get_wbio) = NULL; +DLSYM_PROTOTYPE(SSL_get0_param) = NULL; +DLSYM_PROTOTYPE(SSL_get1_session) = NULL; +DLSYM_PROTOTYPE(SSL_new) = NULL; +DLSYM_PROTOTYPE(SSL_read) = NULL; +DLSYM_PROTOTYPE(SSL_SESSION_free) = NULL; +DLSYM_PROTOTYPE(SSL_set_bio) = NULL; +DLSYM_PROTOTYPE(SSL_set_connect_state) = NULL; +DLSYM_PROTOTYPE(SSL_set_session) = NULL; +DLSYM_PROTOTYPE(SSL_set_verify) = NULL; +DLSYM_PROTOTYPE(SSL_shutdown) = NULL; +DLSYM_PROTOTYPE(SSL_write) = NULL; +DLSYM_PROTOTYPE(TLS_client_method) = NULL; + +#endif + +int dlopen_libssl(int log_level) { +#if HAVE_OPENSSL + SD_ELF_NOTE_DLOPEN( + "libssl", + "Support for TLS", + SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED, + "libssl.so.3"); + + return dlopen_many_sym_or_warn( + &libssl_dl, + "libssl.so.3", + log_level, + DLSYM_ARG(SSL_ctrl), + DLSYM_ARG(SSL_CTX_ctrl), + DLSYM_ARG(SSL_CTX_free), + DLSYM_ARG(SSL_CTX_new), + DLSYM_ARG(SSL_CTX_set_default_verify_paths), + DLSYM_ARG(SSL_CTX_set_options), + DLSYM_ARG(SSL_do_handshake), + DLSYM_ARG(SSL_free), + DLSYM_ARG(SSL_get_error), + DLSYM_ARG(SSL_get_wbio), + DLSYM_ARG(SSL_get0_param), + DLSYM_ARG(SSL_get1_session), + DLSYM_ARG(SSL_new), + DLSYM_ARG(SSL_read), + DLSYM_ARG(SSL_SESSION_free), + DLSYM_ARG(SSL_set_bio), + DLSYM_ARG(SSL_set_connect_state), + DLSYM_ARG(SSL_set_session), + DLSYM_ARG(SSL_set_verify), + DLSYM_ARG(SSL_shutdown), + DLSYM_ARG(SSL_write), + DLSYM_ARG(TLS_client_method)); +#else + return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP), + "libssl support is not compiled in."); +#endif +} diff --git a/src/shared/ssl-util.h b/src/shared/ssl-util.h new file mode 100644 index 0000000000..7deb028cfe --- /dev/null +++ b/src/shared/ssl-util.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "shared-forward.h" + +int dlopen_libssl(int log_level); + +#if HAVE_OPENSSL + +# include /* IWYU pragma: export */ + +# include "dlfcn-util.h" + +extern DLSYM_PROTOTYPE(SSL_ctrl); +extern DLSYM_PROTOTYPE(SSL_CTX_ctrl); +extern DLSYM_PROTOTYPE(SSL_CTX_free); +extern DLSYM_PROTOTYPE(SSL_CTX_new); +extern DLSYM_PROTOTYPE(SSL_CTX_set_default_verify_paths); +extern DLSYM_PROTOTYPE(SSL_CTX_set_options); +extern DLSYM_PROTOTYPE(SSL_do_handshake); +extern DLSYM_PROTOTYPE(SSL_free); +extern DLSYM_PROTOTYPE(SSL_get_error); +extern DLSYM_PROTOTYPE(SSL_get_wbio); +extern DLSYM_PROTOTYPE(SSL_get0_param); +extern DLSYM_PROTOTYPE(SSL_get1_session); +extern DLSYM_PROTOTYPE(SSL_new); +extern DLSYM_PROTOTYPE(SSL_read); +extern DLSYM_PROTOTYPE(SSL_SESSION_free); +extern DLSYM_PROTOTYPE(SSL_set_bio); +extern DLSYM_PROTOTYPE(SSL_set_connect_state); +extern DLSYM_PROTOTYPE(SSL_set_session); +extern DLSYM_PROTOTYPE(SSL_set_verify); +extern DLSYM_PROTOTYPE(SSL_shutdown); +extern DLSYM_PROTOTYPE(SSL_write); +extern DLSYM_PROTOTYPE(TLS_client_method); + +/* Mirrors of OpenSSL macros that go through our dlopen'd sym_* variants, so we don't end up linking against + * libssl just for these. */ +#define sym_SSL_set_tlsext_host_name(s, name) \ + sym_SSL_ctrl((s), SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (void *) (name)) +#define sym_SSL_CTX_set_min_proto_version(ctx, version) \ + sym_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MIN_PROTO_VERSION, (version), NULL) + +DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(SSL*, sym_SSL_free, SSL_freep, NULL); + +#endif diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index d972d39d76..9fe3e01869 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -13,6 +13,7 @@ #include "chase.h" #include "constants.h" #include "creds-util.h" +#include "crypto-util.h" #include "cryptsetup-util.h" #include "device-private.h" #include "device-util.h" @@ -51,10 +52,6 @@ #include "unaligned.h" #include "virt.h" -#if HAVE_OPENSSL -# include -#endif - #if HAVE_TPM2 static void *libtss2_esys_dl = NULL; static void *libtss2_rc_dl = NULL; @@ -3087,11 +3084,15 @@ int tpm2_get_good_pcr_banks_strv( #if HAVE_OPENSSL _cleanup_free_ TPMI_ALG_HASH *algs = NULL; _cleanup_strv_free_ char **l = NULL; - int n_algs; + int n_algs, r; assert(c); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + n_algs = tpm2_get_good_pcr_banks(c, pcr_mask, &algs); if (n_algs < 0) return n_algs; @@ -3105,11 +3106,11 @@ int tpm2_get_good_pcr_banks_strv( if (!salg) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unknown PCR algorithm, can't measure."); - implementation = EVP_get_digestbyname(salg); + implementation = sym_EVP_get_digestbyname(salg); if (!implementation) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 operates with unsupported PCR algorithm, can't measure."); - n = strdup(ASSERT_PTR(EVP_MD_name(implementation))); + n = strdup(ASSERT_PTR(sym_EVP_MD_get0_name(implementation))); if (!n) return log_oom_debug(); @@ -3783,6 +3784,10 @@ int tpm2_policy_signed_hmac_sha256( * specified in the hmac_key parameter. The secret key must be loaded into the TPM already and * referenced in hmac_key_handle. */ + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + log_debug("Submitting PolicySigned policy for HMAC-SHA256."); /* Acquire the nonce from the TPM that we shall sign */ @@ -3818,7 +3823,7 @@ int tpm2_policy_signed_hmac_sha256( unsigned hmac_signature_size = sizeof(hmac_signature); /* And sign this with our key */ - if (!HMAC(EVP_sha256(), + if (!sym_HMAC(sym_EVP_sha256(), hmac_key->iov_base, hmac_key->iov_len, digest_to_sign.buffer, @@ -4555,6 +4560,10 @@ int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) assert(pkey); assert(ret); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + TPMT_PUBLIC public = { .nameAlg = TPM2_ALG_SHA256, .objectAttributes = TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH, @@ -4564,7 +4573,7 @@ int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret) }, }; - int key_id = EVP_PKEY_get_id(pkey); + int key_id = sym_EVP_PKEY_get_id(pkey); switch (key_id) { case EVP_PKEY_EC: { public.type = TPM2_ALG_ECC; @@ -4662,8 +4671,12 @@ int tpm2_tpm2b_public_to_fingerprint( if (r < 0) return r; + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + /* Hardcode fingerprint to SHA256 */ - return pubkey_fingerprint(pkey, EVP_sha256(), ret_fingerprint, ret_fingerprint_size); + return pubkey_fingerprint(pkey, sym_EVP_sha256(), ret_fingerprint, ret_fingerprint_size); #else return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled."); #endif @@ -6812,17 +6825,21 @@ static int tpm2_userspace_log( if (fd < 0) /* Apparently tpm2_local_log_open() failed earlier, let's not complain again */ return 0; + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + for (size_t i = 0; i < values->count; i++) { const EVP_MD *implementation; const char *a; assert_se(a = tpm2_hash_alg_to_string(values->digests[i].hashAlg)); - assert_se(implementation = EVP_get_digestbyname(a)); + assert_se(implementation = sym_EVP_get_digestbyname(a)); r = sd_json_variant_append_arraybo( &array, SD_JSON_BUILD_PAIR_STRING("hashAlg", a), - SD_JSON_BUILD_PAIR_HEX("digest", &values->digests[i].digest, EVP_MD_size(implementation))); + SD_JSON_BUILD_PAIR_HEX("digest", &values->digests[i].digest, sym_EVP_MD_get_size(implementation))); if (r < 0) return log_debug_errno(r, "Failed to append digest object to JSON array: %m"); } @@ -6880,6 +6897,7 @@ int tpm2_pcr_extend_bytes( _cleanup_close_ int log_fd = -EBADF; TPML_DIGEST_VALUES values = {}; TSS2_RC rc; + int r; assert(c); assert(iovec_is_valid(data)); @@ -6894,19 +6912,23 @@ int tpm2_pcr_extend_bytes( if (strv_isempty(banks)) return 0; + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + STRV_FOREACH(bank, banks) { const EVP_MD *implementation; int id; - assert_se(implementation = EVP_get_digestbyname(*bank)); + assert_se(implementation = sym_EVP_get_digestbyname(*bank)); if (values.count >= ELEMENTSOF(values.digests)) return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Too many banks selected."); - if ((size_t) EVP_MD_size(implementation) > sizeof(values.digests[values.count].digest)) + if ((size_t) sym_EVP_MD_get_size(implementation) > sizeof(values.digests[values.count].digest)) return log_debug_errno(SYNTHETIC_ERRNO(E2BIG), "Hash result too large for TPM2."); - id = tpm2_hash_alg_from_string(EVP_MD_name(implementation)); + id = tpm2_hash_alg_from_string(sym_EVP_MD_get0_name(implementation)); if (id < 0) return log_debug_errno(id, "Can't map hash name to TPM2."); @@ -6919,9 +6941,9 @@ int tpm2_pcr_extend_bytes( * some unrelated purpose, who knows). Hence we instead measure an HMAC signature of a * private non-secret string instead. */ if (iovec_is_set(secret) > 0) { - if (!HMAC(implementation, secret->iov_base, secret->iov_len, data->iov_base, data->iov_len, (unsigned char*) &values.digests[values.count].digest, NULL)) + if (!sym_HMAC(implementation, secret->iov_base, secret->iov_len, data->iov_base, data->iov_len, (unsigned char*) &values.digests[values.count].digest, NULL)) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure."); - } else if (EVP_Digest(data->iov_base, data->iov_len, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1) + } else if (sym_EVP_Digest(data->iov_base, data->iov_len, (unsigned char*) &values.digests[values.count].digest, NULL, implementation, NULL) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data to measure."); values.count++; @@ -7054,6 +7076,10 @@ int tpm2_nvpcr_extend_bytes( assert(iovec_is_valid(data)); assert(iovec_is_valid(secret)); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_(nvpcr_data_done) NvPCRData p = {}; r = nvpcr_data_load(name, &p); if (r < 0) @@ -7077,10 +7103,10 @@ int tpm2_nvpcr_extend_bytes( return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unsupported algorithm for NvPCR, refusing."); const EVP_MD *implementation; - assert_se(implementation = EVP_get_digestbyname(an)); + assert_se(implementation = sym_EVP_get_digestbyname(an)); _cleanup_(iovec_done) struct iovec digest = { - .iov_len = EVP_MD_size(implementation), + .iov_len = sym_EVP_MD_get_size(implementation), }; digest.iov_base = malloc(digest.iov_len); @@ -7091,9 +7117,9 @@ int tpm2_nvpcr_extend_bytes( data = &iovec_empty; if (iovec_is_set(secret)) { - if (!HMAC(implementation, secret->iov_base, secret->iov_len, data->iov_base, data->iov_len, digest.iov_base, NULL)) + if (!sym_HMAC(implementation, secret->iov_base, secret->iov_len, data->iov_base, data->iov_len, digest.iov_base, NULL)) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure."); - } else if (EVP_Digest(data->iov_base, data->iov_len, digest.iov_base, NULL, implementation, NULL) != 1) + } else if (sym_EVP_Digest(data->iov_base, data->iov_len, digest.iov_base, NULL, implementation, NULL) != 1) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to hash data to measure."); _cleanup_(tpm2_handle_freep) Tpm2Handle *nv_handle = NULL; @@ -7595,10 +7621,14 @@ int tpm2_nvpcr_initialize( if (!an) return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unsupported algorithm for NvPCR, refusing."); - const EVP_MD *implementation; - assert_se(implementation = EVP_get_digestbyname(an)); + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; - int digest_size = EVP_MD_get_size(implementation); + const EVP_MD *implementation; + assert_se(implementation = sym_EVP_get_digestbyname(an)); + + int digest_size = sym_EVP_MD_get_size(implementation); assert_se(digest_size > 0); if ((size_t) digest_size > sizeof_field(TPM2B_MAX_NV_BUFFER, buffer)) @@ -7619,7 +7649,7 @@ int tpm2_nvpcr_initialize( CLEANUP_ERASE(buf); /* We measure HMAC(anchor_secret, name) into the NvPCR to anchor it on our secret. */ - if (!HMAC(implementation, anchor_secret->iov_base, anchor_secret->iov_len, hmac_buffer, hmac_buffer_size, buf.buffer, NULL)) + if (!sym_HMAC(implementation, anchor_secret->iov_base, anchor_secret->iov_len, hmac_buffer, hmac_buffer_size, buf.buffer, NULL)) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to calculate HMAC of data to measure."); _cleanup_(tpm2_handle_freep) Tpm2Handle *nv_handle = NULL; diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index 8576f278cf..b5a8ec1c1e 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -2,8 +2,9 @@ #pragma once #include "bitfield.h" -#include "openssl-util.h" +#include "iovec-util.h" #include "shared-forward.h" +#include "sha256-fundamental.h" typedef enum TPM2Flags { TPM2_FLAGS_USE_PIN = 1 << 0, diff --git a/src/sysupdate/meson.build b/src/sysupdate/meson.build index 68ac0e14ee..3a1ee1a048 100644 --- a/src/sysupdate/meson.build +++ b/src/sysupdate/meson.build @@ -29,7 +29,7 @@ executables += [ 'extract' : systemd_sysupdate_extract_sources, 'dependencies' : [ libfdisk_cflags, - libopenssl, + libopenssl_cflags, threads, ], }, diff --git a/src/test/meson.build b/src/test/meson.build index 9544c166a5..6f9a24eb04 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -289,8 +289,8 @@ executables += [ 'c_args' : ['-fno-sanitize=all', '-fno-optimize-sibling-calls', '-O1'], }, test_template + { - 'sources' : files('test-cryptolib.c'), - 'dependencies' : libopenssl, + 'sources' : files('test-crypto-util.c'), + 'dependencies' : libopenssl_cflags, 'conditions' : ['HAVE_OPENSSL'], }, test_template + { @@ -410,14 +410,9 @@ executables += [ 'dependencies' : libdl, 'conditions' : ['ENABLE_NSS'], }, - test_template + { - 'sources' : files('test-openssl.c'), - 'dependencies' : libopenssl, - 'conditions' : ['HAVE_OPENSSL'], - }, test_template + { 'sources' : files('test-pkcs7-util.c'), - 'dependencies' : libopenssl, + 'dependencies' : libopenssl_cflags, 'conditions' : ['HAVE_OPENSSL'], }, test_template + { @@ -494,7 +489,7 @@ executables += [ }, test_template + { 'sources' : files('test-tpm2.c'), - 'dependencies' : libopenssl, + 'dependencies' : libopenssl_cflags, 'timeout' : 120, }, test_template + { diff --git a/src/test/test-openssl.c b/src/test/test-crypto-util.c similarity index 93% rename from src/test/test-openssl.c rename to src/test/test-crypto-util.c index a09484a2ba..a2fd090ed3 100644 --- a/src/test/test-openssl.c +++ b/src/test/test-crypto-util.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "openssl-util.h" +#include "crypto-util.h" #include "tests.h" TEST(openssl_pkey_from_pem) { @@ -42,16 +42,16 @@ TEST(rsa_pkey_n_e) { _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; assert_se(rsa_pkey_from_n_e(n, n_len, &e, sizeof(e), &pkey) >= 0); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = sym_EVP_PKEY_CTX_new(pkey, NULL); assert_se(ctx); - assert_se(EVP_PKEY_verify_init(ctx) == 1); + assert_se(sym_EVP_PKEY_verify_init(ctx) == 1); const char *msg = "this is a secret"; DEFINE_HEX_PTR(sig, "14b53e0c6ad99a350c3d7811e8160f4ae03ad159815bb91bddb9735b833588df2eac221fbd3fc4ece0dd63bfaeddfdaf4ae67021e759f3638bc194836413414f54e8c4d01c9c37fa4488ea2ef772276b8a33822a53c97b1c35acfb4bc621cfb8fad88f0cf7d5491f05236886afbf9ed47f9469536482f50f74a20defa59d99676bed62a17b5eb98641df5a2f8080fa4b24f2749cc152fa65ba34c14022fcb27f1b36f52021950d7b9b6c3042c50b84cfb7d55a5f9235bfd58e1bf1f604eb93416c5fb5fd90cb68f1270dfa9daf67f52c604f62c2f2beee5e7e672b0e6e9833dd43dba99b77668540c850c9a81a5ea7aaf6297383e6135bd64572362333121fc7"); - assert_se(EVP_PKEY_verify(ctx, sig, sig_len, (unsigned char*) msg, strlen(msg)) == 1); + assert_se(sym_EVP_PKEY_verify(ctx, sig, sig_len, (unsigned char*) msg, strlen(msg)) == 1); DEFINE_HEX_PTR(invalid_sig, "1234"); - assert_se(EVP_PKEY_verify(ctx, invalid_sig, invalid_sig_len, (unsigned char*) msg, strlen(msg)) != 1); + assert_se(sym_EVP_PKEY_verify(ctx, invalid_sig, invalid_sig_len, (unsigned char*) msg, strlen(msg)) != 1); _cleanup_free_ void *n2 = NULL, *e2 = NULL; size_t n2_size, e2_size; @@ -69,16 +69,16 @@ TEST(ecc_pkey_curve_x_y) { _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; assert_se(ecc_pkey_from_curve_x_y(curveid, x, x_len, y, y_len, &pkey) >= 0); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = sym_EVP_PKEY_CTX_new(pkey, NULL); assert_se(ctx); - assert_se(EVP_PKEY_verify_init(ctx) == 1); + assert_se(sym_EVP_PKEY_verify_init(ctx) == 1); const char *msg = "this is a secret"; DEFINE_HEX_PTR(sig, "3045022100f6ca10f7ed57a020679899b26dd5ac5a1079265885e2a6477f527b6a3f02b5ca02207b550eb3e7b69360aff977f7f6afac99c3f28266b6c5338ce373f6b59263000a"); - assert_se(EVP_PKEY_verify(ctx, sig, sig_len, (unsigned char*) msg, strlen(msg)) == 1); + assert_se(sym_EVP_PKEY_verify(ctx, sig, sig_len, (unsigned char*) msg, strlen(msg)) == 1); DEFINE_HEX_PTR(invalid_sig, "1234"); - assert_se(EVP_PKEY_verify(ctx, invalid_sig, invalid_sig_len, (unsigned char*) msg, strlen(msg)) != 1); + assert_se(sym_EVP_PKEY_verify(ctx, invalid_sig, invalid_sig_len, (unsigned char*) msg, strlen(msg)) != 1); _cleanup_free_ void *x2 = NULL, *y2 = NULL; size_t x2_size, y2_size; @@ -465,4 +465,31 @@ TEST(ecc_ecdh) { assert_se(memcmp_nn(secretAC, secretAC_size, secretAB, secretAB_size) != 0); } -DEFINE_TEST_MAIN(LOG_DEBUG); +TEST(string_hashsum) { + _cleanup_free_ char *out1 = NULL, *out2 = NULL, *out3 = NULL, *out4 = NULL; + + ASSERT_OK(string_hashsum("asdf", 4, "SHA224", &out1)); + /* echo -n 'asdf' | sha224sum - */ + ASSERT_STREQ(out1, "7872a74bcbf298a1e77d507cd95d4f8d96131cbbd4cdfc571e776c8a"); + + ASSERT_OK(string_hashsum("asdf", 4, "SHA256", &out2)); + /* echo -n 'asdf' | sha256sum - */ + ASSERT_STREQ(out2, "f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b"); + + ASSERT_OK(string_hashsum("", 0, "SHA224", &out3)); + /* echo -n '' | sha224sum - */ + ASSERT_STREQ(out3, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"); + + ASSERT_OK(string_hashsum("", 0, "SHA256", &out4)); + /* echo -n '' | sha256sum - */ + ASSERT_STREQ(out4, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); +} + +static int intro(void) { + if (dlopen_libcrypto(LOG_DEBUG) < 0) + return log_tests_skipped("libcrypto is not available"); + + return EXIT_SUCCESS; +} + +DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro); diff --git a/src/test/test-cryptolib.c b/src/test/test-cryptolib.c deleted file mode 100644 index d86236bafe..0000000000 --- a/src/test/test-cryptolib.c +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include "alloc-util.h" -#include "openssl-util.h" -#include "tests.h" - -TEST(string_hashsum) { - _cleanup_free_ char *out1 = NULL, *out2 = NULL, *out3 = NULL, *out4 = NULL; - - ASSERT_OK(string_hashsum("asdf", 4, "SHA224", &out1)); - /* echo -n 'asdf' | sha224sum - */ - ASSERT_STREQ(out1, "7872a74bcbf298a1e77d507cd95d4f8d96131cbbd4cdfc571e776c8a"); - - ASSERT_OK(string_hashsum("asdf", 4, "SHA256", &out2)); - /* echo -n 'asdf' | sha256sum - */ - ASSERT_STREQ(out2, "f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b"); - - ASSERT_OK(string_hashsum("", 0, "SHA224", &out3)); - /* echo -n '' | sha224sum - */ - ASSERT_STREQ(out3, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"); - - ASSERT_OK(string_hashsum("", 0, "SHA256", &out4)); - /* echo -n '' | sha256sum - */ - ASSERT_STREQ(out4, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); -} - -DEFINE_TEST_MAIN(LOG_INFO); diff --git a/src/test/test-dlopen-so.c b/src/test/test-dlopen-so.c index d3121981cf..7421a77024 100644 --- a/src/test/test-dlopen-so.c +++ b/src/test/test-dlopen-so.c @@ -5,6 +5,7 @@ #include "blkid-util.h" #include "bpf-dlopen.h" #include "compress.h" +#include "crypto-util.h" #include "cryptsetup-util.h" #include "curl-util.h" #include "elf-util.h" @@ -28,6 +29,7 @@ #include "qrcode-util.h" #include "seccomp-util.h" #include "selinux-util.h" +#include "ssl-util.h" #include "tests.h" #include "tpm2-util.h" @@ -68,6 +70,8 @@ static int run(int argc, char **argv) { ASSERT_DLOPEN(dlopen_libpam, HAVE_PAM); ASSERT_DLOPEN(dlopen_libseccomp, HAVE_SECCOMP); ASSERT_DLOPEN(dlopen_libselinux, HAVE_SELINUX); + ASSERT_DLOPEN(dlopen_libcrypto, HAVE_OPENSSL); + ASSERT_DLOPEN(dlopen_libssl, HAVE_OPENSSL); ASSERT_DLOPEN(dlopen_xz, HAVE_XZ); ASSERT_DLOPEN(dlopen_lz4, HAVE_LZ4); ASSERT_DLOPEN(dlopen_microhttpd, HAVE_MICROHTTPD); diff --git a/src/test/test-tpm2.c b/src/test/test-tpm2.c index 78e2d234ab..c9a2e0a9bb 100644 --- a/src/test/test-tpm2.c +++ b/src/test/test-tpm2.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "architecture.h" +#include "crypto-util.h" #include "hexdecoct.h" #include "tests.h" #include "tpm2-util.h" @@ -782,25 +783,25 @@ TEST(tpm2b_public_to_openssl_pkey) { _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey_rsa = NULL; assert_se(tpm2_tpm2b_public_to_openssl_pkey(&public, &pkey_rsa) >= 0); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx_rsa = EVP_PKEY_CTX_new(pkey_rsa, NULL); + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx_rsa = sym_EVP_PKEY_CTX_new(pkey_rsa, NULL); assert_se(ctx_rsa); - assert_se(EVP_PKEY_verify_init(ctx_rsa) == 1); - assert_se(EVP_PKEY_CTX_set_signature_md(ctx_rsa, EVP_sha256()) > 0); + assert_se(sym_EVP_PKEY_verify_init(ctx_rsa) == 1); + assert_se(sym_EVP_PKEY_CTX_set_signature_md(ctx_rsa, sym_EVP_sha256()) > 0); DEFINE_HEX_PTR(sig_rsa, "9f70a9e68911be3ec464cae91126328307bf355872127e042d6c61e0a80982872c151033bcf727abfae5fc9500c923120011e7ef4aa5fc690a59a034697b6022c141b4b209e2df6f4b282288cd9181073fbe7158ce113c79d87623423c1f3996ff931e59cc91db74f8e8656215b1436fc93ddec0f1f8fa8510826e674b250f047e6cba94c95ff98072a286baca94646b577974a1e00d56c21944e38960d8ee90511a2f938e5cf1ac7b7cc7ff8e3ac001d321254d3e4f988b90e9f6f873c26ecd0a12a626b3474833cdbb9e9f793238f6c97ee5b75a1a89bb7a7858d34ecfa6d34ac58d95085e6c4fbbebd47a4364be2725c2c6b3fa15d916f3c0b62a66fe76ae"); - assert_se(EVP_PKEY_verify(ctx_rsa, sig_rsa, sig_rsa_len, (unsigned char*) msg, msg_len) == 1); + assert_se(sym_EVP_PKEY_verify(ctx_rsa, sig_rsa, sig_rsa_len, (unsigned char*) msg, msg_len) == 1); /* ECC */ tpm2b_public_ecc_init(&public, TPM2_ECC_NIST_P256, "6fc0ecf3645c673ab7e86d1ec5b315afb950257c5f68ab23296160006711fac2", "8dd2ef7a2c9ecede91493ba98c8fb3f893aff325c6a1e0f752c657b2d6ca1413"); _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey_ecc = NULL; assert_se(tpm2_tpm2b_public_to_openssl_pkey(&public, &pkey_ecc) >= 0); - _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx_ecc = EVP_PKEY_CTX_new(pkey_ecc, NULL); + _cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx_ecc = sym_EVP_PKEY_CTX_new(pkey_ecc, NULL); assert_se(ctx_ecc); - assert_se(EVP_PKEY_verify_init(ctx_ecc) == 1); + assert_se(sym_EVP_PKEY_verify_init(ctx_ecc) == 1); DEFINE_HEX_PTR(sig_ecc, "304602210092447ac0b5b32e90923f79bb4aba864b9c546a9900cf193a83243d35d189a2110221009a8b4df1dfa85e225eff9c606694d4d205a7a3968c9552f50bc2790209a90001"); - assert_se(EVP_PKEY_verify(ctx_ecc, sig_ecc, sig_ecc_len, (unsigned char*) msg, msg_len) == 1); + assert_se(sym_EVP_PKEY_verify(ctx_ecc, sig_ecc, sig_ecc_len, (unsigned char*) msg, msg_len) == 1); } static void get_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PUBLIC *ret) { diff --git a/src/tpm2-setup/meson.build b/src/tpm2-setup/meson.build index bac29cbbdc..e87a13d8e6 100644 --- a/src/tpm2-setup/meson.build +++ b/src/tpm2-setup/meson.build @@ -10,7 +10,7 @@ executables += [ 'HAVE_TPM2', ], 'dependencies' : [ - libopenssl, + libopenssl_cflags, ], }, libexec_template + { diff --git a/src/tpm2-setup/tpm2-setup.c b/src/tpm2-setup/tpm2-setup.c index 74e13219f7..b779650b73 100644 --- a/src/tpm2-setup/tpm2-setup.c +++ b/src/tpm2-setup/tpm2-setup.c @@ -9,6 +9,7 @@ #include "build.h" #include "conf-files.h" #include "constants.h" +#include "crypto-util.h" #include "errno-util.h" #include "fd-util.h" #include "fileio.h" @@ -127,7 +128,7 @@ static void public_key_data_done(struct public_key_data *d) { assert(d); if (d->pkey) { - EVP_PKEY_free(d->pkey); + sym_EVP_PKEY_free(d->pkey); d->pkey = NULL; } if (d->public) { @@ -148,7 +149,7 @@ static int public_key_make_fingerprint(struct public_key_data *d) { assert(!d->fingerprint); assert(!d->fingerprint_hex); - r = pubkey_fingerprint(d->pkey, EVP_sha256(), &d->fingerprint, &d->fingerprint_size); + r = pubkey_fingerprint(d->pkey, sym_EVP_sha256(), &d->fingerprint, &d->fingerprint_size); if (r < 0) return log_error_errno(r, "Failed to calculate fingerprint of public key: %m"); @@ -320,7 +321,7 @@ static int setup_srk(void) { if (r < 0) return log_error_errno(r, "Failed to open SRK public key file '%s' for writing: %m", pem_path); - if (PEM_write_PUBKEY(f, tpm2_key.pkey) <= 0) + if (sym_PEM_write_PUBKEY(f, tpm2_key.pkey) <= 0) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write SRK public key file '%s'.", pem_path); if (fchmod(fileno(f), 0444) < 0) @@ -504,6 +505,10 @@ static int run(int argc, char *argv[]) { return EXIT_SUCCESS; } + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + umask(0022); /* Execute both jobs, and then return unlisted errors preferably, and listed errors