mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
keyutil: support adding content into PKCS#7 signature (#36663)
Support including the data that was signed inside the PKCS#7 signature. This creates a self-contained file where the signature of the data can be verified without any other information, since the file contains the data, signature, and certificate (which contains the public key used for the signing). One use case of this is IPE which requires a PKCS#7 signature that is not "detached", i.e. includes the IPE configuration that has been signed. This also slightly adjusts the test case to use the x509 certificate inside the PKCS#7 signature instead of supplying it externally during verification.
This commit is contained in:
@@ -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>
|
||||
@@ -109,6 +110,15 @@
|
||||
<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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
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;
|
||||
|
||||
@@ -49,9 +49,29 @@ testcase_public() {
|
||||
|
||||
testcase_pkcs7() {
|
||||
echo -n "test" > /tmp/payload
|
||||
|
||||
# Generate PKCS#1 signature
|
||||
openssl dgst -sha256 -sign /tmp/test.key -out /tmp/payload.sig /tmp/payload
|
||||
|
||||
# Generate PKCS#7 "detached" signature
|
||||
/usr/lib/systemd/systemd-keyutil --certificate /tmp/test.crt --output /tmp/payload.p7s --signature /tmp/payload.sig pkcs7
|
||||
openssl smime -verify -binary -inform der -in /tmp/payload.p7s -content /tmp/payload -certfile /tmp/test.crt -nointern -noverify > /dev/null
|
||||
|
||||
# Verify using internal x509 certificate
|
||||
openssl smime -verify -binary -inform der -in /tmp/payload.p7s -content /tmp/payload -noverify > /dev/null
|
||||
|
||||
# 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
|
||||
|
||||
Reference in New Issue
Block a user