blob: f7b5d7f5935b22e00f6481a4dee8ddb04342f704 [file] [log] [blame]
Paul Kehrer890cb7f2015-08-10 21:05:34 -05001# 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
5from __future__ import absolute_import, division, print_function
6
Paul Kehreraa7a3222015-08-11 00:00:54 -05007import abc
Paul Kehrer23c0bbc2015-12-25 22:35:19 -06008import datetime
Paul Kehrer890cb7f2015-08-10 21:05:34 -05009import hashlib
Paul Kehrerfbeaf2a2015-08-10 23:52:10 -050010import ipaddress
Paul Kehrer9f8069a2015-08-10 21:10:34 -050011from enum import Enum
Paul Kehrer890cb7f2015-08-10 21:05:34 -050012
13from pyasn1.codec.der import decoder
14from pyasn1.type import namedtype, univ
15
16import six
17
18from cryptography import utils
Predrag Gruevski38995392015-09-21 21:53:49 -040019from cryptography.hazmat.primitives import constant_time, serialization
Paul Kehreraa7a3222015-08-11 00:00:54 -050020from cryptography.x509.general_name import GeneralName, IPAddress, OtherName
Paul Kehrer9f8069a2015-08-10 21:10:34 -050021from cryptography.x509.name import Name
Paul Kehrer49bb7562015-12-25 16:17:40 -060022from cryptography.x509.oid import (
23 CRLEntryExtensionOID, ExtensionOID, ObjectIdentifier
24)
Paul Kehrer890cb7f2015-08-10 21:05:34 -050025
26
27class _SubjectPublicKeyInfo(univ.Sequence):
28 componentType = namedtype.NamedTypes(
29 namedtype.NamedType('algorithm', univ.Sequence()),
30 namedtype.NamedType('subjectPublicKey', univ.BitString())
31 )
32
33
34def _key_identifier_from_public_key(public_key):
35 # This is a very slow way to do this.
36 serialized = public_key.public_bytes(
37 serialization.Encoding.DER,
38 serialization.PublicFormat.SubjectPublicKeyInfo
39 )
40 spki, remaining = decoder.decode(
41 serialized, asn1Spec=_SubjectPublicKeyInfo()
42 )
43 assert not remaining
44 # the univ.BitString object is a tuple of bits. We need bytes and
45 # pyasn1 really doesn't want to give them to us. To get it we'll
46 # build an integer and convert that to bytes.
47 bits = 0
48 for bit in spki.getComponentByName("subjectPublicKey"):
49 bits = bits << 1 | bit
50
51 data = utils.int_to_bytes(bits)
52 return hashlib.sha1(data).digest()
53
54
Paul Kehrerfbeaf2a2015-08-10 23:52:10 -050055class DuplicateExtension(Exception):
56 def __init__(self, msg, oid):
57 super(DuplicateExtension, self).__init__(msg)
58 self.oid = oid
59
60
61class UnsupportedExtension(Exception):
62 def __init__(self, msg, oid):
63 super(UnsupportedExtension, self).__init__(msg)
64 self.oid = oid
65
66
67class ExtensionNotFound(Exception):
68 def __init__(self, msg, oid):
69 super(ExtensionNotFound, self).__init__(msg)
70 self.oid = oid
71
72
Paul Kehreraa7a3222015-08-11 00:00:54 -050073@six.add_metaclass(abc.ABCMeta)
74class ExtensionType(object):
75 @abc.abstractproperty
76 def oid(self):
77 """
78 Returns the oid associated with the given extension type.
79 """
80
81
Paul Kehrerfbeaf2a2015-08-10 23:52:10 -050082class Extensions(object):
83 def __init__(self, extensions):
84 self._extensions = extensions
85
86 def get_extension_for_oid(self, oid):
87 for ext in self:
88 if ext.oid == oid:
89 return ext
90
91 raise ExtensionNotFound("No {0} extension was found".format(oid), oid)
92
Phoebe Queen64cf4cd2015-08-12 02:28:43 +010093 def get_extension_for_class(self, extclass):
Paul Kehrere69c5fe2015-12-30 21:03:26 -060094 if extclass is UnrecognizedExtension:
95 raise TypeError(
96 "UnrecognizedExtension can't be used with "
97 "get_extension_for_class because more than one instance of the"
98 " class may be present."
99 )
100
Phoebe Queen64cf4cd2015-08-12 02:28:43 +0100101 for ext in self:
Phoebe Queen754be602015-08-12 03:11:35 +0100102 if isinstance(ext.value, extclass):
Phoebe Queen64cf4cd2015-08-12 02:28:43 +0100103 return ext
104
Phoebe Queen2cc111a2015-08-12 04:14:22 +0100105 raise ExtensionNotFound(
Phoebe Queenecae9812015-08-12 05:00:32 +0100106 "No {0} extension was found".format(extclass), extclass.oid
Phoebe Queen2cc111a2015-08-12 04:14:22 +0100107 )
Phoebe Queen64cf4cd2015-08-12 02:28:43 +0100108
Paul Kehrerfbeaf2a2015-08-10 23:52:10 -0500109 def __iter__(self):
110 return iter(self._extensions)
111
112 def __len__(self):
113 return len(self._extensions)
114
Paul Kehrer5b90c972015-12-26 00:52:58 -0600115 def __getitem__(self, idx):
116 return self._extensions[idx]
117
Paul Kehrerafbe75b2015-10-20 08:08:43 -0500118 def __repr__(self):
119 return (
120 "<Extensions({0})>".format(self._extensions)
121 )
122
Paul Kehrerfbeaf2a2015-08-10 23:52:10 -0500123
Paul Kehrer890cb7f2015-08-10 21:05:34 -0500124@utils.register_interface(ExtensionType)
Paul Kehrer3b95cd72015-12-22 21:40:20 -0600125class CRLNumber(object):
126 oid = ExtensionOID.CRL_NUMBER
127
128 def __init__(self, crl_number):
129 if not isinstance(crl_number, six.integer_types):
130 raise TypeError("crl_number must be an integer")
131
132 self._crl_number = crl_number
133
134 def __eq__(self, other):
135 if not isinstance(other, CRLNumber):
136 return NotImplemented
137
138 return self.crl_number == other.crl_number
139
140 def __ne__(self, other):
141 return not self == other
142
Alex Gaynorf9a77b62015-12-26 12:14:25 -0500143 def __hash__(self):
144 return hash(self.crl_number)
145
Paul Kehrer3b95cd72015-12-22 21:40:20 -0600146 def __repr__(self):
147 return "<CRLNumber({0})>".format(self.crl_number)
148
149 crl_number = utils.read_only_property("_crl_number")
150
151
152@utils.register_interface(ExtensionType)
Paul Kehrer890cb7f2015-08-10 21:05:34 -0500153class AuthorityKeyIdentifier(object):
154 oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER
155
156 def __init__(self, key_identifier, authority_cert_issuer,
157 authority_cert_serial_number):
158 if authority_cert_issuer or authority_cert_serial_number:
159 if not authority_cert_issuer or not authority_cert_serial_number:
160 raise ValueError(
161 "authority_cert_issuer and authority_cert_serial_number "
162 "must both be present or both None"
163 )
164
165 if not all(
166 isinstance(x, GeneralName) for x in authority_cert_issuer
167 ):
168 raise TypeError(
169 "authority_cert_issuer must be a list of GeneralName "
170 "objects"
171 )
172
173 if not isinstance(authority_cert_serial_number, six.integer_types):
174 raise TypeError(
175 "authority_cert_serial_number must be an integer"
176 )
177
178 self._key_identifier = key_identifier
179 self._authority_cert_issuer = authority_cert_issuer
180 self._authority_cert_serial_number = authority_cert_serial_number
181
182 @classmethod
183 def from_issuer_public_key(cls, public_key):
184 digest = _key_identifier_from_public_key(public_key)
185 return cls(
186 key_identifier=digest,
187 authority_cert_issuer=None,
188 authority_cert_serial_number=None
189 )
190
191 def __repr__(self):
192 return (
193 "<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
194 "authority_cert_issuer={0.authority_cert_issuer}, "
195 "authority_cert_serial_number={0.authority_cert_serial_number}"
196 ")>".format(self)
197 )
198
199 def __eq__(self, other):
200 if not isinstance(other, AuthorityKeyIdentifier):
201 return NotImplemented
202
203 return (
204 self.key_identifier == other.key_identifier and
205 self.authority_cert_issuer == other.authority_cert_issuer and
206 self.authority_cert_serial_number ==
207 other.authority_cert_serial_number
208 )
209
210 def __ne__(self, other):
211 return not self == other
212
213 key_identifier = utils.read_only_property("_key_identifier")
214 authority_cert_issuer = utils.read_only_property("_authority_cert_issuer")
215 authority_cert_serial_number = utils.read_only_property(
216 "_authority_cert_serial_number"
217 )
218
219
220@utils.register_interface(ExtensionType)
221class SubjectKeyIdentifier(object):
222 oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER
223
224 def __init__(self, digest):
225 self._digest = digest
226
227 @classmethod
228 def from_public_key(cls, public_key):
229 return cls(_key_identifier_from_public_key(public_key))
230
231 digest = utils.read_only_property("_digest")
232
233 def __repr__(self):
234 return "<SubjectKeyIdentifier(digest={0!r})>".format(self.digest)
235
236 def __eq__(self, other):
237 if not isinstance(other, SubjectKeyIdentifier):
238 return NotImplemented
239
Predrag Gruevski57f3b3f2015-09-21 18:51:47 -0400240 return constant_time.bytes_eq(self.digest, other.digest)
Paul Kehrer890cb7f2015-08-10 21:05:34 -0500241
242 def __ne__(self, other):
243 return not self == other
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500244
Alex Gaynor410fe352015-12-26 15:01:25 -0500245 def __hash__(self):
246 return hash(self.digest)
247
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500248
249@utils.register_interface(ExtensionType)
250class AuthorityInformationAccess(object):
251 oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS
252
253 def __init__(self, descriptions):
254 if not all(isinstance(x, AccessDescription) for x in descriptions):
255 raise TypeError(
256 "Every item in the descriptions list must be an "
257 "AccessDescription"
258 )
259
260 self._descriptions = descriptions
261
262 def __iter__(self):
263 return iter(self._descriptions)
264
265 def __len__(self):
266 return len(self._descriptions)
267
268 def __repr__(self):
269 return "<AuthorityInformationAccess({0})>".format(self._descriptions)
270
271 def __eq__(self, other):
272 if not isinstance(other, AuthorityInformationAccess):
273 return NotImplemented
274
275 return self._descriptions == other._descriptions
276
277 def __ne__(self, other):
278 return not self == other
279
Paul Kehrerad4b3592015-12-27 17:27:40 -0600280 def __getitem__(self, idx):
281 return self._descriptions[idx]
282
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500283
284class AccessDescription(object):
285 def __init__(self, access_method, access_location):
Nick Bastind06763d2015-12-12 18:32:59 -0800286 if not isinstance(access_method, ObjectIdentifier):
Nick Bastinbd079ae2015-12-13 05:15:44 -0800287 raise TypeError("access_method must be an ObjectIdentifier")
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500288
289 if not isinstance(access_location, GeneralName):
290 raise TypeError("access_location must be a GeneralName")
291
292 self._access_method = access_method
293 self._access_location = access_location
294
295 def __repr__(self):
296 return (
297 "<AccessDescription(access_method={0.access_method}, access_locati"
298 "on={0.access_location})>".format(self)
299 )
300
301 def __eq__(self, other):
302 if not isinstance(other, AccessDescription):
303 return NotImplemented
304
305 return (
306 self.access_method == other.access_method and
307 self.access_location == other.access_location
308 )
309
310 def __ne__(self, other):
311 return not self == other
312
313 access_method = utils.read_only_property("_access_method")
314 access_location = utils.read_only_property("_access_location")
315
316
317@utils.register_interface(ExtensionType)
318class BasicConstraints(object):
319 oid = ExtensionOID.BASIC_CONSTRAINTS
320
321 def __init__(self, ca, path_length):
322 if not isinstance(ca, bool):
323 raise TypeError("ca must be a boolean value")
324
325 if path_length is not None and not ca:
326 raise ValueError("path_length must be None when ca is False")
327
328 if (
329 path_length is not None and
330 (not isinstance(path_length, six.integer_types) or path_length < 0)
331 ):
332 raise TypeError(
333 "path_length must be a non-negative integer or None"
334 )
335
336 self._ca = ca
337 self._path_length = path_length
338
339 ca = utils.read_only_property("_ca")
340 path_length = utils.read_only_property("_path_length")
341
342 def __repr__(self):
343 return ("<BasicConstraints(ca={0.ca}, "
344 "path_length={0.path_length})>").format(self)
345
346 def __eq__(self, other):
347 if not isinstance(other, BasicConstraints):
348 return NotImplemented
349
350 return self.ca == other.ca and self.path_length == other.path_length
351
352 def __ne__(self, other):
353 return not self == other
354
Paul Kehrer2eb69f62015-12-27 11:46:11 -0600355 def __hash__(self):
356 return hash((self.ca, self.path_length))
357
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500358
359@utils.register_interface(ExtensionType)
360class CRLDistributionPoints(object):
361 oid = ExtensionOID.CRL_DISTRIBUTION_POINTS
362
363 def __init__(self, distribution_points):
364 if not all(
365 isinstance(x, DistributionPoint) for x in distribution_points
366 ):
367 raise TypeError(
368 "distribution_points must be a list of DistributionPoint "
369 "objects"
370 )
371
372 self._distribution_points = distribution_points
373
374 def __iter__(self):
375 return iter(self._distribution_points)
376
377 def __len__(self):
378 return len(self._distribution_points)
379
380 def __repr__(self):
381 return "<CRLDistributionPoints({0})>".format(self._distribution_points)
382
383 def __eq__(self, other):
384 if not isinstance(other, CRLDistributionPoints):
385 return NotImplemented
386
387 return self._distribution_points == other._distribution_points
388
389 def __ne__(self, other):
390 return not self == other
391
Paul Kehreree2e92d2015-12-27 17:29:37 -0600392 def __getitem__(self, idx):
393 return self._distribution_points[idx]
394
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500395
396class DistributionPoint(object):
397 def __init__(self, full_name, relative_name, reasons, crl_issuer):
398 if full_name and relative_name:
399 raise ValueError(
400 "You cannot provide both full_name and relative_name, at "
401 "least one must be None."
402 )
403
404 if full_name and not all(
405 isinstance(x, GeneralName) for x in full_name
406 ):
407 raise TypeError(
408 "full_name must be a list of GeneralName objects"
409 )
410
411 if relative_name and not isinstance(relative_name, Name):
412 raise TypeError("relative_name must be a Name")
413
414 if crl_issuer and not all(
415 isinstance(x, GeneralName) for x in crl_issuer
416 ):
417 raise TypeError(
418 "crl_issuer must be None or a list of general names"
419 )
420
421 if reasons and (not isinstance(reasons, frozenset) or not all(
422 isinstance(x, ReasonFlags) for x in reasons
423 )):
424 raise TypeError("reasons must be None or frozenset of ReasonFlags")
425
426 if reasons and (
427 ReasonFlags.unspecified in reasons or
428 ReasonFlags.remove_from_crl in reasons
429 ):
430 raise ValueError(
431 "unspecified and remove_from_crl are not valid reasons in a "
432 "DistributionPoint"
433 )
434
435 if reasons and not crl_issuer and not (full_name or relative_name):
436 raise ValueError(
437 "You must supply crl_issuer, full_name, or relative_name when "
438 "reasons is not None"
439 )
440
441 self._full_name = full_name
442 self._relative_name = relative_name
443 self._reasons = reasons
444 self._crl_issuer = crl_issuer
445
446 def __repr__(self):
447 return (
448 "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
449 "tive_name}, reasons={0.reasons}, crl_issuer={0.crl_is"
450 "suer})>".format(self)
451 )
452
453 def __eq__(self, other):
454 if not isinstance(other, DistributionPoint):
455 return NotImplemented
456
457 return (
458 self.full_name == other.full_name and
459 self.relative_name == other.relative_name and
460 self.reasons == other.reasons and
461 self.crl_issuer == other.crl_issuer
462 )
463
464 def __ne__(self, other):
465 return not self == other
466
467 full_name = utils.read_only_property("_full_name")
468 relative_name = utils.read_only_property("_relative_name")
469 reasons = utils.read_only_property("_reasons")
470 crl_issuer = utils.read_only_property("_crl_issuer")
471
472
473class ReasonFlags(Enum):
474 unspecified = "unspecified"
475 key_compromise = "keyCompromise"
476 ca_compromise = "cACompromise"
477 affiliation_changed = "affiliationChanged"
478 superseded = "superseded"
479 cessation_of_operation = "cessationOfOperation"
480 certificate_hold = "certificateHold"
481 privilege_withdrawn = "privilegeWithdrawn"
482 aa_compromise = "aACompromise"
483 remove_from_crl = "removeFromCRL"
Paul Kehrer012262c2015-08-10 23:42:57 -0500484
485
486@utils.register_interface(ExtensionType)
487class CertificatePolicies(object):
488 oid = ExtensionOID.CERTIFICATE_POLICIES
489
490 def __init__(self, policies):
491 if not all(isinstance(x, PolicyInformation) for x in policies):
492 raise TypeError(
493 "Every item in the policies list must be a "
494 "PolicyInformation"
495 )
496
497 self._policies = policies
498
499 def __iter__(self):
500 return iter(self._policies)
501
502 def __len__(self):
503 return len(self._policies)
504
505 def __repr__(self):
506 return "<CertificatePolicies({0})>".format(self._policies)
507
508 def __eq__(self, other):
509 if not isinstance(other, CertificatePolicies):
510 return NotImplemented
511
512 return self._policies == other._policies
513
514 def __ne__(self, other):
515 return not self == other
516
Paul Kehrere8db7bd2015-12-27 17:32:57 -0600517 def __getitem__(self, idx):
518 return self._policies[idx]
519
Paul Kehrer012262c2015-08-10 23:42:57 -0500520
521class PolicyInformation(object):
522 def __init__(self, policy_identifier, policy_qualifiers):
523 if not isinstance(policy_identifier, ObjectIdentifier):
524 raise TypeError("policy_identifier must be an ObjectIdentifier")
525
526 self._policy_identifier = policy_identifier
527 if policy_qualifiers and not all(
528 isinstance(
529 x, (six.text_type, UserNotice)
530 ) for x in policy_qualifiers
531 ):
532 raise TypeError(
533 "policy_qualifiers must be a list of strings and/or UserNotice"
534 " objects or None"
535 )
536
537 self._policy_qualifiers = policy_qualifiers
538
539 def __repr__(self):
540 return (
541 "<PolicyInformation(policy_identifier={0.policy_identifier}, polic"
542 "y_qualifiers={0.policy_qualifiers})>".format(self)
543 )
544
545 def __eq__(self, other):
546 if not isinstance(other, PolicyInformation):
547 return NotImplemented
548
549 return (
550 self.policy_identifier == other.policy_identifier and
551 self.policy_qualifiers == other.policy_qualifiers
552 )
553
554 def __ne__(self, other):
555 return not self == other
556
557 policy_identifier = utils.read_only_property("_policy_identifier")
558 policy_qualifiers = utils.read_only_property("_policy_qualifiers")
559
560
561class UserNotice(object):
562 def __init__(self, notice_reference, explicit_text):
563 if notice_reference and not isinstance(
564 notice_reference, NoticeReference
565 ):
566 raise TypeError(
567 "notice_reference must be None or a NoticeReference"
568 )
569
570 self._notice_reference = notice_reference
571 self._explicit_text = explicit_text
572
573 def __repr__(self):
574 return (
575 "<UserNotice(notice_reference={0.notice_reference}, explicit_text="
576 "{0.explicit_text!r})>".format(self)
577 )
578
579 def __eq__(self, other):
580 if not isinstance(other, UserNotice):
581 return NotImplemented
582
583 return (
584 self.notice_reference == other.notice_reference and
585 self.explicit_text == other.explicit_text
586 )
587
588 def __ne__(self, other):
589 return not self == other
590
591 notice_reference = utils.read_only_property("_notice_reference")
592 explicit_text = utils.read_only_property("_explicit_text")
593
594
595class NoticeReference(object):
596 def __init__(self, organization, notice_numbers):
597 self._organization = organization
598 if not isinstance(notice_numbers, list) or not all(
599 isinstance(x, int) for x in notice_numbers
600 ):
601 raise TypeError(
602 "notice_numbers must be a list of integers"
603 )
604
605 self._notice_numbers = notice_numbers
606
607 def __repr__(self):
608 return (
609 "<NoticeReference(organization={0.organization!r}, notice_numbers="
610 "{0.notice_numbers})>".format(self)
611 )
612
613 def __eq__(self, other):
614 if not isinstance(other, NoticeReference):
615 return NotImplemented
616
617 return (
618 self.organization == other.organization and
619 self.notice_numbers == other.notice_numbers
620 )
621
622 def __ne__(self, other):
623 return not self == other
624
625 organization = utils.read_only_property("_organization")
626 notice_numbers = utils.read_only_property("_notice_numbers")
627
628
629@utils.register_interface(ExtensionType)
630class ExtendedKeyUsage(object):
631 oid = ExtensionOID.EXTENDED_KEY_USAGE
632
633 def __init__(self, usages):
634 if not all(isinstance(x, ObjectIdentifier) for x in usages):
635 raise TypeError(
636 "Every item in the usages list must be an ObjectIdentifier"
637 )
638
639 self._usages = usages
640
641 def __iter__(self):
642 return iter(self._usages)
643
644 def __len__(self):
645 return len(self._usages)
646
647 def __repr__(self):
648 return "<ExtendedKeyUsage({0})>".format(self._usages)
649
650 def __eq__(self, other):
651 if not isinstance(other, ExtendedKeyUsage):
652 return NotImplemented
653
654 return self._usages == other._usages
655
656 def __ne__(self, other):
657 return not self == other
658
659
660@utils.register_interface(ExtensionType)
661class OCSPNoCheck(object):
662 oid = ExtensionOID.OCSP_NO_CHECK
663
664
665@utils.register_interface(ExtensionType)
666class InhibitAnyPolicy(object):
667 oid = ExtensionOID.INHIBIT_ANY_POLICY
668
669 def __init__(self, skip_certs):
670 if not isinstance(skip_certs, six.integer_types):
671 raise TypeError("skip_certs must be an integer")
672
673 if skip_certs < 0:
674 raise ValueError("skip_certs must be a non-negative integer")
675
676 self._skip_certs = skip_certs
677
678 def __repr__(self):
679 return "<InhibitAnyPolicy(skip_certs={0.skip_certs})>".format(self)
680
681 def __eq__(self, other):
682 if not isinstance(other, InhibitAnyPolicy):
683 return NotImplemented
684
685 return self.skip_certs == other.skip_certs
686
687 def __ne__(self, other):
688 return not self == other
689
690 skip_certs = utils.read_only_property("_skip_certs")
Paul Kehrerfbeaf2a2015-08-10 23:52:10 -0500691
692
693@utils.register_interface(ExtensionType)
694class KeyUsage(object):
695 oid = ExtensionOID.KEY_USAGE
696
697 def __init__(self, digital_signature, content_commitment, key_encipherment,
698 data_encipherment, key_agreement, key_cert_sign, crl_sign,
699 encipher_only, decipher_only):
700 if not key_agreement and (encipher_only or decipher_only):
701 raise ValueError(
702 "encipher_only and decipher_only can only be true when "
703 "key_agreement is true"
704 )
705
706 self._digital_signature = digital_signature
707 self._content_commitment = content_commitment
708 self._key_encipherment = key_encipherment
709 self._data_encipherment = data_encipherment
710 self._key_agreement = key_agreement
711 self._key_cert_sign = key_cert_sign
712 self._crl_sign = crl_sign
713 self._encipher_only = encipher_only
714 self._decipher_only = decipher_only
715
716 digital_signature = utils.read_only_property("_digital_signature")
717 content_commitment = utils.read_only_property("_content_commitment")
718 key_encipherment = utils.read_only_property("_key_encipherment")
719 data_encipherment = utils.read_only_property("_data_encipherment")
720 key_agreement = utils.read_only_property("_key_agreement")
721 key_cert_sign = utils.read_only_property("_key_cert_sign")
722 crl_sign = utils.read_only_property("_crl_sign")
723
724 @property
725 def encipher_only(self):
726 if not self.key_agreement:
727 raise ValueError(
728 "encipher_only is undefined unless key_agreement is true"
729 )
730 else:
731 return self._encipher_only
732
733 @property
734 def decipher_only(self):
735 if not self.key_agreement:
736 raise ValueError(
737 "decipher_only is undefined unless key_agreement is true"
738 )
739 else:
740 return self._decipher_only
741
742 def __repr__(self):
743 try:
744 encipher_only = self.encipher_only
745 decipher_only = self.decipher_only
746 except ValueError:
747 encipher_only = None
748 decipher_only = None
749
750 return ("<KeyUsage(digital_signature={0.digital_signature}, "
751 "content_commitment={0.content_commitment}, "
752 "key_encipherment={0.key_encipherment}, "
753 "data_encipherment={0.data_encipherment}, "
754 "key_agreement={0.key_agreement}, "
755 "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
756 "encipher_only={1}, decipher_only={2})>").format(
757 self, encipher_only, decipher_only)
758
759 def __eq__(self, other):
760 if not isinstance(other, KeyUsage):
761 return NotImplemented
762
763 return (
764 self.digital_signature == other.digital_signature and
765 self.content_commitment == other.content_commitment and
766 self.key_encipherment == other.key_encipherment and
767 self.data_encipherment == other.data_encipherment and
768 self.key_agreement == other.key_agreement and
769 self.key_cert_sign == other.key_cert_sign and
770 self.crl_sign == other.crl_sign and
771 self._encipher_only == other._encipher_only and
772 self._decipher_only == other._decipher_only
773 )
774
775 def __ne__(self, other):
776 return not self == other
777
778
779@utils.register_interface(ExtensionType)
780class NameConstraints(object):
781 oid = ExtensionOID.NAME_CONSTRAINTS
782
783 def __init__(self, permitted_subtrees, excluded_subtrees):
784 if permitted_subtrees is not None:
785 if not all(
786 isinstance(x, GeneralName) for x in permitted_subtrees
787 ):
788 raise TypeError(
789 "permitted_subtrees must be a list of GeneralName objects "
790 "or None"
791 )
792
793 self._validate_ip_name(permitted_subtrees)
794
795 if excluded_subtrees is not None:
796 if not all(
797 isinstance(x, GeneralName) for x in excluded_subtrees
798 ):
799 raise TypeError(
800 "excluded_subtrees must be a list of GeneralName objects "
801 "or None"
802 )
803
804 self._validate_ip_name(excluded_subtrees)
805
806 if permitted_subtrees is None and excluded_subtrees is None:
807 raise ValueError(
808 "At least one of permitted_subtrees and excluded_subtrees "
809 "must not be None"
810 )
811
812 self._permitted_subtrees = permitted_subtrees
813 self._excluded_subtrees = excluded_subtrees
814
815 def __eq__(self, other):
816 if not isinstance(other, NameConstraints):
817 return NotImplemented
818
819 return (
820 self.excluded_subtrees == other.excluded_subtrees and
821 self.permitted_subtrees == other.permitted_subtrees
822 )
823
824 def __ne__(self, other):
825 return not self == other
826
827 def _validate_ip_name(self, tree):
828 if any(isinstance(name, IPAddress) and not isinstance(
829 name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
830 ) for name in tree):
831 raise TypeError(
832 "IPAddress name constraints must be an IPv4Network or"
833 " IPv6Network object"
834 )
835
836 def __repr__(self):
837 return (
838 u"<NameConstraints(permitted_subtrees={0.permitted_subtrees}, "
839 u"excluded_subtrees={0.excluded_subtrees})>".format(self)
840 )
841
842 permitted_subtrees = utils.read_only_property("_permitted_subtrees")
843 excluded_subtrees = utils.read_only_property("_excluded_subtrees")
Paul Kehreraa7a3222015-08-11 00:00:54 -0500844
845
846class Extension(object):
847 def __init__(self, oid, critical, value):
848 if not isinstance(oid, ObjectIdentifier):
849 raise TypeError(
850 "oid argument must be an ObjectIdentifier instance."
851 )
852
853 if not isinstance(critical, bool):
854 raise TypeError("critical must be a boolean value")
855
856 self._oid = oid
857 self._critical = critical
858 self._value = value
859
860 oid = utils.read_only_property("_oid")
861 critical = utils.read_only_property("_critical")
862 value = utils.read_only_property("_value")
863
864 def __repr__(self):
865 return ("<Extension(oid={0.oid}, critical={0.critical}, "
866 "value={0.value})>").format(self)
867
868 def __eq__(self, other):
869 if not isinstance(other, Extension):
870 return NotImplemented
871
872 return (
873 self.oid == other.oid and
874 self.critical == other.critical and
875 self.value == other.value
876 )
877
878 def __ne__(self, other):
879 return not self == other
880
881
882class GeneralNames(object):
883 def __init__(self, general_names):
884 if not all(isinstance(x, GeneralName) for x in general_names):
885 raise TypeError(
886 "Every item in the general_names list must be an "
887 "object conforming to the GeneralName interface"
888 )
889
890 self._general_names = general_names
891
892 def __iter__(self):
893 return iter(self._general_names)
894
895 def __len__(self):
896 return len(self._general_names)
897
898 def get_values_for_type(self, type):
899 # Return the value of each GeneralName, except for OtherName instances
900 # which we return directly because it has two important properties not
901 # just one value.
902 objs = (i for i in self if isinstance(i, type))
903 if type != OtherName:
904 objs = (i.value for i in objs)
905 return list(objs)
906
907 def __repr__(self):
908 return "<GeneralNames({0})>".format(self._general_names)
909
910 def __eq__(self, other):
911 if not isinstance(other, GeneralNames):
912 return NotImplemented
913
914 return self._general_names == other._general_names
915
916 def __ne__(self, other):
917 return not self == other
918
Paul Kehrer8adb5962015-12-26 14:46:58 -0600919 def __getitem__(self, idx):
920 return self._general_names[idx]
921
Paul Kehreraa7a3222015-08-11 00:00:54 -0500922
923@utils.register_interface(ExtensionType)
924class SubjectAlternativeName(object):
925 oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME
926
927 def __init__(self, general_names):
928 self._general_names = GeneralNames(general_names)
929
930 def __iter__(self):
931 return iter(self._general_names)
932
933 def __len__(self):
934 return len(self._general_names)
935
936 def get_values_for_type(self, type):
937 return self._general_names.get_values_for_type(type)
938
939 def __repr__(self):
940 return "<SubjectAlternativeName({0})>".format(self._general_names)
941
942 def __eq__(self, other):
943 if not isinstance(other, SubjectAlternativeName):
944 return NotImplemented
945
946 return self._general_names == other._general_names
947
Paul Kehrer8adb5962015-12-26 14:46:58 -0600948 def __getitem__(self, idx):
949 return self._general_names[idx]
950
Paul Kehreraa7a3222015-08-11 00:00:54 -0500951 def __ne__(self, other):
952 return not self == other
953
954
955@utils.register_interface(ExtensionType)
956class IssuerAlternativeName(object):
957 oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME
958
959 def __init__(self, general_names):
960 self._general_names = GeneralNames(general_names)
961
962 def __iter__(self):
963 return iter(self._general_names)
964
965 def __len__(self):
966 return len(self._general_names)
967
968 def get_values_for_type(self, type):
969 return self._general_names.get_values_for_type(type)
970
971 def __repr__(self):
972 return "<IssuerAlternativeName({0})>".format(self._general_names)
973
974 def __eq__(self, other):
975 if not isinstance(other, IssuerAlternativeName):
976 return NotImplemented
977
978 return self._general_names == other._general_names
979
980 def __ne__(self, other):
981 return not self == other
Paul Kehrer49bb7562015-12-25 16:17:40 -0600982
Paul Kehrer5c999d32015-12-26 17:45:20 -0600983 def __getitem__(self, idx):
984 return self._general_names[idx]
985
Paul Kehrer49bb7562015-12-25 16:17:40 -0600986
987@utils.register_interface(ExtensionType)
988class CertificateIssuer(object):
989 oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER
990
991 def __init__(self, general_names):
992 self._general_names = GeneralNames(general_names)
993
994 def __iter__(self):
995 return iter(self._general_names)
996
997 def __len__(self):
998 return len(self._general_names)
999
1000 def get_values_for_type(self, type):
1001 return self._general_names.get_values_for_type(type)
1002
1003 def __repr__(self):
1004 return "<CertificateIssuer({0})>".format(self._general_names)
1005
1006 def __eq__(self, other):
1007 if not isinstance(other, CertificateIssuer):
1008 return NotImplemented
1009
1010 return self._general_names == other._general_names
1011
1012 def __ne__(self, other):
1013 return not self == other
Paul Kehrer7058ece2015-12-25 22:28:29 -06001014
Paul Kehrer5c999d32015-12-26 17:45:20 -06001015 def __getitem__(self, idx):
1016 return self._general_names[idx]
1017
Paul Kehrer7058ece2015-12-25 22:28:29 -06001018
1019@utils.register_interface(ExtensionType)
1020class CRLReason(object):
1021 oid = CRLEntryExtensionOID.CRL_REASON
1022
1023 def __init__(self, reason):
1024 if not isinstance(reason, ReasonFlags):
1025 raise TypeError("reason must be an element from ReasonFlags")
1026
1027 self._reason = reason
1028
1029 def __repr__(self):
1030 return "<CRLReason(reason={0})>".format(self._reason)
1031
1032 def __eq__(self, other):
1033 if not isinstance(other, CRLReason):
1034 return NotImplemented
1035
1036 return self.reason == other.reason
1037
1038 def __ne__(self, other):
1039 return not self == other
1040
Alex Gaynor07d5cae2015-12-27 15:30:39 -05001041 def __hash__(self):
1042 return hash(self.reason)
1043
Paul Kehrer7058ece2015-12-25 22:28:29 -06001044 reason = utils.read_only_property("_reason")
Paul Kehrer23c0bbc2015-12-25 22:35:19 -06001045
1046
1047@utils.register_interface(ExtensionType)
1048class InvalidityDate(object):
1049 oid = CRLEntryExtensionOID.INVALIDITY_DATE
1050
1051 def __init__(self, invalidity_date):
1052 if not isinstance(invalidity_date, datetime.datetime):
1053 raise TypeError("invalidity_date must be a datetime.datetime")
1054
1055 self._invalidity_date = invalidity_date
1056
1057 def __repr__(self):
1058 return "<InvalidityDate(invalidity_date={0})>".format(
1059 self._invalidity_date
1060 )
1061
1062 def __eq__(self, other):
1063 if not isinstance(other, InvalidityDate):
1064 return NotImplemented
1065
1066 return self.invalidity_date == other.invalidity_date
1067
1068 def __ne__(self, other):
1069 return not self == other
1070
Paul Kehrer67cde762015-12-26 11:37:14 -06001071 def __hash__(self):
1072 return hash(self.invalidity_date)
1073
Paul Kehrer23c0bbc2015-12-25 22:35:19 -06001074 invalidity_date = utils.read_only_property("_invalidity_date")
Paul Kehrer14fd6972015-12-30 10:58:25 -06001075
1076
1077@utils.register_interface(ExtensionType)
1078class UnrecognizedExtension(object):
1079 def __init__(self, oid, value):
1080 if not isinstance(oid, ObjectIdentifier):
1081 raise TypeError("oid must be an ObjectIdentifier")
1082 self._oid = oid
1083 self._value = value
1084
1085 oid = utils.read_only_property("_oid")
1086 value = utils.read_only_property("_value")
1087
1088 def __repr__(self):
1089 return (
1090 "<UnrecognizedExtension(oid={0.oid}, value={0.value!r})>".format(
1091 self
1092 )
1093 )
1094
1095 def __eq__(self, other):
1096 if not isinstance(other, UnrecognizedExtension):
1097 return NotImplemented
1098
1099 return self.oid == other.oid and self.value == other.value
1100
1101 def __ne__(self, other):
1102 return not self == other
1103
1104 def __hash__(self):
1105 return hash((self.oid, self.value))