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 rfc7191
19
20try:
21    import unittest2 as unittest
22except ImportError:
23    import unittest
24
25
26class ReceiptRequestTestCase(unittest.TestCase):
27    message1_pem_text = """\
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
59"""
60
61    def setUp(self):
62        self.asn1Spec = rfc5652.ContentInfo()
63
64    def testDerCodec(self):
65        substrate = pem.readBase64fromText(self.message1_pem_text)
66        asn1Object, rest = der_decode (substrate, asn1Spec=self.asn1Spec)
67        assert not rest
68        assert asn1Object.prettyPrint()
69        assert der_encode(asn1Object) == substrate
70
71        assert asn1Object['contentType'] == rfc5652.id_signedData
72        sd, rest = der_decode (asn1Object['content'],
73            asn1Spec=rfc5652.SignedData())
74
75        for sa in sd['signerInfos'][0]['signedAttrs']:
76            sat = sa['attrType']
77            sav0 = sa['attrValues'][0]
78
79            if sat == rfc7191.id_aa_KP_keyPkgIdAndReceiptReq:
80                sav, rest = der_decode(sav0,
81                    asn1Spec=rfc7191.KeyPkgIdentifierAndReceiptReq())
82                assert not rest
83                assert sav.prettyPrint()
84                assert der_encode(sav) == sav0
85
86                package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0="
87                package_id = pem.readBase64fromText(package_id_pem_text)
88                assert sav['pkgID'] == package_id
89
90    def testOpenTypes(self):
91        substrate = pem.readBase64fromText(self.message1_pem_text)
92        asn1Object, rest = der_decode (substrate,
93                                       asn1Spec=self.asn1Spec,
94                                       decodeOpenTypes=True)
95        assert not rest
96        assert asn1Object.prettyPrint()
97        assert der_encode(asn1Object) == substrate
98
99        assert asn1Object['contentType'] == rfc5652.id_signedData
100        v3 = rfc5652.CMSVersion().subtype(value='v3')
101        assert asn1Object['content']['version'] == v3
102
103        for sa in asn1Object['content']['signerInfos'][0]['signedAttrs']:
104            if sa['attrType'] == rfc7191.id_aa_KP_keyPkgIdAndReceiptReq:
105                package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0="
106                package_id = pem.readBase64fromText(package_id_pem_text)
107                assert sa['attrValues'][0]['pkgID'] == package_id
108
109
110class ReceiptTestCase(unittest.TestCase):
111    message2_pem_text = """\
112MIIEdAYJKoZIhvcNAQcCoIIEZTCCBGECAQMxDTALBglghkgBZQMEAgIwgawGCmCGSAFlAgEC
113TgOggZ0EgZowgZcEFCe4nFY7FiJRnReHHHm/rIht3/g9MH8GCWCGSAFlAgEQAARyMHAxCzAJ
114BgNVBAYTAlVTMQswCQYDVQQIEwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhh
115bXBsZTEOMAwGA1UEAxMFQWxpY2UxIDAeBgkqhkiG9w0BCQEWEWFsaWNlQGV4YW1wbGUuY29t
116oIICfDCCAngwggH+oAMCAQICCQCls1QoG7BuOzAKBggqhkjOPQQDAzA/MQswCQYDVQQGEwJV
117UzELMAkGA1UECAwCVkExEDAOBgNVBAcMB0hlcm5kb24xETAPBgNVBAoMCEJvZ3VzIENBMB4X
118DTE5MDUyOTE0NDU0MVoXDTIwMDUyODE0NDU0MVowcDELMAkGA1UEBhMCVVMxCzAJBgNVBAgT
119AlZBMRAwDgYDVQQHEwdIZXJuZG9uMRAwDgYDVQQKEwdFeGFtcGxlMQ4wDAYDVQQDEwVBbGlj
120ZTEgMB4GCSqGSIb3DQEJARYRYWxpY2VAZXhhbXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQA
121IgNiAAT4zZ8HL+xEDpXWkoWp5xFMTz4u4Ae1nF6zXCYlmsEGD5vPu5hl9hDEjd1UHRgJIPoy
1223fJcWWeZ8FHCirICtuMgFisNscG/aTwKyDYOFDuqz/C2jyEwqgWCRyxyohuJXtmjgZQwgZEw
123CwYDVR0PBAQDAgeAMEIGCWCGSAGG+EIBDQQ1FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBi
124ZSB0cnVzdGVkIGZvciBhbnkgcHVycG9zZS4wHQYDVR0OBBYEFMS6Wg4+euM8gbD0Aqpouxbg
125lg41MB8GA1UdIwQYMBaAFPI12zQE2qVV8r1pA5mwYuziFQjBMAoGCCqGSM49BAMDA2gAMGUC
126MGO5H9E1uAveRGGaf48lN4pov2yH+hCAc5hOAuZKe/f40MKSF8q4w2ij+0euSaKFiAIxAL3g
127xp6sMitCmLQgOH6/RBIC/2syJ97y0KVp9da0PDAvwxLugCHTKZPjjpSLPHHc9TGCARwwggEY
128AgEDgBTEuloOPnrjPIGw9AKqaLsW4JYONTALBglghkgBZQMEAgKgejAZBgkqhkiG9w0BCQMx
129DAYKYIZIAWUCAQJOAzAcBgkqhkiG9w0BCQUxDxcNMTkwNjEzMTYxNjA4WjA/BgkqhkiG9w0B
130CQQxMgQwQSWYpq4jwhMkmS0as0JL3gjYxKLgDfzP2ndTNsAY0m9p8Igp8ZcK4+5n9fXJ43vU
131MAoGCCqGSM49BAMDBGgwZgIxAMfq2EJ5pSl9tGOEVJEgZitc266ljrOg5GDjkd2d089qw1A3
132bUcOYuCdivgxVuhlAgIxAPR9JavxziwCbVyBUWOAiKKYfglTgG3AwNmrKDj0NtXUQ9qDmGAc
1336L+EAY2P5OVB8Q==
134"""
135
136    def setUp(self):
137        self.asn1Spec = rfc5652.ContentInfo()
138
139    def testDerCodec(self):
140        substrate = pem.readBase64fromText(self.message2_pem_text)
141        asn1Object, rest = der_decode (substrate, asn1Spec=self.asn1Spec)
142        assert not rest
143        assert asn1Object.prettyPrint()
144        assert der_encode(asn1Object) == substrate
145
146        assert asn1Object['contentType'] == rfc5652.id_signedData
147        sd, rest = der_decode (asn1Object['content'],
148            asn1Spec=rfc5652.SignedData())
149        assert not rest
150        assert sd.prettyPrint()
151        assert der_encode(sd) == asn1Object['content']
152
153        oid = sd['encapContentInfo']['eContentType']
154        assert oid == rfc7191.id_ct_KP_keyPackageReceipt
155        receipt, rest = der_decode(sd['encapContentInfo']['eContent'],
156            asn1Spec=rfc7191.KeyPackageReceipt())
157        assert not rest
158        assert receipt.prettyPrint()
159        assert der_encode(receipt) == sd['encapContentInfo']['eContent']
160
161        package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0="
162        package_id = pem.readBase64fromText(package_id_pem_text)
163        assert receipt['receiptOf']['pkgID'] == package_id
164
165    def testOpenTypes(self):
166        substrate = pem.readBase64fromText(self.message2_pem_text)
167        asn1Object, rest = der_decode (substrate,
168                                       asn1Spec=self.asn1Spec,
169                                       decodeOpenTypes=True)
170        assert not rest
171        assert asn1Object.prettyPrint()
172        assert der_encode(asn1Object) == substrate
173
174        assert asn1Object['contentType'] == rfc5652.id_signedData
175        v3 = rfc5652.CMSVersion().subtype(value='v3')
176        assert asn1Object['content']['version'] == v3
177
178        for sa in asn1Object['content']['signerInfos'][0]['signedAttrs']:
179            assert sa['attrType'] in rfc5652.cmsAttributesMap.keys()
180            if sa['attrType'] == rfc5652.id_messageDigest:
181                assert '0x412598a6ae2' in sa['attrValues'][0].prettyPrint()
182
183        ct_oid = asn1Object['content']['encapContentInfo']['eContentType']
184        assert ct_oid in rfc5652.cmsContentTypesMap
185        assert ct_oid == rfc7191.id_ct_KP_keyPackageReceipt
186
187        # Since receipt is inside an OCTET STRING, decodeOpenTypes=True cannot
188        # automatically decode it
189        sd_eci = asn1Object['content']['encapContentInfo']
190        receipt, rest = der_decode(sd_eci['eContent'],
191            asn1Spec=rfc5652.cmsContentTypesMap[sd_eci['eContentType']])
192        package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0="
193        package_id = pem.readBase64fromText(package_id_pem_text)
194        assert receipt['receiptOf']['pkgID'] == package_id
195
196class ErrorTestCase(unittest.TestCase):
197    message3_pem_text = """\
198MIIEbwYJKoZIhvcNAQcCoIIEYDCCBFwCAQMxDTALBglghkgBZQMEAgIwga0GCmCGSAFlAgEC
199TgaggZ4EgZswgZigFgQUJ7icVjsWIlGdF4cceb+siG3f+D0wewYJYIZIAWUCARAABG4wbDEL
200MAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQHEwdIZXJuZG9uMRAwDgYDVQQKEwdF
201eGFtcGxlMQwwCgYDVQQDEwNCb2IxHjAcBgkqhkiG9w0BCQEWD2JvYkBleGFtcGxlLmNvbQoB
202CqCCAncwggJzMIIB+qADAgECAgkApbNUKBuwbjwwCgYIKoZIzj0EAwMwPzELMAkGA1UEBhMC
203VVMxCzAJBgNVBAgMAlZBMRAwDgYDVQQHDAdIZXJuZG9uMREwDwYDVQQKDAhCb2d1cyBDQTAe
204Fw0xOTA1MjkxOTIwMTNaFw0yMDA1MjgxOTIwMTNaMGwxCzAJBgNVBAYTAlVTMQswCQYDVQQI
205EwJWQTEQMA4GA1UEBxMHSGVybmRvbjEQMA4GA1UEChMHRXhhbXBsZTEMMAoGA1UEAxMDQm9i
206MR4wHAYJKoZIhvcNAQkBFg9ib2JAZXhhbXBsZS5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNi
207AAQxpGJVLxa83xhyal+rvmMFs4xS6Q19cCDoAvQkkFe0gUC4glxlWWQuf/FvLCRwwscr877D
2081FZRBrYKPD6Hxv/UKX6Aimou0TnnxsPk98zZpikn9gTrJn2cF9NCzvPVMfmjgZQwgZEwCwYD
209VR0PBAQDAgeAMEIGCWCGSAGG+EIBDQQ1FjNUaGlzIGNlcnRpZmljYXRlIGNhbm5vdCBiZSB0
210cnVzdGVkIGZvciBhbnkgcHVycG9zZS4wHQYDVR0OBBYEFMprZnLeLJtXf5iO4sMq02aOwhql
211MB8GA1UdIwQYMBaAFPI12zQE2qVV8r1pA5mwYuziFQjBMAoGCCqGSM49BAMDA2cAMGQCMBVu
212hLo58RhCiYsOLZFSR3vWHPDCJBnO1vE1uixqEjONHxlBoeGN2MmWs/9PppcHCwIwN9HB5jPc
213J7gTjA9+ipCe+qkztmV+Gy2NBAY6xYC0gh+pb+X5OAI7y7HdctXp+PfrMYIBGzCCARcCAQOA
214FMprZnLeLJtXf5iO4sMq02aOwhqlMAsGCWCGSAFlAwQCAqB6MBkGCSqGSIb3DQEJAzEMBgpg
215hkgBZQIBAk4GMBwGCSqGSIb3DQEJBTEPFw0xOTA2MTMxNjE2MDhaMD8GCSqGSIb3DQEJBDEy
216BDCgXFTUc3ZInjt+MWYkYmXYERk4FgErEZNILlWgVl7Z9pImgLObIpdrGqGPt06/VkwwCgYI
217KoZIzj0EAwMEZzBlAjEAsjJ3iWRUteMKBVsjaYeN6TG9NITRTOpRVkSVq55DcnhwS9g9lu8D
218iNF8uKtW/lk0AjA7z2q40N0lamXkSU7ECasiWOYV1X4cWGiQwMZDKknBPDqXqB6Es6p4J+qe
2190V6+BtY=
220"""
221
222    def setUp(self):
223        self.asn1Spec = rfc5652.ContentInfo()
224
225    def testDerCodec(self):
226        substrate = pem.readBase64fromText(self.message3_pem_text)
227        asn1Object, rest = der_decode (substrate, asn1Spec=self.asn1Spec)
228        assert not rest
229        assert asn1Object.prettyPrint()
230        assert der_encode(asn1Object) == substrate
231
232        assert asn1Object['contentType'] == rfc5652.id_signedData
233        sd, rest = der_decode (asn1Object['content'],
234            asn1Spec=rfc5652.SignedData())
235        assert not rest
236        assert sd.prettyPrint()
237        assert der_encode(sd) == asn1Object['content']
238
239        oid = sd['encapContentInfo']['eContentType']
240        assert oid == rfc7191.id_ct_KP_keyPackageError
241        kpe, rest = der_decode(sd['encapContentInfo']['eContent'],
242            asn1Spec=rfc7191.KeyPackageError())
243        assert not rest
244        assert kpe.prettyPrint()
245        assert der_encode(kpe) == sd['encapContentInfo']['eContent']
246
247        package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0="
248        package_id = pem.readBase64fromText(package_id_pem_text)
249        assert kpe['errorOf']['pkgID'] == package_id
250        assert kpe['errorCode'] == rfc7191.EnumeratedErrorCode(value=10)
251
252    def testOpenTypes(self):
253        substrate = pem.readBase64fromText(self.message3_pem_text)
254        asn1Object, rest = der_decode (substrate,
255                                       asn1Spec=self.asn1Spec,
256                                       decodeOpenTypes=True)
257        assert not rest
258        assert asn1Object.prettyPrint()
259        assert der_encode(asn1Object) == substrate
260
261        assert asn1Object['contentType'] == rfc5652.id_signedData
262        v3 = rfc5652.CMSVersion().subtype(value='v3')
263        assert asn1Object['content']['version'] == v3
264
265        for sa in asn1Object['content']['signerInfos'][0]['signedAttrs']:
266            assert sa['attrType'] in rfc5652.cmsAttributesMap.keys()
267            if sa['attrType'] == rfc5652.id_messageDigest:
268                assert '0xa05c54d4737' in sa['attrValues'][0].prettyPrint()
269
270        ct_oid = asn1Object['content']['encapContentInfo']['eContentType']
271        assert ct_oid in rfc5652.cmsContentTypesMap.keys()
272        assert ct_oid == rfc7191.id_ct_KP_keyPackageError
273
274        # Since receipt is inside an OCTET STRING, decodeOpenTypes=True cannot
275        # automatically decode it
276        sd_eci = asn1Object['content']['encapContentInfo']
277        kpe, rest = der_decode(sd_eci['eContent'],
278            asn1Spec=rfc5652.cmsContentTypesMap[sd_eci['eContentType']])
279        package_id_pem_text = "J7icVjsWIlGdF4cceb+siG3f+D0="
280        package_id = pem.readBase64fromText(package_id_pem_text)
281        assert kpe['errorOf']['pkgID'] == package_id
282        assert kpe['errorCode'] == rfc7191.EnumeratedErrorCode(value=10)
283
284
285suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])
286
287if __name__ == '__main__':
288    import sys
289
290    result = unittest.TextTestRunner(verbosity=2).run(suite)
291    sys.exit(not result.wasSuccessful())
292