From d63d841fb510a920275c66d3e486089c5c718797 Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Mon, 3 Jun 2019 15:19:48 +1000 Subject: Add the content type attribute to additional CMS signerinfo. Fixes #8923 Found using the openssl cms -resign option. This uses an alternate path to do the signing which was not adding the required signed attribute content type. The content type attribute should always exist since it is required is there are any signed attributes. As the signing time attribute is always added in code, the content type attribute is also required. The CMS_si_check_attributes() method adds validity checks for signed and unsigned attributes e.g. The message digest attribute is a signed attribute that must exist if any signed attributes exist, it cannot be an unsigned attribute and there must only be one instance containing a single value. Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/8944) (cherry picked from commit 19e512a8244a6f527d0194339a8f9fc45468537a) --- test/recipes/80-test_cms.t | 69 ++++++++++++++++++++- .../recipes/80-test_cms_data/bad_signtime_attr.cms | Bin 0 -> 1524 bytes test/recipes/80-test_cms_data/ct_multiple_attr.cms | Bin 0 -> 1549 bytes test/recipes/80-test_cms_data/no_ct_attr.cms | Bin 0 -> 1496 bytes test/recipes/80-test_cms_data/no_md_attr.cms | Bin 0 -> 1473 bytes 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 test/recipes/80-test_cms_data/bad_signtime_attr.cms create mode 100644 test/recipes/80-test_cms_data/ct_multiple_attr.cms create mode 100644 test/recipes/80-test_cms_data/no_ct_attr.cms create mode 100644 test/recipes/80-test_cms_data/no_md_attr.cms (limited to 'test/recipes') diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index b57ca66dac..5dc6a3aebe 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -21,12 +21,13 @@ setup("test_cms"); plan skip_all => "CMS is not supported by this OpenSSL build" if disabled("cms"); +my $datadir = srctop_dir("test", "recipes", "80-test_cms_data"); my $smdir = srctop_dir("test", "smime-certs"); my $smcont = srctop_file("test", "smcont.txt"); my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) = disabled qw/des dh dsa ec ec2m rc2 zlib/; -plan tests => 4; +plan tests => 6; my @smime_pkcs7_tests = ( @@ -400,6 +401,26 @@ my @smime_cms_param_tests = ( ] ); +my @contenttype_cms_test = ( + [ "signed content test - check that content type is added to additional signerinfo, RSA keys", + [ "-sign", "-binary", "-nodetach", "-stream", "-in", $smcont, "-outform", "DER", + "-signer", catfile($smdir, "smrsa1.pem"), "-md", "SHA256", + "-out", "test.cms" ], + [ "-resign", "-binary", "-nodetach", "-in", "test.cms", "-inform", "DER", "-outform", "DER", + "-signer", catfile($smdir, "smrsa2.pem"), "-md", "SHA256", + "-out", "test2.cms" ], + [ "-verify", "-in", "test2.cms", "-inform", "DER", + "-CAfile", catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ] + ], +); + +my @incorrect_attribute_cms_test = ( + "bad_signtime_attr.cms", + "no_ct_attr.cms", + "no_md_attr.cms", + "ct_multiple_attr.cms" +); + subtest "CMS => PKCS#7 compatibility tests\n" => sub { plan tests => scalar @smime_pkcs7_tests; @@ -493,6 +514,52 @@ subtest "CMS <=> CMS consistency tests, modified key parameters\n" => sub { } }; +# Returns the number of matches of a Content Type Attribute in a binary file. +sub contentType_matches { + # Read in a binary file + my ($in) = @_; + open (HEX_IN, "$in") or die("open failed for $in : $!"); + binmode(HEX_IN); + local $/; + my $str = ; + + # Find ASN1 data for a Content Type Attribute (with a OID of PKCS7 data) + my @c = $str =~ /\x30\x18\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x03\x31\x0B\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x07\x01/gs; + + close(HEX_IN); + return scalar(@c); +} + +subtest "CMS Check the content type attribute is added for additional signers\n" => sub { + plan tests => + (scalar @contenttype_cms_test); + + foreach (@contenttype_cms_test) { + SKIP: { + my $skip_reason = check_availability($$_[0]); + skip $skip_reason, 1 if $skip_reason; + + ok(run(app(["openssl", "cms", @{$$_[1]}])) + && run(app(["openssl", "cms", @{$$_[2]}])) + && contentType_matches("test2.cms") == 2 + && run(app(["openssl", "cms", @{$$_[3]}])), + $$_[0]); + } + } +}; + +subtest "CMS Check that bad attributes fail when verifying signers\n" => sub { + plan tests => + (scalar @incorrect_attribute_cms_test); + + foreach my $name (@incorrect_attribute_cms_test) { + ok(!run(app(["openssl", "cms", "-verify", "-in", + catfile($datadir, $name), "-inform", "DER", "-CAfile", + catfile($smdir, "smroot.pem"), "-out", "smtst.txt" ])), + $name); + } +}; + unlink "test.cms"; unlink "test2.cms"; unlink "smtst.txt"; diff --git a/test/recipes/80-test_cms_data/bad_signtime_attr.cms b/test/recipes/80-test_cms_data/bad_signtime_attr.cms new file mode 100644 index 0000000000..048a493581 Binary files /dev/null and b/test/recipes/80-test_cms_data/bad_signtime_attr.cms differ diff --git a/test/recipes/80-test_cms_data/ct_multiple_attr.cms b/test/recipes/80-test_cms_data/ct_multiple_attr.cms new file mode 100644 index 0000000000..974db6ef9a Binary files /dev/null and b/test/recipes/80-test_cms_data/ct_multiple_attr.cms differ diff --git a/test/recipes/80-test_cms_data/no_ct_attr.cms b/test/recipes/80-test_cms_data/no_ct_attr.cms new file mode 100644 index 0000000000..64b688b91c Binary files /dev/null and b/test/recipes/80-test_cms_data/no_ct_attr.cms differ diff --git a/test/recipes/80-test_cms_data/no_md_attr.cms b/test/recipes/80-test_cms_data/no_md_attr.cms new file mode 100644 index 0000000000..d0a3afa523 Binary files /dev/null and b/test/recipes/80-test_cms_data/no_md_attr.cms differ -- cgit v1.2.3