1#
2# This file is part of pyasn1-modules software.
3#
4# Created by Russ Housley
5# Copyright (c) 2019, Vigil Security, LLC
6# License: http://snmplabs.com/pyasn1/license.html
7#
8
9import sys
10
11from pyasn1.codec.der.decoder import decode as der_decode
12from pyasn1.codec.der.encoder import encode as der_encode
13
14from pyasn1.type import char
15from pyasn1.type import namedtype
16from pyasn1.type import univ
17
18from pyasn1_modules import pem
19from pyasn1_modules import rfc5280
20from pyasn1_modules import rfc5652
21from pyasn1_modules import rfc6402
22
23try:
24    import unittest2 as unittest
25except ImportError:
26    import unittest
27
28
29class BackwardCompatibilityTestCase(unittest.TestCase):
30    pem_text = """\
31MIIEJQYJKoZIhvcNAQcCoIIEFjCCBBICAQMxCzAJBgUrDgMCGgUAMIIDAgYIKwYBBQUHDAKgggL0
32BIIC8DCCAuwweDB2AgECBgorBgEEAYI3CgoBMWUwYwIBADADAgEBMVkwVwYJKwYBBAGCNxUUMUow
33SAIBBQwZcGl0dWNoYTEuZW1lYS5ocHFjb3JwLm5ldAwMRU1FQVxwaXR1Y2hhDBpDTUNSZXFHZW5l
34cmF0b3IudnNob3N0LmV4ZTCCAmqgggJmAgEBMIICXzCCAcgCAQAwADCBnzANBgkqhkiG9w0BAQEF
35AAOBjQAwgYkCgYEA0jm7SSSm2wyEAzuNKtFZFJKo91SrJq9wQwEhEKHDavZwMQOm1rZ2PF8NWCEb
36PqrhToQ7rtiGLSZa4dF4bzgmBqQ9aoSfEX4jISt31Vy+skHidXjHHpbsjT24NPhrZgANivL7CxD6
37Ft+s7qS1gL4HRm2twQkqSwOLrE/q2QeXl2UCAwEAAaCCAR0wGgYKKwYBBAGCNw0CAzEMFgo2LjIu
38OTIwMC4yMD4GCSqGSIb3DQEJDjExMC8wHQYDVR0OBBYEFMW2skn88gxhONWZQA4sWGBDb68yMA4G
39A1UdDwEB/wQEAwIHgDBXBgkrBgEEAYI3FRQxSjBIAgEFDBlwaXR1Y2hhMS5lbWVhLmhwcWNvcnAu
40bmV0DAxFTUVBXHBpdHVjaGEMGkNNQ1JlcUdlbmVyYXRvci52c2hvc3QuZXhlMGYGCisGAQQBgjcN
41AgIxWDBWAgECHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAHQAcgBvAG4AZwAgAEMAcgB5AHAAdABv
42AGcAcgBhAHAAaABpAGMAIABQAHIAbwB2AGkAZABlAHIDAQAwDQYJKoZIhvcNAQEFBQADgYEAJZlu
43mxjtCxSOQi27jsVdd3y8NSIlzNv0b3LqmzvAly6L+CstXcnuG2MPQqPH9R7tbJonGUniBQO9sQ7C
44KhYWj2gfhiEkSID82lV5chINVUFKoUlSiEhWr0tPGgvOaqdsKQcrHfzrsBbFkhDqrFSVy7Yivbnh
45qYszKrOjJKiiCPMwADAAMYH5MIH2AgEDgBTFtrJJ/PIMYTjVmUAOLFhgQ2+vMjAJBgUrDgMCGgUA
46oD4wFwYJKoZIhvcNAQkDMQoGCCsGAQUFBwwCMCMGCSqGSIb3DQEJBDEWBBTFTkK/OifaFjwqHiJu
47xM7qXcg/VzANBgkqhkiG9w0BAQEFAASBgKfC6jOi1Wgy4xxDCQVK9+e5tktL8wE/j2cb9JSqq+aU
485UxEgXEw7q7BoYZCAzcxMRriGzakXr8aXHcgkRJ7XcFvLPUjpmGg9SOZ2sGW4zQdWAwImN/i8loc
49xicQmJP+VoMHo/ZpjFY9fYCjNZUArgKsEwK/s+p9yrVVeB1Nf8Mn
50"""
51
52    def testDerCodec(self):
53        layers = { }
54        layers.update(rfc5652.cmsContentTypesMap)
55
56        getNextLayer = {
57            rfc5652.id_ct_contentInfo: lambda x: x['contentType'],
58            rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContentType'],
59            rfc6402.id_cct_PKIData: lambda x: None
60        }
61
62        getNextSubstrate = {
63            rfc5652.id_ct_contentInfo: lambda x: x['content'],
64            rfc5652.id_signedData: lambda x: x['encapContentInfo']['eContent'],
65            rfc6402.id_cct_PKIData: lambda x: None
66        }
67
68        substrate = pem.readBase64fromText(self.pem_text)
69
70        next_layer = rfc5652.id_ct_contentInfo
71        while next_layer:
72            asn1Object, rest = der_decode(substrate, asn1Spec=layers[next_layer])
73            assert not rest
74            assert asn1Object.prettyPrint()
75            assert der_encode(asn1Object) == substrate
76
77            substrate = getNextSubstrate[next_layer](asn1Object)
78            next_layer = getNextLayer[next_layer](asn1Object)
79
80
81    def testOpenTypes(self):
82        class ClientInformation(univ.Sequence):
83            pass
84
85        ClientInformation.componentType = namedtype.NamedTypes(
86            namedtype.NamedType('clientId', univ.Integer()),
87            namedtype.NamedType('MachineName', char.UTF8String()),
88            namedtype.NamedType('UserName', char.UTF8String()),
89            namedtype.NamedType('ProcessName', char.UTF8String())
90        )
91
92        class EnrollmentCSP(univ.Sequence):
93            pass
94
95        EnrollmentCSP.componentType = namedtype.NamedTypes(
96            namedtype.NamedType('KeySpec', univ.Integer()),
97            namedtype.NamedType('Name', char.BMPString()),
98            namedtype.NamedType('Signature', univ.BitString())
99        )
100
101        openTypeMap = {
102            # attributes
103            univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.3'): char.IA5String(),
104            univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.2'): EnrollmentCSP(),
105            univ.ObjectIdentifier('1.3.6.1.4.1.311.21.20'): ClientInformation(),
106            # algorithm identifier parameters
107            univ.ObjectIdentifier('1.2.840.113549.1.1.1'): univ.Null(""),
108            univ.ObjectIdentifier('1.2.840.113549.1.1.5'): univ.Null(""),
109            univ.ObjectIdentifier('1.2.840.113549.1.1.11'): univ.Null(""),
110        }
111
112        openTypeMap.update(rfc5652.cmsAttributesMap)
113        openTypeMap.update(rfc6402.cmcControlAttributesMap)
114
115        substrate = pem.readBase64fromText(self.pem_text)
116        asn1Object, rest = der_decode(substrate,
117            asn1Spec=rfc5652.ContentInfo(),
118            decodeOpenTypes=True)
119        assert not rest
120        assert asn1Object.prettyPrint()
121        assert der_encode(asn1Object) == substrate
122
123        eci = asn1Object['content']['encapContentInfo']
124        assert eci['eContentType'] == rfc6402.id_cct_PKIData
125        substrate = eci['eContent']
126        asn1Object, rest = der_decode(substrate,
127            asn1Spec=rfc6402.PKIData(),
128            openTypes=openTypeMap,
129            decodeOpenTypes=True)
130        assert not rest
131        assert asn1Object.prettyPrint()
132        assert der_encode(asn1Object) == substrate
133
134        for req in asn1Object['reqSequence']:
135            cr = req['tcr']['certificationRequest']
136
137            sig_alg = cr['signatureAlgorithm']
138            assert sig_alg['algorithm'] in openTypeMap.keys()
139            assert sig_alg['parameters'] == univ.Null("")
140
141            cri = cr['certificationRequestInfo']
142            spki_alg = cri['subjectPublicKeyInfo']['algorithm']
143            assert spki_alg['algorithm'] in openTypeMap.keys()
144            assert spki_alg['parameters'] == univ.Null("")
145
146            attrs = cr['certificationRequestInfo']['attributes']
147            for attr in attrs:
148                assert attr['attrType'] in openTypeMap.keys()
149                if attr['attrType'] == univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.3'):
150                    assert attr['attrValues'][0] == "6.2.9200.2"
151                else:
152                    assert attr['attrValues'][0].hasValue()
153
154
155suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
156
157if __name__ == '__main__':
158    unittest.TextTestRunner(verbosity=2).run(suite)
159