diff --git a/asn1crypto/cms.py b/asn1crypto/cms.py index 7ce583d..9c8b6db 100644 --- a/asn1crypto/cms.py +++ b/asn1crypto/cms.py @@ -100,6 +100,8 @@ class CMSAttributeType(ObjectIdentifier): '1.2.840.113549.1.9.4': 'message_digest', '1.2.840.113549.1.9.5': 'signing_time', '1.2.840.113549.1.9.6': 'counter_signature', + # https://datatracker.ietf.org/doc/html/rfc2633#section-2.5.2 + '1.2.840.113549.1.9.15': 'smime_capabilities', # https://tools.ietf.org/html/rfc2633#page-26 '1.2.840.113549.1.9.16.2.11': 'encrypt_key_pref', # https://tools.ietf.org/html/rfc3161#page-20 @@ -946,6 +948,21 @@ class SMIMEEncryptionKeyPreferences(SetOf): _child_spec = SMIMEEncryptionKeyPreference +class SMIMECapabilityIdentifier(Sequence): + _fields = [ + ('capability_id', ObjectIdentifier), + ('parameters', Any, {'optional': True}), + ] + + +class SMIMECapabilites(SequenceOf): + _child_spec = SMIMECapabilityIdentifier + + +class SetOfSMIMECapabilites(SetOf): + _child_spec = SMIMECapabilites + + ContentInfo._oid_specs = { 'data': OctetString, 'signed_data': SignedData, @@ -981,4 +998,5 @@ class SMIMEEncryptionKeyPreferences(SetOf): 'microsoft_nested_signature': SetOfContentInfo, 'microsoft_time_stamp_token': SetOfContentInfo, 'encrypt_key_pref': SMIMEEncryptionKeyPreferences, + 'smime_capabilities': SetOfSMIMECapabilites, } diff --git a/tests/fixtures/smime-signature-generated-by-thunderbird.p7s b/tests/fixtures/smime-signature-generated-by-thunderbird.p7s new file mode 100644 index 0000000..c75b2a9 Binary files /dev/null and b/tests/fixtures/smime-signature-generated-by-thunderbird.p7s differ diff --git a/tests/test_cms.py b/tests/test_cms.py index 52d852e..2f503fc 100644 --- a/tests/test_cms.py +++ b/tests/test_cms.py @@ -911,6 +911,60 @@ def test_parse_content_info_pkcs7_signed_digested_data(self): signer['signature'].native ) + def test_parse_content_info_smime_capabilities(self): + with open(os.path.join(fixtures_dir, 'smime-signature-generated-by-thunderbird.p7s'), 'rb') as f: + info = cms.ContentInfo.load(f.read()) + + signed_attrs = info['content']['signer_infos'][0]['signed_attrs'] + + self.assertEqual( + 'smime_capabilities', + signed_attrs[3]['type'].native + ) + smime_capabilities = signed_attrs[3] + + self.assertEqual( + 1, + len(smime_capabilities['values']) + ) + self.assertEqual( + 7, + len(smime_capabilities['values'][0]) + ) + self.assertEqual( + [capability.native for capability in smime_capabilities['values'][0]], + [ + util.OrderedDict([ + ('capability_id', '2.16.840.1.101.3.4.1.42'), + ('parameters', None), + ]), + util.OrderedDict([ + ('capability_id', '2.16.840.1.101.3.4.1.2'), + ('parameters', None), + ]), + util.OrderedDict([ + ('capability_id', '1.2.840.113549.3.7'), + ('parameters', None), + ]), + util.OrderedDict([ + ('capability_id', '1.2.840.113549.3.2'), + ('parameters', 128), + ]), + util.OrderedDict([ + ('capability_id', '1.2.840.113549.3.2'), + ('parameters', 64), + ]), + util.OrderedDict([ + ('capability_id', '1.3.14.3.2.7'), + ('parameters', None), + ]), + util.OrderedDict([ + ('capability_id', '1.2.840.113549.3.2'), + ('parameters', 40), + ]), + ] + ) + def test_bad_teletex_inside_pkcs7(self): with open(os.path.join(fixtures_dir, 'mozilla-generated-by-openssl.pkcs7.der'), 'rb') as f: content = cms.ContentInfo.load(f.read())['content']