]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
cms: fix AuthenticatedData authAttrs and unauthAttrs element type
authorJakub Zelenka <jakub.zelenka@openssl.foundation>
Wed, 15 Jul 2026 10:20:03 +0000 (12:20 +0200)
committerNorbert Pocs <norbertp@openssl.org>
Wed, 29 Jul 2026 09:57:04 +0000 (11:57 +0200)
The CMS_AuthenticatedData ASN.1 template declared the authAttrs and
unauthAttrs fields as X509_ALGOR, whereas per RFC 5652 section 9.1 they
are [2] and [3] IMPLICIT SET OF Attribute and the CMS_AuthenticatedData
structure already declares them as STACK_OF(X509_ATTRIBUTE). The implicit
tags [2] and [3] were already correct, so only the element type was wrong.

An Attribute (SEQUENCE { type, SET OF value }) is structurally accepted as
an AlgorithmIdentifier (SEQUENCE { algorithm, ANY OPTIONAL }), so parsing
did not fail; the attributes were merely misinterpreted, e.g. cms -cmsout
-print rendered them as algorithm/parameter instead of decoding them as
attributes. Use X509_ATTRIBUTE with the existing tags so the template
matches the structure.

Add a parse test using a BouncyCastle-generated AuthenticatedData message
carrying an authenticated and an unauthenticated attribute, asserting both
are decoded as SET OF Attribute.

Assisted-by: Claude:claude-opus-4-8
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
MergeDate: Wed Jul 29 10:02:08 2026
(Merged from https://github.com/openssl/openssl/pull/31960)

crypto/cms/cms_asn1.c
test/recipes/80-test_cms.t
test/recipes/80-test_cms_data/authenticated_attrs.pem [new file with mode: 0644]

index 96b125e9303099d811a4c4e4aa2f8880e0960ca7..f34240ca8e23b28798bec369a29a59a0416e3338 100644 (file)
@@ -318,9 +318,9 @@ ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = {
     ASN1_SIMPLE(CMS_AuthenticatedData, macAlgorithm, X509_ALGOR),
     ASN1_IMP(CMS_AuthenticatedData, digestAlgorithm, X509_ALGOR, 1),
     ASN1_SIMPLE(CMS_AuthenticatedData, encapContentInfo, CMS_EncapsulatedContentInfo),
-    ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, authAttrs, X509_ALGOR, 2),
+    ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, authAttrs, X509_ATTRIBUTE, 2),
     ASN1_SIMPLE(CMS_AuthenticatedData, mac, ASN1_OCTET_STRING),
-    ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, unauthAttrs, X509_ALGOR, 3)
+    ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, unauthAttrs, X509_ATTRIBUTE, 3)
 } static_ASN1_NDEF_SEQUENCE_END(CMS_AuthenticatedData)
 
 ASN1_NDEF_SEQUENCE(CMS_CompressedData)
index 7516cf024ef6a5ad6c57becbc7d25dfe3df917db..bd7ed2cc1e8c555700247421ca9cc5c38d6fe391 100644 (file)
@@ -56,7 +56,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
 
 $no_rc2 = 1 if disabled("legacy");
 
-plan tests => 40;
+plan tests => 41;
 
 ok(run(test(["pkcs7_test"])), "test pkcs7");
 
@@ -1069,6 +1069,29 @@ subtest "CMS decrypt authEnvelopedData with authenticated attributes\n" => sub {
        "tampered authEnvelopedData leaks no plaintext to -out");
 };
 
+subtest "CMS parse authenticatedData authAttrs and unauthAttrs\n" => sub {
+    plan tests => 3;
+
+    # BouncyCastle authenticatedData (HMAC-SHA256, KEK) carrying both an
+    # authenticated and an unauthenticated attribute. Per RFC 5652 these are
+    # SET OF Attribute, so with the CMS_AuthenticatedData template fixed to use
+    # X509_ATTRIBUTE they are rendered as attributes (object:/set:) rather than
+    # as an X509_ALGOR (algorithm:/parameter:) they were misparsed into before.
+    my $exit = 0;
+    my $dump = join "\n",
+               run(app(["openssl", "cms", @defaultprov, "-cmsout", "-noout",
+                        "-print", "-inform", "PEM",
+                        "-in", catfile($datadir, "authenticated_attrs.pem")]),
+                   capture => 1,
+                   statusvar => $exit);
+
+    is($exit, 0, "parse authenticatedData with attributes");
+    ok($dump =~ /authAttrs:.*?object:.*?1\.3\.6\.1\.4\.1\.5949\.99\.1.*?UTF8STRING:auth-attr-value/s,
+       "authAttrs parsed as SET OF Attribute");
+    ok($dump =~ /unauthAttrs:.*?object:.*?1\.3\.6\.1\.4\.1\.5949\.99\.2.*?UTF8STRING:unauth-attr-value/s,
+       "unauthAttrs parsed as SET OF Attribute");
+};
+
 subtest "CAdES <=> CAdES consistency tests\n" => sub {
     plan tests => (scalar @smime_cms_cades_tests);
 
diff --git a/test/recipes/80-test_cms_data/authenticated_attrs.pem b/test/recipes/80-test_cms_data/authenticated_attrs.pem
new file mode 100644 (file)
index 0000000..4f3d212
--- /dev/null
@@ -0,0 +1,8 @@
+-----BEGIN CMS-----
+MIAGCyqGSIb3DQEJEAECoIAwgAIBADFDokECAQQwBQQDwP7gMAsGCWCGSAFlAwQB
+BQQoWM396pUOzWW6mFsNvr+XXTLufCrvzG3jiTOX+l3LpSXbXHhhpadw5DAMBggq
+hkiG9w0CCQUAoQsGCWCGSAFlAwQCATCABgkqhkiG9w0BBwGggCSABB5IZWxsbyBB
+dXRoZW50aWNhdGVkRGF0YSB3b3JsZAoAAAAAAACiIDAeBgkrBgEEAa49YwExEQwP
+YXV0aC1hdHRyLXZhbHVlBCB9kCl8ic3e5461oodeDSyR7heZxtdN7G/N+oqerDIj
+PqMiMCAGCSsGAQQBrj1jAjETDBF1bmF1dGgtYXR0ci12YWx1ZQAAAAAAAA==
+-----END CMS-----