extensions.py 63 KB

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