From: Dan Streetman Date: Mon, 3 Mar 2025 19:49:23 +0000 (-0500) Subject: keyutil: support adding content into PKCS#7 signature X-Git-Tag: v258-rc1~1142^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F36663%2Fhead;p=thirdparty%2Fsystemd.git keyutil: support adding content into PKCS#7 signature --- diff --git a/man/systemd-keyutil.xml b/man/systemd-keyutil.xml index 6b75c7bba84..a1e0bca43d8 100644 --- a/man/systemd-keyutil.xml +++ b/man/systemd-keyutil.xml @@ -71,7 +71,8 @@ This command embeds the PKCS#1 signature (RSA) provided with in a PKCS#7 signature using the certificate given with and writes it to the file specified with - in PKCS#7 format (p7s). + in PKCS#7 format (p7s). If is provided it is included in the p7s, + otherwise a "detached" signature is created. @@ -109,6 +110,15 @@ + + + + Input data that corresponds to the PKCS#1 signature for the pkcs7 + command, used for generating inline (i.e. non-"detached") PKCS#7 signatures. + + + + diff --git a/src/keyutil/keyutil.c b/src/keyutil/keyutil.c index c58ac84e5b5..3e51332aaaf 100644 --- a/src/keyutil/keyutil.c +++ b/src/keyutil/keyutil.c @@ -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; diff --git a/test/units/TEST-74-AUX-UTILS.keyutil.sh b/test/units/TEST-74-AUX-UTILS.keyutil.sh index 96700a58cd4..efe19a0c0c4 100755 --- a/test/units/TEST-74-AUX-UTILS.keyutil.sh +++ b/test/units/TEST-74-AUX-UTILS.keyutil.sh @@ -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