From: Dan Streetman Date: Fri, 6 Jun 2025 16:31:40 +0000 (-0400) Subject: openssl: add hash_algorithm parameter to pkcs7_new() X-Git-Tag: v258-rc1~341^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=768a297c4216656a20c9483bbd003cd91e75ecc3;p=thirdparty%2Fsystemd.git openssl: add hash_algorithm parameter to pkcs7_new() The pkcs7_new() function currently uses the hash algorithm from the X509 certificate's signature, but the content signature may use a different hash algorithm. This adds a parameter to allow specifying what hash algorithm the content signature generation used. --- diff --git a/src/keyutil/keyutil.c b/src/keyutil/keyutil.c index aed34b39d07..396bd1db1eb 100644 --- a/src/keyutil/keyutil.c +++ b/src/keyutil/keyutil.c @@ -355,7 +355,7 @@ static int verb_pkcs7(int argc, char *argv[], void *userdata) { _cleanup_(PKCS7_freep) PKCS7 *pkcs7 = NULL; PKCS7_SIGNER_INFO *signer_info; - r = pkcs7_new(certificate, /* private_key= */ NULL, &pkcs7, &signer_info); + r = pkcs7_new(certificate, /* private_key= */ NULL, /* hash_algorithm= */ NULL, &pkcs7, &signer_info); if (r < 0) return log_error_errno(r, "Failed to allocate PKCS#7 context: %m"); diff --git a/src/sbsign/sbsign.c b/src/sbsign/sbsign.c index be11833d7d2..68e1f24ac27 100644 --- a/src/sbsign/sbsign.c +++ b/src/sbsign/sbsign.c @@ -321,6 +321,7 @@ static int asn1_timestamp(ASN1_TIME **ret) { static int pkcs7_new_with_attributes( X509 *certificate, EVP_PKEY *private_key, + const char *hash_algorithm, STACK_OF(X509_ATTRIBUTE) *signed_attributes, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si) { @@ -336,7 +337,7 @@ static int pkcs7_new_with_attributes( _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL; PKCS7_SIGNER_INFO *si = NULL; /* avoid false maybe-uninitialized warning */ - r = pkcs7_new(certificate, private_key, &p7, &si); + r = pkcs7_new(certificate, private_key, hash_algorithm, &p7, &si); if (r < 0) return log_error_errno(r, "Failed to allocate PKCS# context: %m"); @@ -562,7 +563,7 @@ static int verb_sign(int argc, char *argv[], void *userdata) { _cleanup_(PKCS7_freep) PKCS7 *p7 = NULL; PKCS7_SIGNER_INFO *si = NULL; /* avoid false maybe-uninitialized warning */ - r = pkcs7_new_with_attributes(certificate, private_key, signed_attributes, &p7, &si); + r = pkcs7_new_with_attributes(certificate, private_key, /* hash_algorithm= */ NULL, signed_attributes, &p7, &si); if (r < 0) return r; diff --git a/src/shared/openssl-util.c b/src/shared/openssl-util.c index 180d6f202f3..57b638596aa 100644 --- a/src/shared/openssl-util.c +++ b/src/shared/openssl-util.c @@ -1126,14 +1126,15 @@ int digest_and_sign( return 0; } -int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si) { +int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, const char *hash_algorithm, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si) { assert(certificate); assert(ret_p7); /* This function sets up a new PKCS7 signing context. If a private key is provided, the context is * set up for "in-band" signing with PKCS7_dataFinal(). If a private key is not provided, the context * is set up for "out-of-band" signing, meaning the signature has to be provided by the user and - * copied into the signer info's "enc_digest" field. */ + * 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(); if (!p7) @@ -1151,21 +1152,22 @@ int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, PKCS7 **ret_p7, PKCS7_SI return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS7 certificate: %s", ERR_error_string(ERR_get_error(), NULL)); - int x509_mdnid = 0, x509_pknid = 0; - if (X509_get_signature_info(certificate, &x509_mdnid, &x509_pknid, NULL, NULL) == 0) + int x509_pknid = 0; + if (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)); - const EVP_MD *md = EVP_get_digestbynid(x509_mdnid); + const EVP_MD *md = EVP_get_digestbyname(hash_algorithm ?: "SHA256"); if (!md) - return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to get digest algorithm via digest NID"); + 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(); if (!si) return log_oom(); if (private_key) { - if (PKCS7_SIGNER_INFO_set(si, certificate, private_key, EVP_get_digestbynid(x509_mdnid)) <= 0) + if (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)); } else { @@ -1183,7 +1185,7 @@ int pkcs7_new(X509 *certificate, EVP_PKEY *private_key, PKCS7 **ret_p7, PKCS7_SI return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Failed to set signer info serial: %s", ERR_error_string(ERR_get_error(), NULL)); - if (X509_ALGOR_set0(si->digest_alg, OBJ_nid2obj(x509_mdnid), V_ASN1_NULL, NULL) == 0) + if (X509_ALGOR_set0(si->digest_alg, OBJ_nid2obj(EVP_MD_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)); diff --git a/src/shared/openssl-util.h b/src/shared/openssl-util.h index 8b051435e65..6bcb16af312 100644 --- a/src/shared/openssl-util.h +++ b/src/shared/openssl-util.h @@ -165,7 +165,7 @@ int pubkey_fingerprint(EVP_PKEY *pk, const EVP_MD *md, void **ret, size_t *ret_s 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, PKCS7 **ret_p7, PKCS7_SIGNER_INFO **ret_si); +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);