Add CMS_NO_SIGNING_TIME flag to CMS_sign(), CMS_add1_signer()
Previously there was no way to create a CMS SignedData signature without a signing time attribute, because CMS_SignerInfo_sign added it unconditionally. However, there is a use case (PAdES signatures) where this attribute is not allowed, so this commit introduces a new flag to the CMS API that causes this attribute to be omitted at signing time. Also add -no_signing_time option to cms command. Fixes #15777 Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15783)
This commit is contained in:
parent
b85e6f5349
commit
34ea176abf
12
CHANGES.md
12
CHANGES.md
@ -95,6 +95,18 @@ OpenSSL 3.5
|
||||
|
||||
*Ramkumar*
|
||||
|
||||
* Add CMS_NO_SIGNING_TIME flag to CMS_sign(), CMS_add1_signer()
|
||||
|
||||
Previously there was no way to create a CMS SignedData signature without a
|
||||
signing time attribute, because CMS_SignerInfo_sign added it unconditionally.
|
||||
However, there is a use case (PAdES signatures [ETSI EN 319 142-1](https://www.etsi.org/deliver/etsi_en/319100_319199/31914201/01.01.01_60/en_31914201v010101p.pdf) )
|
||||
where this attribute is not allowed, so a new flag was added to the CMS API
|
||||
that causes this attribute to be omitted at signing time.
|
||||
|
||||
The new `-no_signing_time` option of the `cms` command enables this flag.
|
||||
|
||||
*Juhász Péter*
|
||||
|
||||
OpenSSL 3.4
|
||||
-----------
|
||||
|
||||
|
@ -69,7 +69,8 @@ typedef enum OPTION_choice {
|
||||
OPT_DIGEST, OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
|
||||
OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT,
|
||||
OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS,
|
||||
OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID,
|
||||
OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_NO_SIGNING_TIME,
|
||||
OPT_BINARY, OPT_KEYID,
|
||||
OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF,
|
||||
OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT,
|
||||
OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE,
|
||||
@ -186,6 +187,8 @@ const OPTIONS cms_options[] = {
|
||||
"Don't include signer's certificate when signing"},
|
||||
{"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
|
||||
{"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
|
||||
{"no_signing_time", OPT_NO_SIGNING_TIME, '-',
|
||||
"Omit the signing time attribute"},
|
||||
{"receipt_request_all", OPT_RR_ALL, '-',
|
||||
"When signing, create a receipt request for all recipients"},
|
||||
{"receipt_request_first", OPT_RR_FIRST, '-',
|
||||
@ -429,6 +432,9 @@ int cms_main(int argc, char **argv)
|
||||
case OPT_NOSMIMECAP:
|
||||
flags |= CMS_NOSMIMECAP;
|
||||
break;
|
||||
case OPT_NO_SIGNING_TIME:
|
||||
flags |= CMS_NO_SIGNING_TIME;
|
||||
break;
|
||||
case OPT_BINARY:
|
||||
flags |= CMS_BINARY;
|
||||
break;
|
||||
|
@ -100,6 +100,8 @@ struct CMS_SignerInfo_st {
|
||||
EVP_MD_CTX *mctx;
|
||||
EVP_PKEY_CTX *pctx;
|
||||
const CMS_CTX *cms_ctx;
|
||||
/* Set to 1 if signing time attribute is to be omitted */
|
||||
int omit_signing_time;
|
||||
};
|
||||
|
||||
struct CMS_SignerIdentifier_st {
|
||||
|
@ -364,6 +364,7 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
|
||||
si->signer = signer;
|
||||
si->mctx = EVP_MD_CTX_new();
|
||||
si->pctx = NULL;
|
||||
si->omit_signing_time = 0;
|
||||
|
||||
if (si->mctx == NULL) {
|
||||
ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB);
|
||||
@ -456,6 +457,14 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if ((flags & CMS_NO_SIGNING_TIME) != 0) {
|
||||
/*
|
||||
* The signing-time signed attribute (NID_pkcs9_signingTime)
|
||||
* would normally be added later, in CMS_SignerInfo_sign(),
|
||||
* unless we set this flag here
|
||||
*/
|
||||
si->omit_signing_time = 1;
|
||||
}
|
||||
if (flags & CMS_CADES) {
|
||||
ESS_SIGNING_CERT *sc = NULL;
|
||||
ESS_SIGNING_CERT_V2 *sc2 = NULL;
|
||||
@ -839,7 +848,8 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
|
||||
si->digestAlgorithm->algorithm, 0) <= 0)
|
||||
return 0;
|
||||
|
||||
if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
|
||||
if (!si->omit_signing_time
|
||||
&& CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
|
||||
if (!cms_add1_signingTime(si, NULL))
|
||||
goto err;
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ Signing options:
|
||||
[B<-nocerts>]
|
||||
[B<-noattr>]
|
||||
[B<-nosmimecap>]
|
||||
[B<-no_signing_time>]
|
||||
[B<-receipt_request_all>]
|
||||
[B<-receipt_request_first>]
|
||||
[B<-receipt_request_from> I<emailaddress>]
|
||||
@ -492,7 +493,12 @@ option they are not included.
|
||||
=item B<-nosmimecap>
|
||||
|
||||
Exclude the list of supported algorithms from signed attributes, other options
|
||||
such as signing time and content type are still included.
|
||||
such as content type and (optionally) signing time are still included.
|
||||
|
||||
=item B<-no_signing_time>
|
||||
|
||||
Exclude the signing time from signed attributes, other options
|
||||
such as content type are still included.
|
||||
|
||||
=item B<-receipt_request_all>, B<-receipt_request_first>
|
||||
|
||||
|
@ -67,7 +67,8 @@ previously signed message.
|
||||
The SignedData structure includes several CMS signedAttributes including the
|
||||
signing time, the CMS content type and the supported list of ciphers in an
|
||||
SMIMECapabilities attribute. If B<CMS_NOATTR> is set then no signedAttributes
|
||||
will be used. If B<CMS_NOSMIMECAP> is set then just the SMIMECapabilities are
|
||||
will be used at all. If B<CMS_NOSMIMECAP> is set then the SMIMECapabilities
|
||||
will be omitted. If B<CMS_NO_SIGNING_TIME> is set then the signing time will be
|
||||
omitted.
|
||||
|
||||
OpenSSL will by default identify signing certificates using issuer name
|
||||
|
@ -60,7 +60,8 @@ otherwise the translation will corrupt it.
|
||||
The SignedData structure includes several CMS signedAttributes including the
|
||||
signing time, the CMS content type and the supported list of ciphers in an
|
||||
SMIMECapabilities attribute. If B<CMS_NOATTR> is set then no signedAttributes
|
||||
will be used. If B<CMS_NOSMIMECAP> is set then just the SMIMECapabilities are
|
||||
will be used at all. If B<CMS_NOSMIMECAP> is set then the SMIMECapabilities
|
||||
will be omitted. If B<CMS_NO_SIGNING_TIME> is set then the signing time will be
|
||||
omitted.
|
||||
|
||||
If present the SMIMECapabilities attribute indicates support for the following
|
||||
|
@ -96,6 +96,7 @@ CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
|
||||
# define CMS_ASCIICRLF 0x80000
|
||||
# define CMS_CADES 0x100000
|
||||
# define CMS_USE_ORIGINATOR_KEYID 0x200000
|
||||
# define CMS_NO_SIGNING_TIME 0x400000
|
||||
|
||||
const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms);
|
||||
|
||||
|
@ -52,7 +52,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
|
||||
|
||||
$no_rc2 = 1 if disabled("legacy");
|
||||
|
||||
plan tests => 25;
|
||||
plan tests => 26;
|
||||
|
||||
ok(run(test(["pkcs7_test"])), "test pkcs7");
|
||||
|
||||
@ -1065,6 +1065,46 @@ subtest "CMS signed digest, DER format" => sub {
|
||||
"Verify CMS signed digest, DER format");
|
||||
};
|
||||
|
||||
subtest "CMS signed digest, DER format, no signing time" => sub {
|
||||
# This test also enables CAdES mode and disables S/MIME capabilities
|
||||
# to approximate the kind of signature required for a PAdES-compliant
|
||||
# PDF signature.
|
||||
plan tests => 4;
|
||||
|
||||
# Pre-computed SHA256 digest of $smcont in hexadecimal form
|
||||
my $digest = "ff236ef61b396355f75a4cc6e1c306d4c309084ae271a9e2ad6888f10a101b32";
|
||||
|
||||
my $sig_file = "signature.der";
|
||||
ok(run(app(["openssl", "cms", @prov, "-sign", "-digest", $digest,
|
||||
"-outform", "DER",
|
||||
"-no_signing_time",
|
||||
"-nosmimecap",
|
||||
"-cades",
|
||||
"-certfile", catfile($smdir, "smroot.pem"),
|
||||
"-signer", catfile($smdir, "smrsa1.pem"),
|
||||
"-out", $sig_file])),
|
||||
"CMS sign pre-computed digest, DER format, no signing time");
|
||||
|
||||
my $exit = 0;
|
||||
my $dump = join "\n",
|
||||
run(app(["openssl", "cms", @prov, "-cmsout", "-noout", "-print",
|
||||
"-in", $sig_file,
|
||||
"-inform", "DER"]),
|
||||
capture => 1,
|
||||
statusvar => $exit);
|
||||
|
||||
is($exit, 0, "Parse CMS signed digest, DER format, no signing time");
|
||||
is(index($dump, 'signingTime'), -1,
|
||||
"Check that CMS signed digest does not contain signing time");
|
||||
|
||||
ok(run(app(["openssl", "cms", @prov, "-verify", "-in", $sig_file,
|
||||
"-inform", "DER",
|
||||
"-CAfile", catfile($smdir, "smroot.pem"),
|
||||
"-content", $smcont])),
|
||||
"Verify CMS signed digest, DER format, no signing time");
|
||||
};
|
||||
|
||||
|
||||
subtest "CMS signed digest, S/MIME format" => sub {
|
||||
plan tests => 2;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user