extensions.py 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093
  1. # This file is dual licensed under the terms of the Apache License, Version
  2. # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3. # for complete details.
  4. import abc
  5. import datetime
  6. import hashlib
  7. import ipaddress
  8. import typing
  9. from cryptography import utils
  10. from cryptography.hazmat.bindings._rust import asn1
  11. from cryptography.hazmat.primitives import constant_time, serialization
  12. from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey
  13. from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
  14. from cryptography.hazmat.primitives.asymmetric.types import PUBLIC_KEY_TYPES
  15. from cryptography.x509.certificate_transparency import (
  16. SignedCertificateTimestamp,
  17. )
  18. from cryptography.x509.general_name import (
  19. DNSName,
  20. DirectoryName,
  21. GeneralName,
  22. IPAddress,
  23. OtherName,
  24. RFC822Name,
  25. RegisteredID,
  26. UniformResourceIdentifier,
  27. _IPADDRESS_TYPES,
  28. )
  29. from cryptography.x509.name import Name, RelativeDistinguishedName
  30. from cryptography.x509.oid import (
  31. CRLEntryExtensionOID,
  32. ExtensionOID,
  33. OCSPExtensionOID,
  34. ObjectIdentifier,
  35. )
  36. ExtensionTypeVar = typing.TypeVar("ExtensionTypeVar", bound="ExtensionType")
  37. def _key_identifier_from_public_key(public_key: PUBLIC_KEY_TYPES) -> bytes:
  38. if isinstance(public_key, RSAPublicKey):
  39. data = public_key.public_bytes(
  40. serialization.Encoding.DER,
  41. serialization.PublicFormat.PKCS1,
  42. )
  43. elif isinstance(public_key, EllipticCurvePublicKey):
  44. data = public_key.public_bytes(
  45. serialization.Encoding.X962,
  46. serialization.PublicFormat.UncompressedPoint,
  47. )
  48. else:
  49. # This is a very slow way to do this.
  50. serialized = public_key.public_bytes(
  51. serialization.Encoding.DER,
  52. serialization.PublicFormat.SubjectPublicKeyInfo,
  53. )
  54. data = asn1.parse_spki_for_data(serialized)
  55. return hashlib.sha1(data).digest()
  56. def _make_sequence_methods(field_name: str):
  57. def len_method(self) -> int:
  58. return len(getattr(self, field_name))
  59. def iter_method(self):
  60. return iter(getattr(self, field_name))
  61. def getitem_method(self, idx):
  62. return getattr(self, field_name)[idx]
  63. return len_method, iter_method, getitem_method
  64. class DuplicateExtension(Exception):
  65. def __init__(self, msg: str, oid: ObjectIdentifier) -> None:
  66. super(DuplicateExtension, self).__init__(msg)
  67. self.oid = oid
  68. class ExtensionNotFound(Exception):
  69. def __init__(self, msg: str, oid: ObjectIdentifier) -> None:
  70. super(ExtensionNotFound, self).__init__(msg)
  71. self.oid = oid
  72. class ExtensionType(metaclass=abc.ABCMeta):
  73. oid: typing.ClassVar[ObjectIdentifier]
  74. class Extensions(object):
  75. def __init__(
  76. self, extensions: typing.Iterable["Extension[ExtensionType]"]
  77. ) -> None:
  78. self._extensions = list(extensions)
  79. def get_extension_for_oid(
  80. self, oid: ObjectIdentifier
  81. ) -> "Extension[ExtensionType]":
  82. for ext in self:
  83. if ext.oid == oid:
  84. return ext
  85. raise ExtensionNotFound("No {} extension was found".format(oid), oid)
  86. def get_extension_for_class(
  87. self, extclass: typing.Type[ExtensionTypeVar]
  88. ) -> "Extension[ExtensionTypeVar]":
  89. if extclass is UnrecognizedExtension:
  90. raise TypeError(
  91. "UnrecognizedExtension can't be used with "
  92. "get_extension_for_class because more than one instance of the"
  93. " class may be present."
  94. )
  95. for ext in self:
  96. if isinstance(ext.value, extclass):
  97. return ext
  98. raise ExtensionNotFound(
  99. "No {} extension was found".format(extclass), extclass.oid
  100. )
  101. __len__, __iter__, __getitem__ = _make_sequence_methods("_extensions")
  102. def __repr__(self) -> str:
  103. return "<Extensions({})>".format(self._extensions)
  104. class CRLNumber(ExtensionType):
  105. oid = ExtensionOID.CRL_NUMBER
  106. def __init__(self, crl_number: int) -> None:
  107. if not isinstance(crl_number, int):
  108. raise TypeError("crl_number must be an integer")
  109. self._crl_number = crl_number
  110. def __eq__(self, other: typing.Any) -> bool:
  111. if not isinstance(other, CRLNumber):
  112. return NotImplemented
  113. return self.crl_number == other.crl_number
  114. def __ne__(self, other: typing.Any) -> bool:
  115. return not self == other
  116. def __hash__(self) -> int:
  117. return hash(self.crl_number)
  118. def __repr__(self) -> str:
  119. return "<CRLNumber({})>".format(self.crl_number)
  120. @property
  121. def crl_number(self) -> int:
  122. return self._crl_number
  123. class AuthorityKeyIdentifier(ExtensionType):
  124. oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER
  125. def __init__(
  126. self,
  127. key_identifier: typing.Optional[bytes],
  128. authority_cert_issuer: typing.Optional[typing.Iterable[GeneralName]],
  129. authority_cert_serial_number: typing.Optional[int],
  130. ) -> None:
  131. if (authority_cert_issuer is None) != (
  132. authority_cert_serial_number is None
  133. ):
  134. raise ValueError(
  135. "authority_cert_issuer and authority_cert_serial_number "
  136. "must both be present or both None"
  137. )
  138. if authority_cert_issuer is not None:
  139. authority_cert_issuer = list(authority_cert_issuer)
  140. if not all(
  141. isinstance(x, GeneralName) for x in authority_cert_issuer
  142. ):
  143. raise TypeError(
  144. "authority_cert_issuer must be a list of GeneralName "
  145. "objects"
  146. )
  147. if authority_cert_serial_number is not None and not isinstance(
  148. authority_cert_serial_number, int
  149. ):
  150. raise TypeError("authority_cert_serial_number must be an integer")
  151. self._key_identifier = key_identifier
  152. self._authority_cert_issuer = authority_cert_issuer
  153. self._authority_cert_serial_number = authority_cert_serial_number
  154. @classmethod
  155. def from_issuer_public_key(
  156. cls, public_key: PUBLIC_KEY_TYPES
  157. ) -> "AuthorityKeyIdentifier":
  158. digest = _key_identifier_from_public_key(public_key)
  159. return cls(
  160. key_identifier=digest,
  161. authority_cert_issuer=None,
  162. authority_cert_serial_number=None,
  163. )
  164. @classmethod
  165. def from_issuer_subject_key_identifier(
  166. cls, ski: "SubjectKeyIdentifier"
  167. ) -> "AuthorityKeyIdentifier":
  168. return cls(
  169. key_identifier=ski.digest,
  170. authority_cert_issuer=None,
  171. authority_cert_serial_number=None,
  172. )
  173. def __repr__(self) -> str:
  174. return (
  175. "<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
  176. "authority_cert_issuer={0.authority_cert_issuer}, "
  177. "authority_cert_serial_number={0.authority_cert_serial_number}"
  178. ")>".format(self)
  179. )
  180. def __eq__(self, other: typing.Any) -> bool:
  181. if not isinstance(other, AuthorityKeyIdentifier):
  182. return NotImplemented
  183. return (
  184. self.key_identifier == other.key_identifier
  185. and self.authority_cert_issuer == other.authority_cert_issuer
  186. and self.authority_cert_serial_number
  187. == other.authority_cert_serial_number
  188. )
  189. def __ne__(self, other: typing.Any) -> bool:
  190. return not self == other
  191. def __hash__(self) -> int:
  192. if self.authority_cert_issuer is None:
  193. aci = None
  194. else:
  195. aci = tuple(self.authority_cert_issuer)
  196. return hash(
  197. (self.key_identifier, aci, self.authority_cert_serial_number)
  198. )
  199. @property
  200. def key_identifier(self) -> typing.Optional[bytes]:
  201. return self._key_identifier
  202. @property
  203. def authority_cert_issuer(
  204. self,
  205. ) -> typing.Optional[typing.List[GeneralName]]:
  206. return self._authority_cert_issuer
  207. @property
  208. def authority_cert_serial_number(self) -> typing.Optional[int]:
  209. return self._authority_cert_serial_number
  210. class SubjectKeyIdentifier(ExtensionType):
  211. oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER
  212. def __init__(self, digest: bytes) -> None:
  213. self._digest = digest
  214. @classmethod
  215. def from_public_key(
  216. cls, public_key: PUBLIC_KEY_TYPES
  217. ) -> "SubjectKeyIdentifier":
  218. return cls(_key_identifier_from_public_key(public_key))
  219. @property
  220. def digest(self) -> bytes:
  221. return self._digest
  222. @property
  223. def key_identifier(self) -> bytes:
  224. return self._digest
  225. def __repr__(self) -> str:
  226. return "<SubjectKeyIdentifier(digest={0!r})>".format(self.digest)
  227. def __eq__(self, other: typing.Any) -> bool:
  228. if not isinstance(other, SubjectKeyIdentifier):
  229. return NotImplemented
  230. return constant_time.bytes_eq(self.digest, other.digest)
  231. def __ne__(self, other: typing.Any) -> bool:
  232. return not self == other
  233. def __hash__(self) -> int:
  234. return hash(self.digest)
  235. class AuthorityInformationAccess(ExtensionType):
  236. oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS
  237. def __init__(
  238. self, descriptions: typing.Iterable["AccessDescription"]
  239. ) -> None:
  240. descriptions = list(descriptions)
  241. if not all(isinstance(x, AccessDescription) for x in descriptions):
  242. raise TypeError(
  243. "Every item in the descriptions list must be an "
  244. "AccessDescription"
  245. )
  246. self._descriptions = descriptions
  247. __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
  248. def __repr__(self) -> str:
  249. return "<AuthorityInformationAccess({})>".format(self._descriptions)
  250. def __eq__(self, other: typing.Any) -> bool:
  251. if not isinstance(other, AuthorityInformationAccess):
  252. return NotImplemented
  253. return self._descriptions == other._descriptions
  254. def __ne__(self, other: typing.Any) -> bool:
  255. return not self == other
  256. def __hash__(self) -> int:
  257. return hash(tuple(self._descriptions))
  258. class SubjectInformationAccess(ExtensionType):
  259. oid = ExtensionOID.SUBJECT_INFORMATION_ACCESS
  260. def __init__(
  261. self, descriptions: typing.Iterable["AccessDescription"]
  262. ) -> None:
  263. descriptions = list(descriptions)
  264. if not all(isinstance(x, AccessDescription) for x in descriptions):
  265. raise TypeError(
  266. "Every item in the descriptions list must be an "
  267. "AccessDescription"
  268. )
  269. self._descriptions = descriptions
  270. __len__, __iter__, __getitem__ = _make_sequence_methods("_descriptions")
  271. def __repr__(self) -> str:
  272. return "<SubjectInformationAccess({})>".format(self._descriptions)
  273. def __eq__(self, other: typing.Any) -> bool:
  274. if not isinstance(other, SubjectInformationAccess):
  275. return NotImplemented
  276. return self._descriptions == other._descriptions
  277. def __ne__(self, other: typing.Any) -> bool:
  278. return not self == other
  279. def __hash__(self) -> int:
  280. return hash(tuple(self._descriptions))
  281. class AccessDescription(object):
  282. def __init__(
  283. self, access_method: ObjectIdentifier, access_location: GeneralName
  284. ) -> None:
  285. if not isinstance(access_method, ObjectIdentifier):
  286. raise TypeError("access_method must be an ObjectIdentifier")
  287. if not isinstance(access_location, GeneralName):
  288. raise TypeError("access_location must be a GeneralName")
  289. self._access_method = access_method
  290. self._access_location = access_location
  291. def __repr__(self) -> str:
  292. return (
  293. "<AccessDescription(access_method={0.access_method}, access_locati"
  294. "on={0.access_location})>".format(self)
  295. )
  296. def __eq__(self, other: typing.Any) -> bool:
  297. if not isinstance(other, AccessDescription):
  298. return NotImplemented
  299. return (
  300. self.access_method == other.access_method
  301. and self.access_location == other.access_location
  302. )
  303. def __ne__(self, other: typing.Any) -> bool:
  304. return not self == other
  305. def __hash__(self) -> int:
  306. return hash((self.access_method, self.access_location))
  307. @property
  308. def access_method(self) -> ObjectIdentifier:
  309. return self._access_method
  310. @property
  311. def access_location(self) -> GeneralName:
  312. return self._access_location
  313. class BasicConstraints(ExtensionType):
  314. oid = ExtensionOID.BASIC_CONSTRAINTS
  315. def __init__(self, ca: bool, path_length: typing.Optional[int]) -> None:
  316. if not isinstance(ca, bool):
  317. raise TypeError("ca must be a boolean value")
  318. if path_length is not None and not ca:
  319. raise ValueError("path_length must be None when ca is False")
  320. if path_length is not None and (
  321. not isinstance(path_length, int) or path_length < 0
  322. ):
  323. raise TypeError(
  324. "path_length must be a non-negative integer or None"
  325. )
  326. self._ca = ca
  327. self._path_length = path_length
  328. @property
  329. def ca(self) -> bool:
  330. return self._ca
  331. @property
  332. def path_length(self) -> typing.Optional[int]:
  333. return self._path_length
  334. def __repr__(self) -> str:
  335. return (
  336. "<BasicConstraints(ca={0.ca}, " "path_length={0.path_length})>"
  337. ).format(self)
  338. def __eq__(self, other: typing.Any) -> bool:
  339. if not isinstance(other, BasicConstraints):
  340. return NotImplemented
  341. return self.ca == other.ca and self.path_length == other.path_length
  342. def __ne__(self, other: typing.Any) -> bool:
  343. return not self == other
  344. def __hash__(self) -> int:
  345. return hash((self.ca, self.path_length))
  346. class DeltaCRLIndicator(ExtensionType):
  347. oid = ExtensionOID.DELTA_CRL_INDICATOR
  348. def __init__(self, crl_number: int) -> None:
  349. if not isinstance(crl_number, int):
  350. raise TypeError("crl_number must be an integer")
  351. self._crl_number = crl_number
  352. @property
  353. def crl_number(self) -> int:
  354. return self._crl_number
  355. def __eq__(self, other: typing.Any) -> bool:
  356. if not isinstance(other, DeltaCRLIndicator):
  357. return NotImplemented
  358. return self.crl_number == other.crl_number
  359. def __ne__(self, other: typing.Any) -> bool:
  360. return not self == other
  361. def __hash__(self) -> int:
  362. return hash(self.crl_number)
  363. def __repr__(self) -> str:
  364. return "<DeltaCRLIndicator(crl_number={0.crl_number})>".format(self)
  365. class CRLDistributionPoints(ExtensionType):
  366. oid = ExtensionOID.CRL_DISTRIBUTION_POINTS
  367. def __init__(
  368. self, distribution_points: typing.Iterable["DistributionPoint"]
  369. ) -> None:
  370. distribution_points = list(distribution_points)
  371. if not all(
  372. isinstance(x, DistributionPoint) for x in distribution_points
  373. ):
  374. raise TypeError(
  375. "distribution_points must be a list of DistributionPoint "
  376. "objects"
  377. )
  378. self._distribution_points = distribution_points
  379. __len__, __iter__, __getitem__ = _make_sequence_methods(
  380. "_distribution_points"
  381. )
  382. def __repr__(self) -> str:
  383. return "<CRLDistributionPoints({})>".format(self._distribution_points)
  384. def __eq__(self, other: typing.Any) -> bool:
  385. if not isinstance(other, CRLDistributionPoints):
  386. return NotImplemented
  387. return self._distribution_points == other._distribution_points
  388. def __ne__(self, other: typing.Any) -> bool:
  389. return not self == other
  390. def __hash__(self) -> int:
  391. return hash(tuple(self._distribution_points))
  392. class FreshestCRL(ExtensionType):
  393. oid = ExtensionOID.FRESHEST_CRL
  394. def __init__(
  395. self, distribution_points: typing.Iterable["DistributionPoint"]
  396. ) -> None:
  397. distribution_points = list(distribution_points)
  398. if not all(
  399. isinstance(x, DistributionPoint) for x in distribution_points
  400. ):
  401. raise TypeError(
  402. "distribution_points must be a list of DistributionPoint "
  403. "objects"
  404. )
  405. self._distribution_points = distribution_points
  406. __len__, __iter__, __getitem__ = _make_sequence_methods(
  407. "_distribution_points"
  408. )
  409. def __repr__(self) -> str:
  410. return "<FreshestCRL({})>".format(self._distribution_points)
  411. def __eq__(self, other: typing.Any) -> bool:
  412. if not isinstance(other, FreshestCRL):
  413. return NotImplemented
  414. return self._distribution_points == other._distribution_points
  415. def __ne__(self, other: typing.Any) -> bool:
  416. return not self == other
  417. def __hash__(self) -> int:
  418. return hash(tuple(self._distribution_points))
  419. class DistributionPoint(object):
  420. def __init__(
  421. self,
  422. full_name: typing.Optional[typing.Iterable[GeneralName]],
  423. relative_name: typing.Optional[RelativeDistinguishedName],
  424. reasons: typing.Optional[typing.FrozenSet["ReasonFlags"]],
  425. crl_issuer: typing.Optional[typing.Iterable[GeneralName]],
  426. ) -> None:
  427. if full_name and relative_name:
  428. raise ValueError(
  429. "You cannot provide both full_name and relative_name, at "
  430. "least one must be None."
  431. )
  432. if full_name is not None:
  433. full_name = list(full_name)
  434. if not all(isinstance(x, GeneralName) for x in full_name):
  435. raise TypeError(
  436. "full_name must be a list of GeneralName objects"
  437. )
  438. if relative_name:
  439. if not isinstance(relative_name, RelativeDistinguishedName):
  440. raise TypeError(
  441. "relative_name must be a RelativeDistinguishedName"
  442. )
  443. if crl_issuer is not None:
  444. crl_issuer = list(crl_issuer)
  445. if not all(isinstance(x, GeneralName) for x in crl_issuer):
  446. raise TypeError(
  447. "crl_issuer must be None or a list of general names"
  448. )
  449. if reasons and (
  450. not isinstance(reasons, frozenset)
  451. or not all(isinstance(x, ReasonFlags) for x in reasons)
  452. ):
  453. raise TypeError("reasons must be None or frozenset of ReasonFlags")
  454. if reasons and (
  455. ReasonFlags.unspecified in reasons
  456. or ReasonFlags.remove_from_crl in reasons
  457. ):
  458. raise ValueError(
  459. "unspecified and remove_from_crl are not valid reasons in a "
  460. "DistributionPoint"
  461. )
  462. if reasons and not crl_issuer and not (full_name or relative_name):
  463. raise ValueError(
  464. "You must supply crl_issuer, full_name, or relative_name when "
  465. "reasons is not None"
  466. )
  467. self._full_name = full_name
  468. self._relative_name = relative_name
  469. self._reasons = reasons
  470. self._crl_issuer = crl_issuer
  471. def __repr__(self) -> str:
  472. return (
  473. "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
  474. "tive_name}, reasons={0.reasons}, "
  475. "crl_issuer={0.crl_issuer})>".format(self)
  476. )
  477. def __eq__(self, other: typing.Any) -> bool:
  478. if not isinstance(other, DistributionPoint):
  479. return NotImplemented
  480. return (
  481. self.full_name == other.full_name
  482. and self.relative_name == other.relative_name
  483. and self.reasons == other.reasons
  484. and self.crl_issuer == other.crl_issuer
  485. )
  486. def __ne__(self, other: typing.Any) -> bool:
  487. return not self == other
  488. def __hash__(self) -> int:
  489. if self.full_name is not None:
  490. fn: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple(
  491. self.full_name
  492. )
  493. else:
  494. fn = None
  495. if self.crl_issuer is not None:
  496. crl_issuer: typing.Optional[
  497. typing.Tuple[GeneralName, ...]
  498. ] = tuple(self.crl_issuer)
  499. else:
  500. crl_issuer = None
  501. return hash((fn, self.relative_name, self.reasons, crl_issuer))
  502. @property
  503. def full_name(self) -> typing.Optional[typing.List[GeneralName]]:
  504. return self._full_name
  505. @property
  506. def relative_name(self) -> typing.Optional[RelativeDistinguishedName]:
  507. return self._relative_name
  508. @property
  509. def reasons(self) -> typing.Optional[typing.FrozenSet["ReasonFlags"]]:
  510. return self._reasons
  511. @property
  512. def crl_issuer(self) -> typing.Optional[typing.List[GeneralName]]:
  513. return self._crl_issuer
  514. class ReasonFlags(utils.Enum):
  515. unspecified = "unspecified"
  516. key_compromise = "keyCompromise"
  517. ca_compromise = "cACompromise"
  518. affiliation_changed = "affiliationChanged"
  519. superseded = "superseded"
  520. cessation_of_operation = "cessationOfOperation"
  521. certificate_hold = "certificateHold"
  522. privilege_withdrawn = "privilegeWithdrawn"
  523. aa_compromise = "aACompromise"
  524. remove_from_crl = "removeFromCRL"
  525. # These are distribution point bit string mappings. Not to be confused with
  526. # CRLReason reason flags bit string mappings.
  527. # ReasonFlags ::= BIT STRING {
  528. # unused (0),
  529. # keyCompromise (1),
  530. # cACompromise (2),
  531. # affiliationChanged (3),
  532. # superseded (4),
  533. # cessationOfOperation (5),
  534. # certificateHold (6),
  535. # privilegeWithdrawn (7),
  536. # aACompromise (8) }
  537. _REASON_BIT_MAPPING = {
  538. 1: ReasonFlags.key_compromise,
  539. 2: ReasonFlags.ca_compromise,
  540. 3: ReasonFlags.affiliation_changed,
  541. 4: ReasonFlags.superseded,
  542. 5: ReasonFlags.cessation_of_operation,
  543. 6: ReasonFlags.certificate_hold,
  544. 7: ReasonFlags.privilege_withdrawn,
  545. 8: ReasonFlags.aa_compromise,
  546. }
  547. class PolicyConstraints(ExtensionType):
  548. oid = ExtensionOID.POLICY_CONSTRAINTS
  549. def __init__(
  550. self,
  551. require_explicit_policy: typing.Optional[int],
  552. inhibit_policy_mapping: typing.Optional[int],
  553. ) -> None:
  554. if require_explicit_policy is not None and not isinstance(
  555. require_explicit_policy, int
  556. ):
  557. raise TypeError(
  558. "require_explicit_policy must be a non-negative integer or "
  559. "None"
  560. )
  561. if inhibit_policy_mapping is not None and not isinstance(
  562. inhibit_policy_mapping, int
  563. ):
  564. raise TypeError(
  565. "inhibit_policy_mapping must be a non-negative integer or None"
  566. )
  567. if inhibit_policy_mapping is None and require_explicit_policy is None:
  568. raise ValueError(
  569. "At least one of require_explicit_policy and "
  570. "inhibit_policy_mapping must not be None"
  571. )
  572. self._require_explicit_policy = require_explicit_policy
  573. self._inhibit_policy_mapping = inhibit_policy_mapping
  574. def __repr__(self) -> str:
  575. return (
  576. "<PolicyConstraints(require_explicit_policy={0.require_explicit"
  577. "_policy}, inhibit_policy_mapping={0.inhibit_policy_"
  578. "mapping})>".format(self)
  579. )
  580. def __eq__(self, other: typing.Any) -> bool:
  581. if not isinstance(other, PolicyConstraints):
  582. return NotImplemented
  583. return (
  584. self.require_explicit_policy == other.require_explicit_policy
  585. and self.inhibit_policy_mapping == other.inhibit_policy_mapping
  586. )
  587. def __ne__(self, other: typing.Any) -> bool:
  588. return not self == other
  589. def __hash__(self) -> int:
  590. return hash(
  591. (self.require_explicit_policy, self.inhibit_policy_mapping)
  592. )
  593. @property
  594. def require_explicit_policy(self) -> typing.Optional[int]:
  595. return self._require_explicit_policy
  596. @property
  597. def inhibit_policy_mapping(self) -> typing.Optional[int]:
  598. return self._inhibit_policy_mapping
  599. class CertificatePolicies(ExtensionType):
  600. oid = ExtensionOID.CERTIFICATE_POLICIES
  601. def __init__(self, policies: typing.Iterable["PolicyInformation"]) -> None:
  602. policies = list(policies)
  603. if not all(isinstance(x, PolicyInformation) for x in policies):
  604. raise TypeError(
  605. "Every item in the policies list must be a "
  606. "PolicyInformation"
  607. )
  608. self._policies = policies
  609. __len__, __iter__, __getitem__ = _make_sequence_methods("_policies")
  610. def __repr__(self) -> str:
  611. return "<CertificatePolicies({})>".format(self._policies)
  612. def __eq__(self, other: typing.Any) -> bool:
  613. if not isinstance(other, CertificatePolicies):
  614. return NotImplemented
  615. return self._policies == other._policies
  616. def __ne__(self, other: typing.Any) -> bool:
  617. return not self == other
  618. def __hash__(self) -> int:
  619. return hash(tuple(self._policies))
  620. class PolicyInformation(object):
  621. def __init__(
  622. self,
  623. policy_identifier: ObjectIdentifier,
  624. policy_qualifiers: typing.Optional[
  625. typing.Iterable[typing.Union[str, "UserNotice"]]
  626. ],
  627. ) -> None:
  628. if not isinstance(policy_identifier, ObjectIdentifier):
  629. raise TypeError("policy_identifier must be an ObjectIdentifier")
  630. self._policy_identifier = policy_identifier
  631. if policy_qualifiers is not None:
  632. policy_qualifiers = list(policy_qualifiers)
  633. if not all(
  634. isinstance(x, (str, UserNotice)) for x in policy_qualifiers
  635. ):
  636. raise TypeError(
  637. "policy_qualifiers must be a list of strings and/or "
  638. "UserNotice objects or None"
  639. )
  640. self._policy_qualifiers = policy_qualifiers
  641. def __repr__(self) -> str:
  642. return (
  643. "<PolicyInformation(policy_identifier={0.policy_identifier}, polic"
  644. "y_qualifiers={0.policy_qualifiers})>".format(self)
  645. )
  646. def __eq__(self, other: typing.Any) -> bool:
  647. if not isinstance(other, PolicyInformation):
  648. return NotImplemented
  649. return (
  650. self.policy_identifier == other.policy_identifier
  651. and self.policy_qualifiers == other.policy_qualifiers
  652. )
  653. def __ne__(self, other: typing.Any) -> bool:
  654. return not self == other
  655. def __hash__(self) -> int:
  656. if self.policy_qualifiers is not None:
  657. pq: typing.Optional[
  658. typing.Tuple[typing.Union[str, "UserNotice"], ...]
  659. ] = tuple(self.policy_qualifiers)
  660. else:
  661. pq = None
  662. return hash((self.policy_identifier, pq))
  663. @property
  664. def policy_identifier(self) -> ObjectIdentifier:
  665. return self._policy_identifier
  666. @property
  667. def policy_qualifiers(
  668. self,
  669. ) -> typing.Optional[typing.List[typing.Union[str, "UserNotice"]]]:
  670. return self._policy_qualifiers
  671. class UserNotice(object):
  672. def __init__(
  673. self,
  674. notice_reference: typing.Optional["NoticeReference"],
  675. explicit_text: typing.Optional[str],
  676. ) -> None:
  677. if notice_reference and not isinstance(
  678. notice_reference, NoticeReference
  679. ):
  680. raise TypeError(
  681. "notice_reference must be None or a NoticeReference"
  682. )
  683. self._notice_reference = notice_reference
  684. self._explicit_text = explicit_text
  685. def __repr__(self) -> str:
  686. return (
  687. "<UserNotice(notice_reference={0.notice_reference}, explicit_text="
  688. "{0.explicit_text!r})>".format(self)
  689. )
  690. def __eq__(self, other: typing.Any) -> bool:
  691. if not isinstance(other, UserNotice):
  692. return NotImplemented
  693. return (
  694. self.notice_reference == other.notice_reference
  695. and self.explicit_text == other.explicit_text
  696. )
  697. def __ne__(self, other: typing.Any) -> bool:
  698. return not self == other
  699. def __hash__(self) -> int:
  700. return hash((self.notice_reference, self.explicit_text))
  701. @property
  702. def notice_reference(self) -> typing.Optional["NoticeReference"]:
  703. return self._notice_reference
  704. @property
  705. def explicit_text(self) -> typing.Optional[str]:
  706. return self._explicit_text
  707. class NoticeReference(object):
  708. def __init__(
  709. self,
  710. organization: typing.Optional[str],
  711. notice_numbers: typing.Iterable[int],
  712. ) -> None:
  713. self._organization = organization
  714. notice_numbers = list(notice_numbers)
  715. if not all(isinstance(x, int) for x in notice_numbers):
  716. raise TypeError("notice_numbers must be a list of integers")
  717. self._notice_numbers = notice_numbers
  718. def __repr__(self) -> str:
  719. return (
  720. "<NoticeReference(organization={0.organization!r}, notice_numbers="
  721. "{0.notice_numbers})>".format(self)
  722. )
  723. def __eq__(self, other: typing.Any) -> bool:
  724. if not isinstance(other, NoticeReference):
  725. return NotImplemented
  726. return (
  727. self.organization == other.organization
  728. and self.notice_numbers == other.notice_numbers
  729. )
  730. def __ne__(self, other: typing.Any) -> bool:
  731. return not self == other
  732. def __hash__(self) -> int:
  733. return hash((self.organization, tuple(self.notice_numbers)))
  734. @property
  735. def organization(self) -> typing.Optional[str]:
  736. return self._organization
  737. @property
  738. def notice_numbers(self) -> typing.List[int]:
  739. return self._notice_numbers
  740. class ExtendedKeyUsage(ExtensionType):
  741. oid = ExtensionOID.EXTENDED_KEY_USAGE
  742. def __init__(self, usages: typing.Iterable[ObjectIdentifier]) -> None:
  743. usages = list(usages)
  744. if not all(isinstance(x, ObjectIdentifier) for x in usages):
  745. raise TypeError(
  746. "Every item in the usages list must be an ObjectIdentifier"
  747. )
  748. self._usages = usages
  749. __len__, __iter__, __getitem__ = _make_sequence_methods("_usages")
  750. def __repr__(self) -> str:
  751. return "<ExtendedKeyUsage({})>".format(self._usages)
  752. def __eq__(self, other: typing.Any) -> bool:
  753. if not isinstance(other, ExtendedKeyUsage):
  754. return NotImplemented
  755. return self._usages == other._usages
  756. def __ne__(self, other: typing.Any) -> bool:
  757. return not self == other
  758. def __hash__(self) -> int:
  759. return hash(tuple(self._usages))
  760. class OCSPNoCheck(ExtensionType):
  761. oid = ExtensionOID.OCSP_NO_CHECK
  762. def __eq__(self, other: typing.Any) -> bool:
  763. if not isinstance(other, OCSPNoCheck):
  764. return NotImplemented
  765. return True
  766. def __ne__(self, other: typing.Any) -> bool:
  767. return not self == other
  768. def __hash__(self) -> int:
  769. return hash(OCSPNoCheck)
  770. def __repr__(self) -> str:
  771. return "<OCSPNoCheck()>"
  772. class PrecertPoison(ExtensionType):
  773. oid = ExtensionOID.PRECERT_POISON
  774. def __eq__(self, other: typing.Any) -> bool:
  775. if not isinstance(other, PrecertPoison):
  776. return NotImplemented
  777. return True
  778. def __ne__(self, other: typing.Any) -> bool:
  779. return not self == other
  780. def __hash__(self) -> int:
  781. return hash(PrecertPoison)
  782. def __repr__(self) -> str:
  783. return "<PrecertPoison()>"
  784. class TLSFeature(ExtensionType):
  785. oid = ExtensionOID.TLS_FEATURE
  786. def __init__(self, features: typing.Iterable["TLSFeatureType"]) -> None:
  787. features = list(features)
  788. if (
  789. not all(isinstance(x, TLSFeatureType) for x in features)
  790. or len(features) == 0
  791. ):
  792. raise TypeError(
  793. "features must be a list of elements from the TLSFeatureType "
  794. "enum"
  795. )
  796. self._features = features
  797. __len__, __iter__, __getitem__ = _make_sequence_methods("_features")
  798. def __repr__(self) -> str:
  799. return "<TLSFeature(features={0._features})>".format(self)
  800. def __eq__(self, other: typing.Any) -> bool:
  801. if not isinstance(other, TLSFeature):
  802. return NotImplemented
  803. return self._features == other._features
  804. def __ne__(self, other: typing.Any) -> bool:
  805. return not self == other
  806. def __hash__(self) -> int:
  807. return hash(tuple(self._features))
  808. class TLSFeatureType(utils.Enum):
  809. # status_request is defined in RFC 6066 and is used for what is commonly
  810. # called OCSP Must-Staple when present in the TLS Feature extension in an
  811. # X.509 certificate.
  812. status_request = 5
  813. # status_request_v2 is defined in RFC 6961 and allows multiple OCSP
  814. # responses to be provided. It is not currently in use by clients or
  815. # servers.
  816. status_request_v2 = 17
  817. _TLS_FEATURE_TYPE_TO_ENUM = {x.value: x for x in TLSFeatureType}
  818. class InhibitAnyPolicy(ExtensionType):
  819. oid = ExtensionOID.INHIBIT_ANY_POLICY
  820. def __init__(self, skip_certs: int) -> None:
  821. if not isinstance(skip_certs, int):
  822. raise TypeError("skip_certs must be an integer")
  823. if skip_certs < 0:
  824. raise ValueError("skip_certs must be a non-negative integer")
  825. self._skip_certs = skip_certs
  826. def __repr__(self) -> str:
  827. return "<InhibitAnyPolicy(skip_certs={0.skip_certs})>".format(self)
  828. def __eq__(self, other: typing.Any) -> bool:
  829. if not isinstance(other, InhibitAnyPolicy):
  830. return NotImplemented
  831. return self.skip_certs == other.skip_certs
  832. def __ne__(self, other: typing.Any) -> bool:
  833. return not self == other
  834. def __hash__(self) -> int:
  835. return hash(self.skip_certs)
  836. @property
  837. def skip_certs(self) -> int:
  838. return self._skip_certs
  839. class KeyUsage(ExtensionType):
  840. oid = ExtensionOID.KEY_USAGE
  841. def __init__(
  842. self,
  843. digital_signature: bool,
  844. content_commitment: bool,
  845. key_encipherment: bool,
  846. data_encipherment: bool,
  847. key_agreement: bool,
  848. key_cert_sign: bool,
  849. crl_sign: bool,
  850. encipher_only: bool,
  851. decipher_only: bool,
  852. ) -> None:
  853. if not key_agreement and (encipher_only or decipher_only):
  854. raise ValueError(
  855. "encipher_only and decipher_only can only be true when "
  856. "key_agreement is true"
  857. )
  858. self._digital_signature = digital_signature
  859. self._content_commitment = content_commitment
  860. self._key_encipherment = key_encipherment
  861. self._data_encipherment = data_encipherment
  862. self._key_agreement = key_agreement
  863. self._key_cert_sign = key_cert_sign
  864. self._crl_sign = crl_sign
  865. self._encipher_only = encipher_only
  866. self._decipher_only = decipher_only
  867. @property
  868. def digital_signature(self) -> bool:
  869. return self._digital_signature
  870. @property
  871. def content_commitment(self) -> bool:
  872. return self._content_commitment
  873. @property
  874. def key_encipherment(self) -> bool:
  875. return self._key_encipherment
  876. @property
  877. def data_encipherment(self) -> bool:
  878. return self._data_encipherment
  879. @property
  880. def key_agreement(self) -> bool:
  881. return self._key_agreement
  882. @property
  883. def key_cert_sign(self) -> bool:
  884. return self._key_cert_sign
  885. @property
  886. def crl_sign(self) -> bool:
  887. return self._crl_sign
  888. @property
  889. def encipher_only(self) -> bool:
  890. if not self.key_agreement:
  891. raise ValueError(
  892. "encipher_only is undefined unless key_agreement is true"
  893. )
  894. else:
  895. return self._encipher_only
  896. @property
  897. def decipher_only(self) -> bool:
  898. if not self.key_agreement:
  899. raise ValueError(
  900. "decipher_only is undefined unless key_agreement is true"
  901. )
  902. else:
  903. return self._decipher_only
  904. def __repr__(self) -> str:
  905. try:
  906. encipher_only = self.encipher_only
  907. decipher_only = self.decipher_only
  908. except ValueError:
  909. # Users found None confusing because even though encipher/decipher
  910. # have no meaning unless key_agreement is true, to construct an
  911. # instance of the class you still need to pass False.
  912. encipher_only = False
  913. decipher_only = False
  914. return (
  915. "<KeyUsage(digital_signature={0.digital_signature}, "
  916. "content_commitment={0.content_commitment}, "
  917. "key_encipherment={0.key_encipherment}, "
  918. "data_encipherment={0.data_encipherment}, "
  919. "key_agreement={0.key_agreement}, "
  920. "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
  921. "encipher_only={1}, decipher_only={2})>"
  922. ).format(self, encipher_only, decipher_only)
  923. def __eq__(self, other: typing.Any) -> bool:
  924. if not isinstance(other, KeyUsage):
  925. return NotImplemented
  926. return (
  927. self.digital_signature == other.digital_signature
  928. and self.content_commitment == other.content_commitment
  929. and self.key_encipherment == other.key_encipherment
  930. and self.data_encipherment == other.data_encipherment
  931. and self.key_agreement == other.key_agreement
  932. and self.key_cert_sign == other.key_cert_sign
  933. and self.crl_sign == other.crl_sign
  934. and self._encipher_only == other._encipher_only
  935. and self._decipher_only == other._decipher_only
  936. )
  937. def __ne__(self, other: typing.Any) -> bool:
  938. return not self == other
  939. def __hash__(self) -> int:
  940. return hash(
  941. (
  942. self.digital_signature,
  943. self.content_commitment,
  944. self.key_encipherment,
  945. self.data_encipherment,
  946. self.key_agreement,
  947. self.key_cert_sign,
  948. self.crl_sign,
  949. self._encipher_only,
  950. self._decipher_only,
  951. )
  952. )
  953. class NameConstraints(ExtensionType):
  954. oid = ExtensionOID.NAME_CONSTRAINTS
  955. def __init__(
  956. self,
  957. permitted_subtrees: typing.Optional[typing.Iterable[GeneralName]],
  958. excluded_subtrees: typing.Optional[typing.Iterable[GeneralName]],
  959. ) -> None:
  960. if permitted_subtrees is not None:
  961. permitted_subtrees = list(permitted_subtrees)
  962. if not all(isinstance(x, GeneralName) for x in permitted_subtrees):
  963. raise TypeError(
  964. "permitted_subtrees must be a list of GeneralName objects "
  965. "or None"
  966. )
  967. self._validate_ip_name(permitted_subtrees)
  968. if excluded_subtrees is not None:
  969. excluded_subtrees = list(excluded_subtrees)
  970. if not all(isinstance(x, GeneralName) for x in excluded_subtrees):
  971. raise TypeError(
  972. "excluded_subtrees must be a list of GeneralName objects "
  973. "or None"
  974. )
  975. self._validate_ip_name(excluded_subtrees)
  976. if permitted_subtrees is None and excluded_subtrees is None:
  977. raise ValueError(
  978. "At least one of permitted_subtrees and excluded_subtrees "
  979. "must not be None"
  980. )
  981. self._permitted_subtrees = permitted_subtrees
  982. self._excluded_subtrees = excluded_subtrees
  983. def __eq__(self, other: typing.Any) -> bool:
  984. if not isinstance(other, NameConstraints):
  985. return NotImplemented
  986. return (
  987. self.excluded_subtrees == other.excluded_subtrees
  988. and self.permitted_subtrees == other.permitted_subtrees
  989. )
  990. def __ne__(self, other: typing.Any) -> bool:
  991. return not self == other
  992. def _validate_ip_name(self, tree: typing.Iterable[GeneralName]) -> None:
  993. if any(
  994. isinstance(name, IPAddress)
  995. and not isinstance(
  996. name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
  997. )
  998. for name in tree
  999. ):
  1000. raise TypeError(
  1001. "IPAddress name constraints must be an IPv4Network or"
  1002. " IPv6Network object"
  1003. )
  1004. def __repr__(self) -> str:
  1005. return (
  1006. "<NameConstraints(permitted_subtrees={0.permitted_subtrees}, "
  1007. "excluded_subtrees={0.excluded_subtrees})>".format(self)
  1008. )
  1009. def __hash__(self) -> int:
  1010. if self.permitted_subtrees is not None:
  1011. ps: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple(
  1012. self.permitted_subtrees
  1013. )
  1014. else:
  1015. ps = None
  1016. if self.excluded_subtrees is not None:
  1017. es: typing.Optional[typing.Tuple[GeneralName, ...]] = tuple(
  1018. self.excluded_subtrees
  1019. )
  1020. else:
  1021. es = None
  1022. return hash((ps, es))
  1023. @property
  1024. def permitted_subtrees(
  1025. self,
  1026. ) -> typing.Optional[typing.List[GeneralName]]:
  1027. return self._permitted_subtrees
  1028. @property
  1029. def excluded_subtrees(
  1030. self,
  1031. ) -> typing.Optional[typing.List[GeneralName]]:
  1032. return self._excluded_subtrees
  1033. class Extension(typing.Generic[ExtensionTypeVar]):
  1034. def __init__(
  1035. self, oid: ObjectIdentifier, critical: bool, value: ExtensionTypeVar
  1036. ) -> None:
  1037. if not isinstance(oid, ObjectIdentifier):
  1038. raise TypeError(
  1039. "oid argument must be an ObjectIdentifier instance."
  1040. )
  1041. if not isinstance(critical, bool):
  1042. raise TypeError("critical must be a boolean value")
  1043. self._oid = oid
  1044. self._critical = critical
  1045. self._value = value
  1046. @property
  1047. def oid(self) -> ObjectIdentifier:
  1048. return self._oid
  1049. @property
  1050. def critical(self) -> bool:
  1051. return self._critical
  1052. @property
  1053. def value(self) -> ExtensionTypeVar:
  1054. return self._value
  1055. def __repr__(self) -> str:
  1056. return (
  1057. "<Extension(oid={0.oid}, critical={0.critical}, "
  1058. "value={0.value})>"
  1059. ).format(self)
  1060. def __eq__(self, other: typing.Any) -> bool:
  1061. if not isinstance(other, Extension):
  1062. return NotImplemented
  1063. return (
  1064. self.oid == other.oid
  1065. and self.critical == other.critical
  1066. and self.value == other.value
  1067. )
  1068. def __ne__(self, other: typing.Any) -> bool:
  1069. return not self == other
  1070. def __hash__(self) -> int:
  1071. return hash((self.oid, self.critical, self.value))
  1072. class GeneralNames(object):
  1073. def __init__(self, general_names: typing.Iterable[GeneralName]) -> None:
  1074. general_names = list(general_names)
  1075. if not all(isinstance(x, GeneralName) for x in general_names):
  1076. raise TypeError(
  1077. "Every item in the general_names list must be an "
  1078. "object conforming to the GeneralName interface"
  1079. )
  1080. self._general_names = general_names
  1081. __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
  1082. @typing.overload
  1083. def get_values_for_type(
  1084. self,
  1085. type: typing.Union[
  1086. typing.Type[DNSName],
  1087. typing.Type[UniformResourceIdentifier],
  1088. typing.Type[RFC822Name],
  1089. ],
  1090. ) -> typing.List[str]:
  1091. ...
  1092. @typing.overload
  1093. def get_values_for_type(
  1094. self,
  1095. type: typing.Type[DirectoryName],
  1096. ) -> typing.List[Name]:
  1097. ...
  1098. @typing.overload
  1099. def get_values_for_type(
  1100. self,
  1101. type: typing.Type[RegisteredID],
  1102. ) -> typing.List[ObjectIdentifier]:
  1103. ...
  1104. @typing.overload
  1105. def get_values_for_type(
  1106. self, type: typing.Type[IPAddress]
  1107. ) -> typing.List[_IPADDRESS_TYPES]:
  1108. ...
  1109. @typing.overload
  1110. def get_values_for_type(
  1111. self, type: typing.Type[OtherName]
  1112. ) -> typing.List[OtherName]:
  1113. ...
  1114. def get_values_for_type(
  1115. self,
  1116. type: typing.Union[
  1117. typing.Type[DNSName],
  1118. typing.Type[DirectoryName],
  1119. typing.Type[IPAddress],
  1120. typing.Type[OtherName],
  1121. typing.Type[RFC822Name],
  1122. typing.Type[RegisteredID],
  1123. typing.Type[UniformResourceIdentifier],
  1124. ],
  1125. ) -> typing.Union[
  1126. typing.List[_IPADDRESS_TYPES],
  1127. typing.List[str],
  1128. typing.List[OtherName],
  1129. typing.List[Name],
  1130. typing.List[ObjectIdentifier],
  1131. ]:
  1132. # Return the value of each GeneralName, except for OtherName instances
  1133. # which we return directly because it has two important properties not
  1134. # just one value.
  1135. objs = (i for i in self if isinstance(i, type))
  1136. if type != OtherName:
  1137. return [i.value for i in objs]
  1138. return list(objs)
  1139. def __repr__(self) -> str:
  1140. return "<GeneralNames({})>".format(self._general_names)
  1141. def __eq__(self, other: typing.Any) -> bool:
  1142. if not isinstance(other, GeneralNames):
  1143. return NotImplemented
  1144. return self._general_names == other._general_names
  1145. def __ne__(self, other: typing.Any) -> bool:
  1146. return not self == other
  1147. def __hash__(self) -> int:
  1148. return hash(tuple(self._general_names))
  1149. class SubjectAlternativeName(ExtensionType):
  1150. oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME
  1151. def __init__(self, general_names: typing.Iterable[GeneralName]) -> None:
  1152. self._general_names = GeneralNames(general_names)
  1153. __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
  1154. @typing.overload
  1155. def get_values_for_type(
  1156. self,
  1157. type: typing.Union[
  1158. typing.Type[DNSName],
  1159. typing.Type[UniformResourceIdentifier],
  1160. typing.Type[RFC822Name],
  1161. ],
  1162. ) -> typing.List[str]:
  1163. ...
  1164. @typing.overload
  1165. def get_values_for_type(
  1166. self,
  1167. type: typing.Type[DirectoryName],
  1168. ) -> typing.List[Name]:
  1169. ...
  1170. @typing.overload
  1171. def get_values_for_type(
  1172. self,
  1173. type: typing.Type[RegisteredID],
  1174. ) -> typing.List[ObjectIdentifier]:
  1175. ...
  1176. @typing.overload
  1177. def get_values_for_type(
  1178. self, type: typing.Type[IPAddress]
  1179. ) -> typing.List[_IPADDRESS_TYPES]:
  1180. ...
  1181. @typing.overload
  1182. def get_values_for_type(
  1183. self, type: typing.Type[OtherName]
  1184. ) -> typing.List[OtherName]:
  1185. ...
  1186. def get_values_for_type(
  1187. self,
  1188. type: typing.Union[
  1189. typing.Type[DNSName],
  1190. typing.Type[DirectoryName],
  1191. typing.Type[IPAddress],
  1192. typing.Type[OtherName],
  1193. typing.Type[RFC822Name],
  1194. typing.Type[RegisteredID],
  1195. typing.Type[UniformResourceIdentifier],
  1196. ],
  1197. ) -> typing.Union[
  1198. typing.List[_IPADDRESS_TYPES],
  1199. typing.List[str],
  1200. typing.List[OtherName],
  1201. typing.List[Name],
  1202. typing.List[ObjectIdentifier],
  1203. ]:
  1204. return self._general_names.get_values_for_type(type)
  1205. def __repr__(self) -> str:
  1206. return "<SubjectAlternativeName({})>".format(self._general_names)
  1207. def __eq__(self, other: typing.Any) -> bool:
  1208. if not isinstance(other, SubjectAlternativeName):
  1209. return NotImplemented
  1210. return self._general_names == other._general_names
  1211. def __ne__(self, other: typing.Any) -> bool:
  1212. return not self == other
  1213. def __hash__(self) -> int:
  1214. return hash(self._general_names)
  1215. class IssuerAlternativeName(ExtensionType):
  1216. oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME
  1217. def __init__(self, general_names: typing.Iterable[GeneralName]) -> None:
  1218. self._general_names = GeneralNames(general_names)
  1219. __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
  1220. @typing.overload
  1221. def get_values_for_type(
  1222. self,
  1223. type: typing.Union[
  1224. typing.Type[DNSName],
  1225. typing.Type[UniformResourceIdentifier],
  1226. typing.Type[RFC822Name],
  1227. ],
  1228. ) -> typing.List[str]:
  1229. ...
  1230. @typing.overload
  1231. def get_values_for_type(
  1232. self,
  1233. type: typing.Type[DirectoryName],
  1234. ) -> typing.List[Name]:
  1235. ...
  1236. @typing.overload
  1237. def get_values_for_type(
  1238. self,
  1239. type: typing.Type[RegisteredID],
  1240. ) -> typing.List[ObjectIdentifier]:
  1241. ...
  1242. @typing.overload
  1243. def get_values_for_type(
  1244. self, type: typing.Type[IPAddress]
  1245. ) -> typing.List[_IPADDRESS_TYPES]:
  1246. ...
  1247. @typing.overload
  1248. def get_values_for_type(
  1249. self, type: typing.Type[OtherName]
  1250. ) -> typing.List[OtherName]:
  1251. ...
  1252. def get_values_for_type(
  1253. self,
  1254. type: typing.Union[
  1255. typing.Type[DNSName],
  1256. typing.Type[DirectoryName],
  1257. typing.Type[IPAddress],
  1258. typing.Type[OtherName],
  1259. typing.Type[RFC822Name],
  1260. typing.Type[RegisteredID],
  1261. typing.Type[UniformResourceIdentifier],
  1262. ],
  1263. ) -> typing.Union[
  1264. typing.List[_IPADDRESS_TYPES],
  1265. typing.List[str],
  1266. typing.List[OtherName],
  1267. typing.List[Name],
  1268. typing.List[ObjectIdentifier],
  1269. ]:
  1270. return self._general_names.get_values_for_type(type)
  1271. def __repr__(self) -> str:
  1272. return "<IssuerAlternativeName({})>".format(self._general_names)
  1273. def __eq__(self, other: typing.Any) -> bool:
  1274. if not isinstance(other, IssuerAlternativeName):
  1275. return NotImplemented
  1276. return self._general_names == other._general_names
  1277. def __ne__(self, other: typing.Any) -> bool:
  1278. return not self == other
  1279. def __hash__(self) -> int:
  1280. return hash(self._general_names)
  1281. class CertificateIssuer(ExtensionType):
  1282. oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER
  1283. def __init__(self, general_names: typing.Iterable[GeneralName]) -> None:
  1284. self._general_names = GeneralNames(general_names)
  1285. __len__, __iter__, __getitem__ = _make_sequence_methods("_general_names")
  1286. @typing.overload
  1287. def get_values_for_type(
  1288. self,
  1289. type: typing.Union[
  1290. typing.Type[DNSName],
  1291. typing.Type[UniformResourceIdentifier],
  1292. typing.Type[RFC822Name],
  1293. ],
  1294. ) -> typing.List[str]:
  1295. ...
  1296. @typing.overload
  1297. def get_values_for_type(
  1298. self,
  1299. type: typing.Type[DirectoryName],
  1300. ) -> typing.List[Name]:
  1301. ...
  1302. @typing.overload
  1303. def get_values_for_type(
  1304. self,
  1305. type: typing.Type[RegisteredID],
  1306. ) -> typing.List[ObjectIdentifier]:
  1307. ...
  1308. @typing.overload
  1309. def get_values_for_type(
  1310. self, type: typing.Type[IPAddress]
  1311. ) -> typing.List[_IPADDRESS_TYPES]:
  1312. ...
  1313. @typing.overload
  1314. def get_values_for_type(
  1315. self, type: typing.Type[OtherName]
  1316. ) -> typing.List[OtherName]:
  1317. ...
  1318. def get_values_for_type(
  1319. self,
  1320. type: typing.Union[
  1321. typing.Type[DNSName],
  1322. typing.Type[DirectoryName],
  1323. typing.Type[IPAddress],
  1324. typing.Type[OtherName],
  1325. typing.Type[RFC822Name],
  1326. typing.Type[RegisteredID],
  1327. typing.Type[UniformResourceIdentifier],
  1328. ],
  1329. ) -> typing.Union[
  1330. typing.List[_IPADDRESS_TYPES],
  1331. typing.List[str],
  1332. typing.List[OtherName],
  1333. typing.List[Name],
  1334. typing.List[ObjectIdentifier],
  1335. ]:
  1336. return self._general_names.get_values_for_type(type)
  1337. def __repr__(self) -> str:
  1338. return "<CertificateIssuer({})>".format(self._general_names)
  1339. def __eq__(self, other: typing.Any) -> bool:
  1340. if not isinstance(other, CertificateIssuer):
  1341. return NotImplemented
  1342. return self._general_names == other._general_names
  1343. def __ne__(self, other: typing.Any) -> bool:
  1344. return not self == other
  1345. def __hash__(self) -> int:
  1346. return hash(self._general_names)
  1347. class CRLReason(ExtensionType):
  1348. oid = CRLEntryExtensionOID.CRL_REASON
  1349. def __init__(self, reason: ReasonFlags) -> None:
  1350. if not isinstance(reason, ReasonFlags):
  1351. raise TypeError("reason must be an element from ReasonFlags")
  1352. self._reason = reason
  1353. def __repr__(self) -> str:
  1354. return "<CRLReason(reason={})>".format(self._reason)
  1355. def __eq__(self, other: typing.Any) -> bool:
  1356. if not isinstance(other, CRLReason):
  1357. return NotImplemented
  1358. return self.reason == other.reason
  1359. def __ne__(self, other: typing.Any) -> bool:
  1360. return not self == other
  1361. def __hash__(self) -> int:
  1362. return hash(self.reason)
  1363. @property
  1364. def reason(self) -> ReasonFlags:
  1365. return self._reason
  1366. class InvalidityDate(ExtensionType):
  1367. oid = CRLEntryExtensionOID.INVALIDITY_DATE
  1368. def __init__(self, invalidity_date: datetime.datetime) -> None:
  1369. if not isinstance(invalidity_date, datetime.datetime):
  1370. raise TypeError("invalidity_date must be a datetime.datetime")
  1371. self._invalidity_date = invalidity_date
  1372. def __repr__(self) -> str:
  1373. return "<InvalidityDate(invalidity_date={})>".format(
  1374. self._invalidity_date
  1375. )
  1376. def __eq__(self, other: typing.Any) -> bool:
  1377. if not isinstance(other, InvalidityDate):
  1378. return NotImplemented
  1379. return self.invalidity_date == other.invalidity_date
  1380. def __ne__(self, other: typing.Any) -> bool:
  1381. return not self == other
  1382. def __hash__(self) -> int:
  1383. return hash(self.invalidity_date)
  1384. @property
  1385. def invalidity_date(self) -> datetime.datetime:
  1386. return self._invalidity_date
  1387. class PrecertificateSignedCertificateTimestamps(ExtensionType):
  1388. oid = ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
  1389. def __init__(
  1390. self,
  1391. signed_certificate_timestamps: typing.Iterable[
  1392. SignedCertificateTimestamp
  1393. ],
  1394. ) -> None:
  1395. signed_certificate_timestamps = list(signed_certificate_timestamps)
  1396. if not all(
  1397. isinstance(sct, SignedCertificateTimestamp)
  1398. for sct in signed_certificate_timestamps
  1399. ):
  1400. raise TypeError(
  1401. "Every item in the signed_certificate_timestamps list must be "
  1402. "a SignedCertificateTimestamp"
  1403. )
  1404. self._signed_certificate_timestamps = signed_certificate_timestamps
  1405. __len__, __iter__, __getitem__ = _make_sequence_methods(
  1406. "_signed_certificate_timestamps"
  1407. )
  1408. def __repr__(self) -> str:
  1409. return "<PrecertificateSignedCertificateTimestamps({})>".format(
  1410. list(self)
  1411. )
  1412. def __hash__(self) -> int:
  1413. return hash(tuple(self._signed_certificate_timestamps))
  1414. def __eq__(self, other: typing.Any) -> bool:
  1415. if not isinstance(other, PrecertificateSignedCertificateTimestamps):
  1416. return NotImplemented
  1417. return (
  1418. self._signed_certificate_timestamps
  1419. == other._signed_certificate_timestamps
  1420. )
  1421. def __ne__(self, other: typing.Any) -> bool:
  1422. return not self == other
  1423. class SignedCertificateTimestamps(ExtensionType):
  1424. oid = ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS
  1425. def __init__(
  1426. self,
  1427. signed_certificate_timestamps: typing.Iterable[
  1428. SignedCertificateTimestamp
  1429. ],
  1430. ) -> None:
  1431. signed_certificate_timestamps = list(signed_certificate_timestamps)
  1432. if not all(
  1433. isinstance(sct, SignedCertificateTimestamp)
  1434. for sct in signed_certificate_timestamps
  1435. ):
  1436. raise TypeError(
  1437. "Every item in the signed_certificate_timestamps list must be "
  1438. "a SignedCertificateTimestamp"
  1439. )
  1440. self._signed_certificate_timestamps = signed_certificate_timestamps
  1441. __len__, __iter__, __getitem__ = _make_sequence_methods(
  1442. "_signed_certificate_timestamps"
  1443. )
  1444. def __repr__(self) -> str:
  1445. return "<SignedCertificateTimestamps({})>".format(list(self))
  1446. def __hash__(self) -> int:
  1447. return hash(tuple(self._signed_certificate_timestamps))
  1448. def __eq__(self, other: typing.Any) -> bool:
  1449. if not isinstance(other, SignedCertificateTimestamps):
  1450. return NotImplemented
  1451. return (
  1452. self._signed_certificate_timestamps
  1453. == other._signed_certificate_timestamps
  1454. )
  1455. def __ne__(self, other: typing.Any) -> bool:
  1456. return not self == other
  1457. class OCSPNonce(ExtensionType):
  1458. oid = OCSPExtensionOID.NONCE
  1459. def __init__(self, nonce: bytes) -> None:
  1460. if not isinstance(nonce, bytes):
  1461. raise TypeError("nonce must be bytes")
  1462. self._nonce = nonce
  1463. def __eq__(self, other: typing.Any) -> bool:
  1464. if not isinstance(other, OCSPNonce):
  1465. return NotImplemented
  1466. return self.nonce == other.nonce
  1467. def __ne__(self, other: typing.Any) -> bool:
  1468. return not self == other
  1469. def __hash__(self) -> int:
  1470. return hash(self.nonce)
  1471. def __repr__(self) -> str:
  1472. return "<OCSPNonce(nonce={0.nonce!r})>".format(self)
  1473. @property
  1474. def nonce(self) -> bytes:
  1475. return self._nonce
  1476. class IssuingDistributionPoint(ExtensionType):
  1477. oid = ExtensionOID.ISSUING_DISTRIBUTION_POINT
  1478. def __init__(
  1479. self,
  1480. full_name: typing.Optional[typing.Iterable[GeneralName]],
  1481. relative_name: typing.Optional[RelativeDistinguishedName],
  1482. only_contains_user_certs: bool,
  1483. only_contains_ca_certs: bool,
  1484. only_some_reasons: typing.Optional[typing.FrozenSet[ReasonFlags]],
  1485. indirect_crl: bool,
  1486. only_contains_attribute_certs: bool,
  1487. ) -> None:
  1488. if full_name is not None:
  1489. full_name = list(full_name)
  1490. if only_some_reasons and (
  1491. not isinstance(only_some_reasons, frozenset)
  1492. or not all(isinstance(x, ReasonFlags) for x in only_some_reasons)
  1493. ):
  1494. raise TypeError(
  1495. "only_some_reasons must be None or frozenset of ReasonFlags"
  1496. )
  1497. if only_some_reasons and (
  1498. ReasonFlags.unspecified in only_some_reasons
  1499. or ReasonFlags.remove_from_crl in only_some_reasons
  1500. ):
  1501. raise ValueError(
  1502. "unspecified and remove_from_crl are not valid reasons in an "
  1503. "IssuingDistributionPoint"
  1504. )
  1505. if not (
  1506. isinstance(only_contains_user_certs, bool)
  1507. and isinstance(only_contains_ca_certs, bool)
  1508. and isinstance(indirect_crl, bool)
  1509. and isinstance(only_contains_attribute_certs, bool)
  1510. ):
  1511. raise TypeError(
  1512. "only_contains_user_certs, only_contains_ca_certs, "
  1513. "indirect_crl and only_contains_attribute_certs "
  1514. "must all be boolean."
  1515. )
  1516. crl_constraints = [
  1517. only_contains_user_certs,
  1518. only_contains_ca_certs,
  1519. indirect_crl,
  1520. only_contains_attribute_certs,
  1521. ]
  1522. if len([x for x in crl_constraints if x]) > 1:
  1523. raise ValueError(
  1524. "Only one of the following can be set to True: "
  1525. "only_contains_user_certs, only_contains_ca_certs, "
  1526. "indirect_crl, only_contains_attribute_certs"
  1527. )
  1528. if not any(
  1529. [
  1530. only_contains_user_certs,
  1531. only_contains_ca_certs,
  1532. indirect_crl,
  1533. only_contains_attribute_certs,
  1534. full_name,
  1535. relative_name,
  1536. only_some_reasons,
  1537. ]
  1538. ):
  1539. raise ValueError(
  1540. "Cannot create empty extension: "
  1541. "if only_contains_user_certs, only_contains_ca_certs, "
  1542. "indirect_crl, and only_contains_attribute_certs are all False"
  1543. ", then either full_name, relative_name, or only_some_reasons "
  1544. "must have a value."
  1545. )
  1546. self._only_contains_user_certs = only_contains_user_certs
  1547. self._only_contains_ca_certs = only_contains_ca_certs
  1548. self._indirect_crl = indirect_crl
  1549. self._only_contains_attribute_certs = only_contains_attribute_certs
  1550. self._only_some_reasons = only_some_reasons
  1551. self._full_name = full_name
  1552. self._relative_name = relative_name
  1553. def __repr__(self) -> str:
  1554. return (
  1555. "<IssuingDistributionPoint(full_name={0.full_name}, "
  1556. "relative_name={0.relative_name}, "
  1557. "only_contains_user_certs={0.only_contains_user_certs}, "
  1558. "only_contains_ca_certs={0.only_contains_ca_certs}, "
  1559. "only_some_reasons={0.only_some_reasons}, "
  1560. "indirect_crl={0.indirect_crl}, "
  1561. "only_contains_attribute_certs="
  1562. "{0.only_contains_attribute_certs})>".format(self)
  1563. )
  1564. def __eq__(self, other: typing.Any) -> bool:
  1565. if not isinstance(other, IssuingDistributionPoint):
  1566. return NotImplemented
  1567. return (
  1568. self.full_name == other.full_name
  1569. and self.relative_name == other.relative_name
  1570. and self.only_contains_user_certs == other.only_contains_user_certs
  1571. and self.only_contains_ca_certs == other.only_contains_ca_certs
  1572. and self.only_some_reasons == other.only_some_reasons
  1573. and self.indirect_crl == other.indirect_crl
  1574. and self.only_contains_attribute_certs
  1575. == other.only_contains_attribute_certs
  1576. )
  1577. def __ne__(self, other: typing.Any) -> bool:
  1578. return not self == other
  1579. def __hash__(self) -> int:
  1580. return hash(
  1581. (
  1582. self.full_name,
  1583. self.relative_name,
  1584. self.only_contains_user_certs,
  1585. self.only_contains_ca_certs,
  1586. self.only_some_reasons,
  1587. self.indirect_crl,
  1588. self.only_contains_attribute_certs,
  1589. )
  1590. )
  1591. @property
  1592. def full_name(self) -> typing.Optional[typing.List[GeneralName]]:
  1593. return self._full_name
  1594. @property
  1595. def relative_name(self) -> typing.Optional[RelativeDistinguishedName]:
  1596. return self._relative_name
  1597. @property
  1598. def only_contains_user_certs(self) -> bool:
  1599. return self._only_contains_user_certs
  1600. @property
  1601. def only_contains_ca_certs(self) -> bool:
  1602. return self._only_contains_ca_certs
  1603. @property
  1604. def only_some_reasons(
  1605. self,
  1606. ) -> typing.Optional[typing.FrozenSet[ReasonFlags]]:
  1607. return self._only_some_reasons
  1608. @property
  1609. def indirect_crl(self) -> bool:
  1610. return self._indirect_crl
  1611. @property
  1612. def only_contains_attribute_certs(self) -> bool:
  1613. return self._only_contains_attribute_certs
  1614. class UnrecognizedExtension(ExtensionType):
  1615. def __init__(self, oid: ObjectIdentifier, value: bytes) -> None:
  1616. if not isinstance(oid, ObjectIdentifier):
  1617. raise TypeError("oid must be an ObjectIdentifier")
  1618. self._oid = oid
  1619. self._value = value
  1620. @property
  1621. def oid(self) -> ObjectIdentifier: # type: ignore[override]
  1622. return self._oid
  1623. @property
  1624. def value(self) -> bytes:
  1625. return self._value
  1626. def __repr__(self) -> str:
  1627. return (
  1628. "<UnrecognizedExtension(oid={0.oid}, "
  1629. "value={0.value!r})>".format(self)
  1630. )
  1631. def __eq__(self, other: typing.Any) -> bool:
  1632. if not isinstance(other, UnrecognizedExtension):
  1633. return NotImplemented
  1634. return self.oid == other.oid and self.value == other.value
  1635. def __ne__(self, other: typing.Any) -> bool:
  1636. return not self == other
  1637. def __hash__(self) -> int:
  1638. return hash((self.oid, self.value))