From: Daan De Meyer Date: Wed, 3 Jun 2026 10:58:02 +0000 (+0000) Subject: tree-wide: Beef up openssl logging X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6b158b72f593c5b619a44e4522d15cf71ff6c73e;p=thirdparty%2Fsystemd.git tree-wide: Beef up openssl logging Let's translate openssl's errors to proper errnos where we can instead of returning EIO for everything. Let's also make log_openssl_errors() public so we can use it everywhere and migrate the rest of the codebase to use it. --- diff --git a/src/bootctl/bootctl-install.c b/src/bootctl/bootctl-install.c index 413a9c86bfc..834d46facac 100644 --- a/src/bootctl/bootctl-install.c +++ b/src/bootctl/bootctl-install.c @@ -1092,8 +1092,7 @@ static int install_secure_boot_auto_enroll(InstallContext *c) { int dercertsz; 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to convert X.509 certificate to DER"); if (c->esp_fd < 0) return c->esp_fd; @@ -1150,33 +1149,31 @@ static int install_secure_boot_auto_enroll(InstallContext *c) { /* Don't count the trailing NUL terminator. */ 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"); + return log_openssl_errors(LOG_ERR, "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 (sym_BIO_write(bio, guid, sizeof(*guid)) < 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write variable GUID to bio"); + return log_openssl_errors(LOG_ERR, "Failed to write variable GUID to bio"); if (sym_BIO_write(bio, &attrs, sizeof(attrs)) < 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write variable attributes to bio"); + return log_openssl_errors(LOG_ERR, "Failed to write variable attributes to bio"); if (sym_BIO_write(bio, ×tamp, sizeof(timestamp)) < 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write timestamp to bio"); + return log_openssl_errors(LOG_ERR, "Failed to write timestamp to bio"); if (sym_BIO_write(bio, siglist, siglistsz) < 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write signature list to bio"); + return log_openssl_errors(LOG_ERR, "Failed to write signature list to bio"); _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL; 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to calculate PKCS7 signature"); _cleanup_free_ uint8_t *sig = NULL; 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to convert PKCS7 signature to DER"); size_t authsz = offsetof(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo.CertData) + sigsz; _cleanup_free_ EFI_VARIABLE_AUTHENTICATION_2 *auth = malloc(authsz); diff --git a/src/home/homed-manager-bus.c b/src/home/homed-manager-bus.c index b8385c781e2..eb2a8441f29 100644 --- a/src/home/homed-manager-bus.c +++ b/src/home/homed-manager-bus.c @@ -13,6 +13,7 @@ #include "bus-object.h" #include "bus-polkit.h" #include "crypto-util.h" +#include "errno-util.h" #include "fileio.h" #include "format-util.h" #include "home-util.h" @@ -983,12 +984,23 @@ static int method_add_signing_key(sd_bus_message *message, void *userdata, sd_bu if (r == 0) return 1; /* Will call us back */ + /* Load libcrypto up front so that its unavailability (e.g. -EOPNOTSUPP) is propagated as the real + * error instead of being misattributed to the user-supplied key below. */ + r = dlopen_libcrypto(LOG_DEBUG); + if (r < 0) + return r; + _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; r = openssl_pubkey_from_pem(pem, /* pem_size= */ SIZE_MAX, &pkey); - if (r == -EIO) + if (r < 0) { + /* libcrypto is loaded at this point, so any failure here is a failure to parse or load the + * user-supplied key (the translated OpenSSL errno varies: -EBADMSG, -EINVAL, -EOPNOTSUPP, + * -EIO, …) — treat it as an invalid public key, except resource exhaustion which we + * propagate as-is. */ + if (ERRNO_IS_NEG_RESOURCE(r)) + return r; return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Public key invalid: %s", fn); - if (r < 0) - return r; + } /* Make sure the local key is loaded before can detect conflicts */ r = manager_acquire_key_pair(m); diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index 8ae56476d63..bdee16d2768 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -1338,7 +1338,7 @@ static int manager_load_key_pair(Manager *m) { 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"); + return log_openssl_errors(LOG_ERR, "Failed to load private key pair"); log_info("Successfully loaded private key pair."); @@ -1358,15 +1358,15 @@ static int manager_generate_key_pair(Manager *m) { 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."); + return log_openssl_errors(LOG_ERR, "Failed to allocate Ed25519 key generation context."); if (sym_EVP_PKEY_keygen_init(ctx) <= 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to initialize Ed25519 key generation context."); + return log_openssl_errors(LOG_ERR, "Failed to initialize Ed25519 key generation context."); log_info("Generating key pair for signing local user identity records."); if (sym_EVP_PKEY_keygen(ctx, &m->private_key) <= 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to generate Ed25519 key pair"); + return log_openssl_errors(LOG_ERR, "Failed to generate Ed25519 key pair"); log_info("Successfully created Ed25519 key pair."); @@ -1378,7 +1378,7 @@ static int manager_generate_key_pair(Manager *m) { return log_error_errno(r, "Failed to open key file for writing: %m"); if (sym_PEM_write_PUBKEY(fpublic, m->private_key) <= 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key."); + return log_openssl_errors(LOG_ERR, "Failed to write public key."); (void) fchmod(fileno(fpublic), 0444); /* Make public key world readable */ @@ -1394,7 +1394,7 @@ static int manager_generate_key_pair(Manager *m) { return log_error_errno(r, "Failed to open key file for writing: %m"); 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."); + return log_openssl_errors(LOG_ERR, "Failed to write private key pair."); (void) fchmod(fileno(fprivate), 0400); /* Make private key root readable */ @@ -1497,7 +1497,7 @@ static int manager_load_public_key_one(Manager *m, const char *path) { 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); + return log_openssl_errors(LOG_ERR, "Failed to parse public key file %s.", path); r = hashmap_ensure_put(&m->public_keys, &public_key_hash_ops, fn, pkey); if (r < 0) diff --git a/src/home/user-record-sign.c b/src/home/user-record-sign.c index 6bc97af27a6..c51349d949f 100644 --- a/src/home/user-record-sign.c +++ b/src/home/user-record-sign.c @@ -123,9 +123,14 @@ int user_record_verify(UserRecord *ur, EVP_PKEY *public_key) { return -ENOMEM; if (sym_EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, public_key) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to initialize signature verification"); if (sym_EVP_DigestVerify(md_ctx, signature, signature_size, (uint8_t*) text, strlen(text)) <= 0) { + /* A bad signature is an expected outcome here (counted as n_bad), but it may leave + * entries in the thread-local OpenSSL error queue. Clear them so a later iteration's + * failure — or an unrelated caller on this thread — translates its own error rather + * than this stale one. */ + sym_ERR_clear_error(); n_bad++; continue; } diff --git a/src/keyutil/keyutil.c b/src/keyutil/keyutil.c index c54f347079e..9fa706e1bc4 100644 --- a/src/keyutil/keyutil.c +++ b/src/keyutil/keyutil.c @@ -247,8 +247,8 @@ static int verb_extract_public(int argc, char *argv[], uintptr_t _data, void *us public_key = sym_X509_get_pubkey(certificate); if (!public_key) - return log_error_errno( - SYNTHETIC_ERRNO(EIO), + return log_openssl_errors( + LOG_ERR, "Failed to extract public key from certificate %s.", arg_certificate); @@ -286,7 +286,7 @@ static int verb_extract_public(int argc, char *argv[], uintptr_t _data, void *us return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "One of --certificate=, or --private-key= must be specified"); if (sym_PEM_write_PUBKEY(stdout, public_key) == 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key to stdout"); + return log_openssl_errors(LOG_ERR, "Failed to write public key to stdout"); return 0; } @@ -315,7 +315,7 @@ static int verb_extract_certificate(int argc, char *argv[], uintptr_t _data, voi return log_error_errno(r, "Failed to load X.509 certificate from %s: %m", arg_certificate); if (sym_PEM_write_X509(stdout, certificate) == 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write certificate to stdout."); + return log_openssl_errors(LOG_ERR, "Failed to write certificate to stdout."); return 0; } @@ -374,14 +374,12 @@ static int verb_pkcs7(int argc, char *argv[], uintptr_t _data, void *userdata) { return log_error_errno(SYNTHETIC_ERRNO(EIO), "Content file %s is empty", arg_content); if (!sym_PKCS7_content_new(pkcs7, NID_pkcs7_data)) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Error creating new PKCS7 content field"); + return log_openssl_errors(LOG_ERR, "Error creating new PKCS7 content field"); sym_ASN1_STRING_set0(pkcs7->d.sign->contents->d.data, TAKE_PTR(content), content_len); } else if (sym_PKCS7_set_detached(pkcs7, true) == 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), - "Failed to set PKCS#7 detached attribute: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to set PKCS#7 detached attribute"); /* Add PKCS1 signature to PKCS7_SIGNER_INFO */ sym_ASN1_STRING_set0(signer_info->enc_digest, TAKE_PTR(pkcs1), pkcs1_len); @@ -393,8 +391,7 @@ static int verb_pkcs7(int argc, char *argv[], uintptr_t _data, void *userdata) { return log_error_errno(r, "Failed to open temporary file: %m"); if (!sym_i2d_PKCS7_fp(output, pkcs7)) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write PKCS#7 file: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to write PKCS#7 file"); r = flink_tmpfile(output, tmp, arg_output, LINK_TMPFILE_REPLACE|LINK_TMPFILE_SYNC); if (r < 0) diff --git a/src/repart/repart.c b/src/repart/repart.c index c7814798ad1..244fd74a98b 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -6065,13 +6065,11 @@ static int sign_verity_roothash( 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to calculate PKCS7 signature"); sigsz = sym_i2d_PKCS7(p7, &sig); if (sigsz < 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert PKCS7 signature to DER: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to convert PKCS7 signature to DER"); *ret_signature = IOVEC_MAKE(TAKE_PTR(sig), sigsz); diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 6f14077d9b1..d987ee4fa4a 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -63,6 +63,17 @@ static int rr_compare(DnsResourceRecord * const *a, DnsResourceRecord * const *b return CMP(DNS_RESOURCE_RECORD_RDATA_SIZE(x), DNS_RESOURCE_RECORD_RDATA_SIZE(y)); } +/* The DNSSEC verification and digest helpers below reserve -EOPNOTSUPP to mean "this algorithm or digest + * is not supported (or is disabled by host policy)" — a condition their callers deliberately treat as an + * insecure-but-accepted result (DNSSEC_UNSUPPORTED_ALGORITHM and friends). Once an algorithm has been + * established as supported, a low-level OpenSSL failure during the actual computation can nonetheless + * translate to -EOPNOTSUPP (e.g. an OpenSSL provider pushing ERR_R_UNSUPPORTED, ERR_R_FETCH_FAILED, or + * ERR_R_DISABLED under FIPS or similar). Such a failure must fail closed, so collapse it onto -EIO and + * keep -EOPNOTSUPP exclusively for the genuine unsupported-algorithm signal. */ +static int dnssec_verify_errno(int r) { + return r == -EOPNOTSUPP ? -EIO : r; +} + static int dnssec_rsa_verify_raw( const EVP_MD *hash_algorithm, const void *signature, size_t signature_size, @@ -81,18 +92,18 @@ static int dnssec_rsa_verify_raw( e = sym_BN_bin2bn(exponent, exponent_size, NULL); if (!e) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to convert RSA exponent to BIGNUM"); m = sym_BN_bin2bn(modulus, modulus_size, NULL); if (!m) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to convert RSA modulus to BIGNUM"); rpubkey = sym_RSA_new(); if (!rpubkey) return -ENOMEM; if (sym_RSA_set0_key(rpubkey, m, e, NULL) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to set RSA public key"); e = m = NULL; if ((size_t) sym_RSA_size(rpubkey) != signature_size) @@ -103,25 +114,24 @@ static int dnssec_rsa_verify_raw( return -ENOMEM; if (sym_EVP_PKEY_assign_RSA(epubkey, sym_RSAPublicKey_dup(rpubkey)) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to assign RSA public key"); ctx = sym_EVP_PKEY_CTX_new(epubkey, NULL); if (!ctx) return -ENOMEM; if (sym_EVP_PKEY_verify_init(ctx) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to initialize RSA signature verification"); if (sym_EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to set RSA padding"); if (sym_EVP_PKEY_CTX_set_signature_md(ctx, hash_algorithm) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to set RSA signature digest"); 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", sym_ERR_get_error()); + return log_openssl_errors(LOG_DEBUG, "Signature verification failed"); REENABLE_WARNING; return r; @@ -220,30 +230,28 @@ static int dnssec_ecdsa_verify_raw( return -ENOMEM; if (sym_EC_POINT_oct2point(ec_group, p, key, key_size, bctx) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to parse EC public key point"); eckey = sym_EC_KEY_new(); if (!eckey) return -ENOMEM; if (sym_EC_KEY_set_group(eckey, ec_group) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to set EC group"); 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", sym_ERR_get_error()); + return log_openssl_errors(LOG_DEBUG, "EC_KEY_set_public_key failed"); if (sym_EC_KEY_check_key(eckey) != 1) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), - "EC_KEY_check_key failed: 0x%lx", sym_ERR_get_error()); + return log_openssl_errors(LOG_DEBUG, "EC_KEY_check_key failed"); r = sym_BN_bin2bn(signature_r, signature_r_size, NULL); if (!r) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to convert ECDSA signature r to BIGNUM"); s = sym_BN_bin2bn(signature_s, signature_s_size, NULL); if (!s) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to convert ECDSA signature s to BIGNUM"); /* TODO: We should eventually use the EVP API once it supports ECDSA signature verification */ @@ -252,13 +260,12 @@ static int dnssec_ecdsa_verify_raw( return -ENOMEM; if (sym_ECDSA_SIG_set0(sig, r, s) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to set ECDSA signature"); r = s = NULL; 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", sym_ERR_get_error()); + return log_openssl_errors(LOG_DEBUG, "Signature verification failed"); REENABLE_WARNING; return k; @@ -328,8 +335,7 @@ static int dnssec_eddsa_verify_raw( 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", sym_ERR_get_error()); + return log_openssl_errors(LOG_DEBUG, "EVP_PKEY_new_raw_public_key failed"); pctx = sym_EVP_PKEY_CTX_new(evkey, NULL); if (!pctx) @@ -344,12 +350,11 @@ static int dnssec_eddsa_verify_raw( /* One might be tempted to use EVP_PKEY_verify_init, but see Ed25519(7ssl). */ if (sym_EVP_DigestVerifyInit(ctx, &pctx, NULL, NULL, evkey) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to initialize EdDSA verification"); 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", sym_ERR_get_error()); + return log_openssl_errors(LOG_DEBUG, "Signature verification failed"); return r; } @@ -632,11 +637,13 @@ static int dnssec_rrset_verify_sig( switch (rrsig->rrsig.algorithm) { case DNSSEC_ALGORITHM_ED25519: - return dnssec_eddsa_verify( + /* The algorithm is supported, so a -EOPNOTSUPP from the actual verification is a hard + * crypto failure, not an unsupported-algorithm condition: fail closed. */ + return dnssec_verify_errno(dnssec_eddsa_verify( rrsig->rrsig.algorithm, sig_data, sig_size, rrsig, - dnskey); + dnskey)); case DNSSEC_ALGORITHM_ED448: return -EOPNOTSUPP; default: @@ -655,10 +662,10 @@ static int dnssec_rrset_verify_sig( return -EOPNOTSUPP; if (sym_EVP_DigestUpdate(ctx, sig_data, sig_size) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to update digest")); if (sym_EVP_DigestFinal_ex(ctx, hash, &hash_size) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to finalize digest")); assert(hash_size > 0); } @@ -669,20 +676,20 @@ static int dnssec_rrset_verify_sig( case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1: case DNSSEC_ALGORITHM_RSASHA256: case DNSSEC_ALGORITHM_RSASHA512: - return dnssec_rsa_verify( + return dnssec_verify_errno(dnssec_rsa_verify( md_algorithm, hash, hash_size, rrsig, - dnskey); + dnskey)); case DNSSEC_ALGORITHM_ECDSAP256SHA256: case DNSSEC_ALGORITHM_ECDSAP384SHA384: - return dnssec_ecdsa_verify( + return dnssec_verify_errno(dnssec_ecdsa_verify( md_algorithm, rrsig->rrsig.algorithm, hash, hash_size, rrsig, - dnskey); + dnskey)); default: assert_not_reached(); @@ -1117,7 +1124,7 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, return -EOPNOTSUPP; if (sym_EVP_DigestUpdate(ctx, wire_format, encoded_length) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to update digest")); if (mask_revoke) md_add_uint16(ctx, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE); @@ -1131,10 +1138,10 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, if (r <= 0) return r; if (sym_EVP_DigestUpdate(ctx, dnskey->dnskey.key, dnskey->dnskey.key_size) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to update digest")); if (sym_EVP_DigestFinal_ex(ctx, result, NULL) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to finalize digest")); return memcmp(result, ds->ds.digest, ds->ds.digest_size) == 0; } @@ -1241,24 +1248,24 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) { return r; if (sym_EVP_DigestUpdate(ctx, wire_format, r) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to update digest")); if (sym_EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to update digest")); uint8_t result[EVP_MAX_MD_SIZE]; if (sym_EVP_DigestFinal_ex(ctx, result, NULL) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to finalize digest")); for (unsigned k = 0; k < nsec3->nsec3.iterations; k++) { if (sym_EVP_DigestInit_ex(ctx, algorithm, NULL) <= 0) return -EOPNOTSUPP; if (sym_EVP_DigestUpdate(ctx, result, hash_size) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to update digest")); if (sym_EVP_DigestUpdate(ctx, nsec3->nsec3.salt, nsec3->nsec3.salt_size) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to update digest")); if (sym_EVP_DigestFinal_ex(ctx, result, NULL) <= 0) - return -EIO; + return dnssec_verify_errno(log_openssl_errors(LOG_DEBUG, "Failed to finalize digest")); } memcpy(ret, result, hash_size); diff --git a/src/resolve/resolved-dnstls.c b/src/resolve/resolved-dnstls.c index e7191f2e7f4..6f489ae3bdb 100644 --- a/src/resolve/resolved-dnstls.c +++ b/src/resolve/resolved-dnstls.c @@ -87,9 +87,14 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { return -ENOMEM; sym_SSL_set_connect_state(s); + + /* Clear any errors left in the thread-local queue by a prior connection attempt (resolved drives + * everything from a single event-loop thread), so the translation below reflects this + * SSL_set_session() failure rather than a stale FIFO entry. */ + sym_ERR_clear_error(); r = sym_SSL_set_session(s, server->dnstls_data.session); if (r == 0) - return -EIO; + return openssl_to_errno(sym_ERR_get_error()); sym_SSL_set_bio(s, TAKE_PTR(rb), TAKE_PTR(wb)); if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { @@ -407,23 +412,17 @@ int dnstls_manager_init(Manager *manager) { 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_WARNING, "Failed to create SSL context"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_WARNING, "Failed to set protocol version on SSL context"); (void) sym_SSL_CTX_set_options(manager->dnstls_data.ctx, SSL_OP_NO_COMPRESSION); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_WARNING, "Failed to load system trust store"); return 0; } diff --git a/src/sbsign/sbsign.c b/src/sbsign/sbsign.c index cad7cc54db0..5408ffc6152 100644 --- a/src/sbsign/sbsign.c +++ b/src/sbsign/sbsign.c @@ -208,8 +208,7 @@ static int spc_indirect_data_content_new(const void *digest, size_t digestsz, ui return log_oom(); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to set ASN1 string"); _cleanup_(SpcPeImageData_freep) SpcPeImageData *peid = SpcPeImageData_new(); if (!peid) @@ -220,8 +219,7 @@ static int spc_indirect_data_content_new(const void *digest, size_t digestsz, ui _cleanup_free_ uint8_t *peidraw = NULL; int peidrawsz = i2d_SpcPeImageData(peid, &peidraw); if (peidrawsz < 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to convert SpcPeImageData to BER: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to convert SpcPeImageData to BER"); _cleanup_(SpcIndirectDataContent_freep) SpcIndirectDataContent *idc = SpcIndirectDataContent_new(); idc->data->value = sym_ASN1_TYPE_new(); @@ -235,16 +233,14 @@ static int spc_indirect_data_content_new(const void *digest, size_t digestsz, ui 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to get SpcPeImageData object"); 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."); + return log_openssl_errors(LOG_ERR, "Failed to set ASN1_STRING data."); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to get SHA256 object"); idc->messageDigest->digestAlgorithm->parameters = sym_ASN1_TYPE_new(); if (!idc->messageDigest->digestAlgorithm->parameters) @@ -253,14 +249,12 @@ static int spc_indirect_data_content_new(const void *digest, size_t digestsz, ui idc->messageDigest->digestAlgorithm->parameters->type = V_ASN1_NULL; if (sym_ASN1_OCTET_STRING_set(idc->messageDigest->digest, digest, digestsz) == 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set digest: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to set digest"); _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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to convert SpcIndirectDataContent to BER"); *ret_idc = TAKE_PTR(idcraw); *ret_idcsz = (size_t) idcrawsz; @@ -278,8 +272,7 @@ static int asn1_timestamp(ASN1_TIME **ret) { if (epoch == USEC_INFINITY) { time = sym_X509_gmtime_adj(NULL, 0); if (!time) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get current time: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to get current time"); } else { time = sym_ASN1_TIME_set(NULL, (time_t) (epoch / USEC_PER_SEC)); if (!time) @@ -328,12 +321,10 @@ static int pkcs7_new_with_attributes( return log_oom(); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to add smimecap signed attribute to signer info"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to add content type signed attribute to signer info"); _cleanup_(ASN1_TIME_freep) ASN1_TIME *time = NULL; r = asn1_timestamp(&time); @@ -341,19 +332,16 @@ static int pkcs7_new_with_attributes( return r; 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to add signing time signed attribute to signer info"); TAKE_PTR(time); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to get SpcIndirectDataContent object"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to add signed attribute to pkcs7 signer info"); *ret_p7 = TAKE_PTR(p7); *ret_si = TAKE_PTR(si); @@ -365,8 +353,7 @@ static int pkcs7_populate_data_bio(PKCS7* p7, const void *data, size_t size, BIO _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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to create PKCS7 data bio"); int tag, class; long psz; @@ -374,12 +361,10 @@ static int pkcs7_populate_data_bio(PKCS7* p7, const void *data, size_t size, BIO /* This function weirdly enough reports errors by setting the 0x80 bit in its return value. */ 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to parse ASN.1 object"); if (sym_BIO_write(bio, p, psz) < 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write to PKCS7 data bio: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to write to PKCS7 data bio"); *ret = TAKE_PTR(bio); @@ -393,24 +378,20 @@ static int pkcs7_add_digest_attribute(PKCS7 *p7, BIO *data, PKCS7_SIGNER_INFO *s 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to find digest bio"); EVP_MD_CTX *mdc; if (sym_BIO_get_md_ctx(mdbio, &mdc) <= 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get digest context from bio: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to get digest context from bio"); unsigned char digest[EVP_MAX_MD_SIZE]; unsigned digestsz; if (sym_EVP_DigestFinal_ex(mdc, digest, &digestsz) == 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to get digest: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to get digest"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to add PKCS9 message digest signed attribute to signer info"); return 0; } @@ -492,8 +473,7 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { const uint8_t *p = content; 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to parse signed attributes"); } if (arg_signed_data_signature) { @@ -561,8 +541,7 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { _cleanup_free_ unsigned char *abuf = NULL; 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to convert signed attributes ASN.1 to DER"); r = loop_write(dstfd, abuf, alen); if (r < 0) @@ -585,8 +564,7 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { return r; if (sym_PKCS7_dataFinal(p7, bio) == 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to sign data: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to sign data"); } _cleanup_(PKCS7_freep) PKCS7 *p7c = sym_PKCS7_new(); @@ -595,8 +573,7 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to get SpcIndirectDataContent object"); p7c->d.other = sym_ASN1_TYPE_new(); if (!p7c->d.other) @@ -608,20 +585,17 @@ static int verb_sign(int argc, char *argv[], uintptr_t _data, void *userdata) { return log_oom(); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to set ASN1 string"); if (sym_PKCS7_set_content(p7, p7c) == 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 data: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to set PKCS7 data"); TAKE_PTR(p7c); _cleanup_free_ uint8_t *sig = NULL; 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to convert PKCS7 signature to DER"); _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 6ed43373537..e20b64291ae 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -1066,12 +1066,10 @@ int encrypt_credential_and_warn( context = sym_EVP_CIPHER_CTX_new(); if (!context) - return log_error_errno(SYNTHETIC_ERRNO(ENOMEM), "Failed to allocate encryption object: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to allocate encryption object"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to initialize encryption context"); /* Just an upper estimate */ output.iov_len = @@ -1137,8 +1135,7 @@ int encrypt_credential_and_warn( /* Pass the encrypted + TPM2 header + scoped header as AAD */ 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to write AAD data"); /* Now construct the metadata header */ ml = strlen_ptr(name); @@ -1153,8 +1150,7 @@ int encrypt_credential_and_warn( /* And encrypt the metadata header */ 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to encrypt metadata header"); assert(added >= 0); assert((size_t) added <= output.iov_len - p); @@ -1162,8 +1158,7 @@ int encrypt_credential_and_warn( /* Then encrypt the plaintext */ 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to encrypt data"); assert(added >= 0); assert((size_t) added <= output.iov_len - p); @@ -1171,8 +1166,7 @@ int encrypt_credential_and_warn( /* Finalize */ 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to finalize data encryption"); assert(added >= 0); assert((size_t) added <= output.iov_len - p); @@ -1182,8 +1176,7 @@ int encrypt_credential_and_warn( /* Append tag */ 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to get tag"); p += tsz; assert(p <= output.iov_len); @@ -1454,24 +1447,19 @@ int decrypt_credential_and_warn( context = sym_EVP_CIPHER_CTX_new(); if (!context) - return log_error_errno(SYNTHETIC_ERRNO(ENOMEM), "Failed to allocate decryption object: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to allocate decryption object"); if (sym_EVP_DecryptInit_ex(context, cc, NULL, NULL, NULL) != 1) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to initialize decryption context: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to initialize decryption context"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to set IV size on decryption context"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to set IV and key"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to write AAD data"); plaintext.iov_base = malloc(input->iov_len - p - le32toh(h->tag_size)); if (!plaintext.iov_base) @@ -1483,20 +1471,23 @@ int decrypt_credential_and_warn( &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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to decrypt data"); assert(added >= 0); assert((size_t) added <= input->iov_len - p - le32toh(h->tag_size)); plaintext.iov_len = added; 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); - - 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_ERR, "Failed to set tag"); + + if (sym_EVP_DecryptFinal_ex(context, (uint8_t*) plaintext.iov_base + plaintext.iov_len, &added) != 1) { + log_openssl_errors(LOG_ERR, "Decryption failed (incorrect key?)"); + /* A GCM tag/authentication mismatch (wrong key or corrupted blob) is the common case here + * and typically leaves the OpenSSL error queue empty, so we can't rely on the translated + * errno. Return -EBADMSG unconditionally: it's this function's documented "corrupted file" + * code, and credentials_varlink_error_table[] maps it to io.systemd.Credentials.BadFormat. */ + return -EBADMSG; + } plaintext.iov_len += added; diff --git a/src/shared/crypto-util.c b/src/shared/crypto-util.c index 03ca4d6e80a..42776571956 100644 --- a/src/shared/crypto-util.c +++ b/src/shared/crypto-util.c @@ -636,31 +636,91 @@ int dlopen_libcrypto(int log_level) { #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 - * errors." This logs at level debug. Returns -EIO (or -ENOMEM). */ -#define log_openssl_errors(fmt, ...) _log_openssl_errors(UNIQ, fmt, ##__VA_ARGS__) -#define _log_openssl_errors(u, fmt, ...) \ - ({ \ - size_t UNIQ_T(MAX, u) = 512 /* arbitrary, but openssl doc states it must be >= 256 */; \ - _cleanup_free_ char *UNIQ_T(BUF, u) = malloc(UNIQ_T(MAX, u)); \ - !UNIQ_T(BUF, u) \ - ? log_oom_debug() \ - : __log_openssl_errors(u, UNIQ_T(BUF, u), UNIQ_T(MAX, u), fmt, ##__VA_ARGS__) \ - ?: log_debug_errno(SYNTHETIC_ERRNO(EIO), fmt ": No OpenSSL errors.", ##__VA_ARGS__); \ - }) -#define __log_openssl_errors(u, buf, max, fmt, ...) \ - ({ \ - int UNIQ_T(R, u) = 0; \ - for (;;) { \ - unsigned long UNIQ_T(E, u) = sym_ERR_get_error(); \ - if (UNIQ_T(E, u) == 0) \ - break; \ - 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_to_errno(unsigned long e) { + if (e == 0) + return -ENOTRECOVERABLE; + + if (ERR_SYSTEM_ERROR(e)) + /* ERR_GET_REASON() returns the raw errno in this case. OpenSSL can record a system error + * with a zero errno though (e.g. bio_sock2.c raises ERR_LIB_SYS with a socket error that + * "may be 0"), which would yield 0 here. Clamp that to -ENOTRECOVERABLE so we never return 0 + * and break the negative-return invariant that the log_openssl_errors() call sites depend + * on. */ + return -ERR_GET_REASON(e) ?: -ENOTRECOVERABLE; + + switch (ERR_GET_REASON(e)) { + + case ERR_R_MALLOC_FAILURE: + return -ENOMEM; + + case ERR_R_PASSED_NULL_PARAMETER: + case ERR_R_PASSED_INVALID_ARGUMENT: +#ifdef ERR_R_INVALID_PROPERTY_DEFINITION + case ERR_R_INVALID_PROPERTY_DEFINITION: +#endif + return -EINVAL; + + case ERR_R_UNSUPPORTED: + case ERR_R_FETCH_FAILED: + case ERR_R_DISABLED: + return -EOPNOTSUPP; + + case ERR_R_NESTED_ASN1_ERROR: + case ERR_R_MISSING_ASN1_EOS: + return -EBADMSG; + +#ifdef ERR_R_INTERRUPTED_OR_CANCELLED + case ERR_R_INTERRUPTED_OR_CANCELLED: + return -EINTR; +#endif + + default: + /* Includes the internal/should-not-happen reasons (ERR_R_INTERNAL_ERROR, + * ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, ERR_R_INIT_FAIL, ERR_R_OPERATION_FAIL, …) and the + * "error originated in sub-library X" markers, none of which have a meaningful errno. Use + * -ENOTRECOVERABLE for these opaque OpenSSL failures, matching the convention used for + * unexpected crypto/digest failures elsewhere in the tree, and keeping them distinct from + * genuine -EIO (disk/socket) errors. */ + return -ENOTRECOVERABLE; + } +} + +int log_openssl_errors_internal(int level, const char *file, int line, const char *func, const char *format, ...) { + _cleanup_free_ char *prefix = NULL; + va_list ap; + int r; + + va_start(ap, format); + r = vasprintf(&prefix, format, ap); + va_end(ap); + if (r < 0) + return log_oom_full(level); + + char buf[512]; /* openssl docs require >= 256 */ + int ret = 0; + for (;;) { + unsigned long e = sym_ERR_get_error(); + if (e == 0) + break; + + sym_ERR_error_string_n(e, buf, sizeof(buf)); + + /* The queue is drained oldest-first (ERR_get_error() is FIFO), and the oldest entry is + * normally the deepest, most-specific reason while newer entries are higher-level + * "came-from" wrappers that translate to the -ENOTRECOVERABLE fallback. Keep the first + * specific (non-fallback) errno we see, so a trailing wrapper can't shadow it. */ + int translated = openssl_to_errno(e); + if (ret == 0 || (ret == -ENOTRECOVERABLE && translated != -ENOTRECOVERABLE)) + ret = translated; + + log_internal(level, SYNTHETIC_ERRNO(translated), file, line, func, "%s: %s", prefix, buf); + } + + if (ret == 0) /* The queue was empty. */ + return log_internal(level, SYNTHETIC_ERRNO(ENOTRECOVERABLE), file, line, func, "%s: No OpenSSL errors.", prefix); + + return ret; +} int openssl_pubkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret) { int r; @@ -682,7 +742,7 @@ int openssl_pubkey_from_pem(const void *pem, size_t pem_size, EVP_PKEY **ret) { _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to parse PEM"); *ret = TAKE_PTR(pkey); return 0; @@ -704,7 +764,7 @@ int openssl_pubkey_to_pem(EVP_PKEY *pkey, char **ret) { return -ENOMEM; if (sym_PEM_write_PUBKEY(f, pkey) <= 0) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to write public key in PEM format"); return memstream_finalize(&m, ret, /* ret_size= */ NULL); } @@ -730,7 +790,7 @@ int openssl_digest_size(const char *digest_alg, size_t *ret_digest_size) { size_t digest_size = sym_EVP_MD_get_size(md); if (digest_size == 0) - return log_openssl_errors("Failed to get Digest size"); + return log_openssl_errors(LOG_DEBUG, "Failed to get Digest size"); *ret_digest_size = digest_size; @@ -764,14 +824,14 @@ int openssl_digest_many( _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_MD_CTX"); if (!sym_EVP_DigestInit_ex(ctx, md, NULL)) - return log_openssl_errors("Failed to initialize EVP_MD_CTX"); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize EVP_MD_CTX"); for (size_t i = 0; i < n_data; i++) if (!sym_EVP_DigestUpdate(ctx, data[i].iov_base, data[i].iov_len)) - return log_openssl_errors("Failed to update Digest"); + return log_openssl_errors(LOG_DEBUG, "Failed to update Digest"); size_t digest_size; r = openssl_digest_size(digest_alg, &digest_size); @@ -784,7 +844,7 @@ int openssl_digest_many( unsigned size; if (!sym_EVP_DigestFinal_ex(ctx, buf, &size)) - return log_openssl_errors("Failed to finalize Digest"); + return log_openssl_errors(LOG_DEBUG, "Failed to finalize Digest"); assert(size == digest_size); @@ -826,33 +886,33 @@ int openssl_hmac_many( _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_MAC_CTX"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new OSSL_PARAM_BLD"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to set HMAC OSSL_MAC_PARAM_DIGEST"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to build HMAC OSSL_PARAM"); if (!sym_EVP_MAC_init(ctx, key, key_size, params)) - return log_openssl_errors("Failed to initialize EVP_MAC_CTX"); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize EVP_MAC_CTX"); for (size_t i = 0; i < n_data; i++) if (!sym_EVP_MAC_update(ctx, data[i].iov_base, data[i].iov_len)) - return log_openssl_errors("Failed to update HMAC"); + return log_openssl_errors(LOG_DEBUG, "Failed to update HMAC"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to get HMAC digest size"); _cleanup_free_ void *buf = malloc(digest_size); if (!buf) @@ -860,7 +920,7 @@ int openssl_hmac_many( size_t size; if (!sym_EVP_MAC_final(ctx, buf, &size, digest_size)) - return log_openssl_errors("Failed to finalize HMAC"); + return log_openssl_errors(LOG_DEBUG, "Failed to finalize HMAC"); assert(size == digest_size); @@ -915,7 +975,7 @@ int openssl_cipher_many( _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_CIPHER_CTX"); /* Verify enough key data was provided. */ int cipher_key_length = sym_EVP_CIPHER_get_key_length(cipher); @@ -941,7 +1001,7 @@ int openssl_cipher_many( "Not enough IV bytes provided, require %d", cipher_iv_length); if (!sym_EVP_EncryptInit(ctx, cipher, key, iv)) - return log_openssl_errors("Failed to initialize EVP_CIPHER_CTX."); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize EVP_CIPHER_CTX."); int cipher_block_size = sym_EVP_CIPHER_CTX_get_block_size(ctx); assert(cipher_block_size > 0); @@ -956,7 +1016,7 @@ int openssl_cipher_many( int update_size; 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."); + return log_openssl_errors(LOG_DEBUG, "Failed to update Cipher."); size += update_size; } @@ -966,7 +1026,7 @@ int openssl_cipher_many( int final_size; if (!sym_EVP_EncryptFinal_ex(ctx, &buf[size], &final_size)) - return log_openssl_errors("Failed to finalize Cipher."); + return log_openssl_errors(LOG_DEBUG, "Failed to finalize Cipher."); *ret = TAKE_PTR(buf); *ret_size = size + final_size; @@ -1002,40 +1062,40 @@ int kdf_ss_derive( _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_KDF_CTX"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new OSSL_PARAM_BLD"); _cleanup_free_ void *buf = malloc(derive_size); if (!buf) return log_oom_debug(); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-SS OSSL_KDF_PARAM_DIGEST"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-SS OSSL_KDF_PARAM_KEY"); if (salt) 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-SS OSSL_KDF_PARAM_SALT"); if (info) 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-SS OSSL_KDF_PARAM_INFO"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to build KDF-SS OSSL_PARAM"); if (sym_EVP_KDF_derive(ctx, buf, derive_size, params) <= 0) - return log_openssl_errors("OpenSSL KDF-SS derive failed"); + return log_openssl_errors(LOG_DEBUG, "OpenSSL KDF-SS derive failed"); *ret = TAKE_PTR(buf); @@ -1079,51 +1139,51 @@ int kdf_kb_hmac_derive( _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_KDF_CTX"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new OSSL_PARAM_BLD"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-KB OSSL_KDF_PARAM_MAC"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-KB OSSL_KDF_PARAM_MODE"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-KB OSSL_KDF_PARAM_DIGEST"); if (key) 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-KB OSSL_KDF_PARAM_KEY"); if (salt) 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-KB OSSL_KDF_PARAM_SALT"); if (info) 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-KB OSSL_KDF_PARAM_INFO"); if (seed) 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add KDF-KB OSSL_KDF_PARAM_SEED"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to build KDF-KB OSSL_PARAM"); _cleanup_free_ void *buf = malloc(derive_size); if (!buf) return log_oom_debug(); if (sym_EVP_KDF_derive(ctx, buf, derive_size, params) <= 0) - return log_openssl_errors("OpenSSL KDF-KB derive failed"); + return log_openssl_errors(LOG_DEBUG, "OpenSSL KDF-KB derive failed"); *ret = TAKE_PTR(buf); @@ -1159,16 +1219,16 @@ int rsa_oaep_encrypt_bytes( _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_PKEY_CTX"); if (sym_EVP_PKEY_encrypt_init(ctx) <= 0) - return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize EVP_PKEY_CTX"); if (sym_EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) - return log_openssl_errors("Failed to configure RSA-OAEP padding"); + return log_openssl_errors(LOG_DEBUG, "Failed to configure RSA-OAEP padding"); if (sym_EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) - return log_openssl_errors("Failed to configure RSA-OAEP MD"); + return log_openssl_errors(LOG_DEBUG, "Failed to configure RSA-OAEP MD"); if (label) { _cleanup_free_ char *duplabel = strdup(label); @@ -1176,21 +1236,21 @@ int rsa_oaep_encrypt_bytes( return log_oom_debug(); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to configure RSA-OAEP label"); /* ctx owns this now, don't free */ TAKE_PTR(duplabel); } size_t 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to determine RSA-OAEP encrypted key size"); _cleanup_free_ void *buf = malloc(size); if (!buf) return log_oom_debug(); if (sym_EVP_PKEY_encrypt(ctx, buf, &size, decrypted_key, decrypted_key_size) <= 0) - return log_openssl_errors("Failed to RSA-OAEP encrypt"); + return log_openssl_errors(LOG_DEBUG, "Failed to RSA-OAEP encrypt"); *ret_encrypt_key = TAKE_PTR(buf); *ret_encrypt_key_size = size; @@ -1251,10 +1311,10 @@ int rsa_pkey_from_n_e(const void *n, size_t n_size, const void *e, size_t e_size _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_PKEY_CTX"); if (sym_EVP_PKEY_fromdata_init(ctx) <= 0) - return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize EVP_PKEY_CTX"); OSSL_PARAM params[3]; @@ -1276,7 +1336,7 @@ int rsa_pkey_from_n_e(const void *n, size_t n_size, const void *e, size_t e_size params[2] = sym_OSSL_PARAM_construct_end(); if (sym_EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) - return log_openssl_errors("Failed to create RSA EVP_PKEY"); + return log_openssl_errors(LOG_DEBUG, "Failed to create RSA EVP_PKEY"); *ret = TAKE_PTR(pkey); @@ -1305,11 +1365,11 @@ int rsa_pkey_to_n_e( _cleanup_(BN_freep) BIGNUM *bn_n = NULL; if (!sym_EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bn_n)) - return log_openssl_errors("Failed to get RSA n"); + return log_openssl_errors(LOG_DEBUG, "Failed to get RSA n"); _cleanup_(BN_freep) BIGNUM *bn_e = NULL; if (!sym_EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bn_e)) - return log_openssl_errors("Failed to get RSA e"); + return log_openssl_errors(LOG_DEBUG, "Failed to get RSA 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); @@ -1348,53 +1408,53 @@ int ecc_pkey_from_curve_x_y( _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_PKEY_CTX"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create BIGNUM x"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create BIGNUM y"); _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); + return log_openssl_errors(LOG_DEBUG, "ECC curve id %d not supported", curve_id); _cleanup_(EC_POINT_freep) EC_POINT *point = sym_EC_POINT_new(group); if (!point) - return log_openssl_errors("Failed to create new EC_POINT"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EC_POINT"); if (!sym_EC_POINT_set_affine_coordinates(group, point, bn_x, bn_y, NULL)) - return log_openssl_errors("Failed to set ECC coordinates"); + return log_openssl_errors(LOG_DEBUG, "Failed to set ECC coordinates"); if (sym_EVP_PKEY_fromdata_init(ctx) <= 0) - return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize EVP_PKEY_CTX"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new OSSL_PARAM_BLD"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add ECC OSSL_PKEY_PARAM_GROUP_NAME"); _cleanup_(OPENSSL_freep) void *pbuf = NULL; size_t pbuf_len = 0; 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to convert ECC point to buffer"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to add ECC OSSL_PKEY_PARAM_PUB_KEY"); _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to build ECC OSSL_PARAM"); _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; if (sym_EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) - return log_openssl_errors("Failed to create ECC EVP_PKEY"); + return log_openssl_errors(LOG_DEBUG, "Failed to create ECC EVP_PKEY"); *ret = TAKE_PTR(pkey); return 0; @@ -1419,24 +1479,24 @@ int ecc_pkey_to_curve_x_y( size_t 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to get ECC group name size"); _cleanup_free_ char *name = new(char, name_size + 1); if (!name) return log_oom_debug(); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to get ECC group name"); curve_id = sym_OBJ_sn2nid(name); if (curve_id == NID_undef) - return log_openssl_errors("Failed to get ECC curve id"); + return log_openssl_errors(LOG_DEBUG, "Failed to get ECC curve id"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to get ECC point x"); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to get ECC point 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); @@ -1472,17 +1532,17 @@ int ecc_pkey_new(int curve_id, EVP_PKEY **ret) { _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_PKEY_CTX"); if (sym_EVP_PKEY_keygen_init(ctx) <= 0) - return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize EVP_PKEY_CTX"); 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); + return log_openssl_errors(LOG_DEBUG, "Failed to set ECC curve %d", curve_id); _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; if (sym_EVP_PKEY_keygen(ctx, &pkey) <= 0) - return log_openssl_errors("Failed to generate ECC key"); + return log_openssl_errors(LOG_DEBUG, "Failed to generate ECC key"); *ret = TAKE_PTR(pkey); @@ -1512,24 +1572,24 @@ int ecc_ecdh(const EVP_PKEY *private_pkey, _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_PKEY_CTX"); if (sym_EVP_PKEY_derive_init(ctx) <= 0) - return log_openssl_errors("Failed to initialize EVP_PKEY_CTX"); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize EVP_PKEY_CTX"); if (sym_EVP_PKEY_derive_set_peer(ctx, (EVP_PKEY*) peer_pkey) <= 0) - return log_openssl_errors("Failed to set ECC derive peer"); + return log_openssl_errors(LOG_DEBUG, "Failed to set ECC derive peer"); size_t shared_secret_size; if (sym_EVP_PKEY_derive(ctx, NULL, &shared_secret_size) <= 0) - return log_openssl_errors("Failed to get ECC shared secret size"); + return log_openssl_errors(LOG_DEBUG, "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 (sym_EVP_PKEY_derive(ctx, (unsigned char*) shared_secret, &shared_secret_size) <= 0) - return log_openssl_errors("Failed to derive ECC shared secret"); + return log_openssl_errors(LOG_DEBUG, "Failed to derive ECC shared secret"); *ret_shared_secret = TAKE_PTR(shared_secret); *ret_shared_secret_size = shared_secret_size; @@ -1558,7 +1618,7 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s sz = sym_i2d_PublicKey(pk, NULL); if (sz < 0) - return log_openssl_errors("Unable to convert public key to DER format"); + return log_openssl_errors(LOG_DEBUG, "Unable to convert public key to DER format"); dd = d = malloc(sz); if (!d) @@ -1566,17 +1626,17 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s lsz = sym_i2d_PublicKey(pk, &dd); if (lsz < 0) - return log_openssl_errors("Unable to convert public key to DER format"); + return log_openssl_errors(LOG_DEBUG, "Unable to convert public key to DER format"); m = sym_EVP_MD_CTX_new(); if (!m) - return log_openssl_errors("Failed to create new EVP_MD_CTX"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_MD_CTX"); if (sym_EVP_DigestInit_ex(m, md, NULL) != 1) - return log_openssl_errors("Failed to initialize %s context", sym_EVP_MD_get0_name(md)); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize %s context", sym_EVP_MD_get0_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)); + return log_openssl_errors(LOG_DEBUG, "Failed to run %s context", sym_EVP_MD_get0_name(md)); msz = sym_EVP_MD_get_size(md); assert(msz > 0); @@ -1587,7 +1647,7 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s umsz = msz; if (sym_EVP_DigestFinal_ex(m, h, &umsz) != 1) - return log_openssl_errors("Failed to finalize hash context"); + return log_openssl_errors(LOG_DEBUG, "Failed to finalize hash context"); assert(umsz == (unsigned) msz); @@ -1624,7 +1684,7 @@ int digest_and_sign( _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to create new EVP_MD_CTX"); /* Note that a NULL 'md' (message digest algorithm) means to sign the provided data directly, without * hashing it first, as long as a suitable signing algorithm is used that supports this, such as @@ -1633,21 +1693,21 @@ int digest_and_sign( /* Distro security policies often disable support for SHA-1. Let's return a recognizable * error for that case. */ bool invalid_digest = ERR_GET_REASON(sym_ERR_peek_last_error()) == EVP_R_INVALID_DIGEST; - r = log_openssl_errors("Failed to initialize signature context"); + r = log_openssl_errors(LOG_DEBUG, "Failed to initialize signature context"); return invalid_digest ? -EADDRNOTAVAIL : r; } /* Determine signature size */ size_t ss; if (sym_EVP_DigestSign(mdctx, NULL, &ss, data, size) != 1) - return log_openssl_errors("Failed to determine size of signature"); + return log_openssl_errors(LOG_DEBUG, "Failed to determine size of signature"); _cleanup_free_ void *sig = malloc(ss); if (!sig) return log_oom_debug(); if (sym_EVP_DigestSign(mdctx, sig, &ss, data, size) != 1) - return log_openssl_errors("Failed to sign data"); + return log_openssl_errors(LOG_DEBUG, "Failed to sign data"); *ret = TAKE_PTR(sig); *ret_size = ss; @@ -1675,25 +1735,21 @@ int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorit return log_oom(); if (sym_PKCS7_set_type(p7, NID_pkcs7_signed) == 0) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 type: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to set PKCS7 type"); if (sym_PKCS7_content_new(p7, NID_pkcs7_data) == 0) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 content: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to set PKCS7 content"); if (sym_PKCS7_add_certificate(p7, certificate) == 0) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 certificate: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to set PKCS7 certificate"); int x509_pknid = 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to get X509 digest NID"); 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'", + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Unsupported digest algorithm '%s'", hash_algorithm ?: "SHA256"); _cleanup_(PKCS7_SIGNER_INFO_freep) PKCS7_SIGNER_INFO *si = sym_PKCS7_SIGNER_INFO_new(); @@ -1702,35 +1758,28 @@ int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorit if (private_key) { 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to configure signer info"); } else { if (sym_ASN1_INTEGER_set(si->version, 1) == 0) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set signer info version: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to set signer info version"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to set signer info issuer"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to set signer info serial"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to set signer info digest algorithm"); 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to set signer info signing algorithm"); } if (sym_PKCS7_add_signer(p7, si) == 0) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 signer info: %s", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to set PKCS7 signer info"); *ret_p7 = TAKE_PTR(p7); if (ret_si) @@ -1795,7 +1844,7 @@ static int ecc_pkey_generate_volume_keys( 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to determine PKEY group name length"); len++; curve_name = new(char, len); @@ -1803,7 +1852,7 @@ static int ecc_pkey_generate_volume_keys( return log_oom_debug(); if (sym_EVP_PKEY_get_group_name(pkey, curve_name, len, &len) != 1) - return log_openssl_errors("Failed to get PKEY group name"); + return log_openssl_errors(LOG_DEBUG, "Failed to get PKEY group name"); r = ecc_pkey_new(sym_OBJ_sn2nid(curve_name), &pkey_new); if (r < 0) @@ -1817,7 +1866,7 @@ static int ecc_pkey_generate_volume_keys( See https://github.com/openssl/openssl/discussions/22835 */ 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to convert the generated public key to SEC1 format"); *ret_decrypted_key = TAKE_PTR(decrypted_key); *ret_decrypted_key_size = decrypted_key_size; @@ -1931,9 +1980,9 @@ static int load_key_from_provider( /* 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 (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true)) - return log_openssl_errors("Failed to load OpenSSL provider '%s'", provider); + return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL provider '%s'", provider); if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, "default", /* retain_fallbacks= */ true)) - return log_openssl_errors("Failed to load OpenSSL provider 'default'"); + return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL provider 'default'"); _cleanup_(OSSL_STORE_closep) OSSL_STORE_CTX *store = sym_OSSL_STORE_open( private_key_uri, @@ -1942,18 +1991,18 @@ static int load_key_from_provider( /* post_process= */ NULL, /* post_process_data= */ NULL); if (!store) - return log_openssl_errors("Failed to open OpenSSL store via '%s'", private_key_uri); + return log_openssl_errors(LOG_DEBUG, "Failed to open OpenSSL store via '%s'", private_key_uri); if (sym_OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY) == 0) - return log_openssl_errors("Failed to filter store by private keys"); + return log_openssl_errors(LOG_DEBUG, "Failed to filter store by private keys"); _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); + return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL store via '%s'", private_key_uri); _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); + return log_openssl_errors(LOG_DEBUG, "Failed to load private key via '%s'", private_key_uri); *ret = TAKE_PTR(private_key); @@ -1977,14 +2026,14 @@ static int load_key_from_engine(const char *engine, const char *private_key_uri, DISABLE_WARNING_DEPRECATED_DECLARATIONS; _cleanup_(ENGINE_freep) ENGINE *e = sym_ENGINE_by_id(engine); if (!e) - return log_openssl_errors("Failed to load signing engine '%s'", engine); + return log_openssl_errors(LOG_DEBUG, "Failed to load signing engine '%s'", engine); if (sym_ENGINE_init(e) == 0) - return log_openssl_errors("Failed to initialize signing engine '%s'", engine); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize signing engine '%s'", engine); _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); + return log_openssl_errors(LOG_DEBUG, "Failed to load private key from '%s'", private_key_uri); REENABLE_WARNING; *ret = TAKE_PTR(private_key); @@ -2021,7 +2070,7 @@ static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) { } if (sym_UI_set_result(ui, uis, *l) != 0) { - log_openssl_errors("Failed to set user interface result"); + log_openssl_errors(LOG_DEBUG, "Failed to set user interface result"); return 0; } @@ -2061,8 +2110,7 @@ static int openssl_load_private_key_from_file(const char *path, EVP_PKEY **ret) 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", - sym_ERR_error_string(sym_ERR_get_error(), NULL)); + return log_openssl_errors(LOG_DEBUG, "Failed to parse PEM private key"); *ret = TAKE_PTR(pk); @@ -2084,10 +2132,10 @@ static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSS _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"); + return log_openssl_errors(LOG_DEBUG, "Failed to initialize openssl user interface"); if (sym_UI_method_set_reader(method, openssl_ask_password_ui_read) != 0) - return log_openssl_errors("Failed to set openssl user interface reader"); + return log_openssl_errors(LOG_DEBUG, "Failed to set openssl user interface reader"); OpenSSLAskPasswordUI *ui = new(OpenSSLAskPasswordUI, 1); if (!ui) @@ -2101,7 +2149,7 @@ static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSS sym_UI_set_default_method(ui->method); 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"); + return log_openssl_errors(LOG_DEBUG, "Failed to set extra data for UI method"); *ret = TAKE_PTR(ui); return 0; @@ -2160,9 +2208,9 @@ static int load_x509_certificate_from_provider(const char *provider, const char /* 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 (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, provider, /* retain_fallbacks= */ true)) - return log_openssl_errors("Failed to load OpenSSL provider '%s'", provider); + return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL provider '%s'", provider); if (!sym_OSSL_PROVIDER_try_load(/* ctx= */ NULL, "default", /* retain_fallbacks= */ true)) - return log_openssl_errors("Failed to load OpenSSL provider 'default'"); + return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL provider 'default'"); _cleanup_(OSSL_STORE_closep) OSSL_STORE_CTX *store = sym_OSSL_STORE_open( certificate_uri, @@ -2171,18 +2219,18 @@ static int load_x509_certificate_from_provider(const char *provider, const char /* post_process= */ NULL, /* post_process_data= */ NULL); if (!store) - return log_openssl_errors("Failed to open OpenSSL store via '%s'", certificate_uri); + return log_openssl_errors(LOG_DEBUG, "Failed to open OpenSSL store via '%s'", certificate_uri); if (sym_OSSL_STORE_expect(store, OSSL_STORE_INFO_CERT) == 0) - return log_openssl_errors("Failed to filter store by X.509 certificates"); + return log_openssl_errors(LOG_DEBUG, "Failed to filter store by X.509 certificates"); _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); + return log_openssl_errors(LOG_DEBUG, "Failed to load OpenSSL store via '%s'", certificate_uri); _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); + return log_openssl_errors(LOG_DEBUG, "Failed to load certificate via '%s'", certificate_uri); *ret = TAKE_PTR(cert); @@ -2213,7 +2261,7 @@ int x509_fingerprint(X509 *cert, uint8_t buffer[static SHA256_DIGEST_SIZE]) { dersz = sym_i2d_X509(cert, &der); if (dersz < 0) - return log_openssl_errors("Unable to convert PEM certificate to DER format"); + return log_openssl_errors(LOG_DEBUG, "Unable to convert PEM certificate to DER format"); sha256_direct(der, dersz, buffer); return 0; @@ -2325,7 +2373,7 @@ int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret) { return -ENOMEM; if (sym_i2d_PUBKEY_fp(tf, private_key) != 1) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to extract public key in DER format"); _cleanup_(erase_and_freep) char *buf = NULL; size_t len; @@ -2335,7 +2383,7 @@ int openssl_extract_public_key(EVP_PKEY *private_key, EVP_PKEY **ret) { const unsigned char *t = (const unsigned char*) buf; if (!sym_d2i_PUBKEY(ret, &t, len)) - return -EIO; + return log_openssl_errors(LOG_DEBUG, "Failed to parse public key in DER format"); return 0; } diff --git a/src/shared/crypto-util.h b/src/shared/crypto-util.h index bd0cb7b67b8..00e0b4f4522 100644 --- a/src/shared/crypto-util.h +++ b/src/shared/crypto-util.h @@ -336,6 +336,18 @@ static inline void sk_X509_free_allp(STACK_OF(X509) **sk) { sym_sk_X509_pop_free(*sk, sym_X509_free); } +/* Translates an OpenSSL error code (as returned by ERR_get_error()) into a negative errno. Returns + * -ENOTRECOVERABLE when passed 0 or when the error's reason has no more specific errno. */ +int openssl_to_errno(unsigned long e); + +int log_openssl_errors_internal(int level, const char *file, int line, const char *func, const char *format, ...) _printf_(5, 6); + +/* Logs `format` at `level`, suffixed with each error from the OpenSSL thread-local error queue (or + * "No OpenSSL errors." when it is empty), and returns a negative errno derived from the last error + * (-ENOTRECOVERABLE when the queue is empty or the reason isn't recognized). */ +#define log_openssl_errors(level, format, ...) \ + log_openssl_errors_internal(level, PROJECT_FILE, __LINE__, __func__, format, ##__VA_ARGS__) + 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); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 14744a4c8d1..f9556ea6b49 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -3203,7 +3203,7 @@ static int validate_signature_userspace(const VeritySettings *verity, const char if (r) log_debug("Userspace PKCS#7 validation succeeded."); else - log_debug("Userspace PKCS#7 validation failed: %s", sym_ERR_error_string(sym_ERR_get_error(), NULL)); + log_openssl_errors(LOG_DEBUG, "Userspace PKCS#7 validation failed"); return r; #else diff --git a/src/shared/pkcs11-util.c b/src/shared/pkcs11-util.c index 60d383998b8..60235fa3e08 100644 --- a/src/shared/pkcs11-util.c +++ b/src/shared/pkcs11-util.c @@ -569,10 +569,10 @@ int pkcs11_token_read_public_key( _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."); + return log_openssl_errors(LOG_DEBUG, "Failed to create an EVP_PKEY_CTX for EC."); if (sym_EVP_PKEY_fromdata_init(ctx) != 1) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to init an EVP_PKEY_CTX for EC."); + return log_openssl_errors(LOG_DEBUG, "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 @@ -613,7 +613,7 @@ int pkcs11_token_read_public_key( return log_oom_debug(); 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."); + return log_openssl_errors(LOG_DEBUG, "Failed to extract EC parameters from EC_GROUP."); order_size = sym_BN_num_bytes(bn_order); p_size = sym_BN_num_bytes(bn_p); @@ -640,12 +640,12 @@ int pkcs11_token_read_public_key( 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."); + return log_openssl_errors(LOG_DEBUG, "Failed to store EC parameters in native byte order."); 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."); + return log_openssl_errors(LOG_DEBUG, "Failed to determine size of a EC generator."); generator = malloc(generator_size); if (!generator) @@ -653,7 +653,7 @@ int pkcs11_token_read_public_key( 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."); + return log_openssl_errors(LOG_DEBUG, "Failed to convert a EC generator to octet string."); 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); @@ -665,7 +665,7 @@ int pkcs11_token_read_public_key( } 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."); + return log_openssl_errors(LOG_DEBUG, "Failed to create EVP_PKEY from EC parameters."); break; } default: @@ -725,7 +725,7 @@ int pkcs11_token_read_x509_certificate( _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."); + return log_openssl_errors(LOG_DEBUG, "Failed to format X.509 subject name as string."); log_debug("Using X.509 certificate issued for '%s'.", t); @@ -1050,7 +1050,7 @@ static int ecc_convert_to_compressed( 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"); + return log_openssl_errors(LOG_ERR, "Failed to determine size of a compressed EC point"); compressed_point = malloc(compressed_point_size); if (!compressed_point) @@ -1058,7 +1058,7 @@ static int ecc_convert_to_compressed( 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"); + return log_openssl_errors(LOG_ERR, "Failed to convert a EC point to compressed format"); *ret_compressed_point = TAKE_PTR(compressed_point); *ret_compressed_point_size = compressed_point_size; @@ -1826,7 +1826,7 @@ static int pkcs11_acquire_public_key_callback( pkey = sym_X509_get_pubkey(cert); if (!pkey) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to extract public key from X.509 certificate."); + return log_openssl_errors(LOG_ERR, "Failed to extract public key from X.509 certificate."); } success: /* Let's read some random data off the token and write it to the kernel pool before we generate our diff --git a/src/test/test-crypto-util.c b/src/test/test-crypto-util.c index c4ba6436713..528482eb9d6 100644 --- a/src/test/test-crypto-util.c +++ b/src/test/test-crypto-util.c @@ -93,7 +93,9 @@ TEST(invalid) { _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; DEFINE_HEX_PTR(key, "2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b7b"); - assert_se(openssl_pubkey_from_pem(key, key_len, &pkey) == -EIO); + /* OpenSSL's decoder reports ERR_R_UNSUPPORTED for this garbage, which openssl_to_errno() maps + * to -EOPNOTSUPP. */ + ASSERT_ERROR(openssl_pubkey_from_pem(key, key_len, &pkey), EOPNOTSUPP); ASSERT_NULL(pkey); } diff --git a/src/tpm2-setup/tpm2-setup.c b/src/tpm2-setup/tpm2-setup.c index ab0966f8d92..db508676966 100644 --- a/src/tpm2-setup/tpm2-setup.c +++ b/src/tpm2-setup/tpm2-setup.c @@ -322,7 +322,7 @@ static int setup_srk(void) { return log_error_errno(r, "Failed to open SRK public key file '%s' for writing: %m", pem_path); 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); + return log_openssl_errors(LOG_ERR, "Failed to write SRK public key file '%s'.", pem_path); if (fchmod(fileno(f), 0444) < 0) return log_error_errno(errno, "Failed to adjust access mode of SRK public key file '%s' to 0444: %m", pem_path);