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 univ
15
16from pyasn1_modules import pem
17from pyasn1_modules import rfc5652
18from pyasn1_modules import rfc7292
19
20try:
21    import unittest2 as unittest
22except ImportError:
23    import unittest
24
25
26class PKCS12TestCase(unittest.TestCase):
27    pfx_pem_text = """\
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
75"""
76
77    def setUp(self):
78        self.asn1Spec = rfc7292.PFX()
79
80    def testDerCodec(self):
81        substrate = pem.readBase64fromText(self.pfx_pem_text)
82        asn1Object, rest = der_decode(substrate, asn1Spec=self.asn1Spec)
83        assert not rest
84        assert asn1Object.prettyPrint()
85        assert der_encode(asn1Object) == substrate
86
87        assert asn1Object['version'] == univ.Integer(3)
88        oid = asn1Object['macData']['mac']['digestAlgorithm']['algorithm']
89        assert oid ==  univ.ObjectIdentifier('1.3.14.3.2.26')
90        md_hex = asn1Object['macData']['mac']['digest'].prettyPrint()
91        assert md_hex == '0xa5608ffdf651d132b90701aeaaf4ddd3e76e88a7'
92
93        assert asn1Object['authSafe']['contentType'] == rfc5652.id_data
94        data, rest = der_decode(asn1Object['authSafe']['content'],
95            asn1Spec=univ.OctetString())
96        assert not rest
97
98        authsafe, rest = der_decode(data, asn1Spec=rfc7292.AuthenticatedSafe())
99        assert not rest
100        assert authsafe.prettyPrint()
101        assert der_encode(authsafe) == data
102
103        for ci in authsafe:
104            assert ci['contentType'] == rfc5652.id_data
105            data, rest = der_decode(ci['content'], asn1Spec=univ.OctetString())
106            assert not rest
107
108            sc, rest = der_decode(data, asn1Spec=rfc7292.SafeContents())
109            assert not rest
110            assert sc.prettyPrint()
111            assert der_encode(sc) == data
112
113            for sb in sc:
114                if sb['bagId'] in rfc7292.pkcs12BagTypeMap:
115                    bv, rest = der_decode(sb['bagValue'],
116                       asn1Spec=rfc7292.pkcs12BagTypeMap[sb['bagId']])
117                    assert not rest
118                    assert bv.prettyPrint()
119                    assert der_encode(bv) == sb['bagValue']
120
121                    for attr in sb['bagAttributes']:
122                        if attr['attrType'] in rfc5652.cmsAttributesMap:
123                            av, rest = der_decode(attr['attrValues'][0],
124                                asn1Spec=rfc5652.cmsAttributesMap[attr['attrType']])
125                            assert not rest
126                            assert av.prettyPrint()
127                            assert der_encode(av) == attr['attrValues'][0]
128
129    def testOpenTypes(self):
130        substrate = pem.readBase64fromText(self.pfx_pem_text)
131        asn1Object, rest = der_decode(substrate,
132            asn1Spec=self.asn1Spec,
133            decodeOpenTypes=True
134        )
135        assert not rest
136        assert asn1Object.prettyPrint()
137        assert der_encode(asn1Object) == substrate
138
139        digest_alg = asn1Object['macData']['mac']['digestAlgorithm']
140        assert not digest_alg['parameters'].hasValue()
141
142        authsafe, rest = der_decode(asn1Object['authSafe']['content'],
143            asn1Spec=rfc7292.AuthenticatedSafe(),
144            decodeOpenTypes=True
145        )
146        assert not rest
147        assert authsafe.prettyPrint()
148        assert der_encode(authsafe) == asn1Object['authSafe']['content']
149
150        for ci in authsafe:
151            assert ci['contentType'] == rfc5652.id_data
152            sc, rest = der_decode(ci['content'],
153                asn1Spec=rfc7292.SafeContents(),
154                decodeOpenTypes=True
155            )
156            assert not rest
157            assert sc.prettyPrint()
158            assert der_encode(sc) == ci['content']
159
160            for sb in sc:
161                if sb['bagId'] == rfc7292.id_pkcs8ShroudedKeyBag:
162                    bv = sb['bagValue']
163                    enc_alg = bv['encryptionAlgorithm']['algorithm']
164                    assert enc_alg == rfc7292.pbeWithSHAAnd3_KeyTripleDES_CBC
165                    enc_alg_param = bv['encryptionAlgorithm']['parameters']
166                    assert enc_alg_param['iterations'] == 2000
167
168
169suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
170
171if __name__ == '__main__':
172    unittest.TextTestRunner(verbosity=2).run(suite)
173