• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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