aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst3
-rw-r--r--docs/development/test-vectors.rst2
-rw-r--r--docs/x509/ocsp.rst8
-rw-r--r--src/cryptography/hazmat/backends/openssl/decode_asn1.py10
-rw-r--r--src/cryptography/hazmat/backends/openssl/ocsp.py10
-rw-r--r--src/cryptography/x509/ocsp.py6
-rw-r--r--tests/x509/test_ocsp.py10
-rw-r--r--vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.derbin0 -> 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
new file mode 100644
index 00000000..f89060d6
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/ocsp/resp-single-extension-reason.der
Binary files differ