blob: dd2b8e6359ae839a18ee26eb5dd6ddf13f585ebc [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):
94 for ext in self:
Phoebe Queen754be602015-08-12 03:11:35 +010095 if isinstance(ext.value, extclass):
Phoebe Queen64cf4cd2015-08-12 02:28:43 +010096 return ext
97
Phoebe Queen2cc111a2015-08-12 04:14:22 +010098 raise ExtensionNotFound(
Phoebe Queenecae9812015-08-12 05:00:32 +010099 "No {0} extension was found".format(extclass), extclass.oid
Phoebe Queen2cc111a2015-08-12 04:14:22 +0100100 )
Phoebe Queen64cf4cd2015-08-12 02:28:43 +0100101
Paul Kehrerfbeaf2a2015-08-10 23:52:10 -0500102 def __iter__(self):
103 return iter(self._extensions)
104
105 def __len__(self):
106 return len(self._extensions)
107
Paul Kehrer5b90c972015-12-26 00:52:58 -0600108 def __getitem__(self, idx):
109 return self._extensions[idx]
110
Paul Kehrerafbe75b2015-10-20 08:08:43 -0500111 def __repr__(self):
112 return (
113 "<Extensions({0})>".format(self._extensions)
114 )
115
Paul Kehrerfbeaf2a2015-08-10 23:52:10 -0500116
Paul Kehrer890cb7f2015-08-10 21:05:34 -0500117@utils.register_interface(ExtensionType)
Paul Kehrer3b95cd72015-12-22 21:40:20 -0600118class CRLNumber(object):
119 oid = ExtensionOID.CRL_NUMBER
120
121 def __init__(self, crl_number):
122 if not isinstance(crl_number, six.integer_types):
123 raise TypeError("crl_number must be an integer")
124
125 self._crl_number = crl_number
126
127 def __eq__(self, other):
128 if not isinstance(other, CRLNumber):
129 return NotImplemented
130
131 return self.crl_number == other.crl_number
132
133 def __ne__(self, other):
134 return not self == other
135
Alex Gaynorf9a77b62015-12-26 12:14:25 -0500136 def __hash__(self):
137 return hash(self.crl_number)
138
Paul Kehrer3b95cd72015-12-22 21:40:20 -0600139 def __repr__(self):
140 return "<CRLNumber({0})>".format(self.crl_number)
141
142 crl_number = utils.read_only_property("_crl_number")
143
144
145@utils.register_interface(ExtensionType)
Paul Kehrer890cb7f2015-08-10 21:05:34 -0500146class AuthorityKeyIdentifier(object):
147 oid = ExtensionOID.AUTHORITY_KEY_IDENTIFIER
148
149 def __init__(self, key_identifier, authority_cert_issuer,
150 authority_cert_serial_number):
151 if authority_cert_issuer or authority_cert_serial_number:
152 if not authority_cert_issuer or not authority_cert_serial_number:
153 raise ValueError(
154 "authority_cert_issuer and authority_cert_serial_number "
155 "must both be present or both None"
156 )
157
158 if not all(
159 isinstance(x, GeneralName) for x in authority_cert_issuer
160 ):
161 raise TypeError(
162 "authority_cert_issuer must be a list of GeneralName "
163 "objects"
164 )
165
166 if not isinstance(authority_cert_serial_number, six.integer_types):
167 raise TypeError(
168 "authority_cert_serial_number must be an integer"
169 )
170
171 self._key_identifier = key_identifier
172 self._authority_cert_issuer = authority_cert_issuer
173 self._authority_cert_serial_number = authority_cert_serial_number
174
175 @classmethod
176 def from_issuer_public_key(cls, public_key):
177 digest = _key_identifier_from_public_key(public_key)
178 return cls(
179 key_identifier=digest,
180 authority_cert_issuer=None,
181 authority_cert_serial_number=None
182 )
183
184 def __repr__(self):
185 return (
186 "<AuthorityKeyIdentifier(key_identifier={0.key_identifier!r}, "
187 "authority_cert_issuer={0.authority_cert_issuer}, "
188 "authority_cert_serial_number={0.authority_cert_serial_number}"
189 ")>".format(self)
190 )
191
192 def __eq__(self, other):
193 if not isinstance(other, AuthorityKeyIdentifier):
194 return NotImplemented
195
196 return (
197 self.key_identifier == other.key_identifier and
198 self.authority_cert_issuer == other.authority_cert_issuer and
199 self.authority_cert_serial_number ==
200 other.authority_cert_serial_number
201 )
202
203 def __ne__(self, other):
204 return not self == other
205
206 key_identifier = utils.read_only_property("_key_identifier")
207 authority_cert_issuer = utils.read_only_property("_authority_cert_issuer")
208 authority_cert_serial_number = utils.read_only_property(
209 "_authority_cert_serial_number"
210 )
211
212
213@utils.register_interface(ExtensionType)
214class SubjectKeyIdentifier(object):
215 oid = ExtensionOID.SUBJECT_KEY_IDENTIFIER
216
217 def __init__(self, digest):
218 self._digest = digest
219
220 @classmethod
221 def from_public_key(cls, public_key):
222 return cls(_key_identifier_from_public_key(public_key))
223
224 digest = utils.read_only_property("_digest")
225
226 def __repr__(self):
227 return "<SubjectKeyIdentifier(digest={0!r})>".format(self.digest)
228
229 def __eq__(self, other):
230 if not isinstance(other, SubjectKeyIdentifier):
231 return NotImplemented
232
Predrag Gruevski57f3b3f2015-09-21 18:51:47 -0400233 return constant_time.bytes_eq(self.digest, other.digest)
Paul Kehrer890cb7f2015-08-10 21:05:34 -0500234
235 def __ne__(self, other):
236 return not self == other
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500237
Alex Gaynor410fe352015-12-26 15:01:25 -0500238 def __hash__(self):
239 return hash(self.digest)
240
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500241
242@utils.register_interface(ExtensionType)
243class AuthorityInformationAccess(object):
244 oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS
245
246 def __init__(self, descriptions):
247 if not all(isinstance(x, AccessDescription) for x in descriptions):
248 raise TypeError(
249 "Every item in the descriptions list must be an "
250 "AccessDescription"
251 )
252
253 self._descriptions = descriptions
254
255 def __iter__(self):
256 return iter(self._descriptions)
257
258 def __len__(self):
259 return len(self._descriptions)
260
261 def __repr__(self):
262 return "<AuthorityInformationAccess({0})>".format(self._descriptions)
263
264 def __eq__(self, other):
265 if not isinstance(other, AuthorityInformationAccess):
266 return NotImplemented
267
268 return self._descriptions == other._descriptions
269
270 def __ne__(self, other):
271 return not self == other
272
273
274class AccessDescription(object):
275 def __init__(self, access_method, access_location):
Nick Bastind06763d2015-12-12 18:32:59 -0800276 if not isinstance(access_method, ObjectIdentifier):
Nick Bastinbd079ae2015-12-13 05:15:44 -0800277 raise TypeError("access_method must be an ObjectIdentifier")
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500278
279 if not isinstance(access_location, GeneralName):
280 raise TypeError("access_location must be a GeneralName")
281
282 self._access_method = access_method
283 self._access_location = access_location
284
285 def __repr__(self):
286 return (
287 "<AccessDescription(access_method={0.access_method}, access_locati"
288 "on={0.access_location})>".format(self)
289 )
290
291 def __eq__(self, other):
292 if not isinstance(other, AccessDescription):
293 return NotImplemented
294
295 return (
296 self.access_method == other.access_method and
297 self.access_location == other.access_location
298 )
299
300 def __ne__(self, other):
301 return not self == other
302
303 access_method = utils.read_only_property("_access_method")
304 access_location = utils.read_only_property("_access_location")
305
306
307@utils.register_interface(ExtensionType)
308class BasicConstraints(object):
309 oid = ExtensionOID.BASIC_CONSTRAINTS
310
311 def __init__(self, ca, path_length):
312 if not isinstance(ca, bool):
313 raise TypeError("ca must be a boolean value")
314
315 if path_length is not None and not ca:
316 raise ValueError("path_length must be None when ca is False")
317
318 if (
319 path_length is not None and
320 (not isinstance(path_length, six.integer_types) or path_length < 0)
321 ):
322 raise TypeError(
323 "path_length must be a non-negative integer or None"
324 )
325
326 self._ca = ca
327 self._path_length = path_length
328
329 ca = utils.read_only_property("_ca")
330 path_length = utils.read_only_property("_path_length")
331
332 def __repr__(self):
333 return ("<BasicConstraints(ca={0.ca}, "
334 "path_length={0.path_length})>").format(self)
335
336 def __eq__(self, other):
337 if not isinstance(other, BasicConstraints):
338 return NotImplemented
339
340 return self.ca == other.ca and self.path_length == other.path_length
341
342 def __ne__(self, other):
343 return not self == other
344
Paul Kehrer2eb69f62015-12-27 11:46:11 -0600345 def __hash__(self):
346 return hash((self.ca, self.path_length))
347
Paul Kehrer9f8069a2015-08-10 21:10:34 -0500348
349@utils.register_interface(ExtensionType)
350class CRLDistributionPoints(object):
351 oid = ExtensionOID.CRL_DISTRIBUTION_POINTS
352
353 def __init__(self, distribution_points):
354 if not all(
355 isinstance(x, DistributionPoint) for x in distribution_points
356 ):
357 raise TypeError(
358 "distribution_points must be a list of DistributionPoint "
359 "objects"
360 )
361
362 self._distribution_points = distribution_points
363
364 def __iter__(self):
365 return iter(self._distribution_points)
366
367 def __len__(self):
368 return len(self._distribution_points)
369
370 def __repr__(self):
371 return "<CRLDistributionPoints({0})>".format(self._distribution_points)
372
373 def __eq__(self, other):
374 if not isinstance(other, CRLDistributionPoints):
375 return NotImplemented
376
377 return self._distribution_points == other._distribution_points
378
379 def __ne__(self, other):
380 return not self == other
381
382
383class DistributionPoint(object):
384 def __init__(self, full_name, relative_name, reasons, crl_issuer):
385 if full_name and relative_name:
386 raise ValueError(
387 "You cannot provide both full_name and relative_name, at "
388 "least one must be None."
389 )
390
391 if full_name and not all(
392 isinstance(x, GeneralName) for x in full_name
393 ):
394 raise TypeError(
395 "full_name must be a list of GeneralName objects"
396 )
397
398 if relative_name and not isinstance(relative_name, Name):
399 raise TypeError("relative_name must be a Name")
400
401 if crl_issuer and not all(
402 isinstance(x, GeneralName) for x in crl_issuer
403 ):
404 raise TypeError(
405 "crl_issuer must be None or a list of general names"
406 )
407
408 if reasons and (not isinstance(reasons, frozenset) or not all(
409 isinstance(x, ReasonFlags) for x in reasons
410 )):
411 raise TypeError("reasons must be None or frozenset of ReasonFlags")
412
413 if reasons and (
414 ReasonFlags.unspecified in reasons or
415 ReasonFlags.remove_from_crl in reasons
416 ):
417 raise ValueError(
418 "unspecified and remove_from_crl are not valid reasons in a "
419 "DistributionPoint"
420 )
421
422 if reasons and not crl_issuer and not (full_name or relative_name):
423 raise ValueError(
424 "You must supply crl_issuer, full_name, or relative_name when "
425 "reasons is not None"
426 )
427
428 self._full_name = full_name
429 self._relative_name = relative_name
430 self._reasons = reasons
431 self._crl_issuer = crl_issuer
432
433 def __repr__(self):
434 return (
435 "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
436 "tive_name}, reasons={0.reasons}, crl_issuer={0.crl_is"
437 "suer})>".format(self)
438 )
439
440 def __eq__(self, other):
441 if not isinstance(other, DistributionPoint):
442 return NotImplemented
443
444 return (
445 self.full_name == other.full_name and
446 self.relative_name == other.relative_name and
447 self.reasons == other.reasons and
448 self.crl_issuer == other.crl_issuer
449 )
450
451 def __ne__(self, other):
452 return not self == other
453
454 full_name = utils.read_only_property("_full_name")
455 relative_name = utils.read_only_property("_relative_name")
456 reasons = utils.read_only_property("_reasons")
457 crl_issuer = utils.read_only_property("_crl_issuer")
458
459
460class ReasonFlags(Enum):
461 unspecified = "unspecified"
462 key_compromise = "keyCompromise"
463 ca_compromise = "cACompromise"
464 affiliation_changed = "affiliationChanged"
465 superseded = "superseded"
466 cessation_of_operation = "cessationOfOperation"
467 certificate_hold = "certificateHold"
468 privilege_withdrawn = "privilegeWithdrawn"
469 aa_compromise = "aACompromise"
470 remove_from_crl = "removeFromCRL"
Paul Kehrer012262c2015-08-10 23:42:57 -0500471
472
473@utils.register_interface(ExtensionType)
474class CertificatePolicies(object):
475 oid = ExtensionOID.CERTIFICATE_POLICIES
476
477 def __init__(self, policies):
478 if not all(isinstance(x, PolicyInformation) for x in policies):
479 raise TypeError(
480 "Every item in the policies list must be a "
481 "PolicyInformation"
482 )
483
484 self._policies = policies
485
486 def __iter__(self):
487 return iter(self._policies)
488
489 def __len__(self):
490 return len(self._policies)
491
492 def __repr__(self):
493 return "<CertificatePolicies({0})>".format(self._policies)
494
495 def __eq__(self, other):
496 if not isinstance(other, CertificatePolicies):
497 return NotImplemented
498
499 return self._policies == other._policies
500
501 def __ne__(self, other):
502 return not self == other
503
Paul Kehrere8db7bd2015-12-27 17:32:57 -0600504 def __getitem__(self, idx):
505 return self._policies[idx]
506
Paul Kehrer012262c2015-08-10 23:42:57 -0500507
508class PolicyInformation(object):
509 def __init__(self, policy_identifier, policy_qualifiers):
510 if not isinstance(policy_identifier, ObjectIdentifier):
511 raise TypeError("policy_identifier must be an ObjectIdentifier")
512
513 self._policy_identifier = policy_identifier
514 if policy_qualifiers and not all(
515 isinstance(
516 x, (six.text_type, UserNotice)
517 ) for x in policy_qualifiers
518 ):
519 raise TypeError(
520 "policy_qualifiers must be a list of strings and/or UserNotice"
521 " objects or None"
522 )
523
524 self._policy_qualifiers = policy_qualifiers
525
526 def __repr__(self):
527 return (
528 "<PolicyInformation(policy_identifier={0.policy_identifier}, polic"
529 "y_qualifiers={0.policy_qualifiers})>".format(self)
530 )
531
532 def __eq__(self, other):
533 if not isinstance(other, PolicyInformation):
534 return NotImplemented
535
536 return (
537 self.policy_identifier == other.policy_identifier and
538 self.policy_qualifiers == other.policy_qualifiers
539 )
540
541 def __ne__(self, other):
542 return not self == other
543
544 policy_identifier = utils.read_only_property("_policy_identifier")
545 policy_qualifiers = utils.read_only_property("_policy_qualifiers")
546
547
548class UserNotice(object):
549 def __init__(self, notice_reference, explicit_text):
550 if notice_reference and not isinstance(
551 notice_reference, NoticeReference
552 ):
553 raise TypeError(
554 "notice_reference must be None or a NoticeReference"
555 )
556
557 self._notice_reference = notice_reference
558 self._explicit_text = explicit_text
559
560 def __repr__(self):
561 return (
562 "<UserNotice(notice_reference={0.notice_reference}, explicit_text="
563 "{0.explicit_text!r})>".format(self)
564 )
565
566 def __eq__(self, other):
567 if not isinstance(other, UserNotice):
568 return NotImplemented
569
570 return (
571 self.notice_reference == other.notice_reference and
572 self.explicit_text == other.explicit_text
573 )
574
575 def __ne__(self, other):
576 return not self == other
577
578 notice_reference = utils.read_only_property("_notice_reference")
579 explicit_text = utils.read_only_property("_explicit_text")
580
581
582class NoticeReference(object):
583 def __init__(self, organization, notice_numbers):
584 self._organization = organization
585 if not isinstance(notice_numbers, list) or not all(
586 isinstance(x, int) for x in notice_numbers
587 ):
588 raise TypeError(
589 "notice_numbers must be a list of integers"
590 )
591
592 self._notice_numbers = notice_numbers
593
594 def __repr__(self):
595 return (
596 "<NoticeReference(organization={0.organization!r}, notice_numbers="
597 "{0.notice_numbers})>".format(self)
598 )
599
600 def __eq__(self, other):
601 if not isinstance(other, NoticeReference):
602 return NotImplemented
603
604 return (
605 self.organization == other.organization and
606 self.notice_numbers == other.notice_numbers
607 )
608
609 def __ne__(self, other):
610 return not self == other
611
612 organization = utils.read_only_property("_organization")
613 notice_numbers = utils.read_only_property("_notice_numbers")
614
615
616@utils.register_interface(ExtensionType)
617class ExtendedKeyUsage(object):
618 oid = ExtensionOID.EXTENDED_KEY_USAGE
619
620 def __init__(self, usages):
621 if not all(isinstance(x, ObjectIdentifier) for x in usages):
622 raise TypeError(
623 "Every item in the usages list must be an ObjectIdentifier"
624 )
625
626 self._usages = usages
627
628 def __iter__(self):
629 return iter(self._usages)
630
631 def __len__(self):
632 return len(self._usages)
633
634 def __repr__(self):
635 return "<ExtendedKeyUsage({0})>".format(self._usages)
636
637 def __eq__(self, other):
638 if not isinstance(other, ExtendedKeyUsage):
639 return NotImplemented
640
641 return self._usages == other._usages
642
643 def __ne__(self, other):
644 return not self == other
645
646
647@utils.register_interface(ExtensionType)
648class OCSPNoCheck(object):
649 oid = ExtensionOID.OCSP_NO_CHECK
650
651
652@utils.register_interface(ExtensionType)
653class InhibitAnyPolicy(object):
654 oid = ExtensionOID.INHIBIT_ANY_POLICY
655
656 def __init__(self, skip_certs):
657 if not isinstance(skip_certs, six.integer_types):
658 raise TypeError("skip_certs must be an integer")
659
660 if skip_certs < 0:
661 raise ValueError("skip_certs must be a non-negative integer")
662
663 self._skip_certs = skip_certs
664
665 def __repr__(self):
666 return "<InhibitAnyPolicy(skip_certs={0.skip_certs})>".format(self)
667
668 def __eq__(self, other):
669 if not isinstance(other, InhibitAnyPolicy):
670 return NotImplemented
671
672 return self.skip_certs == other.skip_certs
673
674 def __ne__(self, other):
675 return not self == other
676
677 skip_certs = utils.read_only_property("_skip_certs")
Paul Kehrerfbeaf2a2015-08-10 23:52:10 -0500678
679
680@utils.register_interface(ExtensionType)
681class KeyUsage(object):
682 oid = ExtensionOID.KEY_USAGE
683
684 def __init__(self, digital_signature, content_commitment, key_encipherment,
685 data_encipherment, key_agreement, key_cert_sign, crl_sign,
686 encipher_only, decipher_only):
687 if not key_agreement and (encipher_only or decipher_only):
688 raise ValueError(
689 "encipher_only and decipher_only can only be true when "
690 "key_agreement is true"
691 )
692
693 self._digital_signature = digital_signature
694 self._content_commitment = content_commitment
695 self._key_encipherment = key_encipherment
696 self._data_encipherment = data_encipherment
697 self._key_agreement = key_agreement
698 self._key_cert_sign = key_cert_sign
699 self._crl_sign = crl_sign
700 self._encipher_only = encipher_only
701 self._decipher_only = decipher_only
702
703 digital_signature = utils.read_only_property("_digital_signature")
704 content_commitment = utils.read_only_property("_content_commitment")
705 key_encipherment = utils.read_only_property("_key_encipherment")
706 data_encipherment = utils.read_only_property("_data_encipherment")
707 key_agreement = utils.read_only_property("_key_agreement")
708 key_cert_sign = utils.read_only_property("_key_cert_sign")
709 crl_sign = utils.read_only_property("_crl_sign")
710
711 @property
712 def encipher_only(self):
713 if not self.key_agreement:
714 raise ValueError(
715 "encipher_only is undefined unless key_agreement is true"
716 )
717 else:
718 return self._encipher_only
719
720 @property
721 def decipher_only(self):
722 if not self.key_agreement:
723 raise ValueError(
724 "decipher_only is undefined unless key_agreement is true"
725 )
726 else:
727 return self._decipher_only
728
729 def __repr__(self):
730 try:
731 encipher_only = self.encipher_only
732 decipher_only = self.decipher_only
733 except ValueError:
734 encipher_only = None
735 decipher_only = None
736
737 return ("<KeyUsage(digital_signature={0.digital_signature}, "
738 "content_commitment={0.content_commitment}, "
739 "key_encipherment={0.key_encipherment}, "
740 "data_encipherment={0.data_encipherment}, "
741 "key_agreement={0.key_agreement}, "
742 "key_cert_sign={0.key_cert_sign}, crl_sign={0.crl_sign}, "
743 "encipher_only={1}, decipher_only={2})>").format(
744 self, encipher_only, decipher_only)
745
746 def __eq__(self, other):
747 if not isinstance(other, KeyUsage):
748 return NotImplemented
749
750 return (
751 self.digital_signature == other.digital_signature and
752 self.content_commitment == other.content_commitment and
753 self.key_encipherment == other.key_encipherment and
754 self.data_encipherment == other.data_encipherment and
755 self.key_agreement == other.key_agreement and
756 self.key_cert_sign == other.key_cert_sign and
757 self.crl_sign == other.crl_sign and
758 self._encipher_only == other._encipher_only and
759 self._decipher_only == other._decipher_only
760 )
761
762 def __ne__(self, other):
763 return not self == other
764
765
766@utils.register_interface(ExtensionType)
767class NameConstraints(object):
768 oid = ExtensionOID.NAME_CONSTRAINTS
769
770 def __init__(self, permitted_subtrees, excluded_subtrees):
771 if permitted_subtrees is not None:
772 if not all(
773 isinstance(x, GeneralName) for x in permitted_subtrees
774 ):
775 raise TypeError(
776 "permitted_subtrees must be a list of GeneralName objects "
777 "or None"
778 )
779
780 self._validate_ip_name(permitted_subtrees)
781
782 if excluded_subtrees is not None:
783 if not all(
784 isinstance(x, GeneralName) for x in excluded_subtrees
785 ):
786 raise TypeError(
787 "excluded_subtrees must be a list of GeneralName objects "
788 "or None"
789 )
790
791 self._validate_ip_name(excluded_subtrees)
792
793 if permitted_subtrees is None and excluded_subtrees is None:
794 raise ValueError(
795 "At least one of permitted_subtrees and excluded_subtrees "
796 "must not be None"
797 )
798
799 self._permitted_subtrees = permitted_subtrees
800 self._excluded_subtrees = excluded_subtrees
801
802 def __eq__(self, other):
803 if not isinstance(other, NameConstraints):
804 return NotImplemented
805
806 return (
807 self.excluded_subtrees == other.excluded_subtrees and
808 self.permitted_subtrees == other.permitted_subtrees
809 )
810
811 def __ne__(self, other):
812 return not self == other
813
814 def _validate_ip_name(self, tree):
815 if any(isinstance(name, IPAddress) and not isinstance(
816 name.value, (ipaddress.IPv4Network, ipaddress.IPv6Network)
817 ) for name in tree):
818 raise TypeError(
819 "IPAddress name constraints must be an IPv4Network or"
820 " IPv6Network object"
821 )
822
823 def __repr__(self):
824 return (
825 u"<NameConstraints(permitted_subtrees={0.permitted_subtrees}, "
826 u"excluded_subtrees={0.excluded_subtrees})>".format(self)
827 )
828
829 permitted_subtrees = utils.read_only_property("_permitted_subtrees")
830 excluded_subtrees = utils.read_only_property("_excluded_subtrees")
Paul Kehreraa7a3222015-08-11 00:00:54 -0500831
832
833class Extension(object):
834 def __init__(self, oid, critical, value):
835 if not isinstance(oid, ObjectIdentifier):
836 raise TypeError(
837 "oid argument must be an ObjectIdentifier instance."
838 )
839
840 if not isinstance(critical, bool):
841 raise TypeError("critical must be a boolean value")
842
843 self._oid = oid
844 self._critical = critical
845 self._value = value
846
847 oid = utils.read_only_property("_oid")
848 critical = utils.read_only_property("_critical")
849 value = utils.read_only_property("_value")
850
851 def __repr__(self):
852 return ("<Extension(oid={0.oid}, critical={0.critical}, "
853 "value={0.value})>").format(self)
854
855 def __eq__(self, other):
856 if not isinstance(other, Extension):
857 return NotImplemented
858
859 return (
860 self.oid == other.oid and
861 self.critical == other.critical and
862 self.value == other.value
863 )
864
865 def __ne__(self, other):
866 return not self == other
867
868
869class GeneralNames(object):
870 def __init__(self, general_names):
871 if not all(isinstance(x, GeneralName) for x in general_names):
872 raise TypeError(
873 "Every item in the general_names list must be an "
874 "object conforming to the GeneralName interface"
875 )
876
877 self._general_names = general_names
878
879 def __iter__(self):
880 return iter(self._general_names)
881
882 def __len__(self):
883 return len(self._general_names)
884
885 def get_values_for_type(self, type):
886 # Return the value of each GeneralName, except for OtherName instances
887 # which we return directly because it has two important properties not
888 # just one value.
889 objs = (i for i in self if isinstance(i, type))
890 if type != OtherName:
891 objs = (i.value for i in objs)
892 return list(objs)
893
894 def __repr__(self):
895 return "<GeneralNames({0})>".format(self._general_names)
896
897 def __eq__(self, other):
898 if not isinstance(other, GeneralNames):
899 return NotImplemented
900
901 return self._general_names == other._general_names
902
903 def __ne__(self, other):
904 return not self == other
905
Paul Kehrer8adb5962015-12-26 14:46:58 -0600906 def __getitem__(self, idx):
907 return self._general_names[idx]
908
Paul Kehreraa7a3222015-08-11 00:00:54 -0500909
910@utils.register_interface(ExtensionType)
911class SubjectAlternativeName(object):
912 oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME
913
914 def __init__(self, general_names):
915 self._general_names = GeneralNames(general_names)
916
917 def __iter__(self):
918 return iter(self._general_names)
919
920 def __len__(self):
921 return len(self._general_names)
922
923 def get_values_for_type(self, type):
924 return self._general_names.get_values_for_type(type)
925
926 def __repr__(self):
927 return "<SubjectAlternativeName({0})>".format(self._general_names)
928
929 def __eq__(self, other):
930 if not isinstance(other, SubjectAlternativeName):
931 return NotImplemented
932
933 return self._general_names == other._general_names
934
Paul Kehrer8adb5962015-12-26 14:46:58 -0600935 def __getitem__(self, idx):
936 return self._general_names[idx]
937
Paul Kehreraa7a3222015-08-11 00:00:54 -0500938 def __ne__(self, other):
939 return not self == other
940
941
942@utils.register_interface(ExtensionType)
943class IssuerAlternativeName(object):
944 oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME
945
946 def __init__(self, general_names):
947 self._general_names = GeneralNames(general_names)
948
949 def __iter__(self):
950 return iter(self._general_names)
951
952 def __len__(self):
953 return len(self._general_names)
954
955 def get_values_for_type(self, type):
956 return self._general_names.get_values_for_type(type)
957
958 def __repr__(self):
959 return "<IssuerAlternativeName({0})>".format(self._general_names)
960
961 def __eq__(self, other):
962 if not isinstance(other, IssuerAlternativeName):
963 return NotImplemented
964
965 return self._general_names == other._general_names
966
967 def __ne__(self, other):
968 return not self == other
Paul Kehrer49bb7562015-12-25 16:17:40 -0600969
Paul Kehrer5c999d32015-12-26 17:45:20 -0600970 def __getitem__(self, idx):
971 return self._general_names[idx]
972
Paul Kehrer49bb7562015-12-25 16:17:40 -0600973
974@utils.register_interface(ExtensionType)
975class CertificateIssuer(object):
976 oid = CRLEntryExtensionOID.CERTIFICATE_ISSUER
977
978 def __init__(self, general_names):
979 self._general_names = GeneralNames(general_names)
980
981 def __iter__(self):
982 return iter(self._general_names)
983
984 def __len__(self):
985 return len(self._general_names)
986
987 def get_values_for_type(self, type):
988 return self._general_names.get_values_for_type(type)
989
990 def __repr__(self):
991 return "<CertificateIssuer({0})>".format(self._general_names)
992
993 def __eq__(self, other):
994 if not isinstance(other, CertificateIssuer):
995 return NotImplemented
996
997 return self._general_names == other._general_names
998
999 def __ne__(self, other):
1000 return not self == other
Paul Kehrer7058ece2015-12-25 22:28:29 -06001001
Paul Kehrer5c999d32015-12-26 17:45:20 -06001002 def __getitem__(self, idx):
1003 return self._general_names[idx]
1004
Paul Kehrer7058ece2015-12-25 22:28:29 -06001005
1006@utils.register_interface(ExtensionType)
1007class CRLReason(object):
1008 oid = CRLEntryExtensionOID.CRL_REASON
1009
1010 def __init__(self, reason):
1011 if not isinstance(reason, ReasonFlags):
1012 raise TypeError("reason must be an element from ReasonFlags")
1013
1014 self._reason = reason
1015
1016 def __repr__(self):
1017 return "<CRLReason(reason={0})>".format(self._reason)
1018
1019 def __eq__(self, other):
1020 if not isinstance(other, CRLReason):
1021 return NotImplemented
1022
1023 return self.reason == other.reason
1024
1025 def __ne__(self, other):
1026 return not self == other
1027
Alex Gaynor07d5cae2015-12-27 15:30:39 -05001028 def __hash__(self):
1029 return hash(self.reason)
1030
Paul Kehrer7058ece2015-12-25 22:28:29 -06001031 reason = utils.read_only_property("_reason")
Paul Kehrer23c0bbc2015-12-25 22:35:19 -06001032
1033
1034@utils.register_interface(ExtensionType)
1035class InvalidityDate(object):
1036 oid = CRLEntryExtensionOID.INVALIDITY_DATE
1037
1038 def __init__(self, invalidity_date):
1039 if not isinstance(invalidity_date, datetime.datetime):
1040 raise TypeError("invalidity_date must be a datetime.datetime")
1041
1042 self._invalidity_date = invalidity_date
1043
1044 def __repr__(self):
1045 return "<InvalidityDate(invalidity_date={0})>".format(
1046 self._invalidity_date
1047 )
1048
1049 def __eq__(self, other):
1050 if not isinstance(other, InvalidityDate):
1051 return NotImplemented
1052
1053 return self.invalidity_date == other.invalidity_date
1054
1055 def __ne__(self, other):
1056 return not self == other
1057
Paul Kehrer67cde762015-12-26 11:37:14 -06001058 def __hash__(self):
1059 return hash(self.invalidity_date)
1060
Paul Kehrer23c0bbc2015-12-25 22:35:19 -06001061 invalidity_date = utils.read_only_property("_invalidity_date")