blob: 951e19f56d5e78c65086824c3f752d61a9db1fd8 [file] [log] [blame]
wbonde91513e2015-06-03 14:52:18 -04001# coding: utf-8
wbondea25fc22015-06-19 15:07:04 -04002
3"""
4ASN.1 type classes for X509 certificates. Exports the following items:
5
6 - Attributes()
7 - Certificate()
8 - Extensions()
9 - GeneralName()
10 - GeneralNames()
11 - Name()
12
13Also adds TimeStampedData() support to asn1crypto.cms.ContentInfo(),
14TimeStampedData() and TSTInfo() support to
15asn1crypto.cms.EncapsulatedContentInfo() and some oids and value parsers to
16asn1crypto.cms.CMSAttribute().
17
18Other type classes are defined that help compose the types listed above.
19"""
20
wbond6b66ab52015-06-21 10:26:45 -040021from __future__ import unicode_literals, division, absolute_import, print_function
wbonde91513e2015-06-03 14:52:18 -040022
23from collections import OrderedDict
24
25from .core import (
26 Any,
27 BitString,
28 BMPString,
29 Boolean,
30 Choice,
31 GeneralizedTime,
32 GeneralString,
33 IA5String,
34 Integer,
35 Null,
36 NumericString,
37 ObjectIdentifier,
38 OctetBitString,
39 OctetString,
40 PrintableString,
41 Sequence,
42 SequenceOf,
43 Set,
44 SetOf,
45 TeletexString,
46 UniversalString,
47 UTCTime,
48 UTF8String,
49 VisibleString,
50)
51from .algos import SignedDigestAlgorithm
52from .keys import PublicKeyInfo
53
54
55# The structures in this file are taken from https://tools.ietf.org/html/rfc5280
56# and a few other supplementary sources, mostly due to extra supported
57# extension and name OIDs
58
59class Attribute(Sequence):
60 _fields = [
61 ('type', ObjectIdentifier),
62 ('values', SetOf, {'spec': Any}),
63 ]
64
65
66class Attributes(SequenceOf):
67 _child_spec = Attribute
68
69
70class KeyUsage(BitString):
71 _map = {
72 0: 'digital_signature',
73 1: 'non_repudiation',
74 2: 'key_encipherment',
75 3: 'data_encipherment',
76 4: 'key_agreement',
77 5: 'key_cert_sign',
78 6: 'crl_sign',
79 7: 'encipher_only',
80 8: 'decipher_only',
81 }
82
83
84class PrivateKeyUsagePeriod(Sequence):
85 _fields = [
86 ('not_before', GeneralizedTime, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
87 ('not_after', GeneralizedTime, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
88 ]
89
90
91class DirectoryString(Choice):
92 _alternatives = [
93 ('teletex_string', TeletexString),
94 ('printable_string', PrintableString),
95 ('universal_string', UniversalString),
96 ('utf8_string', UTF8String),
97 ('bmp_string', BMPString),
98 ]
99
100
101class NameType(ObjectIdentifier):
102 _map = {
103 '2.5.4.3': 'common_name',
104 '2.5.4.4': 'surname',
105 '2.5.4.5': 'serial_number',
106 '2.5.4.6': 'country_name',
107 '2.5.4.7': 'locality_name',
108 '2.5.4.8': 'state_or_province_name',
109 '2.5.4.10': 'organization_name',
110 '2.5.4.11': 'organizational_unit_name',
111 '2.5.4.12': 'title',
112 '2.5.4.41': 'name',
113 '2.5.4.42': 'given_name',
114 '2.5.4.43': 'initials',
115 '2.5.4.44': 'generation_qualifier',
116 '2.5.4.46': 'dn_qualifier',
117 # https://tools.ietf.org/html/rfc2985#page-26
118 '1.2.840.113549.1.9.1': 'email_address',
119 # Page 10 of https://cabforum.org/wp-content/uploads/EV-V1_5_5.pdf
120 '1.3.6.1.4.1.311.60.2.1.1': 'incorporation_locality',
121 '1.3.6.1.4.1.311.60.2.1.2': 'incorporation_state_or_province',
122 '1.3.6.1.4.1.311.60.2.1.3': 'incorporation_country',
123 }
124
125
126class NameTypeAndValue(Sequence):
127 _fields = [
128 ('type', NameType),
129 ('value', Any),
130 ]
131
132 _oid_pair = ('type', 'value')
133 _oid_specs = {
134 'common_name': DirectoryString,
135 'surname': DirectoryString,
wbond25e96a92015-07-01 09:23:12 -0400136 'serial_number': DirectoryString,
137 'country_name': DirectoryString,
wbonde91513e2015-06-03 14:52:18 -0400138 'locality_name': DirectoryString,
139 'state_or_province_name': DirectoryString,
140 'organization_name': DirectoryString,
141 'organizational_unit_name': DirectoryString,
142 'title': DirectoryString,
143 'name': DirectoryString,
144 'given_name': DirectoryString,
145 'initials': DirectoryString,
146 'generation_qualifier': DirectoryString,
wbond25e96a92015-07-01 09:23:12 -0400147 'dn_qualifier': DirectoryString,
wbonde91513e2015-06-03 14:52:18 -0400148 # https://tools.ietf.org/html/rfc2985#page-26
149 'email_address': IA5String,
150 # Page 10 of https://cabforum.org/wp-content/uploads/EV-V1_5_5.pdf
151 'incorporation_locality': DirectoryString,
152 'incorporation_state_or_province': DirectoryString,
wbond25e96a92015-07-01 09:23:12 -0400153 'incorporation_country': DirectoryString,
wbonde91513e2015-06-03 14:52:18 -0400154 }
155
156
157class RelativeDistinguishedName(SetOf):
158 _child_spec = NameTypeAndValue
159
160
161class RDNSequence(SequenceOf):
162 _child_spec = RelativeDistinguishedName
163
164
165class Name(Choice):
166 _alternatives = [
167 ('', RDNSequence),
168 ]
169
170 @property
171 def native(self):
172 if self.contents is None:
173 return None
174 if self._native is None:
175 self._native = OrderedDict()
176 for rdn in self.chosen.native:
177 for type_val in rdn:
178 type_val_type = type_val['type']
179 if type_val_type in self._native:
180 self._native[type_val_type] = [self._native[type_val_type]]
181 self._native[type_val_type].append(type_val['value'])
182 else:
183 self._native[type_val_type] = type_val['value']
184 return self._native
185
186
187class AnotherName(Sequence):
188 _fields = [
189 ('type_id', ObjectIdentifier),
190 ('value', Any, {'tag_type': 'explicit', 'tag': 0}),
191 ]
192
193
194class CountryName(Choice):
195 class_ = 1
196 tag = 1
197
198 _alternatives = [
199 ('x121_dcc_code', NumericString),
200 ('iso_3166_alpha2_code', PrintableString),
201 ]
202
203
204class AdministrationDomainName(Choice):
205 class_ = 1
206 tag = 2
207
208 _alternatives = [
209 ('numeric', NumericString),
210 ('printable', PrintableString),
211 ]
212
213
214class PrivateDomainName(Choice):
215 _alternatives = [
216 ('numeric', NumericString),
217 ('printable', PrintableString),
218 ]
219
220
221class PersonalName(Set):
222 _fields = [
223 ('surname', PrintableString, {'tag_type': 'implicit', 'tag': 0}),
224 ('given_name', PrintableString, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
225 ('initials', PrintableString, {'tag_type': 'implicit', 'tag': 2, 'optional': True}),
226 ('generation_qualifier', PrintableString, {'tag_type': 'implicit', 'tag': 3, 'optional': True}),
227 ]
228
229
230class TeletexPersonalName(Set):
231 _fields = [
232 ('surname', TeletexString, {'tag_type': 'implicit', 'tag': 0}),
233 ('given_name', TeletexString, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
234 ('initials', TeletexString, {'tag_type': 'implicit', 'tag': 2, 'optional': True}),
235 ('generation_qualifier', TeletexString, {'tag_type': 'implicit', 'tag': 3, 'optional': True}),
236 ]
237
238
239class OrganizationalUnitNames(SequenceOf):
240 _child_spec = PrintableString
241
242
243class TeletexOrganizationalUnitNames(SequenceOf):
244 _child_spec = TeletexString
245
246
247class BuiltInStandardAttributes(Sequence):
248 _fields = [
249 ('country_name', CountryName, {'optional': True}),
250 ('administration_domain_name', AdministrationDomainName, {'optional': True}),
251 ('network_address', NumericString, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
252 ('terminal_identifier', PrintableString, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
253 ('private_domain_name', PrivateDomainName, {'tag_type': 'explicit', 'tag': 2, 'optional': True}),
254 ('organization_name', PrintableString, {'tag_type': 'implicit', 'tag': 3, 'optional': True}),
255 ('numeric_user_identifier', NumericString, {'tag_type': 'implicit', 'tag': 4, 'optional': True}),
256 ('personal_name', PersonalName, {'tag_type': 'implicit', 'tag': 5, 'optional': True}),
257 ('organizational_unit_names', OrganizationalUnitNames, {'tag_type': 'implicit', 'tag': 6, 'optional': True}),
258 ]
259
260
261class BuiltInDomainDefinedAttribute(Sequence):
262 _fields = [
263 ('type', PrintableString),
264 ('value', PrintableString),
265 ]
266
267
268class BuiltInDomainDefinedAttributes(SequenceOf):
269 _child_spec = BuiltInDomainDefinedAttribute
270
271
272class TeletexDomainDefinedAttribute(Sequence):
273 _fields = [
274 ('type', TeletexString),
275 ('value', TeletexString),
276 ]
277
278
279class TeletexDomainDefinedAttributes(SequenceOf):
280 _child_spec = TeletexDomainDefinedAttribute
281
282
283class PhysicalDeliveryCountryName(Choice):
284 _alternatives = [
285 ('x121_dcc_code', NumericString),
286 ('iso_3166_alpha2_code', PrintableString),
287 ]
288
289
290class PostalCode(Choice):
291 _alternatives = [
292 ('numeric_code', NumericString),
293 ('printable_code', PrintableString),
294 ]
295
296
297class PDSParameter(Set):
298 _fields = [
299 ('printable_string', PrintableString, {'optional': True}),
300 ('teletex_string', TeletexString, {'optional': True}),
301 ]
302
303
304class PrintableAddress(SequenceOf):
305 _child_spec = PrintableString
306
307
308class UnformattedPostalAddress(Set):
309 _fields = [
310 ('printable_address', PrintableAddress, {'optional': True}),
311 ('teletex_string', TeletexString, {'optional': True}),
312 ]
313
314
315class E1634Address(Sequence):
316 _fields = [
317 ('number', NumericString, {'tag_type': 'implicit', 'tag': 0}),
318 ('sub_address', NumericString, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
319 ]
320
321
322class NAddresses(SetOf):
323 _child_spec = OctetString
324
325
326class PresentationAddress(Sequence):
327 _fields = [
328 ('p_selector', OctetString, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
329 ('s_selector', OctetString, {'tag_type': 'explicit', 'tag': 1, 'optional': True}),
330 ('t_selector', OctetString, {'tag_type': 'explicit', 'tag': 2, 'optional': True}),
331 ('n_addresses', NAddresses, {'tag_type': 'explicit', 'tag': 3}),
332 ]
333
334
335class ExtendedNetworkAddress(Choice):
336 _alternatives = [
337 ('e163_4_address', E1634Address),
338 ('psap_address', PresentationAddress, {'tag_type': 'implicit', 'tag': 0})
339 ]
340
341
342class TerminalType(Integer):
343 _map = {
344 3: 'telex',
345 4: 'teletex',
346 5: 'g3_facsimile',
347 6: 'g4_facsimile',
348 7: 'ia5_terminal',
349 8: 'videotex',
350 }
351
352
353class ExtensionAttributeType(Integer):
354 _map = {
355 1: 'common_name',
356 2: 'teletex_common_name',
357 3: 'teletex_organization_name',
358 4: 'teletex_personal_name',
359 5: 'teletex_organization_unit_names',
360 6: 'teletex_domain_defined_attributes',
361 7: 'pds_name',
362 8: 'physical_delivery_country_name',
363 9: 'postal_code',
364 10: 'physical_delivery_office_name',
365 11: 'physical_delivery_office_number',
366 12: 'extension_of_address_components',
367 13: 'physical_delivery_personal_name',
368 14: 'physical_delivery_organization_name',
369 15: 'extension_physical_delivery_address_components',
370 16: 'unformatted_postal_address',
371 17: 'street_address',
372 18: 'post_office_box_address',
373 19: 'poste_restante_address',
374 20: 'unique_postal_name',
375 21: 'local_postal_attributes',
376 22: 'extended_network_address',
377 23: 'terminal_type',
378 }
379
380
381class ExtensionAttribute(Sequence):
382 _fields = [
383 ('extension_attribute_type', ExtensionAttributeType, {'tag_type': 'implicit', 'tag': 0}),
384 ('extension_attribute_value', Any, {'tag_type': 'explicit', 'tag': 1}),
385 ]
386
387 _oid_pair = ('extension_attribute_type', 'extension_attribute_value')
388 _oid_specs = {
389 'common_name': PrintableString,
390 'teletex_common_name': TeletexString,
391 'teletex_organization_name': TeletexString,
392 'teletex_personal_name': TeletexPersonalName,
393 'teletex_organization_unit_names': TeletexOrganizationalUnitNames,
394 'teletex_domain_defined_attributes': TeletexDomainDefinedAttributes,
395 'pds_name': PrintableString,
396 'physical_delivery_country_name': PhysicalDeliveryCountryName,
397 'postal_code': PostalCode,
398 'physical_delivery_office_name': PDSParameter,
399 'physical_delivery_office_number': PDSParameter,
400 'extension_of_address_components': PDSParameter,
401 'physical_delivery_personal_name': PDSParameter,
402 'physical_delivery_organization_name': PDSParameter,
403 'extension_physical_delivery_address_components': PDSParameter,
404 'unformatted_postal_address': UnformattedPostalAddress,
405 'street_address': PDSParameter,
406 'post_office_box_address': PDSParameter,
407 'poste_restante_address': PDSParameter,
408 'unique_postal_name': PDSParameter,
409 'local_postal_attributes': PDSParameter,
410 'extended_network_address': ExtendedNetworkAddress,
411 'terminal_type': TerminalType,
412 }
413
414
415class ExtensionAttributes(SequenceOf):
416 _child_spec = ExtensionAttribute
417
418
419class ORAddress(Sequence):
420 _fields = [
421 ('built_in_standard_attributes', BuiltInStandardAttributes),
422 ('built_in_domain_defined_attributes', BuiltInDomainDefinedAttributes, {'optional': True}),
423 ('extension_attributes', ExtensionAttributes, {'optional': True}),
424 ]
425
426
427class EDIPartyName(Sequence):
428 _fields = [
429 ('name_assigner', DirectoryString, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
430 ('party_name', DirectoryString, {'tag_type': 'implicit', 'tag': 1}),
431 ]
432
433
434class GeneralName(Choice):
435 _alternatives = [
436 ('other_name', AnotherName, {'tag_type': 'implicit', 'tag': 0}),
437 ('rfc822_name', IA5String, {'tag_type': 'implicit', 'tag': 1}),
438 ('dns_name', IA5String, {'tag_type': 'implicit', 'tag': 2}),
439 ('x400_address', ORAddress, {'tag_type': 'implicit', 'tag': 3}),
440 ('directory_name', Name, {'tag_type': 'explicit', 'tag': 4}),
441 ('edi_party_name', EDIPartyName, {'tag_type': 'implicit', 'tag': 5}),
442 ('uniform_resource_identifier', IA5String, {'tag_type': 'implicit', 'tag': 6}),
443 ('ip_address', OctetString, {'tag_type': 'implicit', 'tag': 7}),
444 ('registered_id', ObjectIdentifier, {'tag_type': 'implicit', 'tag': 8}),
445 ]
446
447
448class GeneralNames(SequenceOf):
449 _child_spec = GeneralName
450
451
452class Time(Choice):
453 _alternatives = [
454 ('utc_time', UTCTime),
455 ('general_time', GeneralizedTime),
456 ]
457
458
459class Validity(Sequence):
460 _fields = [
461 ('not_before', Time),
462 ('not_after', Time),
463 ]
464
465
466class BasicConstraints(Sequence):
467 _fields = [
468 ('ca', Boolean, {'default': False}),
469 ('path_len_constraint', Integer, {'optional': True}),
470 ]
471
472
473class AuthorityKeyIdentifier(Sequence):
474 _fields = [
475 ('key_identifier', OctetString, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
476 ('authority_cert_issuer', GeneralNames, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
477 ('authority_cert_serial_number', Integer, {'tag_type': 'implicit', 'tag': 2, 'optional': True}),
478 ]
479
480
481class DistributionPointName(Choice):
482 _alternatives = [
483 ('full_name', GeneralNames, {'tag_type': 'implicit', 'tag': 0}),
484 ('name_relative_to_crl_issuer', RelativeDistinguishedName, {'tag_type': 'implicit', 'tag': 1}),
485 ]
486
487
488class ReasonFlags(BitString):
489 _map = {
490 0: 'unused',
491 1: 'key_compromise',
492 2: 'ca_compromise',
493 3: 'affiliation_changed',
494 4: 'superseded',
495 5: 'cessation_of_operation',
496 6: 'certificate_hold',
497 7: 'privilege_withdrawn',
498 8: 'aa_compromise',
499 }
500
501
502class GeneralSubtree(Sequence):
503 _fields = [
504 ('base', GeneralName),
505 ('minimum', Integer, {'tag_type': 'implicit', 'tag': 0, 'default': 0}),
506 ('maximum', Integer, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
507 ]
508
509
510class GeneralSubtrees(SequenceOf):
511 _child_spec = GeneralSubtree
512
513
514class NameConstraints(Sequence):
515 _fields = [
516 ('permitted_subtrees', GeneralSubtrees, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
517 ('excluded_subtrees', GeneralSubtrees, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
518 ]
519
520
521class DistributionPoint(Sequence):
522 _fields = [
523 ('distribution_point', DistributionPointName, {'tag_type': 'explicit', 'tag': 0, 'optional': True}),
524 ('reasons', ReasonFlags, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
525 ('crl_issuer', GeneralNames, {'tag_type': 'implicit', 'tag': 2, 'optional': True}),
526 ]
527
528
529class CRLDistributionPoints(SequenceOf):
530 _child_spec = DistributionPoint
531
532
533class DisplayText(Choice):
534 _alternatives = [
535 ('ia5_string', IA5String),
536 ('visible_string', VisibleString),
537 ('bmp_string', BMPString),
538 ('utf8_string', UTF8String),
539 ]
540
541
542class NoticeNumbers(SequenceOf):
543 _child_spec = Integer
544
545
546class NoticeReference(Sequence):
547 _fields = [
548 ('organization', DisplayText),
549 ('notice_numbers', NoticeNumbers),
550 ]
551
552
553class UserNotice(Sequence):
554 _fields = [
555 ('notice_ref', NoticeReference, {'optional': True}),
556 ('explicit_text', DisplayText, {'optional': True}),
557 ]
558
559
560class PolicyQualifierId(ObjectIdentifier):
561 _map = {
562 '1.3.6.1.5.5.7.2.1': 'certification_practice_statement',
563 '1.3.6.1.5.5.7.2.2': 'user_notice',
564 }
565
566
567class PolicyQualifierInfo(Sequence):
568 _fields = [
569 ('policy_qualifier_id', PolicyQualifierId),
570 ('qualifier', Any),
571 ]
572
573 _oid_pair = ('policy_qualifier_id', 'qualifier')
574 _oid_specs = {
575 'certification_practice_statement': IA5String,
576 'user_notice': UserNotice,
577 }
578
579
580class PolicyQualifierInfos(SequenceOf):
581 _child_spec = PolicyQualifierInfo
582
583
wbond8bb77d02015-07-13 17:44:29 -0400584class PolicyIdentifier(ObjectIdentifier):
585 _map = {
586 '2.5.29.32.0': 'any_policy',
587 }
588
589
wbonde91513e2015-06-03 14:52:18 -0400590class PolicyInformation(Sequence):
591 _fields = [
wbond8bb77d02015-07-13 17:44:29 -0400592 ('policy_identifier', PolicyIdentifier),
wbonde91513e2015-06-03 14:52:18 -0400593 ('policy_qualifiers', PolicyQualifierInfos, {'optional': True})
594 ]
595
596
597class CertificatePolicies(SequenceOf):
598 _child_spec = PolicyInformation
599
600
601class PolicyMapping(Sequence):
602 _fields = [
603 ('issuer_domain_policy', ObjectIdentifier),
604 ('subject_domain_policy', ObjectIdentifier),
605 ]
606
607
608class PolicyMappings(SequenceOf):
609 _child_spec = PolicyMapping
610
611
612class PolicyConstraints(Sequence):
613 _fields = [
614 ('require_explicit_policy', Integer, {'tag_type': 'implicit', 'tag': 0, 'optional': True}),
615 ('inhibit_policy_mapping', Integer, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
616 ]
617
618
619class KeyPurposeId(ObjectIdentifier):
620 _map = {
621 '1.3.6.1.5.5.7.3.1': 'server_auth',
622 '1.3.6.1.5.5.7.3.2': 'client_auth',
623 '1.3.6.1.5.5.7.3.3': 'code_signing',
624 '1.3.6.1.5.5.7.3.4': 'email_protection',
625 '1.3.6.1.5.5.7.3.5': 'ipsec_end_system',
626 '1.3.6.1.5.5.7.3.6': 'ipsec_tunnel',
627 '1.3.6.1.5.5.7.3.7': 'ipsec_user',
628 '1.3.6.1.5.5.7.3.8': 'time_stamping',
629 '1.3.6.1.5.5.7.3.9': 'ocsp_signing',
630 '1.3.6.1.5.5.7.3.19': 'wireless_access_points',
631 }
632
633
634class ExtKeyUsageSyntax(SequenceOf):
635 _child_spec = KeyPurposeId
636
637
wbonda0d45482015-07-13 22:10:20 -0400638class AccessMethod(ObjectIdentifier):
639 _map = {
640 '1.3.6.1.5.5.7.48.1': 'ocsp',
641 '1.3.6.1.5.5.7.48.2': 'ca_issuers',
642 }
643
644
645class AccessDescription(Sequence):
646 _fields = [
647 ('access_method', AccessMethod),
648 ('access_location', GeneralName),
649 ]
650
651
652class AuthorityInfoAccessSyntax(SequenceOf):
653 _child_spec = AccessDescription
654
655
wbonde91513e2015-06-03 14:52:18 -0400656class EntrustVersionInfo(Sequence):
657 _fields = [
658 ('entrust_vers', GeneralString),
659 ('entrust_info_flags', BitString)
660 ]
661
662
663class NetscapeCertificateType(BitString):
664 _map = {
665 0: 'ssl_client',
666 1: 'ssl_server',
667 2: 'email',
668 3: 'object_signing',
669 4: 'reserved',
670 5: 'ssl_ca',
671 6: 'email_ca',
672 7: 'object_signing_ca',
673 }
674
675
676class ExtensionId(ObjectIdentifier):
677 _map = {
678 '2.5.29.9': 'subject_directory_attributes',
679 '2.5.29.14': 'key_identifier',
680 '2.5.29.15': 'key_usage',
681 '2.5.29.16': 'private_key_usage_period',
682 '2.5.29.17': 'subject_alt_name',
683 '2.5.29.19': 'basic_constraints',
684 '2.5.29.23': 'hold_instruction_code',
685 '2.5.29.30': 'name_constraints',
686 '2.5.29.31': 'crl_distribution_points',
687 '2.5.29.32': 'certificate_policies',
688 '2.5.29.33': 'policy_mappings',
689 '2.5.29.35': 'authority_key_identifier',
690 '2.5.29.36': 'policy_constraints',
691 '2.5.29.37': 'extended_key_usage',
wbonda43b3fb2015-07-13 17:52:25 -0400692 '2.5.29.54': 'inhibit_any_policy',
wbonda0d45482015-07-13 22:10:20 -0400693 '1.3.6.1.5.5.7.1.1': 'authority_information_access',
wbonde91513e2015-06-03 14:52:18 -0400694 '1.3.6.1.5.5.7.48.1.5': 'ocsp_no_check',
695 '1.2.840.113533.7.65.0': 'entrust_version_extension',
696 '2.16.840.1.113730.1.1': 'netscape_certificate_type',
697 }
698
699
700class Extension(Sequence):
701 _fields = [
702 ('extn_id', ExtensionId),
703 ('critical', Boolean, {'default': False}),
704 ('extn_value', OctetString),
705 ]
706
707 _oid_pair = ('extn_id', 'extn_value')
708 _oid_specs = {
709 'subject_directory_attributes': Attributes,
710 'key_identifier': OctetString,
711 'key_usage': KeyUsage,
712 'private_key_usage_period': PrivateKeyUsagePeriod,
713 'subject_alt_name': GeneralNames,
714 'basic_constraints': BasicConstraints,
715 'hold_instruction_code': ObjectIdentifier,
716 'name_constraints': NameConstraints,
717 'crl_distribution_points': CRLDistributionPoints,
718 'certificate_policies': CertificatePolicies,
719 'policy_mappings': PolicyMappings,
720 'authority_key_identifier': AuthorityKeyIdentifier,
721 'policy_constraints': PolicyConstraints,
722 'extended_key_usage': ExtKeyUsageSyntax,
wbonda43b3fb2015-07-13 17:52:25 -0400723 'inhibit_any_policy': Integer,
wbonda0d45482015-07-13 22:10:20 -0400724 'authority_information_access': AuthorityInfoAccessSyntax,
wbonde91513e2015-06-03 14:52:18 -0400725 'ocsp_no_check': Null,
726 'entrust_version_extension': EntrustVersionInfo,
727 'netscape_certificate_type': NetscapeCertificateType,
728 }
729
730
731class Extensions(SequenceOf):
732 _child_spec = Extension
733
734
735class Version(Integer):
736 _map = {
737 0: 'v1',
738 1: 'v2',
739 2: 'v3',
740 }
741
742
743class TbsCertificate(Sequence):
744 _fields = [
745 ('version', Version, {'tag_type': 'explicit', 'tag': 0, 'default': 'v1'}),
746 ('serial_number', Integer),
747 ('signature', SignedDigestAlgorithm),
748 ('issuer', Name),
749 ('validity', Validity),
750 ('subject', Name),
751 ('subject_public_key_info', PublicKeyInfo),
752 ('issuer_unique_id', OctetBitString, {'tag_type': 'implicit', 'tag': 1, 'optional': True}),
753 ('subject_unique_id', OctetBitString, {'tag_type': 'implicit', 'tag': 2, 'optional': True}),
754 ('extensions', Extensions, {'tag_type': 'explicit', 'tag': 3, 'optional': True}),
755 ]
756
757
758class Certificate(Sequence):
759 _fields = [
760 ('tbs_certificate', TbsCertificate),
761 ('signature_algorithm', SignedDigestAlgorithm),
762 ('signature_value', OctetBitString),
763 ]
wbond8bb77d02015-07-13 17:44:29 -0400764
765 _processed_extensions = False
766 _critical_extensions = None
767 _key_identifier_value = None
768 _key_usage_value = None
769 _subject_alt_name_value = None
770 _basic_constraints_value = None
771 _name_constraints_value = None
772 _crl_distribution_points_value = None
773 _certificate_policies_value = None
774 _policy_mappings_value = None
775 _authority_key_identifier_value = None
776 _policy_constraints_value = None
777 _extended_key_usage_value = None
wbond08c60fa2015-07-13 23:02:13 -0400778 _authority_information_access_value = None
wbond8bb77d02015-07-13 17:44:29 -0400779 _ocsp_no_check_value = None
780
781 def _set_extensions(self):
782 """
783 Sets common named extensions to private attributes and creates a list
784 of critical extensions
785 """
786
787 self._critical_extensions = []
788
789 for extension in self['tbs_certificate']['extensions']:
790 name = extension['extn_id'].native
791 attribute_name = '_%s_value' % name
792 if hasattr(self, attribute_name):
793 setattr(self, attribute_name, extension['extn_value'].parsed)
794 if extension['critical'].native:
795 self._critical_extensions.append(name)
796
797 self._processed_extensions = True
798
799 @property
800 def critical_extensions(self):
801 """
802 Returns a list of the names (or OID if not a known extension) of the
803 extensions marked as critical
804
805 :return:
806 A list of unicode strings
807 """
808
809 if not self._processed_extensions:
810 self._set_extensions()
811 return self._critical_extensions
812
813 @property
814 def key_identifier_value(self):
815 """
816 :return:
817 None or the parsed value of the key identifier extension
818 """
819
820 if not self._processed_extensions:
821 self._set_extensions()
822 return self._key_identifier_value
823
824 @property
825 def key_usage_value(self):
826 """
827 :return:
828 None or the parsed value of the key usage extension
829 """
830
831 if not self._processed_extensions:
832 self._set_extensions()
833 return self._key_usage_value
834
835 @property
836 def subject_alt_name_value(self):
837 """
838 :return:
839 None or the parsed value of the subject alt name extension
840 """
841
842 if not self._processed_extensions:
843 self._set_extensions()
844 return self._subject_alt_name_value
845
846 @property
847 def basic_constraints_value(self):
848 """
849 :return:
850 None or the parsed value of the basic constraints extension
851 """
852
853 if not self._processed_extensions:
854 self._set_extensions()
855 return self._basic_constraints_value
856
857 @property
858 def name_constraints_value(self):
859 """
860 :return:
861 None or the parsed value of the name constraints extension
862 """
863
864 if not self._processed_extensions:
865 self._set_extensions()
866 return self._name_constraints_value
867
868 @property
869 def crl_distribution_points_value(self):
870 """
871 :return:
872 None or the parsed value of the CRL distribution points
873 extension
874 """
875
876 if not self._processed_extensions:
877 self._set_extensions()
878 return self._crl_distribution_points_value
879
880 @property
881 def certificate_policies_value(self):
882 """
883 :return:
884 None or the parsed value of the certificate policies extension
885 """
886
887 if not self._processed_extensions:
888 self._set_extensions()
889 return self._certificate_policies_value
890
891 @property
892 def policy_mappings_value(self):
893 """
894 :return:
895 None or the parsed value of the policy mappings extension
896 """
897
898 if not self._processed_extensions:
899 self._set_extensions()
900 return self._policy_mappings_value
901
902 @property
903 def authority_key_identifier_value(self):
904 """
905 :return:
906 None or the parsed value of the authority key identifier
907 extension
908 """
909
910 if not self._processed_extensions:
911 self._set_extensions()
912 return self._authority_key_identifier_value
913
914 @property
915 def policy_constraints_value(self):
916 """
917 :return:
918 None or the parsed value of the policy constraints extension
919 """
920
921 if not self._processed_extensions:
922 self._set_extensions()
923 return self._policy_constraints_value
924
925 @property
926 def extended_key_usage_value(self):
927 """
928 :return:
929 None or the parsed value of the extended key usage extension
930 """
931
932 if not self._processed_extensions:
933 self._set_extensions()
934 return self._extended_key_usage_value
935
936 @property
wbond08c60fa2015-07-13 23:02:13 -0400937 def authority_information_access_value(self):
938 """
939 :return:
940 None or the parsed value of the authority information access extension
941 """
942
943 if not self._processed_extensions:
944 self._set_extensions()
945 return self._authority_information_access_value
946
947 @property
wbond8bb77d02015-07-13 17:44:29 -0400948 def ocsp_no_check_value(self):
949 """
950 :return:
951 None or the parsed value of the OCSP no check extension
952 """
953
954 if not self._processed_extensions:
955 self._set_extensions()
956 return self._ocsp_no_check_value