diff options
| author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2020-08-15 18:05:46 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-15 19:05:46 -0400 |
| commit | 9a55f775e5faa58e260451725d8d5bd3b41ce379 (patch) | |
| tree | 32669fb280712477f373c8e385346924bf1da59b /src | |
| parent | 679a1c7b93cb9d48f4813e7fdffd51c427667841 (diff) | |
| download | cryptography-9a55f775e5faa58e260451725d8d5bd3b41ce379.tar.gz | |
move the x509 parsers into the backend object (#5405)
* move the parser into the backend object
This allows us to generate the list of supported extensions when
instantiating the backend object rather than building multiple parsers
and picking the right one at runtime when parsing the extensions themselves.
* sigh
Diffstat (limited to 'src')
| -rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 62 | ||||
| -rw-r--r-- | src/cryptography/hazmat/backends/openssl/decode_asn1.py | 120 | ||||
| -rw-r--r-- | src/cryptography/hazmat/backends/openssl/ocsp.py | 17 | ||||
| -rw-r--r-- | src/cryptography/hazmat/backends/openssl/x509.py | 22 |
4 files changed, 103 insertions, 118 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index afe57a537..3d1079ad9 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -42,6 +42,14 @@ from cryptography.hazmat.backends.openssl.ciphers import _CipherContext from cryptography.hazmat.backends.openssl.cmac import _CMACContext from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CRL_ENTRY_REASON_ENUM_TO_CODE, + _CRL_EXTENSION_HANDLERS, + _EXTENSION_HANDLERS_BASE, + _EXTENSION_HANDLERS_SCT, + _OCSP_BASICRESP_EXTENSION_HANDLERS, + _OCSP_REQ_EXTENSION_HANDLERS, + _OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT, + _REVOKED_EXTENSION_HANDLERS, + _X509ExtensionParser, ) from cryptography.hazmat.backends.openssl.dh import ( _DHParameters, @@ -219,6 +227,7 @@ class Backend(object): self._cipher_registry = {} self._register_default_ciphers() + self._register_x509_ext_parsers() if self._fips_enabled and self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: warnings.warn( "OpenSSL FIPS mode is enabled. Can't enable DRBG fork safety.", @@ -404,6 +413,59 @@ class Backend(object): ) self.register_cipher_adapter(AES, XTS, _get_xts_cipher) + def _register_x509_ext_parsers(self): + ext_handlers = _EXTENSION_HANDLERS_BASE.copy() + # All revoked extensions are valid single response extensions, see: + # https://tools.ietf.org/html/rfc6960#section-4.4.5 + singleresp_handlers = _REVOKED_EXTENSION_HANDLERS.copy() + + if self._lib.Cryptography_HAS_SCT: + ext_handlers.update(_EXTENSION_HANDLERS_SCT) + singleresp_handlers.update(_OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT) + + self._certificate_extension_parser = _X509ExtensionParser( + self, + ext_count=self._lib.X509_get_ext_count, + get_ext=self._lib.X509_get_ext, + handlers=ext_handlers, + ) + self._csr_extension_parser = _X509ExtensionParser( + self, + ext_count=self._lib.sk_X509_EXTENSION_num, + get_ext=self._lib.sk_X509_EXTENSION_value, + handlers=ext_handlers, + ) + self._revoked_cert_extension_parser = _X509ExtensionParser( + self, + ext_count=self._lib.X509_REVOKED_get_ext_count, + get_ext=self._lib.X509_REVOKED_get_ext, + handlers=_REVOKED_EXTENSION_HANDLERS, + ) + self._crl_extension_parser = _X509ExtensionParser( + self, + ext_count=self._lib.X509_CRL_get_ext_count, + get_ext=self._lib.X509_CRL_get_ext, + handlers=_CRL_EXTENSION_HANDLERS, + ) + self._ocsp_req_ext_parser = _X509ExtensionParser( + self, + ext_count=self._lib.OCSP_REQUEST_get_ext_count, + get_ext=self._lib.OCSP_REQUEST_get_ext, + handlers=_OCSP_REQ_EXTENSION_HANDLERS, + ) + self._ocsp_basicresp_ext_parser = _X509ExtensionParser( + self, + ext_count=self._lib.OCSP_BASICRESP_get_ext_count, + get_ext=self._lib.OCSP_BASICRESP_get_ext, + handlers=_OCSP_BASICRESP_EXTENSION_HANDLERS, + ) + self._ocsp_singleresp_ext_parser = _X509ExtensionParser( + self, + ext_count=self._lib.OCSP_SINGLERESP_get_ext_count, + get_ext=self._lib.OCSP_SINGLERESP_get_ext, + handlers=singleresp_handlers, + ) + def create_symmetric_encryption_ctx(self, cipher, mode): return _CipherContext(self, cipher, mode, _CipherContext._ENCRYPT) diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 56dcf26c1..279b00ca5 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -181,21 +181,25 @@ def _decode_delta_crl_indicator(backend, ext): class _X509ExtensionParser(object): - def __init__(self, ext_count, get_ext, handlers): + def __init__(self, backend, ext_count, get_ext, handlers): self.ext_count = ext_count self.get_ext = get_ext self.handlers = handlers + self._backend = backend - def parse(self, backend, x509_obj): + def parse(self, x509_obj): extensions = [] seen_oids = set() - for i in range(self.ext_count(backend, x509_obj)): - ext = self.get_ext(backend, x509_obj, i) - backend.openssl_assert(ext != backend._ffi.NULL) - crit = backend._lib.X509_EXTENSION_get_critical(ext) + for i in range(self.ext_count(x509_obj)): + ext = self.get_ext(x509_obj, i) + self._backend.openssl_assert(ext != self._backend._ffi.NULL) + crit = self._backend._lib.X509_EXTENSION_get_critical(ext) critical = crit == 1 oid = x509.ObjectIdentifier( - _obj2txt(backend, backend._lib.X509_EXTENSION_get_object(ext)) + _obj2txt( + self._backend, + self._backend._lib.X509_EXTENSION_get_object(ext), + ) ) if oid in seen_oids: raise x509.DuplicateExtension( @@ -207,8 +211,8 @@ class _X509ExtensionParser(object): # ourselves. if oid == ExtensionOID.TLS_FEATURE: # The extension contents are a SEQUENCE OF INTEGERs. - data = backend._lib.X509_EXTENSION_get_data(ext) - data_bytes = _asn1_string_to_bytes(backend, data) + data = self._backend._lib.X509_EXTENSION_get_data(ext) + data_bytes = _asn1_string_to_bytes(self._backend, data) features = DERReader(data_bytes).read_single_element(SEQUENCE) parsed = [] while not features.is_empty(): @@ -221,9 +225,9 @@ class _X509ExtensionParser(object): seen_oids.add(oid) continue elif oid == ExtensionOID.PRECERT_POISON: - data = backend._lib.X509_EXTENSION_get_data(ext) + data = self._backend._lib.X509_EXTENSION_get_data(ext) # The contents of the extension must be an ASN.1 NULL. - reader = DERReader(_asn1_string_to_bytes(backend, data)) + reader = DERReader(_asn1_string_to_bytes(self._backend, data)) reader.read_single_element(NULL).check_empty() extensions.append( x509.Extension(oid, critical, x509.PrecertPoison()) @@ -235,21 +239,21 @@ class _X509ExtensionParser(object): handler = self.handlers[oid] except KeyError: # Dump the DER payload into an UnrecognizedExtension object - data = backend._lib.X509_EXTENSION_get_data(ext) - backend.openssl_assert(data != backend._ffi.NULL) - der = backend._ffi.buffer(data.data, data.length)[:] + data = self._backend._lib.X509_EXTENSION_get_data(ext) + self._backend.openssl_assert(data != self._backend._ffi.NULL) + der = self._backend._ffi.buffer(data.data, data.length)[:] unrecognized = x509.UnrecognizedExtension(oid, der) extensions.append(x509.Extension(oid, critical, unrecognized)) else: - ext_data = backend._lib.X509V3_EXT_d2i(ext) - if ext_data == backend._ffi.NULL: - backend._consume_errors() + ext_data = self._backend._lib.X509V3_EXT_d2i(ext) + if ext_data == self._backend._ffi.NULL: + self._backend._consume_errors() raise ValueError( "The {} extension is invalid and can't be " "parsed".format(oid) ) - value = handler(backend, ext_data) + value = handler(self._backend, ext_data) extensions.append(x509.Extension(oid, critical, value)) seen_oids.add(oid) @@ -813,7 +817,7 @@ def _decode_nonce(backend, nonce): return x509.OCSPNonce(_asn1_string_to_bytes(backend, nonce)) -_EXTENSION_HANDLERS_NO_SCT = { +_EXTENSION_HANDLERS_BASE = { ExtensionOID.BASIC_CONSTRAINTS: _decode_basic_constraints, ExtensionOID.SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier, ExtensionOID.KEY_USAGE: _decode_key_usage, @@ -835,11 +839,11 @@ _EXTENSION_HANDLERS_NO_SCT = { ExtensionOID.NAME_CONSTRAINTS: _decode_name_constraints, ExtensionOID.POLICY_CONSTRAINTS: _decode_policy_constraints, } -_EXTENSION_HANDLERS = _EXTENSION_HANDLERS_NO_SCT.copy() -_EXTENSION_HANDLERS[ - ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS -] = _decode_precert_signed_certificate_timestamps - +_EXTENSION_HANDLERS_SCT = { + ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( + _decode_precert_signed_certificate_timestamps + ) +} _REVOKED_EXTENSION_HANDLERS = { CRLEntryExtensionOID.CRL_REASON: _decode_crl_reason, @@ -867,66 +871,8 @@ _OCSP_BASICRESP_EXTENSION_HANDLERS = { OCSPExtensionOID.NONCE: _decode_nonce, } -# All revoked extensions are valid single response extensions, see: -# https://tools.ietf.org/html/rfc6960#section-4.4.5 -_OCSP_SINGLERESP_EXTENSION_HANDLERS_NO_SCT = _REVOKED_EXTENSION_HANDLERS.copy() -_OCSP_SINGLERESP_EXTENSION_HANDLERS = ( - _OCSP_SINGLERESP_EXTENSION_HANDLERS_NO_SCT.copy() -) -_OCSP_SINGLERESP_EXTENSION_HANDLERS[ - ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS -] = _decode_signed_certificate_timestamps - -_CERTIFICATE_EXTENSION_PARSER_NO_SCT = _X509ExtensionParser( - ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x), - get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i), - handlers=_EXTENSION_HANDLERS_NO_SCT, -) - -_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser( - ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x), - get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i), - handlers=_EXTENSION_HANDLERS, -) - -_CSR_EXTENSION_PARSER = _X509ExtensionParser( - ext_count=lambda backend, x: backend._lib.sk_X509_EXTENSION_num(x), - get_ext=lambda backend, x, i: backend._lib.sk_X509_EXTENSION_value(x, i), - handlers=_EXTENSION_HANDLERS, -) - -_REVOKED_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser( - ext_count=lambda backend, x: backend._lib.X509_REVOKED_get_ext_count(x), - get_ext=lambda backend, x, i: backend._lib.X509_REVOKED_get_ext(x, i), - handlers=_REVOKED_EXTENSION_HANDLERS, -) - -_CRL_EXTENSION_PARSER = _X509ExtensionParser( - ext_count=lambda backend, x: backend._lib.X509_CRL_get_ext_count(x), - get_ext=lambda backend, x, i: backend._lib.X509_CRL_get_ext(x, i), - handlers=_CRL_EXTENSION_HANDLERS, -) - -_OCSP_REQ_EXT_PARSER = _X509ExtensionParser( - ext_count=lambda backend, x: backend._lib.OCSP_REQUEST_get_ext_count(x), - get_ext=lambda backend, x, i: backend._lib.OCSP_REQUEST_get_ext(x, i), - handlers=_OCSP_REQ_EXTENSION_HANDLERS, -) - -_OCSP_BASICRESP_EXT_PARSER = _X509ExtensionParser( - ext_count=lambda backend, x: backend._lib.OCSP_BASICRESP_get_ext_count(x), - get_ext=lambda backend, x, i: backend._lib.OCSP_BASICRESP_get_ext(x, i), - handlers=_OCSP_BASICRESP_EXTENSION_HANDLERS, -) - -_OCSP_SINGLERESP_EXT_PARSER = _X509ExtensionParser( - ext_count=lambda backend, x: backend._lib.OCSP_SINGLERESP_get_ext_count(x), - get_ext=lambda backend, x, i: backend._lib.OCSP_SINGLERESP_get_ext(x, i), - handlers=_OCSP_SINGLERESP_EXTENSION_HANDLERS, -) - -_OCSP_SINGLERESP_EXT_PARSER_NO_SCT = _X509ExtensionParser( - ext_count=lambda backend, x: backend._lib.OCSP_SINGLERESP_get_ext_count(x), - get_ext=lambda backend, x, i: backend._lib.OCSP_SINGLERESP_get_ext(x, i), - handlers=_OCSP_SINGLERESP_EXTENSION_HANDLERS_NO_SCT, -) +_OCSP_SINGLERESP_EXTENSION_HANDLERS_SCT = { + ExtensionOID.SIGNED_CERTIFICATE_TIMESTAMPS: ( + _decode_signed_certificate_timestamps + ) +} diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py index c432e222c..50c02e7a8 100644 --- a/src/cryptography/hazmat/backends/openssl/ocsp.py +++ b/src/cryptography/hazmat/backends/openssl/ocsp.py @@ -10,10 +10,6 @@ from cryptography import utils, x509 from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.openssl.decode_asn1 import ( _CRL_ENTRY_REASON_CODE_TO_ENUM, - _OCSP_BASICRESP_EXT_PARSER, - _OCSP_REQ_EXT_PARSER, - _OCSP_SINGLERESP_EXT_PARSER, - _OCSP_SINGLERESP_EXT_PARSER_NO_SCT, _asn1_integer_to_int, _asn1_string_to_bytes, _decode_x509_name, @@ -340,19 +336,12 @@ class _OCSPResponse(object): @utils.cached_property @_requires_successful_response def extensions(self): - return _OCSP_BASICRESP_EXT_PARSER.parse(self._backend, self._basic) + return self._backend._ocsp_basicresp_ext_parser.parse(self._basic) @utils.cached_property @_requires_successful_response def single_extensions(self): - if self._backend._lib.Cryptography_HAS_SCT: - return _OCSP_SINGLERESP_EXT_PARSER.parse( - self._backend, self._single - ) - else: - return _OCSP_SINGLERESP_EXT_PARSER_NO_SCT.parse( - self._backend, self._single - ) + return self._backend._ocsp_singleresp_ext_parser.parse(self._single) def public_bytes(self, encoding): if encoding is not serialization.Encoding.DER: @@ -400,7 +389,7 @@ class _OCSPRequest(object): @utils.cached_property def extensions(self): - return _OCSP_REQ_EXT_PARSER.parse(self._backend, self._ocsp_request) + return self._backend._ocsp_req_ext_parser.parse(self._ocsp_request) def public_bytes(self, encoding): if encoding is not serialization.Encoding.DER: diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 1ebb69468..4d0dac764 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -10,11 +10,6 @@ import operator 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, @@ -133,14 +128,7 @@ class _Certificate(object): @utils.cached_property def extensions(self): - if self._backend._lib.Cryptography_HAS_SCT: - 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): @@ -207,8 +195,8 @@ class _RevokedCertificate(object): @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 ) @@ -363,7 +351,7 @@ 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( @@ -449,7 +437,7 @@ class _CertificateSigningRequest(object): ), ), ) - 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() |
