1# coding: utf-8 2 3""" 4ASN.1 type classes for PKCS#12 files. Exports the following items: 5 6 - CertBag() 7 - CrlBag() 8 - Pfx() 9 - SafeBag() 10 - SecretBag() 11 12Other type classes are defined that help compose the types listed above. 13""" 14 15from __future__ import unicode_literals, division, absolute_import, print_function 16 17from .algos import DigestInfo 18from .cms import ContentInfo, SignedData 19from .core import ( 20 Any, 21 BMPString, 22 Integer, 23 ObjectIdentifier, 24 OctetString, 25 ParsableOctetString, 26 Sequence, 27 SequenceOf, 28 SetOf, 29) 30from .keys import PrivateKeyInfo, EncryptedPrivateKeyInfo 31from .x509 import Certificate, KeyPurposeId 32 33 34# The structures in this file are taken from https://tools.ietf.org/html/rfc7292 35 36class MacData(Sequence): 37 _fields = [ 38 ('mac', DigestInfo), 39 ('mac_salt', OctetString), 40 ('iterations', Integer, {'default': 1}), 41 ] 42 43 44class Version(Integer): 45 _map = { 46 3: 'v3' 47 } 48 49 50class AttributeType(ObjectIdentifier): 51 _map = { 52 # https://tools.ietf.org/html/rfc2985#page-18 53 '1.2.840.113549.1.9.20': 'friendly_name', 54 '1.2.840.113549.1.9.21': 'local_key_id', 55 # https://support.microsoft.com/en-us/kb/287547 56 '1.3.6.1.4.1.311.17.1': 'microsoft_local_machine_keyset', 57 # https://github.com/frohoff/jdk8u-dev-jdk/blob/master/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java 58 # this is a set of OIDs, representing key usage, the usual value is a SET of one element OID 2.5.29.37.0 59 '2.16.840.1.113894.746875.1.1': 'trusted_key_usage', 60 } 61 62 63class SetOfAny(SetOf): 64 _child_spec = Any 65 66 67class SetOfBMPString(SetOf): 68 _child_spec = BMPString 69 70 71class SetOfOctetString(SetOf): 72 _child_spec = OctetString 73 74 75class SetOfKeyPurposeId(SetOf): 76 _child_spec = KeyPurposeId 77 78 79class Attribute(Sequence): 80 _fields = [ 81 ('type', AttributeType), 82 ('values', None), 83 ] 84 85 _oid_specs = { 86 'friendly_name': SetOfBMPString, 87 'local_key_id': SetOfOctetString, 88 'microsoft_csp_name': SetOfBMPString, 89 'trusted_key_usage': SetOfKeyPurposeId, 90 } 91 92 def _values_spec(self): 93 return self._oid_specs.get(self['type'].native, SetOfAny) 94 95 _spec_callbacks = { 96 'values': _values_spec 97 } 98 99 100class Attributes(SetOf): 101 _child_spec = Attribute 102 103 104class Pfx(Sequence): 105 _fields = [ 106 ('version', Version), 107 ('auth_safe', ContentInfo), 108 ('mac_data', MacData, {'optional': True}) 109 ] 110 111 _authenticated_safe = None 112 113 @property 114 def authenticated_safe(self): 115 if self._authenticated_safe is None: 116 content = self['auth_safe']['content'] 117 if isinstance(content, SignedData): 118 content = content['content_info']['content'] 119 self._authenticated_safe = AuthenticatedSafe.load(content.native) 120 return self._authenticated_safe 121 122 123class AuthenticatedSafe(SequenceOf): 124 _child_spec = ContentInfo 125 126 127class BagId(ObjectIdentifier): 128 _map = { 129 '1.2.840.113549.1.12.10.1.1': 'key_bag', 130 '1.2.840.113549.1.12.10.1.2': 'pkcs8_shrouded_key_bag', 131 '1.2.840.113549.1.12.10.1.3': 'cert_bag', 132 '1.2.840.113549.1.12.10.1.4': 'crl_bag', 133 '1.2.840.113549.1.12.10.1.5': 'secret_bag', 134 '1.2.840.113549.1.12.10.1.6': 'safe_contents', 135 } 136 137 138class CertId(ObjectIdentifier): 139 _map = { 140 '1.2.840.113549.1.9.22.1': 'x509', 141 '1.2.840.113549.1.9.22.2': 'sdsi', 142 } 143 144 145class CertBag(Sequence): 146 _fields = [ 147 ('cert_id', CertId), 148 ('cert_value', ParsableOctetString, {'explicit': 0}), 149 ] 150 151 _oid_pair = ('cert_id', 'cert_value') 152 _oid_specs = { 153 'x509': Certificate, 154 } 155 156 157class CrlBag(Sequence): 158 _fields = [ 159 ('crl_id', ObjectIdentifier), 160 ('crl_value', OctetString, {'explicit': 0}), 161 ] 162 163 164class SecretBag(Sequence): 165 _fields = [ 166 ('secret_type_id', ObjectIdentifier), 167 ('secret_value', OctetString, {'explicit': 0}), 168 ] 169 170 171class SafeContents(SequenceOf): 172 pass 173 174 175class SafeBag(Sequence): 176 _fields = [ 177 ('bag_id', BagId), 178 ('bag_value', Any, {'explicit': 0}), 179 ('bag_attributes', Attributes, {'optional': True}), 180 ] 181 182 _oid_pair = ('bag_id', 'bag_value') 183 _oid_specs = { 184 'key_bag': PrivateKeyInfo, 185 'pkcs8_shrouded_key_bag': EncryptedPrivateKeyInfo, 186 'cert_bag': CertBag, 187 'crl_bag': CrlBag, 188 'secret_bag': SecretBag, 189 'safe_contents': SafeContents 190 } 191 192 193SafeContents._child_spec = SafeBag 194