]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
openssl: add hash_algorithm parameter to pkcs7_new()
authorDan Streetman <ddstreet@ieee.org>
Fri, 6 Jun 2025 16:31:40 +0000 (12:31 -0400)
committerDan Streetman <ddstreet@ieee.org>
Tue, 10 Jun 2025 12:44:51 +0000 (08:44 -0400)
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.

src/keyutil/keyutil.c
src/sbsign/sbsign.c
src/shared/openssl-util.c
src/shared/openssl-util.h

index aed34b39d07ead8f576768fbfb5777ac0d9d066a..396bd1db1eb82a65305c1a16c7d479000e180f9e 100644 (file)
@@ -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");
 
index be11833d7d2dcf20cb51257a787c2be22f253cb3..68e1f24ac27fafdd2dde90759b7466cc1ca45cf6 100644 (file)
@@ -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;
 
index 180d6f202f3fb9d9a6baa81e8844ceaaa8e529c5..57b638596aa53ce2c22fb2f298e10b98703a6088 100644 (file)
@@ -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));
 
index 8b051435e654f5905d7a54ebff58372713d35ea4..6bcb16af31296d97cb14a03318df6fcaa8aa3855 100644 (file)
@@ -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);