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