| # | |
| # This file is part of pyasn1-modules software. | |
| # | |
| # Created by Russ Housley | |
| # Copyright (c) 2019, Vigil Security, LLC | |
| # License: http://snmplabs.com/pyasn1/license.html | |
| # | |
| import sys | |
| from pyasn1.codec.der.decoder import decode as der_decode | |
| from pyasn1.codec.der.encoder import encode as der_encode | |
| from pyasn1.compat.octets import str2octs | |
| from pyasn1_modules import pem | |
| from pyasn1_modules import rfc2634 | |
| from pyasn1_modules import rfc4073 | |
| from pyasn1_modules import rfc5652 | |
| try: | |
| import unittest2 as unittest | |
| except ImportError: | |
| import unittest | |
| class ContentCollectionTestCase(unittest.TestCase): | |
| pem_text = """\ | |
| MIIG/QYLKoZIhvcNAQkQAROgggbsMIIG6DCCAWcGCyqGSIb3DQEJEAEUoIIBVjCC | |
| AVIwgfEGCSqGSIb3DQEHAaCB4wSB4ENvbnRlbnQtVHlwZTogdGV4dC9wbGFpbgoK | |
| UkZDIDQwNzMsIHB1Ymxpc2hlZCBpbiBNYXkgMjAwNSwgZGVzY3JpYmVzIGEgY29u | |
| dmVudGlvbiBmb3IgdXNpbmcgdGhlCkNyeXB0b2dyYXBoaWMgTWVzc2FnZSBTeW50 | |
| YXggKENNUykgdG8gcHJvdGVjdCBhIGNvbnRlbnQgY29sbGVjdGlvbi4gIElmCmRl | |
| c2lyZWQsIGF0dHJpYnV0ZXMgY2FuIGJlIGFzc29jaWF0ZWQgd2l0aCB0aGUgY29u | |
| dGVudC4KMFwwMwYLKoZIhvcNAQkQAgQxJDAiDBVBYnN0cmFjdCBmb3IgUkZDIDQw | |
| NzMGCSqGSIb3DQEHATAlBgsqhkiG9w0BCRACBzEWBBSkLSXBiRWvbwnJKb4EGb1X | |
| FwCa3zCCBXkGCyqGSIb3DQEJEAEUoIIFaDCCBWQwggT9BgkqhkiG9w0BBwGgggTu | |
| BIIE6kNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbgoKVGhlIGZvbGxvd2luZyBBU04u | |
| MSBtb2R1bGUgZGVmaW5lcyB0aGUgc3RydWN0dXJlcyB0aGF0IGFyZSBuZWVkZWQg | |
| dG8KaW1wbGVtZW50IHRoZSBzcGVjaWZpY2F0aW9uIGluIFJGQyA0MDczLiAgSXQg | |
| aXMgZXhwZWN0ZWQgdG8gYmUgdXNlZCBpbgpjb25qdW5jdGlvbiB3aXRoIHRoZSBB | |
| U04uMSBtb2R1bGVzIGluIFJGQyA1NjUyIGFuZCBSRkMgMzI3NC4KCiAgIENvbnRl | |
| bnRDb2xsZWN0aW9uTW9kdWxlCiAgICAgeyBpc28oMSkgbWVtYmVyLWJvZHkoMikg | |
| dXMoODQwKSByc2Fkc2koMTEzNTQ5KSBwa2NzKDEpCiAgICAgICBwa2NzLTkoOSkg | |
| c21pbWUoMTYpIG1vZHVsZXMoMCkgMjYgfQoKICAgREVGSU5JVElPTlMgSU1QTElD | |
| SVQgVEFHUyA6Oj0KICAgQkVHSU4KCiAgIElNUE9SVFMKICAgICBBdHRyaWJ1dGUs | |
| IENvbnRlbnRJbmZvCiAgICAgICBGUk9NIENyeXB0b2dyYXBoaWNNZXNzYWdlU3lu | |
| dGF4MjAwNCAtLSBbQ01TXQogICAgICAgICB7IGlzbygxKSBtZW1iZXItYm9keSgy | |
| KSB1cyg4NDApIHJzYWRzaSgxMTM1NDkpCiAgICAgICAgICAgcGtjcygxKSBwa2Nz | |
| LTkoOSkgc21pbWUoMTYpIG1vZHVsZXMoMCkgY21zLTIwMDEoMTQpIH07CgoKICAg | |
| LS0gQ29udGVudCBDb2xsZWN0aW9uIENvbnRlbnQgVHlwZSBhbmQgT2JqZWN0IElk | |
| ZW50aWZpZXIKCiAgIGlkLWN0LWNvbnRlbnRDb2xsZWN0aW9uIE9CSkVDVCBJREVO | |
| VElGSUVSIDo6PSB7CiAgICAgICAgICAgaXNvKDEpIG1lbWJlci1ib2R5KDIpIHVz | |
| KDg0MCkgcnNhZHNpKDExMzU0OSkgcGtjcygxKQogICAgICAgICAgIHBrY3M5KDkp | |
| IHNtaW1lKDE2KSBjdCgxKSAxOSB9CgogICBDb250ZW50Q29sbGVjdGlvbiA6Oj0g | |
| U0VRVUVOQ0UgU0laRSAoMS4uTUFYKSBPRiBDb250ZW50SW5mbwoKICAgLS0gQ29u | |
| dGVudCBXaXRoIEF0dHJpYnV0ZXMgQ29udGVudCBUeXBlIGFuZCBPYmplY3QgSWRl | |
| bnRpZmllcgoKICAgaWQtY3QtY29udGVudFdpdGhBdHRycyBPQkpFQ1QgSURFTlRJ | |
| RklFUiA6Oj0gewogICAgICAgICAgIGlzbygxKSBtZW1iZXItYm9keSgyKSB1cyg4 | |
| NDApIHJzYWRzaSgxMTM1NDkpIHBrY3MoMSkKICAgICAgICAgICBwa2NzOSg5KSBz | |
| bWltZSgxNikgY3QoMSkgMjAgfQoKICAgQ29udGVudFdpdGhBdHRyaWJ1dGVzIDo6 | |
| PSBTRVFVRU5DRSB7CiAgICAgICBjb250ZW50ICAgICBDb250ZW50SW5mbywKICAg | |
| ICAgIGF0dHJzICAgICAgIFNFUVVFTkNFIFNJWkUgKDEuLk1BWCkgT0YgQXR0cmli | |
| dXRlIH0KCiAgIEVORAowYTA4BgsqhkiG9w0BCRACBDEpMCcMGkFTTi4xIE1vZHVs | |
| ZSBmcm9tIFJGQyA0MDczBgkqhkiG9w0BBwEwJQYLKoZIhvcNAQkQAgcxFgQUMbeK | |
| buWO3egPDL8Kf7tBhzjIKLw= | |
| """ | |
| def setUp(self): | |
| self.asn1Spec = rfc5652.ContentInfo() | |
| def testDerCodec(self): | |
| def test_layer(substrate, content_type): | |
| asn1Object, rest = der_decode(substrate, asn1Spec=layers[content_type]) | |
| assert not rest | |
| assert asn1Object.prettyPrint() | |
| assert der_encode(asn1Object) == substrate | |
| if content_type == rfc4073.id_ct_contentWithAttrs: | |
| for attr in asn1Object['attrs']: | |
| assert attr['attrType'] in rfc5652.cmsAttributesMap.keys() | |
| return asn1Object | |
| layers = rfc5652.cmsContentTypesMap | |
| getNextLayer = { | |
| rfc5652.id_ct_contentInfo: lambda x: x['contentType'], | |
| rfc4073.id_ct_contentCollection: lambda x: x[0]['contentType'], | |
| rfc4073.id_ct_contentWithAttrs: lambda x: x['content']['contentType'], | |
| rfc5652.id_data: lambda x: None, | |
| } | |
| getNextSubstrate = { | |
| rfc5652.id_ct_contentInfo: lambda x: x['content'], | |
| rfc4073.id_ct_contentCollection: lambda x: x[0]['content'], | |
| rfc4073.id_ct_contentWithAttrs: lambda x: x['content']['content'], | |
| rfc5652.id_data: lambda x: None, | |
| } | |
| substrate = pem.readBase64fromText(self.pem_text) | |
| this_layer = rfc5652.id_ct_contentInfo | |
| while this_layer != rfc5652.id_data: | |
| if this_layer == rfc4073.id_ct_contentCollection: | |
| asn1Object = test_layer(substrate, this_layer) | |
| for ci in asn1Object: | |
| substrate = ci['content'] | |
| this_layer = ci['contentType'] | |
| while this_layer != rfc5652.id_data: | |
| asn1Object = test_layer(substrate, this_layer) | |
| substrate = getNextSubstrate[this_layer](asn1Object) | |
| this_layer = getNextLayer[this_layer](asn1Object) | |
| else: | |
| asn1Object = test_layer(substrate, this_layer) | |
| substrate = getNextSubstrate[this_layer](asn1Object) | |
| this_layer = getNextLayer[this_layer](asn1Object) | |
| def testOpenTypes(self): | |
| substrate = pem.readBase64fromText(self.pem_text) | |
| asn1Object, rest = der_decode(substrate, | |
| asn1Spec=rfc5652.ContentInfo(), | |
| decodeOpenTypes=True) | |
| assert not rest | |
| assert asn1Object.prettyPrint() | |
| assert der_encode(asn1Object) == substrate | |
| assert asn1Object['contentType'] == rfc4073.id_ct_contentCollection | |
| for ci in asn1Object['content']: | |
| assert ci['contentType'] in rfc5652.cmsContentTypesMap.keys() | |
| assert ci['contentType'] == rfc4073.id_ct_contentWithAttrs | |
| next_ci = ci['content']['content'] | |
| assert next_ci['contentType'] in rfc5652.cmsContentTypesMap.keys() | |
| assert next_ci['contentType'] == rfc5652.id_data | |
| assert str2octs('Content-Type: text') in next_ci['content'] | |
| for attr in ci['content']['attrs']: | |
| assert attr['attrType'] in rfc5652.cmsAttributesMap.keys() | |
| if attr['attrType'] == rfc2634.id_aa_contentHint: | |
| assert 'RFC 4073' in attr['attrValues'][0]['contentDescription'] | |
| suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) | |
| if __name__ == '__main__': | |
| import sys | |
| result = unittest.TextTestRunner(verbosity=2).run(suite) | |
| sys.exit(not result.wasSuccessful()) |