diff options
-rw-r--r-- | CHANGELOG.rst | 3 | ||||
-rw-r--r-- | docs/development/test-vectors.rst | 2 | ||||
-rw-r--r-- | docs/x509/ocsp.rst | 8 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/decode_asn1.py | 10 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/ocsp.py | 10 | ||||
-rw-r--r-- | src/cryptography/x509/ocsp.py | 6 | ||||
-rw-r--r-- | tests/x509/test_ocsp.py | 10 | ||||
-rw-r--r-- | vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der | bin | 0 -> 280 bytes |
8 files changed, 48 insertions, 1 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 964f43da..f142dde5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,9 @@ Changelog :meth:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PublicKey.public_bytes` with no arguments, as per our deprecation policy. You must now pass ``encoding`` and ``format``. +* Added support for parsing + :attr:`~cryptography.x509.ocsp.OCSPResponse.single_extensions` in an OCSP + response. .. _v2-8: diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 9976d138..5b20b827 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -517,6 +517,8 @@ X.509 OCSP Test Vectors contains a revoked certificate and no ``nextUpdate`` value. * ``x509/ocsp/resp-invalid-signature-oid.der`` - An OCSP response that was modified to contain an MD2 signature algorithm object identifier. +* ``x509/ocsp/resp-single-extension-reason.der`` - An OCSP response that + contains a ``CRLReason`` single extension. Custom X.509 OCSP Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/x509/ocsp.rst b/docs/x509/ocsp.rst index e28c05a7..80ff9908 100644 --- a/docs/x509/ocsp.rst +++ b/docs/x509/ocsp.rst @@ -601,6 +601,14 @@ Interfaces The extensions encoded in the response. + .. attribute:: single_extensions + + .. versionadded:: 2.9 + + :type: :class:`~cryptography.x509.Extensions` + + The single extensions encoded in the response. + .. method:: public_bytes(encoding) :param encoding: The encoding to use. Only diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 47c6c654..87a3cc73 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -857,6 +857,10 @@ _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 = _REVOKED_EXTENSION_HANDLERS.copy() + _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), @@ -898,3 +902,9 @@ _OCSP_BASICRESP_EXT_PARSER = _X509ExtensionParser( 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, +) diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py index 7420f657..e42565ef 100644 --- a/src/cryptography/hazmat/backends/openssl/ocsp.py +++ b/src/cryptography/hazmat/backends/openssl/ocsp.py @@ -10,7 +10,8 @@ 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, _asn1_integer_to_int, + _OCSP_REQ_EXT_PARSER, _OCSP_SINGLERESP_EXT_PARSER, + _asn1_integer_to_int, _asn1_string_to_bytes, _decode_x509_name, _obj2txt, _parse_asn1_generalized_time, ) @@ -319,6 +320,13 @@ class _OCSPResponse(object): def extensions(self): return _OCSP_BASICRESP_EXT_PARSER.parse(self._backend, self._basic) + @utils.cached_property + @_requires_successful_response + def single_extensions(self): + return _OCSP_SINGLERESP_EXT_PARSER.parse( + self._backend, self._single + ) + def public_bytes(self, encoding): if encoding is not serialization.Encoding.DER: raise ValueError( diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index b15063d1..fb357334 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -427,3 +427,9 @@ class OCSPResponse(object): """ The list of response extensions. Not single response extensions. """ + + @abc.abstractproperty + def single_extensions(self): + """ + The list of single response extensions. Not response extensions. + """ diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 3e2923e1..2b6ec569 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -756,6 +756,16 @@ class TestOCSPResponse(object): with pytest.raises(ValueError): resp.public_bytes(serialization.Encoding.PEM) + def test_single_extensions(self, backend): + resp = _load_data( + os.path.join("x509", "ocsp", "resp-single-extension-reason.der"), + ocsp.load_der_ocsp_response, + ) + assert len(resp.single_extensions) == 1 + ext = resp.single_extensions[0] + assert ext.oid == x509.CRLReason.oid + assert ext.value == x509.CRLReason(x509.ReasonFlags.unspecified) + class TestOCSPEdDSA(object): @pytest.mark.supported( diff --git a/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der b/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der Binary files differnew file mode 100644 index 00000000..f89060d6 --- /dev/null +++ b/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der |