aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2018-08-15 18:04:28 -0500
committerAlex Gaynor <alex.gaynor@gmail.com>2018-08-15 19:04:28 -0400
commit732cf642141f57f26db84ec2a4f6122cf7918c9e (patch)
tree50902db869cba9ff9599491c76767bd2755e40ec /src
parent962c963f75327f43592d7be31b156837f1f9eff1 (diff)
downloadcryptography-732cf642141f57f26db84ec2a4f6122cf7918c9e.tar.gz
cryptography-732cf642141f57f26db84ec2a4f6122cf7918c9e.tar.bz2
cryptography-732cf642141f57f26db84ec2a4f6122cf7918c9e.zip
OCSP request parsing (#4393)
* add public_bytes to OCSPRequest * review feedback * OCSP request parsing * change some prose * add __len__ as a required method
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py11
-rw-r--r--src/cryptography/hazmat/backends/openssl/ocsp.py119
-rw-r--r--src/cryptography/x509/ocsp.py79
3 files changed, 209 insertions, 0 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index af14bfaa..6a0446bc 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -40,6 +40,7 @@ from cryptography.hazmat.backends.openssl.encode_asn1 import (
)
from cryptography.hazmat.backends.openssl.hashes import _HashContext
from cryptography.hazmat.backends.openssl.hmac import _HMACContext
+from cryptography.hazmat.backends.openssl.ocsp import _OCSPRequest
from cryptography.hazmat.backends.openssl.rsa import (
_RSAPrivateKey, _RSAPublicKey
)
@@ -1419,6 +1420,16 @@ class Backend(object):
return _EllipticCurvePrivateKey(self, ec_cdata, evp_pkey)
+ def load_der_ocsp_request(self, data):
+ mem_bio = self._bytes_to_bio(data)
+ request = self._lib.d2i_OCSP_REQUEST_bio(mem_bio.bio, self._ffi.NULL)
+ if request == self._ffi.NULL:
+ self._consume_errors()
+ raise ValueError("Unable to load OCSP request")
+
+ request = self._ffi.gc(request, self._lib.OCSP_REQUEST_free)
+ return _OCSPRequest(self, request)
+
def elliptic_curve_exchange_algorithm_supported(self, algorithm, curve):
return (
self.elliptic_curve_supported(curve) and
diff --git a/src/cryptography/hazmat/backends/openssl/ocsp.py b/src/cryptography/hazmat/backends/openssl/ocsp.py
new file mode 100644
index 00000000..38e871ec
--- /dev/null
+++ b/src/cryptography/hazmat/backends/openssl/ocsp.py
@@ -0,0 +1,119 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import operator
+
+from cryptography import utils
+from cryptography.exceptions import UnsupportedAlgorithm
+from cryptography.hazmat.backends.openssl.decode_asn1 import (
+ _asn1_integer_to_int, _asn1_string_to_bytes, _obj2txt
+)
+from cryptography.hazmat.primitives import serialization
+from cryptography.x509.ocsp import OCSPRequest, Request, _OIDS_TO_HASH
+
+
+@utils.register_interface(Request)
+class _Request(object):
+ def __init__(self, backend, ocsp_request, request):
+ self._backend = backend
+ self._ocsp_request = ocsp_request
+ self._request = request
+ self._cert_id = self._backend._lib.OCSP_onereq_get0_id(self._request)
+ self._backend.openssl_assert(self._cert_id != self._backend._ffi.NULL)
+
+ @property
+ def issuer_key_hash(self):
+ key_hash = self._backend._ffi.new("ASN1_OCTET_STRING **")
+ res = self._backend._lib.OCSP_id_get0_info(
+ self._backend._ffi.NULL, self._backend._ffi.NULL,
+ key_hash, self._backend._ffi.NULL, self._cert_id
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(key_hash[0] != self._backend._ffi.NULL)
+ return _asn1_string_to_bytes(self._backend, key_hash[0])
+
+ @property
+ def issuer_name_hash(self):
+ name_hash = self._backend._ffi.new("ASN1_OCTET_STRING **")
+ res = self._backend._lib.OCSP_id_get0_info(
+ name_hash, self._backend._ffi.NULL,
+ self._backend._ffi.NULL, self._backend._ffi.NULL, self._cert_id
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(name_hash[0] != self._backend._ffi.NULL)
+ return _asn1_string_to_bytes(self._backend, name_hash[0])
+
+ @property
+ def serial_number(self):
+ num = self._backend._ffi.new("ASN1_INTEGER **")
+ res = self._backend._lib.OCSP_id_get0_info(
+ self._backend._ffi.NULL, self._backend._ffi.NULL,
+ self._backend._ffi.NULL, num, self._cert_id
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(num[0] != self._backend._ffi.NULL)
+ return _asn1_integer_to_int(self._backend, num[0])
+
+ @property
+ def hash_algorithm(self):
+ asn1obj = self._backend._ffi.new("ASN1_OBJECT **")
+ res = self._backend._lib.OCSP_id_get0_info(
+ self._backend._ffi.NULL, asn1obj,
+ self._backend._ffi.NULL, self._backend._ffi.NULL, self._cert_id
+ )
+ self._backend.openssl_assert(res == 1)
+ self._backend.openssl_assert(asn1obj[0] != self._backend._ffi.NULL)
+ oid = _obj2txt(self._backend, asn1obj[0])
+ try:
+ return _OIDS_TO_HASH[oid]
+ except KeyError:
+ raise UnsupportedAlgorithm(
+ "Signature algorithm OID: {0} not recognized".format(oid)
+ )
+
+
+@utils.register_interface(OCSPRequest)
+class _OCSPRequest(object):
+ def __init__(self, backend, ocsp_request):
+ self._backend = backend
+ self._ocsp_request = ocsp_request
+
+ def __len__(self):
+ return self._backend._lib.OCSP_request_onereq_count(self._ocsp_request)
+
+ def _request(self, idx):
+ request = self._backend._lib.OCSP_request_onereq_get0(
+ self._ocsp_request, idx
+ )
+ self._backend.openssl_assert(request != self._backend._ffi.NULL)
+ return _Request(self._backend, self._ocsp_request, request)
+
+ def public_bytes(self, encoding):
+ if encoding is not serialization.Encoding.DER:
+ raise ValueError(
+ "The only allowed encoding value is Encoding.DER"
+ )
+
+ bio = self._backend._create_mem_bio_gc()
+ res = self._backend._lib.i2d_OCSP_REQUEST_bio(bio, self._ocsp_request)
+ self._backend.openssl_assert(res > 0)
+ return self._backend._read_mem_bio(bio)
+
+ def __iter__(self):
+ for i in range(len(self)):
+ yield self._request(i)
+
+ def __getitem__(self, idx):
+ if isinstance(idx, slice):
+ start, stop, step = idx.indices(len(self))
+ return [self._request(i) for i in range(start, stop, step)]
+ else:
+ idx = operator.index(idx)
+ if idx < 0:
+ idx += len(self)
+ if not 0 <= idx < len(self):
+ raise IndexError
+ return self._request(idx)
diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py
new file mode 100644
index 00000000..22894dde
--- /dev/null
+++ b/src/cryptography/x509/ocsp.py
@@ -0,0 +1,79 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import abc
+
+import six
+
+from cryptography.hazmat.primitives import hashes
+
+
+_OIDS_TO_HASH = {
+ "1.3.14.3.2.26": hashes.SHA1(),
+ "2.16.840.1.101.3.4.2.4": hashes.SHA224(),
+ "2.16.840.1.101.3.4.2.1": hashes.SHA256(),
+ "2.16.840.1.101.3.4.2.2": hashes.SHA384(),
+ "2.16.840.1.101.3.4.2.3": hashes.SHA512(),
+}
+
+
+def load_der_ocsp_request(data):
+ from cryptography.hazmat.backends.openssl.backend import backend
+ return backend.load_der_ocsp_request(data)
+
+
+@six.add_metaclass(abc.ABCMeta)
+class OCSPRequest(object):
+ @abc.abstractmethod
+ def __iter__(self):
+ """
+ Iteration of Requests
+ """
+
+ @abc.abstractmethod
+ def __len__(self):
+ """
+ Number of Requests inside the OCSPRequest object
+ """
+
+ @abc.abstractmethod
+ def __getitem__(self, idx):
+ """
+ Returns a Request or range of Requests
+ """
+
+ @abc.abstractmethod
+ def public_bytes(self, encoding):
+ """
+ Serializes the request to DER
+ """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class Request(object):
+ @abc.abstractproperty
+ def issuer_key_hash(self):
+ """
+ The hash of the issuer public key
+ """
+
+ @abc.abstractproperty
+ def issuer_name_hash(self):
+ """
+ The hash of the issuer name
+ """
+
+ @abc.abstractproperty
+ def hash_algorithm(self):
+ """
+ The hash algorithm used in the issuer name and key hashes
+ """
+
+ @abc.abstractproperty
+ def serial_number(self):
+ """
+ The serial number of the cert whose status is being checked
+ """