summaryrefslogtreecommitdiff
path: root/src/cryptography/hazmat/backends/openssl/x509.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptography/hazmat/backends/openssl/x509.py')
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py157
1 files changed, 94 insertions, 63 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index ac1838c6d..4d0dac764 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -6,31 +6,43 @@ from __future__ import absolute_import, division, print_function
import datetime
import operator
-import warnings
from cryptography import utils, x509
from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.backends.openssl.decode_asn1 import (
- _CERTIFICATE_EXTENSION_PARSER, _CERTIFICATE_EXTENSION_PARSER_NO_SCT,
- _CRL_EXTENSION_PARSER, _CSR_EXTENSION_PARSER,
- _REVOKED_CERTIFICATE_EXTENSION_PARSER, _asn1_integer_to_int,
- _asn1_string_to_bytes, _decode_x509_name, _obj2txt, _parse_asn1_time
+ _asn1_integer_to_int,
+ _asn1_string_to_bytes,
+ _decode_x509_name,
+ _obj2txt,
+ _parse_asn1_time,
)
from cryptography.hazmat.backends.openssl.encode_asn1 import (
- _encode_asn1_int_gc
+ _encode_asn1_int_gc,
+ _txt2obj_gc,
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
+from cryptography.x509.name import _ASN1Type
@utils.register_interface(x509.Certificate)
class _Certificate(object):
- def __init__(self, backend, x509):
+ def __init__(self, backend, x509_cert):
self._backend = backend
- self._x509 = x509
+ self._x509 = x509_cert
+
+ version = self._backend._lib.X509_get_version(self._x509)
+ if version == 0:
+ self._version = x509.Version.v1
+ elif version == 2:
+ self._version = x509.Version.v3
+ else:
+ raise x509.InvalidVersion(
+ "{} is not a valid X509 version".format(version), version
+ )
def __repr__(self):
- return "<Certificate(subject={0}, ...)>".format(self.subject)
+ return "<Certificate(subject={}, ...)>".format(self.subject)
def __eq__(self, other):
if not isinstance(other, x509.Certificate):
@@ -45,31 +57,15 @@ class _Certificate(object):
def __hash__(self):
return hash(self.public_bytes(serialization.Encoding.DER))
+ def __deepcopy__(self, memo):
+ return self
+
def fingerprint(self, algorithm):
h = hashes.Hash(algorithm, self._backend)
h.update(self.public_bytes(serialization.Encoding.DER))
return h.finalize()
- @property
- def version(self):
- version = self._backend._lib.X509_get_version(self._x509)
- if version == 0:
- return x509.Version.v1
- elif version == 2:
- return x509.Version.v3
- else:
- raise x509.InvalidVersion(
- "{0} is not a valid X509 version".format(version), version
- )
-
- @property
- def serial(self):
- warnings.warn(
- "Certificate serial is deprecated, use serial_number instead.",
- utils.PersistentlyDeprecated,
- stacklevel=2
- )
- return self.serial_number
+ version = utils.read_only_property("_version")
@property
def serial_number(self):
@@ -90,12 +86,12 @@ class _Certificate(object):
@property
def not_valid_before(self):
- asn1_time = self._backend._lib.X509_get_notBefore(self._x509)
+ asn1_time = self._backend._lib.X509_getm_notBefore(self._x509)
return _parse_asn1_time(self._backend, asn1_time)
@property
def not_valid_after(self):
- asn1_time = self._backend._lib.X509_get_notAfter(self._x509)
+ asn1_time = self._backend._lib.X509_getm_notAfter(self._x509)
return _parse_asn1_time(self._backend, asn1_time)
@property
@@ -117,7 +113,7 @@ class _Certificate(object):
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
raise UnsupportedAlgorithm(
- "Signature algorithm OID:{0} not recognized".format(oid)
+ "Signature algorithm OID:{} not recognized".format(oid)
)
@property
@@ -132,14 +128,7 @@ class _Certificate(object):
@utils.cached_property
def extensions(self):
- if self._backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER:
- return _CERTIFICATE_EXTENSION_PARSER.parse(
- self._backend, self._x509
- )
- else:
- return _CERTIFICATE_EXTENSION_PARSER_NO_SCT.parse(
- self._backend, self._x509
- )
+ return self._backend._certificate_extension_parser.parse(self._x509)
@property
def signature(self):
@@ -201,13 +190,13 @@ class _RevokedCertificate(object):
self._backend,
self._backend._lib.X509_REVOKED_get0_revocationDate(
self._x509_revoked
- )
+ ),
)
@utils.cached_property
def extensions(self):
- return _REVOKED_CERTIFICATE_EXTENSION_PARSER.parse(
- self._backend, self._x509_revoked
+ return self._backend._revoked_cert_extension_parser.parse(
+ self._x509_revoked
)
@@ -230,9 +219,7 @@ class _CertificateRevocationList(object):
def fingerprint(self, algorithm):
h = hashes.Hash(algorithm, self._backend)
bio = self._backend._create_mem_bio_gc()
- res = self._backend._lib.i2d_X509_CRL_bio(
- bio, self._x509_crl
- )
+ res = self._backend._lib.i2d_X509_CRL_bio(bio, self._x509_crl)
self._backend.openssl_assert(res == 1)
der = self._backend._read_mem_bio(bio)
h.update(der)
@@ -257,9 +244,7 @@ class _CertificateRevocationList(object):
if res == 0:
return None
else:
- self._backend.openssl_assert(
- revoked[0] != self._backend._ffi.NULL
- )
+ self._backend.openssl_assert(revoked[0] != self._backend._ffi.NULL)
return _RevokedCertificate(
self._backend, self._sorted_crl, revoked[0]
)
@@ -271,7 +256,7 @@ class _CertificateRevocationList(object):
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
raise UnsupportedAlgorithm(
- "Signature algorithm OID:{0} not recognized".format(oid)
+ "Signature algorithm OID:{} not recognized".format(oid)
)
@property
@@ -366,13 +351,17 @@ class _CertificateRevocationList(object):
@utils.cached_property
def extensions(self):
- return _CRL_EXTENSION_PARSER.parse(self._backend, self._x509_crl)
+ return self._backend._crl_extension_parser.parse(self._x509_crl)
def is_signature_valid(self, public_key):
- if not isinstance(public_key, (dsa.DSAPublicKey, rsa.RSAPublicKey,
- ec.EllipticCurvePublicKey)):
- raise TypeError('Expecting one of DSAPublicKey, RSAPublicKey,'
- ' or EllipticCurvePublicKey.')
+ if not isinstance(
+ public_key,
+ (dsa.DSAPublicKey, rsa.RSAPublicKey, ec.EllipticCurvePublicKey),
+ ):
+ raise TypeError(
+ "Expecting one of DSAPublicKey, RSAPublicKey,"
+ " or EllipticCurvePublicKey."
+ )
res = self._backend._lib.X509_CRL_verify(
self._x509_crl, public_key._evp_pkey
)
@@ -423,7 +412,7 @@ class _CertificateSigningRequest(object):
return x509._SIG_OIDS_TO_HASH[oid]
except KeyError:
raise UnsupportedAlgorithm(
- "Signature algorithm OID:{0} not recognized".format(oid)
+ "Signature algorithm OID:{} not recognized".format(oid)
)
@property
@@ -442,12 +431,13 @@ class _CertificateSigningRequest(object):
x509_exts = self._backend._ffi.gc(
x509_exts,
lambda x: self._backend._lib.sk_X509_EXTENSION_pop_free(
- x, self._backend._ffi.addressof(
+ x,
+ self._backend._ffi.addressof(
self._backend._lib._original_lib, "X509_EXTENSION_free"
- )
- )
+ ),
+ ),
)
- return _CSR_EXTENSION_PARSER.parse(self._backend, x509_exts)
+ return self._backend._csr_extension_parser.parse(x509_exts)
def public_bytes(self, encoding):
bio = self._backend._create_mem_bio_gc()
@@ -495,6 +485,47 @@ class _CertificateSigningRequest(object):
return True
+ def get_attribute_for_oid(self, oid):
+ obj = _txt2obj_gc(self._backend, oid.dotted_string)
+ pos = self._backend._lib.X509_REQ_get_attr_by_OBJ(
+ self._x509_req, obj, -1
+ )
+ if pos == -1:
+ raise x509.AttributeNotFound(
+ "No {} attribute was found".format(oid), oid
+ )
+
+ attr = self._backend._lib.X509_REQ_get_attr(self._x509_req, pos)
+ self._backend.openssl_assert(attr != self._backend._ffi.NULL)
+ # We don't support multiple valued attributes for now.
+ self._backend.openssl_assert(
+ self._backend._lib.X509_ATTRIBUTE_count(attr) == 1
+ )
+ asn1_type = self._backend._lib.X509_ATTRIBUTE_get0_type(attr, 0)
+ self._backend.openssl_assert(asn1_type != self._backend._ffi.NULL)
+ # We need this to ensure that our C type cast is safe.
+ # Also this should always be a sane string type, but we'll see if
+ # that is true in the real world...
+ if asn1_type.type not in (
+ _ASN1Type.UTF8String.value,
+ _ASN1Type.PrintableString.value,
+ _ASN1Type.IA5String.value,
+ ):
+ raise ValueError(
+ "OID {} has a disallowed ASN.1 type: {}".format(
+ oid, asn1_type.type
+ )
+ )
+
+ data = self._backend._lib.X509_ATTRIBUTE_get0_data(
+ attr, 0, asn1_type.type, self._backend._ffi.NULL
+ )
+ self._backend.openssl_assert(data != self._backend._ffi.NULL)
+ # This cast is safe iff we assert on the type above to ensure
+ # that it is always a type of ASN1_STRING
+ data = self._backend._ffi.cast("ASN1_STRING *", data)
+ return _asn1_string_to_bytes(self._backend, data)
+
@utils.register_interface(
x509.certificate_transparency.SignedCertificateTimestamp
@@ -523,9 +554,9 @@ class _SignedCertificateTimestamp(object):
def timestamp(self):
timestamp = self._backend._lib.SCT_get_timestamp(self._sct)
milliseconds = timestamp % 1000
- return datetime.datetime.utcfromtimestamp(
- timestamp // 1000
- ).replace(microsecond=milliseconds * 1000)
+ return datetime.datetime.utcfromtimestamp(timestamp // 1000).replace(
+ microsecond=milliseconds * 1000
+ )
@property
def entry_type(self):