]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
keyutil: support adding content into PKCS#7 signature 36663/head
authorDan Streetman <ddstreet@ieee.org>
Mon, 3 Mar 2025 19:49:23 +0000 (14:49 -0500)
committerDan Streetman <ddstreet@ieee.org>
Fri, 7 Mar 2025 23:36:23 +0000 (18:36 -0500)
man/systemd-keyutil.xml
src/keyutil/keyutil.c
test/units/TEST-74-AUX-UTILS.keyutil.sh

index 6b75c7bba849dc4171d07369cbc5c07df733c8c2..a1e0bca43d8d02d45fbdf3c22b7f403a4977d4d7 100644 (file)
@@ -71,7 +71,8 @@
         <listitem><para>This command embeds the PKCS#1 signature (RSA) provided with
         <option>--signature=</option> in a PKCS#7 signature using the certificate given with
         <option>--certificate=</option> and writes it to the file specified with <option>--output=</option>
-        in PKCS#7 format (p7s).</para>
+        in PKCS#7 format (p7s). If <option>--content=</option> is provided it is included in the p7s,
+        otherwise a "detached" signature is created.</para>
 
         <xi:include href="version-info.xml" xpointer="v258"/></listitem>
       </varlistentry>
         <xi:include href="version-info.xml" xpointer="v258"/></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--content=<replaceable>PATH</replaceable></option></term>
+
+        <listitem><para>Input data that corresponds to the PKCS#1 signature for the <command>pkcs7</command>
+        command, used for generating inline (i.e. non-"detached") PKCS#7 signatures.</para>
+
+        <xi:include href="version-info.xml" xpointer="v258"/></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--output=<replaceable>PATH</replaceable></option></term>
 
index c58ac84e5b57a2c4f59c7e2a5f488c2104201572..3e51332aaaf3d66df6fde0842bee084d517d9259 100644 (file)
@@ -23,6 +23,7 @@ static char *arg_certificate = NULL;
 static char *arg_certificate_source = NULL;
 static CertificateSourceType arg_certificate_source_type = OPENSSL_CERTIFICATE_SOURCE_FILE;
 static char *arg_signature = NULL;
+static char *arg_content = NULL;
 static char *arg_output = NULL;
 
 STATIC_DESTRUCTOR_REGISTER(arg_private_key, freep);
@@ -30,6 +31,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_private_key_source, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_certificate, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_certificate_source, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_signature, freep);
+STATIC_DESTRUCTOR_REGISTER(arg_content, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_output, freep);
 
 static int help(int argc, char *argv[], void *userdata) {
@@ -60,6 +62,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "                         Specify how to interpret the certificate from\n"
                "                         --certificate=. Allows the certificate to be loaded\n"
                "                         from an OpenSSL provider\n"
+               "     --content=PATH      Raw data content to embed in PKCS#7 signature\n"
                "     --signature=PATH    PKCS#1 signature to embed in PKCS#7 signature\n"
                "     --output=PATH       Where to write the PKCS#7 signature\n"
                "\nSee the %2$s for details.\n",
@@ -81,6 +84,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_CERTIFICATE,
                 ARG_CERTIFICATE_SOURCE,
                 ARG_SIGNATURE,
+                ARG_CONTENT,
                 ARG_OUTPUT,
         };
 
@@ -92,6 +96,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "certificate",        required_argument, NULL, ARG_CERTIFICATE        },
                 { "certificate-source", required_argument, NULL, ARG_CERTIFICATE_SOURCE },
                 { "signature",          required_argument, NULL, ARG_SIGNATURE          },
+                { "content",            required_argument, NULL, ARG_CONTENT            },
                 { "output",             required_argument, NULL, ARG_OUTPUT             },
                 {}
         };
@@ -150,6 +155,13 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_CONTENT:
+                        r = parse_path_argument(optarg, /*suppress_root=*/ false, &arg_content);
+                        if (r < 0)
+                                return r;
+
+                        break;
+
                 case ARG_OUTPUT:
                         r = parse_path_argument(optarg, /*suppress_root=*/ false, &arg_output);
                         if (r < 0)
@@ -345,12 +357,27 @@ static int verb_pkcs7(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return log_error_errno(r, "Failed to allocate PKCS#7 context: %m");
 
-        if (PKCS7_set_detached(pkcs7, true) == 0)
-                return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to set PKCS#7 detached attribute: %s",
-                                       ERR_error_string(ERR_get_error(), NULL));
+        if (arg_content) {
+                _cleanup_free_ char *content = NULL;
+                size_t content_len = 0;
 
-        /* Add PKCS1 signature to PKCS7_SIGNER_INFO */
+                r = read_full_file(arg_content, &content, &content_len);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to read content file %s: %m", arg_content);
+                if (content_len == 0)
+                        return log_error_errno(SYNTHETIC_ERRNO(EIO), "Content file %s is empty", arg_content);
+
+                if (!PKCS7_content_new(pkcs7, NID_pkcs7_data))
+                        return log_error_errno(SYNTHETIC_ERRNO(EIO), "Error creating new PKCS7 content field");
+
+                ASN1_STRING_set0(pkcs7->d.sign->contents->d.data, TAKE_PTR(content), content_len);
+        } else
+                if (PKCS7_set_detached(pkcs7, true) == 0)
+                        return log_error_errno(SYNTHETIC_ERRNO(EIO),
+                                               "Failed to set PKCS#7 detached attribute: %s",
+                                               ERR_error_string(ERR_get_error(), NULL));
 
+        /* Add PKCS1 signature to PKCS7_SIGNER_INFO */
         ASN1_STRING_set0(signer_info->enc_digest, TAKE_PTR(pkcs1), pkcs1_len);
 
         _cleanup_fclose_ FILE *output = NULL;
index 96700a58cd42ca1e1d49cb2d4c1d004cae0a6b48..efe19a0c0c44d33c47103d86efb9b7af1523f0d2 100755 (executable)
@@ -53,7 +53,7 @@ testcase_pkcs7() {
     # Generate PKCS#1 signature
     openssl dgst -sha256 -sign /tmp/test.key -out /tmp/payload.sig /tmp/payload
 
-    # Generate PKCS#7 signature
+    # Generate PKCS#7 "detached" signature
     /usr/lib/systemd/systemd-keyutil --certificate /tmp/test.crt --output /tmp/payload.p7s --signature /tmp/payload.sig pkcs7
 
     # Verify using internal x509 certificate
@@ -61,6 +61,17 @@ testcase_pkcs7() {
 
     # Verify using external (original) x509 certificate
     openssl smime -verify -binary -inform der -in /tmp/payload.p7s -content /tmp/payload -certificate /tmp/test.crt -nointern -noverify > /dev/null
+
+    rm -f /tmp/payload.p7s
+
+    # Generate PKCS#7 non-"detached" signature
+    /usr/lib/systemd/systemd-keyutil --certificate /tmp/test.crt --output /tmp/payload.p7s --signature /tmp/payload.sig --content /tmp/payload pkcs7
+
+    # Verify using internal x509 certificate
+    openssl smime -verify -binary -inform der -in /tmp/payload.p7s -noverify > /dev/null
+
+    # Verify using external (original) x509 certificate
+    openssl smime -verify -binary -inform der -in /tmp/payload.p7s -certificate /tmp/test.crt -nointern -noverify > /dev/null
 }
 
 run_testcases