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# 8import sys 9 10from pyasn1.codec.der.decoder import decode as der_decode 11from pyasn1.codec.der.encoder import encode as der_encode 12 13from pyasn1.type import univ 14 15from pyasn1_modules import pem 16from pyasn1_modules import rfc2985 17from pyasn1_modules import rfc5280 18from pyasn1_modules import rfc5652 19from pyasn1_modules import rfc7292 20 21 22try: 23 import unittest2 as unittest 24 25except ImportError: 26 import unittest 27 28 29class PKCS9AttrsTestCase(unittest.TestCase): 30 pem_text = """\ 31MYIQjzAOBgNVBEExBwwFQWxpY2UwDwYIKwYBBQUHCQMxAxMBTTAQBgNVBAUxCRMH 32QjQ4LTAwNzAQBggrBgEFBQcJBDEEEwJVUzAQBggrBgEFBQcJBTEEEwJVUzARBgoq 33hkiG9w0BCRkEMQMCATAwFAYJKoZIhvcNAQkCMQcWBUFsaWNlMBgGCiqGSIb3DQEJ 34GQMxCgQIUTeqnHYky4AwHAYJKoZIhvcNAQkPMQ8wDTALBglghkgBZQMEAS0wHQYI 35KwYBBQUHCQExERgPMjAxOTA4MDMxMjAwMDBaMB0GCCsGAQUFBwkCMREMD0hlcm5k 36b24sIFZBLCBVUzApBgkqhkiG9w0BCRQxHB4aAEYAcgBpAGUAbgBkAGwAeQAgAE4A 37YQBtAGUwLwYJKoZIhvcNAQkIMSITIDEyMyBVbmtub3duIFdheSwgTm93aGVyZSwg 38VkEsIFVTMIGZBgoqhkiG9w0BCRkCMYGKMIGHMAsGCWCGSAFlAwQBLQR4VsJb7t4l 39IqjJCT54rqkbCJsBPE17YQJeEYvyA4M1aDIUU5GnCgEhctgMiDPWGMvaSziixdIg 40aU/0zvWvYCm8UwPvBBwMtm9X5NDvk9p4nXbGAT8E/OsV1SYWVvwRJwYak0yWWexM 41HSixw1Ljh2nb0fIbqwLOeMmIMIIEsQYKKoZIhvcNAQkZBTGCBKEwggSdBgkqhkiG 429w0BBwKgggSOMIIEigIBATENMAsGCWCGSAFlAwQCAjBRBgkqhkiG9w0BBwGgRARC 43Q29udGVudC1UeXBlOiB0ZXh0L3BsYWluDQoNCldhdHNvbiwgY29tZSBoZXJlIC0g 44SSB3YW50IHRvIHNlZSB5b3UuoIICfDCCAngwggH+oAMCAQICCQCls1QoG7BuOzAK 45BggqhkjOPQQDAzA/MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExEDAOBgNVBAcM 46B0hlcm5kb24xETAPBgNVBAoMCEJvZ3VzIENBMB4XDTE5MDUyOTE0NDU0MVoXDTIw 47MDUyODE0NDU0MVowcDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlZBMRAwDgYDVQQH 48EwdIZXJuZG9uMRAwDgYDVQQKEwdFeGFtcGxlMQ4wDAYDVQQDEwVBbGljZTEgMB4G 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 850L0c2bbkom3WkPq/po/dPDuoaX61nKmztUHaL5r5QZzBBwKVyhdw9J0btnWAFPNK 86vzgy5U9iV4+6jXH5TCmlIreszwRPoqqEaYRIfmUpp2+zy91PpzjTs98tx/HIAbOM 87fT3WmuTahEnEHehABhwq+S4xwzoVIskLbrcOP6l7UYYR7GTUCjKxh7ru0rSwHrqG 889t33YdzJaFbz+8jb88xtf454Rvur66Cew/4GYX9u1Zef0DF9So1ay3IicpOf5emo 89VWIwg4bh7bELi78i/MbdWtNZQcXimykfeTsYH8Q4u+1uxHS5pwEWWwKiUnLQVpZP 902ut255TdgSIhEILwsaLVelRrx/lp14EpY355FOusXiju6g14aWfBnt5udvuTXxDQ 91ZHPPNNk+gwzgvvTey98T941hYUctjg0NApJiB66bfrlYB9mkc5ftg5zqhEasYH5C 924ajKKRNMM7zGlwSZvy8PPhnAeE3Q9LTnos0l4ygjQD/kMlvd7XSLW3GUzjyxtkG4 93gQh6LGvnafAbgu7GpcapKEppN86sXEePHiQjj92n103+TxMYWwtaO4iAwkjqdEdt 94avEHcXRcpdqC0st6nUwPAPAC4LKJbZgLQnNG+wlWIiCMMD56IdfQ7r/zGIr13MxC 95kjNNUdISoWWE5GnQMYHbMBMGCSqGSIb3DQEJFTEGBAQBAAAAMFcGCSqGSIb3DQEJ 96FDFKHkgAMwBmADcAMQBhAGYANgA1AC0AMQA2ADgANwAtADQANAA0AGEALQA5AGYA 97NAA2AC0AYwA4AGIAZQAxADkANABjADMAZQA4AGUwawYJKwYBBAGCNxEBMV4eXABN 98AGkAYwByAG8AcwBvAGYAdAAgAEUAbgBoAGEAbgBjAGUAZAAgAEMAcgB5AHAAdABv 99AGcAcgBhAHAAaABpAGMAIABQAHIAbwB2AGkAZABlAHIAIAB2ADEALgAwMIIDaAYJ 100KoZIhvcNAQcBoIIDWQSCA1UwggNRMIIDTQYLKoZIhvcNAQwKAQOgggMlMIIDIQYK 101KoZIhvcNAQkWAaCCAxEEggMNMIIDCTCCAfGgAwIBAgIQNu32hzqhCKdHATXzboyI 102ETANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDEwlhbm9ueW1vdXMwIBcNMTYwNzE5 103MjIwMDAxWhgPMjExNjA2MjUyMjAwMDFaMBQxEjAQBgNVBAMTCWFub255bW91czCC 104ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALy2sEJMGNdcDg6BI7mdFM5T 105lPzo5sKBzvUnagK5SKBJ11xMPN5toPTBzICB/XTWEB3AwpD0O+srSca+bsUAyedS 1065V4BNp8qCyEu5RNRR8qPHheJ/guhLT96/gGI4jlrUyUhFntPkLKODxu+7KanMy6K 107dD+PVE8shXRUZTYe4PG64/c7z3wapnf4XoCXkJRzCY5f3MKz3Ul039kVnTlJcikd 108C7I9I9RflXLwXVl4nxUbeeRt6Z8WVWS4pCq+14v2aVPvP3mtVmAYHedRkvS04Hrx 1094xx98D3NSSw6Z5OLkzqOcFw15fYmH2NLdhh34gSWJmaaCBAbuQ+1rx/42p7MvvsC 110AwEAAaNVMFMwFQYDVR0lBA4wDAYKKwYBBAGCNwoDBDAvBgNVHREEKDAmoCQGCisG 111AQQBgjcUAgOgFgwUYW5vbnltb3VzQHdpbmRvd3MteAAwCQYDVR0TBAIwADANBgkq 112hkiG9w0BAQUFAAOCAQEAuH7iqY0/MLozwFb39ILYAJDHE+HToZBQbHQP4YtienrU 113Stk60rIp0WH65lam7m/JhgAcItc/tV1L8mEnLrvvKcA+NeIL8sDOtM28azvgcOi0 114P3roeLLLRCuiykUaKmUcZEDm9cDYKIpJf7QetWQ3uuGTk9iRzpH79x2ix35BnyWQ 115Rr3INZzmX/+9YRvPBXKYl/89F/w1ORYArpI9XtjfuPWaGQmM4f1WRHE2t3qRyKFF 116ri7QiZdpcSx5zvsRHSyjfUMoKs+b6upk+P01lIhg/ewwYngGab+fZhF15pTNN2hx 1178PdNGcrGzrkNKCmJKrWCa2xczuMA+z8SCuC1tYTKmDEVMBMGCSqGSIb3DQEJFTEG 118BAQBAAAAMDswHzAHBgUrDgMCGgQUpWCP/fZR0TK5BwGuqvTd0+duiKcEFJTubF2k 119HktMK+isIjxOTk4yJTOOAgIH0A== 120""" 121 122 def setUp(self): 123 self.asn1Spec = rfc2985.AttributeSet() 124 125 def testDerCodec(self): 126 substrate = pem.readBase64fromText(self.pem_text) 127 asn1Object, rest = der_decode(substrate, asn1Spec=self.asn1Spec) 128 assert not rest 129 assert asn1Object.prettyPrint() 130 assert der_encode(asn1Object) == substrate 131 132 openTypesMap = { 133 rfc2985.pkcs_9_at_smimeCapabilities: rfc2985.SMIMECapabilities(), 134 } 135 openTypesMap.update(rfc5280.certificateAttributesMap) 136 openTypesMap.update(rfc5652.cmsAttributesMap) 137 138 for attr in asn1Object: 139 assert attr['type'] in openTypesMap.keys() 140 av, rest = der_decode(attr['values'][0], 141 asn1Spec=openTypesMap[attr['type']]) 142 assert not rest 143 assert av.prettyPrint() 144 assert der_encode(av) == attr['values'][0] 145 146 if attr['type'] == rfc2985.pkcs_9_at_userPKCS12: 147 assert av['version'] == univ.Integer(3) 148 assert av['authSafe']['contentType'] == rfc5652.id_data 149 outdata, rest = der_decode(av['authSafe']['content'], 150 asn1Spec=univ.OctetString()) 151 assert not rest 152 authsafe, rest = der_decode(outdata, 153 asn1Spec=rfc7292.AuthenticatedSafe()) 154 assert not rest 155 156 for ci in authsafe: 157 assert ci['contentType'] == rfc5652.id_data 158 indata, rest = der_decode(ci['content'], 159 asn1Spec=univ.OctetString()) 160 assert not rest 161 sc, rest = der_decode(indata, 162 asn1Spec=rfc7292.SafeContents()) 163 assert not rest 164 165 for sb in sc: 166 if sb['bagId'] in rfc7292.pkcs12BagTypeMap: 167 bv, rest = der_decode(sb['bagValue'], 168 asn1Spec=rfc7292.pkcs12BagTypeMap[sb['bagId']]) 169 assert not rest 170 171 for bagattr in sb['bagAttributes']: 172 if bagattr['attrType'] in openTypesMap: 173 inav, rest = der_decode(bagattr['attrValues'][0], 174 asn1Spec=openTypesMap[bagattr['attrType']]) 175 assert not rest 176 177 if bagattr['attrType'] == rfc2985.pkcs_9_at_friendlyName: 178 assert inav == "3f71af65-1687-444a-9f46-c8be194c3e8e" 179 180 if bagattr['attrType'] == rfc2985.pkcs_9_at_localKeyId: 181 assert inav == univ.OctetString(hexValue='01000000') 182 183 if attr['type'] == rfc2985.pkcs_9_at_pkcs7PDU: 184 ci, rest = der_decode(attr['values'][0], 185 asn1Spec=rfc5652.ContentInfo()) 186 assert not rest 187 assert ci['contentType'] == rfc5652.id_signedData 188 189 sd, rest = der_decode(ci['content'], 190 asn1Spec=rfc5652.SignedData()) 191 assert not rest 192 assert sd['version'] == 1 193 194 for si in sd['signerInfos']: 195 assert si['version'] == 1 196 197 for siattr in si['signedAttrs']: 198 if siattr['attrType'] in openTypesMap: 199 siav, rest = der_decode(siattr['attrValues'][0], 200 asn1Spec=openTypesMap[siattr['attrType']]) 201 assert not rest 202 203 if siattr['attrType'] == rfc2985.pkcs_9_at_contentType: 204 assert siav == rfc5652.id_data 205 206 if siattr['attrType'] == rfc2985.pkcs_9_at_messageDigest: 207 assert siav.prettyPrint()[2:10] == 'b6e422a4' 208 209 if siattr['attrType'] == rfc2985.pkcs_9_at_signingTime: 210 assert siav['utcTime'] == '190529182319Z' 211 212 for choices in sd['certificates']: 213 for rdn in choices[0]['tbsCertificate']['subject']['rdnSequence']: 214 if rdn[0]['type'] in openTypesMap: 215 nv, rest = der_decode(rdn[0]['value'], 216 asn1Spec=openTypesMap[rdn[0]['type']]) 217 assert not rest 218 219 if rdn[0]['type'] == rfc2985.pkcs_9_at_emailAddress: 220 assert nv == '[email protected]' 221 222 def testOpenTypes(self): 223 openTypesMap = { 224 rfc2985.pkcs_9_at_smimeCapabilities: rfc2985.SMIMECapabilities(), 225 } 226 openTypesMap.update(rfc5280.certificateAttributesMap) 227 openTypesMap.update(rfc5652.cmsAttributesMap) 228 229 substrate = pem.readBase64fromText(self.pem_text) 230 asn1Object, rest = der_decode(substrate, 231 asn1Spec=self.asn1Spec, 232 openTypes=openTypesMap, 233 decodeOpenTypes=True) 234 assert not rest 235 assert asn1Object.prettyPrint() 236 assert der_encode(asn1Object) == substrate 237 238 for attr in asn1Object: 239 assert attr['type'] in openTypesMap.keys() 240 241 if attr['type'] == rfc2985.pkcs_9_at_userPKCS12: 242 assert attr['values'][0]['version'] == univ.Integer(3) 243 assert attr['values'][0]['authSafe']['contentType'] == rfc5652.id_data 244 authsafe, rest = der_decode(attr['values'][0]['authSafe']['content'], 245 asn1Spec=rfc7292.AuthenticatedSafe()) 246 assert not rest 247 248 for ci in authsafe: 249 assert ci['contentType'] == rfc5652.id_data 250 indata, rest = der_decode(ci['content'], 251 asn1Spec=univ.OctetString()) 252 assert not rest 253 254 sc, rest = der_decode(indata, 255 asn1Spec=rfc7292.SafeContents(), 256 decodeOpenTypes=True) 257 assert not rest 258 259 for sb in sc: 260 if sb['bagId'] in rfc7292.pkcs12BagTypeMap: 261 for bagattr in sb['bagAttributes']: 262 if bagattr['attrType'] in openTypesMap: 263 264 if bagattr['attrType'] == rfc2985.pkcs_9_at_friendlyName: 265 assert bagattr['attrValues'][0] == "3f71af65-1687-444a-9f46-c8be194c3e8e" 266 267 if bagattr['attrType'] == rfc2985.pkcs_9_at_localKeyId: 268 assert bagattr['attrValues'][0] == univ.OctetString(hexValue='01000000') 269 270 if attr['type'] == rfc2985.pkcs_9_at_pkcs7PDU: 271 assert attr['values'][0]['contentType'] == rfc5652.id_signedData 272 assert attr['values'][0]['content']['version'] == 1 273 274 for si in attr['values'][0]['content']['signerInfos']: 275 assert si['version'] == 1 276 277 for siattr in si['signedAttrs']: 278 if siattr['attrType'] in openTypesMap: 279 280 if siattr['attrType'] == rfc2985.pkcs_9_at_contentType: 281 assert siattr['attrValues'][0] == rfc5652.id_data 282 283 if siattr['attrType'] == rfc2985.pkcs_9_at_messageDigest: 284 assert siattr['attrValues'][0].prettyPrint()[2:10] == 'b6e422a4' 285 286 if siattr['attrType'] == rfc2985.pkcs_9_at_signingTime: 287 assert siattr['attrValues'][0]['utcTime'] == '190529182319Z' 288 289 for choices in attr['values'][0]['content']['certificates']: 290 for rdn in choices[0]['tbsCertificate']['subject']['rdnSequence']: 291 if rdn[0]['type'] in openTypesMap: 292 if rdn[0]['type'] == rfc2985.pkcs_9_at_emailAddress: 293 assert rdn[0]['value'] == '[email protected]' 294 295 296suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) 297 298if __name__ == '__main__': 299 unittest.TextTestRunner(verbosity=2).run(suite) 300