You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3002 lines
90 KiB

4 years ago
  1. # coding: utf-8
  2. """
  3. ASN.1 type classes for X.509 certificates. Exports the following items:
  4. - Attributes()
  5. - Certificate()
  6. - Extensions()
  7. - GeneralName()
  8. - GeneralNames()
  9. - Name()
  10. Other type classes are defined that help compose the types listed above.
  11. """
  12. from __future__ import unicode_literals, division, absolute_import, print_function
  13. from contextlib import contextmanager
  14. from encodings import idna # noqa
  15. import hashlib
  16. import re
  17. import socket
  18. import stringprep
  19. import sys
  20. import unicodedata
  21. from ._errors import unwrap
  22. from ._iri import iri_to_uri, uri_to_iri
  23. from ._ordereddict import OrderedDict
  24. from ._types import type_name, str_cls, bytes_to_list
  25. from .algos import AlgorithmIdentifier, AnyAlgorithmIdentifier, DigestAlgorithm, SignedDigestAlgorithm
  26. from .core import (
  27. Any,
  28. BitString,
  29. BMPString,
  30. Boolean,
  31. Choice,
  32. Concat,
  33. Enumerated,
  34. GeneralizedTime,
  35. GeneralString,
  36. IA5String,
  37. Integer,
  38. Null,
  39. NumericString,
  40. ObjectIdentifier,
  41. OctetBitString,
  42. OctetString,
  43. ParsableOctetString,
  44. PrintableString,
  45. Sequence,
  46. SequenceOf,
  47. Set,
  48. SetOf,
  49. TeletexString,
  50. UniversalString,
  51. UTCTime,
  52. UTF8String,
  53. VisibleString,
  54. VOID,
  55. )
  56. from .keys import PublicKeyInfo
  57. from .util import int_to_bytes, int_from_bytes, inet_ntop, inet_pton
  58. # The structures in this file are taken from https://tools.ietf.org/html/rfc5280
  59. # and a few other supplementary sources, mostly due to extra supported
  60. # extension and name OIDs
  61. class DNSName(IA5String):
  62. _encoding = 'idna'
  63. _bad_tag = 19
  64. def __ne__(self, other):
  65. return not self == other
  66. def __eq__(self, other):
  67. """
  68. Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.2
  69. :param other:
  70. Another DNSName object
  71. :return:
  72. A boolean
  73. """
  74. if not isinstance(other, DNSName):
  75. return False
  76. return self.__unicode__().lower() == other.__unicode__().lower()
  77. def set(self, value):
  78. """
  79. Sets the value of the DNS name
  80. :param value:
  81. A unicode string
  82. """
  83. if not isinstance(value, str_cls):
  84. raise TypeError(unwrap(
  85. '''
  86. %s value must be a unicode string, not %s
  87. ''',
  88. type_name(self),
  89. type_name(value)
  90. ))
  91. if value.startswith('.'):
  92. encoded_value = b'.' + value[1:].encode(self._encoding)
  93. else:
  94. encoded_value = value.encode(self._encoding)
  95. self._unicode = value
  96. self.contents = encoded_value
  97. self._header = None
  98. if self._trailer != b'':
  99. self._trailer = b''
  100. class URI(IA5String):
  101. def set(self, value):
  102. """
  103. Sets the value of the string
  104. :param value:
  105. A unicode string
  106. """
  107. if not isinstance(value, str_cls):
  108. raise TypeError(unwrap(
  109. '''
  110. %s value must be a unicode string, not %s
  111. ''',
  112. type_name(self),
  113. type_name(value)
  114. ))
  115. self._unicode = value
  116. self.contents = iri_to_uri(value)
  117. self._header = None
  118. if self._trailer != b'':
  119. self._trailer = b''
  120. def __ne__(self, other):
  121. return not self == other
  122. def __eq__(self, other):
  123. """
  124. Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.4
  125. :param other:
  126. Another URI object
  127. :return:
  128. A boolean
  129. """
  130. if not isinstance(other, URI):
  131. return False
  132. return iri_to_uri(self.native) == iri_to_uri(other.native)
  133. def __unicode__(self):
  134. """
  135. :return:
  136. A unicode string
  137. """
  138. if self.contents is None:
  139. return ''
  140. if self._unicode is None:
  141. self._unicode = uri_to_iri(self._merge_chunks())
  142. return self._unicode
  143. class EmailAddress(IA5String):
  144. _contents = None
  145. # If the value has gone through the .set() method, thus normalizing it
  146. _normalized = False
  147. @property
  148. def contents(self):
  149. """
  150. :return:
  151. A byte string of the DER-encoded contents of the sequence
  152. """
  153. return self._contents
  154. @contents.setter
  155. def contents(self, value):
  156. """
  157. :param value:
  158. A byte string of the DER-encoded contents of the sequence
  159. """
  160. self._normalized = False
  161. self._contents = value
  162. def set(self, value):
  163. """
  164. Sets the value of the string
  165. :param value:
  166. A unicode string
  167. """
  168. if not isinstance(value, str_cls):
  169. raise TypeError(unwrap(
  170. '''
  171. %s value must be a unicode string, not %s
  172. ''',
  173. type_name(self),
  174. type_name(value)
  175. ))
  176. if value.find('@') != -1:
  177. mailbox, hostname = value.rsplit('@', 1)
  178. encoded_value = mailbox.encode('ascii') + b'@' + hostname.encode('idna')
  179. else:
  180. encoded_value = value.encode('ascii')
  181. self._normalized = True
  182. self._unicode = value
  183. self.contents = encoded_value
  184. self._header = None
  185. if self._trailer != b'':
  186. self._trailer = b''
  187. def __unicode__(self):
  188. """
  189. :return:
  190. A unicode string
  191. """
  192. if self._unicode is None:
  193. contents = self._merge_chunks()
  194. if contents.find(b'@') == -1:
  195. self._unicode = contents.decode('ascii')
  196. else:
  197. mailbox, hostname = contents.rsplit(b'@', 1)
  198. self._unicode = mailbox.decode('ascii') + '@' + hostname.decode('idna')
  199. return self._unicode
  200. def __ne__(self, other):
  201. return not self == other
  202. def __eq__(self, other):
  203. """
  204. Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.5
  205. :param other:
  206. Another EmailAddress object
  207. :return:
  208. A boolean
  209. """
  210. if not isinstance(other, EmailAddress):
  211. return False
  212. if not self._normalized:
  213. self.set(self.native)
  214. if not other._normalized:
  215. other.set(other.native)
  216. if self._contents.find(b'@') == -1 or other._contents.find(b'@') == -1:
  217. return self._contents == other._contents
  218. other_mailbox, other_hostname = other._contents.rsplit(b'@', 1)
  219. mailbox, hostname = self._contents.rsplit(b'@', 1)
  220. if mailbox != other_mailbox:
  221. return False
  222. if hostname.lower() != other_hostname.lower():
  223. return False
  224. return True
  225. class IPAddress(OctetString):
  226. def parse(self, spec=None, spec_params=None):
  227. """
  228. This method is not applicable to IP addresses
  229. """
  230. raise ValueError(unwrap(
  231. '''
  232. IP address values can not be parsed
  233. '''
  234. ))
  235. def set(self, value):
  236. """
  237. Sets the value of the object
  238. :param value:
  239. A unicode string containing an IPv4 address, IPv4 address with CIDR,
  240. an IPv6 address or IPv6 address with CIDR
  241. """
  242. if not isinstance(value, str_cls):
  243. raise TypeError(unwrap(
  244. '''
  245. %s value must be a unicode string, not %s
  246. ''',
  247. type_name(self),
  248. type_name(value)
  249. ))
  250. original_value = value
  251. has_cidr = value.find('/') != -1
  252. cidr = 0
  253. if has_cidr:
  254. parts = value.split('/', 1)
  255. value = parts[0]
  256. cidr = int(parts[1])
  257. if cidr < 0:
  258. raise ValueError(unwrap(
  259. '''
  260. %s value contains a CIDR range less than 0
  261. ''',
  262. type_name(self)
  263. ))
  264. if value.find(':') != -1:
  265. family = socket.AF_INET6
  266. if cidr > 128:
  267. raise ValueError(unwrap(
  268. '''
  269. %s value contains a CIDR range bigger than 128, the maximum
  270. value for an IPv6 address
  271. ''',
  272. type_name(self)
  273. ))
  274. cidr_size = 128
  275. else:
  276. family = socket.AF_INET
  277. if cidr > 32:
  278. raise ValueError(unwrap(
  279. '''
  280. %s value contains a CIDR range bigger than 32, the maximum
  281. value for an IPv4 address
  282. ''',
  283. type_name(self)
  284. ))
  285. cidr_size = 32
  286. cidr_bytes = b''
  287. if has_cidr:
  288. cidr_mask = '1' * cidr
  289. cidr_mask += '0' * (cidr_size - len(cidr_mask))
  290. cidr_bytes = int_to_bytes(int(cidr_mask, 2))
  291. cidr_bytes = (b'\x00' * ((cidr_size // 8) - len(cidr_bytes))) + cidr_bytes
  292. self._native = original_value
  293. self.contents = inet_pton(family, value) + cidr_bytes
  294. self._bytes = self.contents
  295. self._header = None
  296. if self._trailer != b'':
  297. self._trailer = b''
  298. @property
  299. def native(self):
  300. """
  301. The a native Python datatype representation of this value
  302. :return:
  303. A unicode string or None
  304. """
  305. if self.contents is None:
  306. return None
  307. if self._native is None:
  308. byte_string = self.__bytes__()
  309. byte_len = len(byte_string)
  310. cidr_int = None
  311. if byte_len in set([32, 16]):
  312. value = inet_ntop(socket.AF_INET6, byte_string[0:16])
  313. if byte_len > 16:
  314. cidr_int = int_from_bytes(byte_string[16:])
  315. elif byte_len in set([8, 4]):
  316. value = inet_ntop(socket.AF_INET, byte_string[0:4])
  317. if byte_len > 4:
  318. cidr_int = int_from_bytes(byte_string[4:])
  319. if cidr_int is not None:
  320. cidr_bits = '{0:b}'.format(cidr_int)
  321. cidr = len(cidr_bits.rstrip('0'))
  322. value = value + '/' + str_cls(cidr)
  323. self._native = value
  324. return self._native
  325. def __ne__(self, other):
  326. return not self == other
  327. def __eq__(self, other):
  328. """
  329. :param other:
  330. Another IPAddress object
  331. :return:
  332. A boolean
  333. """
  334. if not isinstance(other, IPAddress):
  335. return False
  336. return self.__bytes__() == other.__bytes__()
  337. class Attribute(Sequence):
  338. _fields = [
  339. ('type', ObjectIdentifier),
  340. ('values', SetOf, {'spec': Any}),
  341. ]
  342. class Attributes(SequenceOf):
  343. _child_spec = Attribute
  344. class KeyUsage(BitString):
  345. _map = {
  346. 0: 'digital_signature',
  347. 1: 'non_repudiation',
  348. 2: 'key_encipherment',
  349. 3: 'data_encipherment',
  350. 4: 'key_agreement',
  351. 5: 'key_cert_sign',
  352. 6: 'crl_sign',
  353. 7: 'encipher_only',
  354. 8: 'decipher_only',
  355. }
  356. class PrivateKeyUsagePeriod(Sequence):
  357. _fields = [
  358. ('not_before', GeneralizedTime, {'implicit': 0, 'optional': True}),
  359. ('not_after', GeneralizedTime, {'implicit': 1, 'optional': True}),
  360. ]
  361. class NotReallyTeletexString(TeletexString):
  362. """
  363. OpenSSL (and probably some other libraries) puts ISO-8859-1
  364. into TeletexString instead of ITU T.61. We use Windows-1252 when
  365. decoding since it is a superset of ISO-8859-1, and less likely to
  366. cause encoding issues, but we stay strict with encoding to prevent
  367. us from creating bad data.
  368. """
  369. _decoding_encoding = 'cp1252'
  370. def __unicode__(self):
  371. """
  372. :return:
  373. A unicode string
  374. """
  375. if self.contents is None:
  376. return ''
  377. if self._unicode is None:
  378. self._unicode = self._merge_chunks().decode(self._decoding_encoding)
  379. return self._unicode
  380. @contextmanager
  381. def strict_teletex():
  382. try:
  383. NotReallyTeletexString._decoding_encoding = 'teletex'
  384. yield
  385. finally:
  386. NotReallyTeletexString._decoding_encoding = 'cp1252'
  387. class DirectoryString(Choice):
  388. _alternatives = [
  389. ('teletex_string', NotReallyTeletexString),
  390. ('printable_string', PrintableString),
  391. ('universal_string', UniversalString),
  392. ('utf8_string', UTF8String),
  393. ('bmp_string', BMPString),
  394. # This is an invalid/bad alternative, but some broken certs use it
  395. ('ia5_string', IA5String),
  396. ]
  397. class NameType(ObjectIdentifier):
  398. _map = {
  399. '2.5.4.3': 'common_name',
  400. '2.5.4.4': 'surname',
  401. '2.5.4.5': 'serial_number',
  402. '2.5.4.6': 'country_name',
  403. '2.5.4.7': 'locality_name',
  404. '2.5.4.8': 'state_or_province_name',
  405. '2.5.4.9': 'street_address',
  406. '2.5.4.10': 'organization_name',
  407. '2.5.4.11': 'organizational_unit_name',
  408. '2.5.4.12': 'title',
  409. '2.5.4.15': 'business_category',
  410. '2.5.4.17': 'postal_code',
  411. '2.5.4.20': 'telephone_number',
  412. '2.5.4.41': 'name',
  413. '2.5.4.42': 'given_name',
  414. '2.5.4.43': 'initials',
  415. '2.5.4.44': 'generation_qualifier',
  416. '2.5.4.45': 'unique_identifier',
  417. '2.5.4.46': 'dn_qualifier',
  418. '2.5.4.65': 'pseudonym',
  419. '2.5.4.97': 'organization_identifier',
  420. # https://www.trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf
  421. '2.23.133.2.1': 'tpm_manufacturer',
  422. '2.23.133.2.2': 'tpm_model',
  423. '2.23.133.2.3': 'tpm_version',
  424. '2.23.133.2.4': 'platform_manufacturer',
  425. '2.23.133.2.5': 'platform_model',
  426. '2.23.133.2.6': 'platform_version',
  427. # https://tools.ietf.org/html/rfc2985#page-26
  428. '1.2.840.113549.1.9.1': 'email_address',
  429. # Page 10 of https://cabforum.org/wp-content/uploads/EV-V1_5_5.pdf
  430. '1.3.6.1.4.1.311.60.2.1.1': 'incorporation_locality',
  431. '1.3.6.1.4.1.311.60.2.1.2': 'incorporation_state_or_province',
  432. '1.3.6.1.4.1.311.60.2.1.3': 'incorporation_country',
  433. # https://tools.ietf.org/html/rfc2247#section-4
  434. '0.9.2342.19200300.100.1.25': 'domain_component',
  435. # http://www.alvestrand.no/objectid/0.2.262.1.10.7.20.html
  436. '0.2.262.1.10.7.20': 'name_distinguisher',
  437. }
  438. # This order is largely based on observed order seen in EV certs from
  439. # Symantec and DigiCert. Some of the uncommon name-related fields are
  440. # just placed in what seems like a reasonable order.
  441. preferred_order = [
  442. 'incorporation_country',
  443. 'incorporation_state_or_province',
  444. 'incorporation_locality',
  445. 'business_category',
  446. 'serial_number',
  447. 'country_name',
  448. 'postal_code',
  449. 'state_or_province_name',
  450. 'locality_name',
  451. 'street_address',
  452. 'organization_name',
  453. 'organizational_unit_name',
  454. 'title',
  455. 'common_name',
  456. 'initials',
  457. 'generation_qualifier',
  458. 'surname',
  459. 'given_name',
  460. 'name',
  461. 'pseudonym',
  462. 'dn_qualifier',
  463. 'telephone_number',
  464. 'email_address',
  465. 'domain_component',
  466. 'name_distinguisher',
  467. 'organization_identifier',
  468. 'tpm_manufacturer',
  469. 'tpm_model',
  470. 'tpm_version',
  471. 'platform_manufacturer',
  472. 'platform_model',
  473. 'platform_version',
  474. ]
  475. @classmethod
  476. def preferred_ordinal(cls, attr_name):
  477. """
  478. Returns an ordering value for a particular attribute key.
  479. Unrecognized attributes and OIDs will be sorted lexically at the end.
  480. :return:
  481. An orderable value.
  482. """
  483. attr_name = cls.map(attr_name)
  484. if attr_name in cls.preferred_order:
  485. ordinal = cls.preferred_order.index(attr_name)
  486. else:
  487. ordinal = len(cls.preferred_order)
  488. return (ordinal, attr_name)
  489. @property
  490. def human_friendly(self):
  491. """
  492. :return:
  493. A human-friendly unicode string to display to users
  494. """
  495. return {
  496. 'common_name': 'Common Name',
  497. 'surname': 'Surname',
  498. 'serial_number': 'Serial Number',
  499. 'country_name': 'Country',
  500. 'locality_name': 'Locality',
  501. 'state_or_province_name': 'State/Province',
  502. 'street_address': 'Street Address',
  503. 'organization_name': 'Organization',
  504. 'organizational_unit_name': 'Organizational Unit',
  505. 'title': 'Title',
  506. 'business_category': 'Business Category',
  507. 'postal_code': 'Postal Code',
  508. 'telephone_number': 'Telephone Number',
  509. 'name': 'Name',
  510. 'given_name': 'Given Name',
  511. 'initials': 'Initials',
  512. 'generation_qualifier': 'Generation Qualifier',
  513. 'unique_identifier': 'Unique Identifier',
  514. 'dn_qualifier': 'DN Qualifier',
  515. 'pseudonym': 'Pseudonym',
  516. 'email_address': 'Email Address',
  517. 'incorporation_locality': 'Incorporation Locality',
  518. 'incorporation_state_or_province': 'Incorporation State/Province',
  519. 'incorporation_country': 'Incorporation Country',
  520. 'domain_component': 'Domain Component',
  521. 'name_distinguisher': 'Name Distinguisher',
  522. 'organization_identifier': 'Organization Identifier',
  523. 'tpm_manufacturer': 'TPM Manufacturer',
  524. 'tpm_model': 'TPM Model',
  525. 'tpm_version': 'TPM Version',
  526. 'platform_manufacturer': 'Platform Manufacturer',
  527. 'platform_model': 'Platform Model',
  528. 'platform_version': 'Platform Version',
  529. }.get(self.native, self.native)
  530. class NameTypeAndValue(Sequence):
  531. _fields = [
  532. ('type', NameType),
  533. ('value', Any),
  534. ]
  535. _oid_pair = ('type', 'value')
  536. _oid_specs = {
  537. 'common_name': DirectoryString,
  538. 'surname': DirectoryString,
  539. 'serial_number': DirectoryString,
  540. 'country_name': DirectoryString,
  541. 'locality_name': DirectoryString,
  542. 'state_or_province_name': DirectoryString,
  543. 'street_address': DirectoryString,
  544. 'organization_name': DirectoryString,
  545. 'organizational_unit_name': DirectoryString,
  546. 'title': DirectoryString,
  547. 'business_category': DirectoryString,
  548. 'postal_code': DirectoryString,
  549. 'telephone_number': PrintableString,
  550. 'name': DirectoryString,
  551. 'given_name': DirectoryString,
  552. 'initials': DirectoryString,
  553. 'generation_qualifier': DirectoryString,
  554. 'unique_identifier': OctetBitString,
  555. 'dn_qualifier': DirectoryString,
  556. 'pseudonym': DirectoryString,
  557. # https://tools.ietf.org/html/rfc2985#page-26
  558. 'email_address': EmailAddress,
  559. # Page 10 of https://cabforum.org/wp-content/uploads/EV-V1_5_5.pdf
  560. 'incorporation_locality': DirectoryString,
  561. 'incorporation_state_or_province': DirectoryString,
  562. 'incorporation_country': DirectoryString,
  563. 'domain_component': DNSName,
  564. 'name_distinguisher': DirectoryString,
  565. 'organization_identifier': DirectoryString,
  566. 'tpm_manufacturer': UTF8String,
  567. 'tpm_model': UTF8String,
  568. 'tpm_version': UTF8String,
  569. 'platform_manufacturer': UTF8String,
  570. 'platform_model': UTF8String,
  571. 'platform_version': UTF8String,
  572. }
  573. _prepped = None
  574. @property
  575. def prepped_value(self):
  576. """
  577. Returns the value after being processed by the internationalized string
  578. preparation as specified by RFC 5280
  579. :return:
  580. A unicode string
  581. """
  582. if self._prepped is None:
  583. self._prepped = self._ldap_string_prep(self['value'].native)
  584. return self._prepped
  585. def __ne__(self, other):
  586. return not self == other
  587. def __eq__(self, other):
  588. """
  589. Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.1
  590. :param other:
  591. Another NameTypeAndValue object
  592. :return:
  593. A boolean
  594. """
  595. if not isinstance(other, NameTypeAndValue):
  596. return False
  597. if other['type'].native != self['type'].native:
  598. return False
  599. return other.prepped_value == self.prepped_value
  600. def _ldap_string_prep(self, string):
  601. """
  602. Implements the internationalized string preparation algorithm from
  603. RFC 4518. https://tools.ietf.org/html/rfc4518#section-2
  604. :param string:
  605. A unicode string to prepare
  606. :return:
  607. A prepared unicode string, ready for comparison
  608. """
  609. # Map step
  610. string = re.sub('[\u00ad\u1806\u034f\u180b-\u180d\ufe0f-\uff00\ufffc]+', '', string)
  611. string = re.sub('[\u0009\u000a\u000b\u000c\u000d\u0085]', ' ', string)
  612. if sys.maxunicode == 0xffff:
  613. # Some installs of Python 2.7 don't support 8-digit unicode escape
  614. # ranges, so we have to break them into pieces
  615. # Original was: \U0001D173-\U0001D17A and \U000E0020-\U000E007F
  616. string = re.sub('\ud834[\udd73-\udd7a]|\udb40[\udc20-\udc7f]|\U000e0001', '', string)
  617. else:
  618. string = re.sub('[\U0001D173-\U0001D17A\U000E0020-\U000E007F\U000e0001]', '', string)
  619. string = re.sub(
  620. '[\u0000-\u0008\u000e-\u001f\u007f-\u0084\u0086-\u009f\u06dd\u070f\u180e\u200c-\u200f'
  621. '\u202a-\u202e\u2060-\u2063\u206a-\u206f\ufeff\ufff9-\ufffb]+',
  622. '',
  623. string
  624. )
  625. string = string.replace('\u200b', '')
  626. string = re.sub('[\u00a0\u1680\u2000-\u200a\u2028-\u2029\u202f\u205f\u3000]', ' ', string)
  627. string = ''.join(map(stringprep.map_table_b2, string))
  628. # Normalize step
  629. string = unicodedata.normalize('NFKC', string)
  630. # Prohibit step
  631. for char in string:
  632. if stringprep.in_table_a1(char):
  633. raise ValueError(unwrap(
  634. '''
  635. X.509 Name objects may not contain unassigned code points
  636. '''
  637. ))
  638. if stringprep.in_table_c8(char):
  639. raise ValueError(unwrap(
  640. '''
  641. X.509 Name objects may not contain change display or
  642. zzzzdeprecated characters
  643. '''
  644. ))
  645. if stringprep.in_table_c3(char):
  646. raise ValueError(unwrap(
  647. '''
  648. X.509 Name objects may not contain private use characters
  649. '''
  650. ))
  651. if stringprep.in_table_c4(char):
  652. raise ValueError(unwrap(
  653. '''
  654. X.509 Name objects may not contain non-character code points
  655. '''
  656. ))
  657. if stringprep.in_table_c5(char):
  658. raise ValueError(unwrap(
  659. '''
  660. X.509 Name objects may not contain surrogate code points
  661. '''
  662. ))
  663. if char == '\ufffd':
  664. raise ValueError(unwrap(
  665. '''
  666. X.509 Name objects may not contain the replacement character
  667. '''
  668. ))
  669. # Check bidirectional step - here we ensure that we are not mixing
  670. # left-to-right and right-to-left text in the string
  671. has_r_and_al_cat = False
  672. has_l_cat = False
  673. for char in string:
  674. if stringprep.in_table_d1(char):
  675. has_r_and_al_cat = True
  676. elif stringprep.in_table_d2(char):
  677. has_l_cat = True
  678. if has_r_and_al_cat:
  679. first_is_r_and_al = stringprep.in_table_d1(string[0])
  680. last_is_r_and_al = stringprep.in_table_d1(string[-1])
  681. if has_l_cat or not first_is_r_and_al or not last_is_r_and_al:
  682. raise ValueError(unwrap(
  683. '''
  684. X.509 Name object contains a malformed bidirectional
  685. sequence
  686. '''
  687. ))
  688. # Insignificant space handling step
  689. string = ' ' + re.sub(' +', ' ', string).strip() + ' '
  690. return string
  691. class RelativeDistinguishedName(SetOf):
  692. _child_spec = NameTypeAndValue
  693. @property
  694. def hashable(self):
  695. """
  696. :return:
  697. A unicode string that can be used as a dict key or in a set
  698. """
  699. output = []
  700. values = self._get_values(self)
  701. for key in sorted(values.keys()):
  702. output.append('%s: %s' % (key, values[key]))
  703. # Unit separator is used here since the normalization process for
  704. # values moves any such character, and the keys are all dotted integers
  705. # or under_score_words
  706. return '\x1F'.join(output)
  707. def __ne__(self, other):
  708. return not self == other
  709. def __eq__(self, other):
  710. """
  711. Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.1
  712. :param other:
  713. Another RelativeDistinguishedName object
  714. :return:
  715. A boolean
  716. """
  717. if not isinstance(other, RelativeDistinguishedName):
  718. return False
  719. if len(self) != len(other):
  720. return False
  721. self_types = self._get_types(self)
  722. other_types = self._get_types(other)
  723. if self_types != other_types:
  724. return False
  725. self_values = self._get_values(self)
  726. other_values = self._get_values(other)
  727. for type_name_ in self_types:
  728. if self_values[type_name_] != other_values[type_name_]:
  729. return False
  730. return True
  731. def _get_types(self, rdn):
  732. """
  733. Returns a set of types contained in an RDN
  734. :param rdn:
  735. A RelativeDistinguishedName object
  736. :return:
  737. A set object with unicode strings of NameTypeAndValue type field
  738. values
  739. """
  740. return set([ntv['type'].native for ntv in rdn])
  741. def _get_values(self, rdn):
  742. """
  743. Returns a dict of prepped values contained in an RDN
  744. :param rdn:
  745. A RelativeDistinguishedName object
  746. :return:
  747. A dict object with unicode strings of NameTypeAndValue value field
  748. values that have been prepped for comparison
  749. """
  750. output = {}
  751. [output.update([(ntv['type'].native, ntv.prepped_value)]) for ntv in rdn]
  752. return output
  753. class RDNSequence(SequenceOf):
  754. _child_spec = RelativeDistinguishedName
  755. @property
  756. def hashable(self):
  757. """
  758. :return:
  759. A unicode string that can be used as a dict key or in a set
  760. """
  761. # Record separator is used here since the normalization process for
  762. # values moves any such character, and the keys are all dotted integers
  763. # or under_score_words
  764. return '\x1E'.join(rdn.hashable for rdn in self)
  765. def __ne__(self, other):
  766. return not self == other
  767. def __eq__(self, other):
  768. """
  769. Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.1
  770. :param other:
  771. Another RDNSequence object
  772. :return:
  773. A boolean
  774. """
  775. if not isinstance(other, RDNSequence):
  776. return False
  777. if len(self) != len(other):
  778. return False
  779. for index, self_rdn in enumerate(self):
  780. if other[index] != self_rdn:
  781. return False
  782. return True
  783. class Name(Choice):
  784. _alternatives = [
  785. ('', RDNSequence),
  786. ]
  787. _human_friendly = None
  788. _sha1 = None
  789. _sha256 = None
  790. @classmethod
  791. def build(cls, name_dict, use_printable=False):
  792. """
  793. Creates a Name object from a dict of unicode string keys and values.
  794. The keys should be from NameType._map, or a dotted-integer OID unicode
  795. string.
  796. :param name_dict:
  797. A dict of name information, e.g. {"common_name": "Will Bond",
  798. "country_name": "US", "organization": "Codex Non Sufficit LC"}
  799. :param use_printable:
  800. A bool - if PrintableString should be used for encoding instead of
  801. UTF8String. This is for backwards compatibility with old software.
  802. :return:
  803. An x509.Name object
  804. """
  805. rdns = []
  806. if not use_printable:
  807. encoding_name = 'utf8_string'
  808. encoding_class = UTF8String
  809. else:
  810. encoding_name = 'printable_string'
  811. encoding_class = PrintableString
  812. # Sort the attributes according to NameType.preferred_order
  813. name_dict = OrderedDict(
  814. sorted(
  815. name_dict.items(),
  816. key=lambda item: NameType.preferred_ordinal(item[0])
  817. )
  818. )
  819. for attribute_name, attribute_value in name_dict.items():
  820. attribute_name = NameType.map(attribute_name)
  821. if attribute_name == 'email_address':
  822. value = EmailAddress(attribute_value)
  823. elif attribute_name == 'domain_component':
  824. value = DNSName(attribute_value)
  825. elif attribute_name in set(['dn_qualifier', 'country_name', 'serial_number']):
  826. value = DirectoryString(
  827. name='printable_string',
  828. value=PrintableString(attribute_value)
  829. )
  830. else:
  831. value = DirectoryString(
  832. name=encoding_name,
  833. value=encoding_class(attribute_value)
  834. )
  835. rdns.append(RelativeDistinguishedName([
  836. NameTypeAndValue({
  837. 'type': attribute_name,
  838. 'value': value
  839. })
  840. ]))
  841. return cls(name='', value=RDNSequence(rdns))
  842. @property
  843. def hashable(self):
  844. """
  845. :return:
  846. A unicode string that can be used as a dict key or in a set
  847. """
  848. return self.chosen.hashable
  849. def __len__(self):
  850. return len(self.chosen)
  851. def __ne__(self, other):
  852. return not self == other
  853. def __eq__(self, other):
  854. """
  855. Equality as defined by https://tools.ietf.org/html/rfc5280#section-7.1
  856. :param other:
  857. Another Name object
  858. :return:
  859. A boolean
  860. """
  861. if not isinstance(other, Name):
  862. return False
  863. return self.chosen == other.chosen
  864. @property
  865. def native(self):
  866. if self._native is None:
  867. self._native = OrderedDict()
  868. for rdn in self.chosen.native:
  869. for type_val in rdn:
  870. field_name = type_val['type']
  871. if field_name in self._native:
  872. existing = self._native[field_name]
  873. if not isinstance(existing, list):
  874. existing = self._native[field_name] = [existing]
  875. existing.append(type_val['value'])
  876. else:
  877. self._native[field_name] = type_val['value']
  878. return self._native
  879. @property
  880. def human_friendly(self):
  881. """
  882. :return:
  883. A human-friendly unicode string containing the parts of the name
  884. """
  885. if self._human_friendly is None:
  886. data = OrderedDict()
  887. last_field = None
  888. for rdn in self.chosen:
  889. for type_val in rdn:
  890. field_name = type_val['type'].human_friendly
  891. last_field = field_name
  892. if field_name in data:
  893. data[field_name] = [data[field_name]]
  894. data[field_name].append(type_val['value'])
  895. else:
  896. data[field_name] = type_val['value']
  897. to_join = []
  898. keys = data.keys()
  899. if last_field == 'Country':
  900. keys = reversed(list(keys))
  901. for key in keys:
  902. value = data[key]
  903. native_value = self._recursive_humanize(value)
  904. to_join.append('%s: %s' % (key, native_value))
  905. has_comma = False
  906. for element in to_join:
  907. if element.find(',') != -1:
  908. has_comma = True
  909. break
  910. separator = ', ' if not has_comma else '; '
  911. self._human_friendly = separator.join(to_join[::-1])
  912. return self._human_friendly
  913. def _recursive_humanize(self, value):
  914. """
  915. Recursively serializes data compiled from the RDNSequence
  916. :param value:
  917. An Asn1Value object, or a list of Asn1Value objects
  918. :return:
  919. A unicode string
  920. """
  921. if isinstance(value, list):
  922. return', '.join(
  923. reversed([self._recursive_humanize(sub_value) for sub_value in value])
  924. )
  925. return value.native
  926. @property
  927. def sha1(self):
  928. """
  929. :return:
  930. The SHA1 hash of the DER-encoded bytes of this name
  931. """
  932. if self._sha1 is None:
  933. self._sha1 = hashlib.sha1(self.dump()).digest()
  934. return self._sha1
  935. @property
  936. def sha256(self):
  937. """
  938. :return:
  939. The SHA-256 hash of the DER-encoded bytes of this name
  940. """
  941. if self._sha256 is None:
  942. self._sha256 = hashlib.sha256(self.dump()).digest()
  943. return self._sha256
  944. class AnotherName(Sequence):
  945. _fields = [
  946. ('type_id', ObjectIdentifier),
  947. ('value', Any, {'explicit': 0}),
  948. ]
  949. class CountryName(Choice):
  950. class_ = 1
  951. tag = 1
  952. _alternatives = [
  953. ('x121_dcc_code', NumericString),
  954. ('iso_3166_alpha2_code', PrintableString),
  955. ]
  956. class AdministrationDomainName(Choice):
  957. class_ = 1
  958. tag = 2
  959. _alternatives = [
  960. ('numeric', NumericString),
  961. ('printable', PrintableString),
  962. ]
  963. class PrivateDomainName(Choice):
  964. _alternatives = [
  965. ('numeric', NumericString),
  966. ('printable', PrintableString),
  967. ]
  968. class PersonalName(Set):
  969. _fields = [
  970. ('surname', PrintableString, {'implicit': 0}),
  971. ('given_name', PrintableString, {'implicit': 1, 'optional': True}),
  972. ('initials', PrintableString, {'implicit': 2, 'optional': True}),
  973. ('generation_qualifier', PrintableString, {'implicit': 3, 'optional': True}),
  974. ]
  975. class TeletexPersonalName(Set):
  976. _fields = [
  977. ('surname', TeletexString, {'implicit': 0}),
  978. ('given_name', TeletexString, {'implicit': 1, 'optional': True}),
  979. ('initials', TeletexString, {'implicit': 2, 'optional': True}),
  980. ('generation_qualifier', TeletexString, {'implicit': 3, 'optional': True}),
  981. ]
  982. class OrganizationalUnitNames(SequenceOf):
  983. _child_spec = PrintableString
  984. class TeletexOrganizationalUnitNames(SequenceOf):
  985. _child_spec = TeletexString
  986. class BuiltInStandardAttributes(Sequence):
  987. _fields = [
  988. ('country_name', CountryName, {'optional': True}),
  989. ('administration_domain_name', AdministrationDomainName, {'optional': True}),
  990. ('network_address', NumericString, {'implicit': 0, 'optional': True}),
  991. ('terminal_identifier', PrintableString, {'implicit': 1, 'optional': True}),
  992. ('private_domain_name', PrivateDomainName, {'explicit': 2, 'optional': True}),
  993. ('organization_name', PrintableString, {'implicit': 3, 'optional': True}),
  994. ('numeric_user_identifier', NumericString, {'implicit': 4, 'optional': True}),
  995. ('personal_name', PersonalName, {'implicit': 5, 'optional': True}),
  996. ('organizational_unit_names', OrganizationalUnitNames, {'implicit': 6, 'optional': True}),
  997. ]
  998. class BuiltInDomainDefinedAttribute(Sequence):
  999. _fields = [
  1000. ('type', PrintableString),
  1001. ('value', PrintableString),
  1002. ]
  1003. class BuiltInDomainDefinedAttributes(SequenceOf):
  1004. _child_spec = BuiltInDomainDefinedAttribute
  1005. class TeletexDomainDefinedAttribute(Sequence):
  1006. _fields = [
  1007. ('type', TeletexString),
  1008. ('value', TeletexString),
  1009. ]
  1010. class TeletexDomainDefinedAttributes(SequenceOf):
  1011. _child_spec = TeletexDomainDefinedAttribute
  1012. class PhysicalDeliveryCountryName(Choice):
  1013. _alternatives = [
  1014. ('x121_dcc_code', NumericString),
  1015. ('iso_3166_alpha2_code', PrintableString),
  1016. ]
  1017. class PostalCode(Choice):
  1018. _alternatives = [
  1019. ('numeric_code', NumericString),
  1020. ('printable_code', PrintableString),
  1021. ]
  1022. class PDSParameter(Set):
  1023. _fields = [
  1024. ('printable_string', PrintableString, {'optional': True}),
  1025. ('teletex_string', TeletexString, {'optional': True}),
  1026. ]
  1027. class PrintableAddress(SequenceOf):
  1028. _child_spec = PrintableString
  1029. class UnformattedPostalAddress(Set):
  1030. _fields = [
  1031. ('printable_address', PrintableAddress, {'optional': True}),
  1032. ('teletex_string', TeletexString, {'optional': True}),
  1033. ]
  1034. class E1634Address(Sequence):
  1035. _fields = [
  1036. ('number', NumericString, {'implicit': 0}),
  1037. ('sub_address', NumericString, {'implicit': 1, 'optional': True}),
  1038. ]
  1039. class NAddresses(SetOf):
  1040. _child_spec = OctetString
  1041. class PresentationAddress(Sequence):
  1042. _fields = [
  1043. ('p_selector', OctetString, {'explicit': 0, 'optional': True}),
  1044. ('s_selector', OctetString, {'explicit': 1, 'optional': True}),
  1045. ('t_selector', OctetString, {'explicit': 2, 'optional': True}),
  1046. ('n_addresses', NAddresses, {'explicit': 3}),
  1047. ]
  1048. class ExtendedNetworkAddress(Choice):
  1049. _alternatives = [
  1050. ('e163_4_address', E1634Address),
  1051. ('psap_address', PresentationAddress, {'implicit': 0})
  1052. ]
  1053. class TerminalType(Integer):
  1054. _map = {
  1055. 3: 'telex',
  1056. 4: 'teletex',
  1057. 5: 'g3_facsimile',
  1058. 6: 'g4_facsimile',
  1059. 7: 'ia5_terminal',
  1060. 8: 'videotex',
  1061. }
  1062. class ExtensionAttributeType(Integer):
  1063. _map = {
  1064. 1: 'common_name',
  1065. 2: 'teletex_common_name',
  1066. 3: 'teletex_organization_name',
  1067. 4: 'teletex_personal_name',
  1068. 5: 'teletex_organization_unit_names',
  1069. 6: 'teletex_domain_defined_attributes',
  1070. 7: 'pds_name',
  1071. 8: 'physical_delivery_country_name',
  1072. 9: 'postal_code',
  1073. 10: 'physical_delivery_office_name',
  1074. 11: 'physical_delivery_office_number',
  1075. 12: 'extension_of_address_components',
  1076. 13: 'physical_delivery_personal_name',
  1077. 14: 'physical_delivery_organization_name',
  1078. 15: 'extension_physical_delivery_address_components',
  1079. 16: 'unformatted_postal_address',
  1080. 17: 'street_address',
  1081. 18: 'post_office_box_address',
  1082. 19: 'poste_restante_address',
  1083. 20: 'unique_postal_name',
  1084. 21: 'local_postal_attributes',
  1085. 22: 'extended_network_address',
  1086. 23: 'terminal_type',
  1087. }
  1088. class ExtensionAttribute(Sequence):
  1089. _fields = [
  1090. ('extension_attribute_type', ExtensionAttributeType, {'implicit': 0}),
  1091. ('extension_attribute_value', Any, {'explicit': 1}),
  1092. ]
  1093. _oid_pair = ('extension_attribute_type', 'extension_attribute_value')
  1094. _oid_specs = {
  1095. 'common_name': PrintableString,
  1096. 'teletex_common_name': TeletexString,
  1097. 'teletex_organization_name': TeletexString,
  1098. 'teletex_personal_name': TeletexPersonalName,
  1099. 'teletex_organization_unit_names': TeletexOrganizationalUnitNames,
  1100. 'teletex_domain_defined_attributes': TeletexDomainDefinedAttributes,
  1101. 'pds_name': PrintableString,
  1102. 'physical_delivery_country_name': PhysicalDeliveryCountryName,
  1103. 'postal_code': PostalCode,
  1104. 'physical_delivery_office_name': PDSParameter,
  1105. 'physical_delivery_office_number': PDSParameter,
  1106. 'extension_of_address_components': PDSParameter,
  1107. 'physical_delivery_personal_name': PDSParameter,
  1108. 'physical_delivery_organization_name': PDSParameter,
  1109. 'extension_physical_delivery_address_components': PDSParameter,
  1110. 'unformatted_postal_address': UnformattedPostalAddress,
  1111. 'street_address': PDSParameter,
  1112. 'post_office_box_address': PDSParameter,
  1113. 'poste_restante_address': PDSParameter,
  1114. 'unique_postal_name': PDSParameter,
  1115. 'local_postal_attributes': PDSParameter,
  1116. 'extended_network_address': ExtendedNetworkAddress,
  1117. 'terminal_type': TerminalType,
  1118. }
  1119. class ExtensionAttributes(SequenceOf):
  1120. _child_spec = ExtensionAttribute
  1121. class ORAddress(Sequence):
  1122. _fields = [
  1123. ('built_in_standard_attributes', BuiltInStandardAttributes),
  1124. ('built_in_domain_defined_attributes', BuiltInDomainDefinedAttributes, {'optional': True}),
  1125. ('extension_attributes', ExtensionAttributes, {'optional': True}),
  1126. ]
  1127. class EDIPartyName(Sequence):
  1128. _fields = [
  1129. ('name_assigner', DirectoryString, {'implicit': 0, 'optional': True}),
  1130. ('party_name', DirectoryString, {'implicit': 1}),
  1131. ]
  1132. class GeneralName(Choice):
  1133. _alternatives = [
  1134. ('other_name', AnotherName, {'implicit': 0}),
  1135. ('rfc822_name', EmailAddress, {'implicit': 1}),
  1136. ('dns_name', DNSName, {'implicit': 2}),
  1137. ('x400_address', ORAddress, {'implicit': 3}),
  1138. ('directory_name', Name, {'explicit': 4}),
  1139. ('edi_party_name', EDIPartyName, {'implicit': 5}),
  1140. ('uniform_resource_identifier', URI, {'implicit': 6}),
  1141. ('ip_address', IPAddress, {'implicit': 7}),
  1142. ('registered_id', ObjectIdentifier, {'implicit': 8}),
  1143. ]
  1144. def __ne__(self, other):
  1145. return not self == other
  1146. def __eq__(self, other):
  1147. """
  1148. Does not support other_name, x400_address or edi_party_name
  1149. :param other:
  1150. The other GeneralName to compare to
  1151. :return:
  1152. A boolean
  1153. """
  1154. if self.name in ('other_name', 'x400_address', 'edi_party_name'):
  1155. raise ValueError(unwrap(
  1156. '''
  1157. Comparison is not supported for GeneralName objects of
  1158. choice %s
  1159. ''',
  1160. self.name
  1161. ))
  1162. if other.name in ('other_name', 'x400_address', 'edi_party_name'):
  1163. raise ValueError(unwrap(
  1164. '''
  1165. Comparison is not supported for GeneralName objects of choice
  1166. %s''',
  1167. other.name
  1168. ))
  1169. if self.name != other.name:
  1170. return False
  1171. return self.chosen == other.chosen
  1172. class GeneralNames(SequenceOf):
  1173. _child_spec = GeneralName
  1174. class Time(Choice):
  1175. _alternatives = [
  1176. ('utc_time', UTCTime),
  1177. ('general_time', GeneralizedTime),
  1178. ]
  1179. class Validity(Sequence):
  1180. _fields = [
  1181. ('not_before', Time),
  1182. ('not_after', Time),
  1183. ]
  1184. class BasicConstraints(Sequence):
  1185. _fields = [
  1186. ('ca', Boolean, {'default': False}),
  1187. ('path_len_constraint', Integer, {'optional': True}),
  1188. ]
  1189. class AuthorityKeyIdentifier(Sequence):
  1190. _fields = [
  1191. ('key_identifier', OctetString, {'implicit': 0, 'optional': True}),
  1192. ('authority_cert_issuer', GeneralNames, {'implicit': 1, 'optional': True}),
  1193. ('authority_cert_serial_number', Integer, {'implicit': 2, 'optional': True}),
  1194. ]
  1195. class DistributionPointName(Choice):
  1196. _alternatives = [
  1197. ('full_name', GeneralNames, {'implicit': 0}),
  1198. ('name_relative_to_crl_issuer', RelativeDistinguishedName, {'implicit': 1}),
  1199. ]
  1200. class ReasonFlags(BitString):
  1201. _map = {
  1202. 0: 'unused',
  1203. 1: 'key_compromise',
  1204. 2: 'ca_compromise',
  1205. 3: 'affiliation_changed',
  1206. 4: 'superseded',
  1207. 5: 'cessation_of_operation',
  1208. 6: 'certificate_hold',
  1209. 7: 'privilege_withdrawn',
  1210. 8: 'aa_compromise',
  1211. }
  1212. class GeneralSubtree(Sequence):
  1213. _fields = [
  1214. ('base', GeneralName),
  1215. ('minimum', Integer, {'implicit': 0, 'default': 0}),
  1216. ('maximum', Integer, {'implicit': 1, 'optional': True}),
  1217. ]
  1218. class GeneralSubtrees(SequenceOf):
  1219. _child_spec = GeneralSubtree
  1220. class NameConstraints(Sequence):
  1221. _fields = [
  1222. ('permitted_subtrees', GeneralSubtrees, {'implicit': 0, 'optional': True}),
  1223. ('excluded_subtrees', GeneralSubtrees, {'implicit': 1, 'optional': True}),
  1224. ]
  1225. class DistributionPoint(Sequence):
  1226. _fields = [
  1227. ('distribution_point', DistributionPointName, {'explicit': 0, 'optional': True}),
  1228. ('reasons', ReasonFlags, {'implicit': 1, 'optional': True}),
  1229. ('crl_issuer', GeneralNames, {'implicit': 2, 'optional': True}),
  1230. ]
  1231. _url = False
  1232. @property
  1233. def url(self):
  1234. """
  1235. :return:
  1236. None or a unicode string of the distribution point's URL
  1237. """
  1238. if self._url is False:
  1239. self._url = None
  1240. name = self['distribution_point']
  1241. if name.name != 'full_name':
  1242. raise ValueError(unwrap(
  1243. '''
  1244. CRL distribution points that are relative to the issuer are
  1245. not supported
  1246. '''
  1247. ))
  1248. for general_name in name.chosen:
  1249. if general_name.name == 'uniform_resource_identifier':
  1250. url = general_name.native
  1251. if url.lower().startswith(('http://', 'https://', 'ldap://', 'ldaps://')):
  1252. self._url = url
  1253. break
  1254. return self._url
  1255. class CRLDistributionPoints(SequenceOf):
  1256. _child_spec = DistributionPoint
  1257. class DisplayText(Choice):
  1258. _alternatives = [
  1259. ('ia5_string', IA5String),
  1260. ('visible_string', VisibleString),
  1261. ('bmp_string', BMPString),
  1262. ('utf8_string', UTF8String),
  1263. ]
  1264. class NoticeNumbers(SequenceOf):
  1265. _child_spec = Integer
  1266. class NoticeReference(Sequence):
  1267. _fields = [
  1268. ('organization', DisplayText),
  1269. ('notice_numbers', NoticeNumbers),
  1270. ]
  1271. class UserNotice(Sequence):
  1272. _fields = [
  1273. ('notice_ref', NoticeReference, {'optional': True}),
  1274. ('explicit_text', DisplayText, {'optional': True}),
  1275. ]
  1276. class PolicyQualifierId(ObjectIdentifier):
  1277. _map = {
  1278. '1.3.6.1.5.5.7.2.1': 'certification_practice_statement',
  1279. '1.3.6.1.5.5.7.2.2': 'user_notice',
  1280. }
  1281. class PolicyQualifierInfo(Sequence):
  1282. _fields = [
  1283. ('policy_qualifier_id', PolicyQualifierId),
  1284. ('qualifier', Any),
  1285. ]
  1286. _oid_pair = ('policy_qualifier_id', 'qualifier')
  1287. _oid_specs = {
  1288. 'certification_practice_statement': IA5String,
  1289. 'user_notice': UserNotice,
  1290. }
  1291. class PolicyQualifierInfos(SequenceOf):
  1292. _child_spec = PolicyQualifierInfo
  1293. class PolicyIdentifier(ObjectIdentifier):
  1294. _map = {
  1295. '2.5.29.32.0': 'any_policy',
  1296. }
  1297. class PolicyInformation(Sequence):
  1298. _fields = [
  1299. ('policy_identifier', PolicyIdentifier),
  1300. ('policy_qualifiers', PolicyQualifierInfos, {'optional': True})
  1301. ]
  1302. class CertificatePolicies(SequenceOf):
  1303. _child_spec = PolicyInformation
  1304. class PolicyMapping(Sequence):
  1305. _fields = [
  1306. ('issuer_domain_policy', PolicyIdentifier),
  1307. ('subject_domain_policy', PolicyIdentifier),
  1308. ]
  1309. class PolicyMappings(SequenceOf):
  1310. _child_spec = PolicyMapping
  1311. class PolicyConstraints(Sequence):
  1312. _fields = [
  1313. ('require_explicit_policy', Integer, {'implicit': 0, 'optional': True}),
  1314. ('inhibit_policy_mapping', Integer, {'implicit': 1, 'optional': True}),
  1315. ]
  1316. class KeyPurposeId(ObjectIdentifier):
  1317. _map = {
  1318. # https://tools.ietf.org/html/rfc5280#page-45
  1319. '2.5.29.37.0': 'any_extended_key_usage',
  1320. '1.3.6.1.5.5.7.3.1': 'server_auth',
  1321. '1.3.6.1.5.5.7.3.2': 'client_auth',
  1322. '1.3.6.1.5.5.7.3.3': 'code_signing',
  1323. '1.3.6.1.5.5.7.3.4': 'email_protection',
  1324. '1.3.6.1.5.5.7.3.5': 'ipsec_end_system',
  1325. '1.3.6.1.5.5.7.3.6': 'ipsec_tunnel',
  1326. '1.3.6.1.5.5.7.3.7': 'ipsec_user',
  1327. '1.3.6.1.5.5.7.3.8': 'time_stamping',
  1328. '1.3.6.1.5.5.7.3.9': 'ocsp_signing',
  1329. # http://tools.ietf.org/html/rfc3029.html#page-9
  1330. '1.3.6.1.5.5.7.3.10': 'dvcs',
  1331. # http://tools.ietf.org/html/rfc6268.html#page-16
  1332. '1.3.6.1.5.5.7.3.13': 'eap_over_ppp',
  1333. '1.3.6.1.5.5.7.3.14': 'eap_over_lan',
  1334. # https://tools.ietf.org/html/rfc5055#page-76
  1335. '1.3.6.1.5.5.7.3.15': 'scvp_server',
  1336. '1.3.6.1.5.5.7.3.16': 'scvp_client',
  1337. # https://tools.ietf.org/html/rfc4945#page-31
  1338. '1.3.6.1.5.5.7.3.17': 'ipsec_ike',
  1339. # https://tools.ietf.org/html/rfc5415#page-38
  1340. '1.3.6.1.5.5.7.3.18': 'capwap_ac',
  1341. '1.3.6.1.5.5.7.3.19': 'capwap_wtp',
  1342. # https://tools.ietf.org/html/rfc5924#page-8
  1343. '1.3.6.1.5.5.7.3.20': 'sip_domain',
  1344. # https://tools.ietf.org/html/rfc6187#page-7
  1345. '1.3.6.1.5.5.7.3.21': 'secure_shell_client',
  1346. '1.3.6.1.5.5.7.3.22': 'secure_shell_server',
  1347. # https://tools.ietf.org/html/rfc6494#page-7
  1348. '1.3.6.1.5.5.7.3.23': 'send_router',
  1349. '1.3.6.1.5.5.7.3.24': 'send_proxied_router',
  1350. '1.3.6.1.5.5.7.3.25': 'send_owner',
  1351. '1.3.6.1.5.5.7.3.26': 'send_proxied_owner',
  1352. # https://tools.ietf.org/html/rfc6402#page-10
  1353. '1.3.6.1.5.5.7.3.27': 'cmc_ca',
  1354. '1.3.6.1.5.5.7.3.28': 'cmc_ra',
  1355. '1.3.6.1.5.5.7.3.29': 'cmc_archive',
  1356. # https://tools.ietf.org/html/draft-ietf-sidr-bgpsec-pki-profiles-15#page-6
  1357. '1.3.6.1.5.5.7.3.30': 'bgpspec_router',
  1358. # https://msdn.microsoft.com/en-us/library/windows/desktop/aa378132(v=vs.85).aspx
  1359. # and https://support.microsoft.com/en-us/kb/287547
  1360. '1.3.6.1.4.1.311.10.3.1': 'microsoft_trust_list_signing',
  1361. '1.3.6.1.4.1.311.10.3.2': 'microsoft_time_stamp_signing',
  1362. '1.3.6.1.4.1.311.10.3.3': 'microsoft_server_gated',
  1363. '1.3.6.1.4.1.311.10.3.3.1': 'microsoft_serialized',
  1364. '1.3.6.1.4.1.311.10.3.4': 'microsoft_efs',
  1365. '1.3.6.1.4.1.311.10.3.4.1': 'microsoft_efs_recovery',
  1366. '1.3.6.1.4.1.311.10.3.5': 'microsoft_whql',
  1367. '1.3.6.1.4.1.311.10.3.6': 'microsoft_nt5',
  1368. '1.3.6.1.4.1.311.10.3.7': 'microsoft_oem_whql',
  1369. '1.3.6.1.4.1.311.10.3.8': 'microsoft_embedded_nt',
  1370. '1.3.6.1.4.1.311.10.3.9': 'microsoft_root_list_signer',
  1371. '1.3.6.1.4.1.311.10.3.10': 'microsoft_qualified_subordination',
  1372. '1.3.6.1.4.1.311.10.3.11': 'microsoft_key_recovery',
  1373. '1.3.6.1.4.1.311.10.3.12': 'microsoft_document_signing',
  1374. '1.3.6.1.4.1.311.10.3.13': 'microsoft_lifetime_signing',
  1375. '1.3.6.1.4.1.311.10.3.14': 'microsoft_mobile_device_software',
  1376. # https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography
  1377. '1.3.6.1.4.1.311.20.2.2': 'microsoft_smart_card_logon',
  1378. # https://opensource.apple.com/source
  1379. # - /Security/Security-57031.40.6/Security/libsecurity_keychain/lib/SecPolicy.cpp
  1380. # - /libsecurity_cssm/libsecurity_cssm-36064/lib/oidsalg.c
  1381. '1.2.840.113635.100.1.2': 'apple_x509_basic',
  1382. '1.2.840.113635.100.1.3': 'apple_ssl',
  1383. '1.2.840.113635.100.1.4': 'apple_local_cert_gen',
  1384. '1.2.840.113635.100.1.5': 'apple_csr_gen',
  1385. '1.2.840.113635.100.1.6': 'apple_revocation_crl',
  1386. '1.2.840.113635.100.1.7': 'apple_revocation_ocsp',
  1387. '1.2.840.113635.100.1.8': 'apple_smime',
  1388. '1.2.840.113635.100.1.9': 'apple_eap',
  1389. '1.2.840.113635.100.1.10': 'apple_software_update_signing',
  1390. '1.2.840.113635.100.1.11': 'apple_ipsec',
  1391. '1.2.840.113635.100.1.12': 'apple_ichat',
  1392. '1.2.840.113635.100.1.13': 'apple_resource_signing',
  1393. '1.2.840.113635.100.1.14': 'apple_pkinit_client',
  1394. '1.2.840.113635.100.1.15': 'apple_pkinit_server',
  1395. '1.2.840.113635.100.1.16': 'apple_code_signing',
  1396. '1.2.840.113635.100.1.17': 'apple_package_signing',
  1397. '1.2.840.113635.100.1.18': 'apple_id_validation',
  1398. '1.2.840.113635.100.1.20': 'apple_time_stamping',
  1399. '1.2.840.113635.100.1.21': 'apple_revocation',
  1400. '1.2.840.113635.100.1.22': 'apple_passbook_signing',
  1401. '1.2.840.113635.100.1.23': 'apple_mobile_store',
  1402. '1.2.840.113635.100.1.24': 'apple_escrow_service',
  1403. '1.2.840.113635.100.1.25': 'apple_profile_signer',
  1404. '1.2.840.113635.100.1.26': 'apple_qa_profile_signer',
  1405. '1.2.840.113635.100.1.27': 'apple_test_mobile_store',
  1406. '1.2.840.113635.100.1.28': 'apple_otapki_signer',
  1407. '1.2.840.113635.100.1.29': 'apple_test_otapki_signer',
  1408. '1.2.840.113625.100.1.30': 'apple_id_validation_record_signing_policy',
  1409. '1.2.840.113625.100.1.31': 'apple_smp_encryption',
  1410. '1.2.840.113625.100.1.32': 'apple_test_smp_encryption',
  1411. '1.2.840.113635.100.1.33': 'apple_server_authentication',
  1412. '1.2.840.113635.100.1.34': 'apple_pcs_escrow_service',
  1413. # http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.201-2.pdf
  1414. '2.16.840.1.101.3.6.8': 'piv_card_authentication',
  1415. '2.16.840.1.101.3.6.7': 'piv_content_signing',
  1416. # https://tools.ietf.org/html/rfc4556.html
  1417. '1.3.6.1.5.2.3.4': 'pkinit_kpclientauth',
  1418. '1.3.6.1.5.2.3.5': 'pkinit_kpkdc',
  1419. # https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/changes.html
  1420. '1.2.840.113583.1.1.5': 'adobe_authentic_documents_trust',
  1421. # https://www.idmanagement.gov/wp-content/uploads/sites/1171/uploads/fpki-pivi-cert-profiles.pdf
  1422. '2.16.840.1.101.3.8.7': 'fpki_pivi_content_signing'
  1423. }
  1424. class ExtKeyUsageSyntax(SequenceOf):
  1425. _child_spec = KeyPurposeId
  1426. class AccessMethod(ObjectIdentifier):
  1427. _map = {
  1428. '1.3.6.1.5.5.7.48.1': 'ocsp',
  1429. '1.3.6.1.5.5.7.48.2': 'ca_issuers',
  1430. '1.3.6.1.5.5.7.48.3': 'time_stamping',
  1431. '1.3.6.1.5.5.7.48.5': 'ca_repository',
  1432. }
  1433. class AccessDescription(Sequence):
  1434. _fields = [
  1435. ('access_method', AccessMethod),
  1436. ('access_location', GeneralName),
  1437. ]
  1438. class AuthorityInfoAccessSyntax(SequenceOf):
  1439. _child_spec = AccessDescription
  1440. class SubjectInfoAccessSyntax(SequenceOf):
  1441. _child_spec = AccessDescription
  1442. # https://tools.ietf.org/html/rfc7633
  1443. class Features(SequenceOf):
  1444. _child_spec = Integer
  1445. class EntrustVersionInfo(Sequence):
  1446. _fields = [
  1447. ('entrust_vers', GeneralString),
  1448. ('entrust_info_flags', BitString)
  1449. ]
  1450. class NetscapeCertificateType(BitString):
  1451. _map = {
  1452. 0: 'ssl_client',
  1453. 1: 'ssl_server',
  1454. 2: 'email',
  1455. 3: 'object_signing',
  1456. 4: 'reserved',
  1457. 5: 'ssl_ca',
  1458. 6: 'email_ca',
  1459. 7: 'object_signing_ca',
  1460. }
  1461. class Version(Integer):
  1462. _map = {
  1463. 0: 'v1',
  1464. 1: 'v2',
  1465. 2: 'v3',
  1466. }
  1467. class TPMSpecification(Sequence):
  1468. _fields = [
  1469. ('family', UTF8String),
  1470. ('level', Integer),
  1471. ('revision', Integer),
  1472. ]
  1473. class SetOfTPMSpecification(SetOf):
  1474. _child_spec = TPMSpecification
  1475. class TCGSpecificationVersion(Sequence):
  1476. _fields = [
  1477. ('major_version', Integer),
  1478. ('minor_version', Integer),
  1479. ('revision', Integer),
  1480. ]
  1481. class TCGPlatformSpecification(Sequence):
  1482. _fields = [
  1483. ('version', TCGSpecificationVersion),
  1484. ('platform_class', OctetString),
  1485. ]
  1486. class SetOfTCGPlatformSpecification(SetOf):
  1487. _child_spec = TCGPlatformSpecification
  1488. class EKGenerationType(Enumerated):
  1489. _map = {
  1490. 0: 'internal',
  1491. 1: 'injected',
  1492. 2: 'internal_revocable',
  1493. 3: 'injected_revocable',
  1494. }
  1495. class EKGenerationLocation(Enumerated):
  1496. _map = {
  1497. 0: 'tpm_manufacturer',
  1498. 1: 'platform_manufacturer',
  1499. 2: 'ek_cert_signer',
  1500. }
  1501. class EKCertificateGenerationLocation(Enumerated):
  1502. _map = {
  1503. 0: 'tpm_manufacturer',
  1504. 1: 'platform_manufacturer',
  1505. 2: 'ek_cert_signer',
  1506. }
  1507. class EvaluationAssuranceLevel(Enumerated):
  1508. _map = {
  1509. 1: 'level1',
  1510. 2: 'level2',
  1511. 3: 'level3',
  1512. 4: 'level4',
  1513. 5: 'level5',
  1514. 6: 'level6',
  1515. 7: 'level7',
  1516. }
  1517. class EvaluationStatus(Enumerated):
  1518. _map = {
  1519. 0: 'designed_to_meet',
  1520. 1: 'evaluation_in_progress',
  1521. 2: 'evaluation_completed',
  1522. }
  1523. class StrengthOfFunction(Enumerated):
  1524. _map = {
  1525. 0: 'basic',
  1526. 1: 'medium',
  1527. 2: 'high',
  1528. }
  1529. class URIReference(Sequence):
  1530. _fields = [
  1531. ('uniform_resource_identifier', IA5String),
  1532. ('hash_algorithm', DigestAlgorithm, {'optional': True}),
  1533. ('hash_value', BitString, {'optional': True}),
  1534. ]
  1535. class CommonCriteriaMeasures(Sequence):
  1536. _fields = [
  1537. ('version', IA5String),
  1538. ('assurance_level', EvaluationAssuranceLevel),
  1539. ('evaluation_status', EvaluationStatus),
  1540. ('plus', Boolean, {'default': False}),
  1541. ('strengh_of_function', StrengthOfFunction, {'implicit': 0, 'optional': True}),
  1542. ('profile_oid', ObjectIdentifier, {'implicit': 1, 'optional': True}),
  1543. ('profile_url', URIReference, {'implicit': 2, 'optional': True}),
  1544. ('target_oid', ObjectIdentifier, {'implicit': 3, 'optional': True}),
  1545. ('target_uri', URIReference, {'implicit': 4, 'optional': True}),
  1546. ]
  1547. class SecurityLevel(Enumerated):
  1548. _map = {
  1549. 1: 'level1',
  1550. 2: 'level2',
  1551. 3: 'level3',
  1552. 4: 'level4',
  1553. }
  1554. class FIPSLevel(Sequence):
  1555. _fields = [
  1556. ('version', IA5String),
  1557. ('level', SecurityLevel),
  1558. ('plus', Boolean, {'default': False}),
  1559. ]
  1560. class TPMSecurityAssertions(Sequence):
  1561. _fields = [
  1562. ('version', Version, {'default': 'v1'}),
  1563. ('field_upgradable', Boolean, {'default': False}),
  1564. ('ek_generation_type', EKGenerationType, {'implicit': 0, 'optional': True}),
  1565. ('ek_generation_location', EKGenerationLocation, {'implicit': 1, 'optional': True}),
  1566. ('ek_certificate_generation_location', EKCertificateGenerationLocation, {'implicit': 2, 'optional': True}),
  1567. ('cc_info', CommonCriteriaMeasures, {'implicit': 3, 'optional': True}),
  1568. ('fips_level', FIPSLevel, {'implicit': 4, 'optional': True}),
  1569. ('iso_9000_certified', Boolean, {'implicit': 5, 'default': False}),
  1570. ('iso_9000_uri', IA5String, {'optional': True}),
  1571. ]
  1572. class SetOfTPMSecurityAssertions(SetOf):
  1573. _child_spec = TPMSecurityAssertions
  1574. class SubjectDirectoryAttributeId(ObjectIdentifier):
  1575. _map = {
  1576. # https://tools.ietf.org/html/rfc2256#page-11
  1577. '2.5.4.52': 'supported_algorithms',
  1578. # https://www.trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf
  1579. '2.23.133.2.16': 'tpm_specification',
  1580. '2.23.133.2.17': 'tcg_platform_specification',
  1581. '2.23.133.2.18': 'tpm_security_assertions',
  1582. # https://tools.ietf.org/html/rfc3739#page-18
  1583. '1.3.6.1.5.5.7.9.1': 'pda_date_of_birth',
  1584. '1.3.6.1.5.5.7.9.2': 'pda_place_of_birth',
  1585. '1.3.6.1.5.5.7.9.3': 'pda_gender',
  1586. '1.3.6.1.5.5.7.9.4': 'pda_country_of_citizenship',
  1587. '1.3.6.1.5.5.7.9.5': 'pda_country_of_residence',
  1588. # https://holtstrom.com/michael/tools/asn1decoder.php
  1589. '1.2.840.113533.7.68.29': 'entrust_user_role',
  1590. }
  1591. class SetOfGeneralizedTime(SetOf):
  1592. _child_spec = GeneralizedTime
  1593. class SetOfDirectoryString(SetOf):
  1594. _child_spec = DirectoryString
  1595. class SetOfPrintableString(SetOf):
  1596. _child_spec = PrintableString
  1597. class SupportedAlgorithm(Sequence):
  1598. _fields = [
  1599. ('algorithm_identifier', AnyAlgorithmIdentifier),
  1600. ('intended_usage', KeyUsage, {'explicit': 0, 'optional': True}),
  1601. ('intended_certificate_policies', CertificatePolicies, {'explicit': 1, 'optional': True}),
  1602. ]
  1603. class SetOfSupportedAlgorithm(SetOf):
  1604. _child_spec = SupportedAlgorithm
  1605. class SubjectDirectoryAttribute(Sequence):
  1606. _fields = [
  1607. ('type', SubjectDirectoryAttributeId),
  1608. ('values', Any),
  1609. ]
  1610. _oid_pair = ('type', 'values')
  1611. _oid_specs = {
  1612. 'supported_algorithms': SetOfSupportedAlgorithm,
  1613. 'tpm_specification': SetOfTPMSpecification,
  1614. 'tcg_platform_specification': SetOfTCGPlatformSpecification,
  1615. 'tpm_security_assertions': SetOfTPMSecurityAssertions,
  1616. 'pda_date_of_birth': SetOfGeneralizedTime,
  1617. 'pda_place_of_birth': SetOfDirectoryString,
  1618. 'pda_gender': SetOfPrintableString,
  1619. 'pda_country_of_citizenship': SetOfPrintableString,
  1620. 'pda_country_of_residence': SetOfPrintableString,
  1621. }
  1622. def _values_spec(self):
  1623. type_ = self['type'].native
  1624. if type_ in self._oid_specs:
  1625. return self._oid_specs[type_]
  1626. return SetOf
  1627. _spec_callbacks = {
  1628. 'values': _values_spec
  1629. }
  1630. class SubjectDirectoryAttributes(SequenceOf):
  1631. _child_spec = SubjectDirectoryAttribute
  1632. class ExtensionId(ObjectIdentifier):
  1633. _map = {
  1634. '2.5.29.9': 'subject_directory_attributes',
  1635. '2.5.29.14': 'key_identifier',
  1636. '2.5.29.15': 'key_usage',
  1637. '2.5.29.16': 'private_key_usage_period',
  1638. '2.5.29.17': 'subject_alt_name',
  1639. '2.5.29.18': 'issuer_alt_name',
  1640. '2.5.29.19': 'basic_constraints',
  1641. '2.5.29.30': 'name_constraints',
  1642. '2.5.29.31': 'crl_distribution_points',
  1643. '2.5.29.32': 'certificate_policies',
  1644. '2.5.29.33': 'policy_mappings',
  1645. '2.5.29.35': 'authority_key_identifier',
  1646. '2.5.29.36': 'policy_constraints',
  1647. '2.5.29.37': 'extended_key_usage',
  1648. '2.5.29.46': 'freshest_crl',
  1649. '2.5.29.54': 'inhibit_any_policy',
  1650. '1.3.6.1.5.5.7.1.1': 'authority_information_access',
  1651. '1.3.6.1.5.5.7.1.11': 'subject_information_access',
  1652. # https://tools.ietf.org/html/rfc7633
  1653. '1.3.6.1.5.5.7.1.24': 'tls_feature',
  1654. '1.3.6.1.5.5.7.48.1.5': 'ocsp_no_check',
  1655. '1.2.840.113533.7.65.0': 'entrust_version_extension',
  1656. '2.16.840.1.113730.1.1': 'netscape_certificate_type',
  1657. # https://tools.ietf.org/html/rfc6962.html#page-14
  1658. '1.3.6.1.4.1.11129.2.4.2': 'signed_certificate_timestamp_list',
  1659. }
  1660. class Extension(Sequence):
  1661. _fields = [
  1662. ('extn_id', ExtensionId),
  1663. ('critical', Boolean, {'default': False}),
  1664. ('extn_value', ParsableOctetString),
  1665. ]
  1666. _oid_pair = ('extn_id', 'extn_value')
  1667. _oid_specs = {
  1668. 'subject_directory_attributes': SubjectDirectoryAttributes,
  1669. 'key_identifier': OctetString,
  1670. 'key_usage': KeyUsage,
  1671. 'private_key_usage_period': PrivateKeyUsagePeriod,
  1672. 'subject_alt_name': GeneralNames,
  1673. 'issuer_alt_name': GeneralNames,
  1674. 'basic_constraints': BasicConstraints,
  1675. 'name_constraints': NameConstraints,
  1676. 'crl_distribution_points': CRLDistributionPoints,
  1677. 'certificate_policies': CertificatePolicies,
  1678. 'policy_mappings': PolicyMappings,
  1679. 'authority_key_identifier': AuthorityKeyIdentifier,
  1680. 'policy_constraints': PolicyConstraints,
  1681. 'extended_key_usage': ExtKeyUsageSyntax,
  1682. 'freshest_crl': CRLDistributionPoints,
  1683. 'inhibit_any_policy': Integer,
  1684. 'authority_information_access': AuthorityInfoAccessSyntax,
  1685. 'subject_information_access': SubjectInfoAccessSyntax,
  1686. 'tls_feature': Features,
  1687. 'ocsp_no_check': Null,
  1688. 'entrust_version_extension': EntrustVersionInfo,
  1689. 'netscape_certificate_type': NetscapeCertificateType,
  1690. 'signed_certificate_timestamp_list': OctetString,
  1691. }
  1692. class Extensions(SequenceOf):
  1693. _child_spec = Extension
  1694. class TbsCertificate(Sequence):
  1695. _fields = [
  1696. ('version', Version, {'explicit': 0, 'default': 'v1'}),
  1697. ('serial_number', Integer),
  1698. ('signature', SignedDigestAlgorithm),
  1699. ('issuer', Name),
  1700. ('validity', Validity),
  1701. ('subject', Name),
  1702. ('subject_public_key_info', PublicKeyInfo),
  1703. ('issuer_unique_id', OctetBitString, {'implicit': 1, 'optional': True}),
  1704. ('subject_unique_id', OctetBitString, {'implicit': 2, 'optional': True}),
  1705. ('extensions', Extensions, {'explicit': 3, 'optional': True}),
  1706. ]
  1707. class Certificate(Sequence):
  1708. _fields = [
  1709. ('tbs_certificate', TbsCertificate),
  1710. ('signature_algorithm', SignedDigestAlgorithm),
  1711. ('signature_value', OctetBitString),
  1712. ]
  1713. _processed_extensions = False
  1714. _critical_extensions = None
  1715. _subject_directory_attributes = None
  1716. _key_identifier_value = None
  1717. _key_usage_value = None
  1718. _subject_alt_name_value = None
  1719. _issuer_alt_name_value = None
  1720. _basic_constraints_value = None
  1721. _name_constraints_value = None
  1722. _crl_distribution_points_value = None
  1723. _certificate_policies_value = None
  1724. _policy_mappings_value = None
  1725. _authority_key_identifier_value = None
  1726. _policy_constraints_value = None
  1727. _freshest_crl_value = None
  1728. _inhibit_any_policy_value = None
  1729. _extended_key_usage_value = None
  1730. _authority_information_access_value = None
  1731. _subject_information_access_value = None
  1732. _private_key_usage_period_value = None
  1733. _tls_feature_value = None
  1734. _ocsp_no_check_value = None
  1735. _issuer_serial = None
  1736. _authority_issuer_serial = False
  1737. _crl_distribution_points = None
  1738. _delta_crl_distribution_points = None
  1739. _valid_domains = None
  1740. _valid_ips = None
  1741. _self_issued = None
  1742. _self_signed = None
  1743. _sha1 = None
  1744. _sha256 = None
  1745. def _set_extensions(self):
  1746. """
  1747. Sets common named extensions to private attributes and creates a list
  1748. of critical extensions
  1749. """
  1750. self._critical_extensions = set()
  1751. for extension in self['tbs_certificate']['extensions']:
  1752. name = extension['extn_id'].native
  1753. attribute_name = '_%s_value' % name
  1754. if hasattr(self, attribute_name):
  1755. setattr(self, attribute_name, extension['extn_value'].parsed)
  1756. if extension['critical'].native:
  1757. self._critical_extensions.add(name)
  1758. self._processed_extensions = True
  1759. @property
  1760. def critical_extensions(self):
  1761. """
  1762. Returns a set of the names (or OID if not a known extension) of the
  1763. extensions marked as critical
  1764. :return:
  1765. A set of unicode strings
  1766. """
  1767. if not self._processed_extensions:
  1768. self._set_extensions()
  1769. return self._critical_extensions
  1770. @property
  1771. def private_key_usage_period_value(self):
  1772. """
  1773. This extension is used to constrain the period over which the subject
  1774. private key may be used
  1775. :return:
  1776. None or a PrivateKeyUsagePeriod object
  1777. """
  1778. if not self._processed_extensions:
  1779. self._set_extensions()
  1780. return self._private_key_usage_period_value
  1781. @property
  1782. def subject_directory_attributes_value(self):
  1783. """
  1784. This extension is used to contain additional identification attributes
  1785. about the subject.
  1786. :return:
  1787. None or a SubjectDirectoryAttributes object
  1788. """
  1789. if not self._processed_extensions:
  1790. self._set_extensions()
  1791. return self._subject_directory_attributes
  1792. @property
  1793. def key_identifier_value(self):
  1794. """
  1795. This extension is used to help in creating certificate validation paths.
  1796. It contains an identifier that should generally, but is not guaranteed
  1797. to, be unique.
  1798. :return:
  1799. None or an OctetString object
  1800. """
  1801. if not self._processed_extensions:
  1802. self._set_extensions()
  1803. return self._key_identifier_value
  1804. @property
  1805. def key_usage_value(self):
  1806. """
  1807. This extension is used to define the purpose of the public key
  1808. contained within the certificate.
  1809. :return:
  1810. None or a KeyUsage
  1811. """
  1812. if not self._processed_extensions:
  1813. self._set_extensions()
  1814. return self._key_usage_value
  1815. @property
  1816. def subject_alt_name_value(self):
  1817. """
  1818. This extension allows for additional names to be associate with the
  1819. subject of the certificate. While it may contain a whole host of
  1820. possible names, it is usually used to allow certificates to be used
  1821. with multiple different domain names.
  1822. :return:
  1823. None or a GeneralNames object
  1824. """
  1825. if not self._processed_extensions:
  1826. self._set_extensions()
  1827. return self._subject_alt_name_value
  1828. @property
  1829. def issuer_alt_name_value(self):
  1830. """
  1831. This extension allows associating one or more alternative names with
  1832. the issuer of the certificate.
  1833. :return:
  1834. None or an x509.GeneralNames object
  1835. """
  1836. if not self._processed_extensions:
  1837. self._set_extensions()
  1838. return self._issuer_alt_name_value
  1839. @property
  1840. def basic_constraints_value(self):
  1841. """
  1842. This extension is used to determine if the subject of the certificate
  1843. is a CA, and if so, what the maximum number of intermediate CA certs
  1844. after this are, before an end-entity certificate is found.
  1845. :return:
  1846. None or a BasicConstraints object
  1847. """
  1848. if not self._processed_extensions:
  1849. self._set_extensions()
  1850. return self._basic_constraints_value
  1851. @property
  1852. def name_constraints_value(self):
  1853. """
  1854. This extension is used in CA certificates, and is used to limit the
  1855. possible names of certificates issued.
  1856. :return:
  1857. None or a NameConstraints object
  1858. """
  1859. if not self._processed_extensions:
  1860. self._set_extensions()
  1861. return self._name_constraints_value
  1862. @property
  1863. def crl_distribution_points_value(self):
  1864. """
  1865. This extension is used to help in locating the CRL for this certificate.
  1866. :return:
  1867. None or a CRLDistributionPoints object
  1868. extension
  1869. """
  1870. if not self._processed_extensions:
  1871. self._set_extensions()
  1872. return self._crl_distribution_points_value
  1873. @property
  1874. def certificate_policies_value(self):
  1875. """
  1876. This extension defines policies in CA certificates under which
  1877. certificates may be issued. In end-entity certificates, the inclusion
  1878. of a policy indicates the issuance of the certificate follows the
  1879. policy.
  1880. :return:
  1881. None or a CertificatePolicies object
  1882. """
  1883. if not self._processed_extensions:
  1884. self._set_extensions()
  1885. return self._certificate_policies_value
  1886. @property
  1887. def policy_mappings_value(self):
  1888. """
  1889. This extension allows mapping policy OIDs to other OIDs. This is used
  1890. to allow different policies to be treated as equivalent in the process
  1891. of validation.
  1892. :return:
  1893. None or a PolicyMappings object
  1894. """
  1895. if not self._processed_extensions:
  1896. self._set_extensions()
  1897. return self._policy_mappings_value
  1898. @property
  1899. def authority_key_identifier_value(self):
  1900. """
  1901. This extension helps in identifying the public key with which to
  1902. validate the authenticity of the certificate.
  1903. :return:
  1904. None or an AuthorityKeyIdentifier object
  1905. """
  1906. if not self._processed_extensions:
  1907. self._set_extensions()
  1908. return self._authority_key_identifier_value
  1909. @property
  1910. def policy_constraints_value(self):
  1911. """
  1912. This extension is used to control if policy mapping is allowed and
  1913. when policies are required.
  1914. :return:
  1915. None or a PolicyConstraints object
  1916. """
  1917. if not self._processed_extensions:
  1918. self._set_extensions()
  1919. return self._policy_constraints_value
  1920. @property
  1921. def freshest_crl_value(self):
  1922. """
  1923. This extension is used to help locate any available delta CRLs
  1924. :return:
  1925. None or an CRLDistributionPoints object
  1926. """
  1927. if not self._processed_extensions:
  1928. self._set_extensions()
  1929. return self._freshest_crl_value
  1930. @property
  1931. def inhibit_any_policy_value(self):
  1932. """
  1933. This extension is used to prevent mapping of the any policy to
  1934. specific requirements
  1935. :return:
  1936. None or a Integer object
  1937. """
  1938. if not self._processed_extensions:
  1939. self._set_extensions()
  1940. return self._inhibit_any_policy_value
  1941. @property
  1942. def extended_key_usage_value(self):
  1943. """
  1944. This extension is used to define additional purposes for the public key
  1945. beyond what is contained in the basic constraints.
  1946. :return:
  1947. None or an ExtKeyUsageSyntax object
  1948. """
  1949. if not self._processed_extensions:
  1950. self._set_extensions()
  1951. return self._extended_key_usage_value
  1952. @property
  1953. def authority_information_access_value(self):
  1954. """
  1955. This extension is used to locate the CA certificate used to sign this
  1956. certificate, or the OCSP responder for this certificate.
  1957. :return:
  1958. None or an AuthorityInfoAccessSyntax object
  1959. """
  1960. if not self._processed_extensions:
  1961. self._set_extensions()
  1962. return self._authority_information_access_value
  1963. @property
  1964. def subject_information_access_value(self):
  1965. """
  1966. This extension is used to access information about the subject of this
  1967. certificate.
  1968. :return:
  1969. None or a SubjectInfoAccessSyntax object
  1970. """
  1971. if not self._processed_extensions:
  1972. self._set_extensions()
  1973. return self._subject_information_access_value
  1974. @property
  1975. def tls_feature_value(self):
  1976. """
  1977. This extension is used to list the TLS features a server must respond
  1978. with if a client initiates a request supporting them.
  1979. :return:
  1980. None or a Features object
  1981. """
  1982. if not self._processed_extensions:
  1983. self._set_extensions()
  1984. return self._tls_feature_value
  1985. @property
  1986. def ocsp_no_check_value(self):
  1987. """
  1988. This extension is used on certificates of OCSP responders, indicating
  1989. that revocation information for the certificate should never need to
  1990. be verified, thus preventing possible loops in path validation.
  1991. :return:
  1992. None or a Null object (if present)
  1993. """
  1994. if not self._processed_extensions:
  1995. self._set_extensions()
  1996. return self._ocsp_no_check_value
  1997. @property
  1998. def signature(self):
  1999. """
  2000. :return:
  2001. A byte string of the signature
  2002. """
  2003. return self['signature_value'].native
  2004. @property
  2005. def signature_algo(self):
  2006. """
  2007. :return:
  2008. A unicode string of "rsassa_pkcs1v15", "rsassa_pss", "dsa", "ecdsa"
  2009. """
  2010. return self['signature_algorithm'].signature_algo
  2011. @property
  2012. def hash_algo(self):
  2013. """
  2014. :return:
  2015. A unicode string of "md2", "md5", "sha1", "sha224", "sha256",
  2016. "sha384", "sha512", "sha512_224", "sha512_256"
  2017. """
  2018. return self['signature_algorithm'].hash_algo
  2019. @property
  2020. def public_key(self):
  2021. """
  2022. :return:
  2023. The PublicKeyInfo object for this certificate
  2024. """
  2025. return self['tbs_certificate']['subject_public_key_info']
  2026. @property
  2027. def subject(self):
  2028. """
  2029. :return:
  2030. The Name object for the subject of this certificate
  2031. """
  2032. return self['tbs_certificate']['subject']
  2033. @property
  2034. def issuer(self):
  2035. """
  2036. :return:
  2037. The Name object for the issuer of this certificate
  2038. """
  2039. return self['tbs_certificate']['issuer']
  2040. @property
  2041. def serial_number(self):
  2042. """
  2043. :return:
  2044. An integer of the certificate's serial number
  2045. """
  2046. return self['tbs_certificate']['serial_number'].native
  2047. @property
  2048. def key_identifier(self):
  2049. """
  2050. :return:
  2051. None or a byte string of the certificate's key identifier from the
  2052. key identifier extension
  2053. """
  2054. if not self.key_identifier_value:
  2055. return None
  2056. return self.key_identifier_value.native
  2057. @property
  2058. def issuer_serial(self):
  2059. """
  2060. :return:
  2061. A byte string of the SHA-256 hash of the issuer concatenated with
  2062. the ascii character ":", concatenated with the serial number as
  2063. an ascii string
  2064. """
  2065. if self._issuer_serial is None:
  2066. self._issuer_serial = self.issuer.sha256 + b':' + str_cls(self.serial_number).encode('ascii')
  2067. return self._issuer_serial
  2068. @property
  2069. def authority_key_identifier(self):
  2070. """
  2071. :return:
  2072. None or a byte string of the key_identifier from the authority key
  2073. identifier extension
  2074. """
  2075. if not self.authority_key_identifier_value:
  2076. return None
  2077. return self.authority_key_identifier_value['key_identifier'].native
  2078. @property
  2079. def authority_issuer_serial(self):
  2080. """
  2081. :return:
  2082. None or a byte string of the SHA-256 hash of the isser from the
  2083. authority key identifier extension concatenated with the ascii
  2084. character ":", concatenated with the serial number from the
  2085. authority key identifier extension as an ascii string
  2086. """
  2087. if self._authority_issuer_serial is False:
  2088. akiv = self.authority_key_identifier_value
  2089. if akiv and akiv['authority_cert_issuer'].native:
  2090. issuer = self.authority_key_identifier_value['authority_cert_issuer'][0].chosen
  2091. # We untag the element since it is tagged via being a choice from GeneralName
  2092. issuer = issuer.untag()
  2093. authority_serial = self.authority_key_identifier_value['authority_cert_serial_number'].native
  2094. self._authority_issuer_serial = issuer.sha256 + b':' + str_cls(authority_serial).encode('ascii')
  2095. else:
  2096. self._authority_issuer_serial = None
  2097. return self._authority_issuer_serial
  2098. @property
  2099. def crl_distribution_points(self):
  2100. """
  2101. Returns complete CRL URLs - does not include delta CRLs
  2102. :return:
  2103. A list of zero or more DistributionPoint objects
  2104. """
  2105. if self._crl_distribution_points is None:
  2106. self._crl_distribution_points = self._get_http_crl_distribution_points(self.crl_distribution_points_value)
  2107. return self._crl_distribution_points
  2108. @property
  2109. def delta_crl_distribution_points(self):
  2110. """
  2111. Returns delta CRL URLs - does not include complete CRLs
  2112. :return:
  2113. A list of zero or more DistributionPoint objects
  2114. """
  2115. if self._delta_crl_distribution_points is None:
  2116. self._delta_crl_distribution_points = self._get_http_crl_distribution_points(self.freshest_crl_value)
  2117. return self._delta_crl_distribution_points
  2118. def _get_http_crl_distribution_points(self, crl_distribution_points):
  2119. """
  2120. Fetches the DistributionPoint object for non-relative, HTTP CRLs
  2121. referenced by the certificate
  2122. :param crl_distribution_points:
  2123. A CRLDistributionPoints object to grab the DistributionPoints from
  2124. :return:
  2125. A list of zero or more DistributionPoint objects
  2126. """
  2127. output = []
  2128. if crl_distribution_points is None:
  2129. return []
  2130. for distribution_point in crl_distribution_points:
  2131. distribution_point_name = distribution_point['distribution_point']
  2132. if distribution_point_name is VOID:
  2133. continue
  2134. # RFC 5280 indicates conforming CA should not use the relative form
  2135. if distribution_point_name.name == 'name_relative_to_crl_issuer':
  2136. continue
  2137. # This library is currently only concerned with HTTP-based CRLs
  2138. for general_name in distribution_point_name.chosen:
  2139. if general_name.name == 'uniform_resource_identifier':
  2140. output.append(distribution_point)
  2141. return output
  2142. @property
  2143. def ocsp_urls(self):
  2144. """
  2145. :return:
  2146. A list of zero or more unicode strings of the OCSP URLs for this
  2147. cert
  2148. """
  2149. if not self.authority_information_access_value:
  2150. return []
  2151. output = []
  2152. for entry in self.authority_information_access_value:
  2153. if entry['access_method'].native == 'ocsp':
  2154. location = entry['access_location']
  2155. if location.name != 'uniform_resource_identifier':
  2156. continue
  2157. url = location.native
  2158. if url.lower().startswith(('http://', 'https://', 'ldap://', 'ldaps://')):
  2159. output.append(url)
  2160. return output
  2161. @property
  2162. def valid_domains(self):
  2163. """
  2164. :return:
  2165. A list of unicode strings of valid domain names for the certificate.
  2166. Wildcard certificates will have a domain in the form: *.example.com
  2167. """
  2168. if self._valid_domains is None:
  2169. self._valid_domains = []
  2170. # For the subject alt name extension, we can look at the name of
  2171. # the choice selected since it distinguishes between domain names,
  2172. # email addresses, IPs, etc
  2173. if self.subject_alt_name_value:
  2174. for general_name in self.subject_alt_name_value:
  2175. if general_name.name == 'dns_name' and general_name.native not in self._valid_domains:
  2176. self._valid_domains.append(general_name.native)
  2177. # If there was no subject alt name extension, and the common name
  2178. # in the subject looks like a domain, that is considered the valid
  2179. # list. This is done because according to
  2180. # https://tools.ietf.org/html/rfc6125#section-6.4.4, the common
  2181. # name should not be used if the subject alt name is present.
  2182. else:
  2183. pattern = re.compile('^(\\*\\.)?(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-]*[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}$')
  2184. for rdn in self.subject.chosen:
  2185. for name_type_value in rdn:
  2186. if name_type_value['type'].native == 'common_name':
  2187. value = name_type_value['value'].native
  2188. if pattern.match(value):
  2189. self._valid_domains.append(value)
  2190. return self._valid_domains
  2191. @property
  2192. def valid_ips(self):
  2193. """
  2194. :return:
  2195. A list of unicode strings of valid IP addresses for the certificate
  2196. """
  2197. if self._valid_ips is None:
  2198. self._valid_ips = []
  2199. if self.subject_alt_name_value:
  2200. for general_name in self.subject_alt_name_value:
  2201. if general_name.name == 'ip_address':
  2202. self._valid_ips.append(general_name.native)
  2203. return self._valid_ips
  2204. @property
  2205. def ca(self):
  2206. """
  2207. :return;
  2208. A boolean - if the certificate is marked as a CA
  2209. """
  2210. return self.basic_constraints_value and self.basic_constraints_value['ca'].native
  2211. @property
  2212. def max_path_length(self):
  2213. """
  2214. :return;
  2215. None or an integer of the maximum path length
  2216. """
  2217. if not self.ca:
  2218. return None
  2219. return self.basic_constraints_value['path_len_constraint'].native
  2220. @property
  2221. def self_issued(self):
  2222. """
  2223. :return:
  2224. A boolean - if the certificate is self-issued, as defined by RFC
  2225. 5280
  2226. """
  2227. if self._self_issued is None:
  2228. self._self_issued = self.subject == self.issuer
  2229. return self._self_issued
  2230. @property
  2231. def self_signed(self):
  2232. """
  2233. :return:
  2234. A unicode string of "no" or "maybe". The "maybe" result will
  2235. be returned if the certificate issuer and subject are the same.
  2236. If a key identifier and authority key identifier are present,
  2237. they will need to match otherwise "no" will be returned.
  2238. To verify is a certificate is truly self-signed, the signature
  2239. will need to be verified. See the certvalidator package for
  2240. one possible solution.
  2241. """
  2242. if self._self_signed is None:
  2243. self._self_signed = 'no'
  2244. if self.self_issued:
  2245. if self.key_identifier:
  2246. if not self.authority_key_identifier:
  2247. self._self_signed = 'maybe'
  2248. elif self.authority_key_identifier == self.key_identifier:
  2249. self._self_signed = 'maybe'
  2250. else:
  2251. self._self_signed = 'maybe'
  2252. return self._self_signed
  2253. @property
  2254. def sha1(self):
  2255. """
  2256. :return:
  2257. The SHA-1 hash of the DER-encoded bytes of this complete certificate
  2258. """
  2259. if self._sha1 is None:
  2260. self._sha1 = hashlib.sha1(self.dump()).digest()
  2261. return self._sha1
  2262. @property
  2263. def sha1_fingerprint(self):
  2264. """
  2265. :return:
  2266. A unicode string of the SHA-1 hash, formatted using hex encoding
  2267. with a space between each pair of characters, all uppercase
  2268. """
  2269. return ' '.join('%02X' % c for c in bytes_to_list(self.sha1))
  2270. @property
  2271. def sha256(self):
  2272. """
  2273. :return:
  2274. The SHA-256 hash of the DER-encoded bytes of this complete
  2275. certificate
  2276. """
  2277. if self._sha256 is None:
  2278. self._sha256 = hashlib.sha256(self.dump()).digest()
  2279. return self._sha256
  2280. @property
  2281. def sha256_fingerprint(self):
  2282. """
  2283. :return:
  2284. A unicode string of the SHA-256 hash, formatted using hex encoding
  2285. with a space between each pair of characters, all uppercase
  2286. """
  2287. return ' '.join('%02X' % c for c in bytes_to_list(self.sha256))
  2288. def is_valid_domain_ip(self, domain_ip):
  2289. """
  2290. Check if a domain name or IP address is valid according to the
  2291. certificate
  2292. :param domain_ip:
  2293. A unicode string of a domain name or IP address
  2294. :return:
  2295. A boolean - if the domain or IP is valid for the certificate
  2296. """
  2297. if not isinstance(domain_ip, str_cls):
  2298. raise TypeError(unwrap(
  2299. '''
  2300. domain_ip must be a unicode string, not %s
  2301. ''',
  2302. type_name(domain_ip)
  2303. ))
  2304. encoded_domain_ip = domain_ip.encode('idna').decode('ascii').lower()
  2305. is_ipv6 = encoded_domain_ip.find(':') != -1
  2306. is_ipv4 = not is_ipv6 and re.match('^\\d+\\.\\d+\\.\\d+\\.\\d+$', encoded_domain_ip)
  2307. is_domain = not is_ipv6 and not is_ipv4
  2308. # Handle domain name checks
  2309. if is_domain:
  2310. if not self.valid_domains:
  2311. return False
  2312. domain_labels = encoded_domain_ip.split('.')
  2313. for valid_domain in self.valid_domains:
  2314. encoded_valid_domain = valid_domain.encode('idna').decode('ascii').lower()
  2315. valid_domain_labels = encoded_valid_domain.split('.')
  2316. # The domain must be equal in label length to match
  2317. if len(valid_domain_labels) != len(domain_labels):
  2318. continue
  2319. if valid_domain_labels == domain_labels:
  2320. return True
  2321. is_wildcard = self._is_wildcard_domain(encoded_valid_domain)
  2322. if is_wildcard and self._is_wildcard_match(domain_labels, valid_domain_labels):
  2323. return True
  2324. return False
  2325. # Handle IP address checks
  2326. if not self.valid_ips:
  2327. return False
  2328. family = socket.AF_INET if is_ipv4 else socket.AF_INET6
  2329. normalized_ip = inet_pton(family, encoded_domain_ip)
  2330. for valid_ip in self.valid_ips:
  2331. valid_family = socket.AF_INET if valid_ip.find('.') != -1 else socket.AF_INET6
  2332. normalized_valid_ip = inet_pton(valid_family, valid_ip)
  2333. if normalized_valid_ip == normalized_ip:
  2334. return True
  2335. return False
  2336. def _is_wildcard_domain(self, domain):
  2337. """
  2338. Checks if a domain is a valid wildcard according to
  2339. https://tools.ietf.org/html/rfc6125#section-6.4.3
  2340. :param domain:
  2341. A unicode string of the domain name, where any U-labels from an IDN
  2342. have been converted to A-labels
  2343. :return:
  2344. A boolean - if the domain is a valid wildcard domain
  2345. """
  2346. # The * character must be present for a wildcard match, and if there is
  2347. # most than one, it is an invalid wildcard specification
  2348. if domain.count('*') != 1:
  2349. return False
  2350. labels = domain.lower().split('.')
  2351. if not labels:
  2352. return False
  2353. # Wildcards may only appear in the left-most label
  2354. if labels[0].find('*') == -1:
  2355. return False
  2356. # Wildcards may not be embedded in an A-label from an IDN
  2357. if labels[0][0:4] == 'xn--':
  2358. return False
  2359. return True
  2360. def _is_wildcard_match(self, domain_labels, valid_domain_labels):
  2361. """
  2362. Determines if the labels in a domain are a match for labels from a
  2363. wildcard valid domain name
  2364. :param domain_labels:
  2365. A list of unicode strings, with A-label form for IDNs, of the labels
  2366. in the domain name to check
  2367. :param valid_domain_labels:
  2368. A list of unicode strings, with A-label form for IDNs, of the labels
  2369. in a wildcard domain pattern
  2370. :return:
  2371. A boolean - if the domain matches the valid domain
  2372. """
  2373. first_domain_label = domain_labels[0]
  2374. other_domain_labels = domain_labels[1:]
  2375. wildcard_label = valid_domain_labels[0]
  2376. other_valid_domain_labels = valid_domain_labels[1:]
  2377. # The wildcard is only allowed in the first label, so if
  2378. # The subsequent labels are not equal, there is no match
  2379. if other_domain_labels != other_valid_domain_labels:
  2380. return False
  2381. if wildcard_label == '*':
  2382. return True
  2383. wildcard_regex = re.compile('^' + wildcard_label.replace('*', '.*') + '$')
  2384. if wildcard_regex.match(first_domain_label):
  2385. return True
  2386. return False
  2387. # The structures are taken from the OpenSSL source file x_x509a.c, and specify
  2388. # extra information that is added to X.509 certificates to store trust
  2389. # information about the certificate.
  2390. class KeyPurposeIdentifiers(SequenceOf):
  2391. _child_spec = KeyPurposeId
  2392. class SequenceOfAlgorithmIdentifiers(SequenceOf):
  2393. _child_spec = AlgorithmIdentifier
  2394. class CertificateAux(Sequence):
  2395. _fields = [
  2396. ('trust', KeyPurposeIdentifiers, {'optional': True}),
  2397. ('reject', KeyPurposeIdentifiers, {'implicit': 0, 'optional': True}),
  2398. ('alias', UTF8String, {'optional': True}),
  2399. ('keyid', OctetString, {'optional': True}),
  2400. ('other', SequenceOfAlgorithmIdentifiers, {'implicit': 1, 'optional': True}),
  2401. ]
  2402. class TrustedCertificate(Concat):
  2403. _child_specs = [Certificate, CertificateAux]