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