aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2014-11-24 17:12:46 -1000
committerPaul Kehrer <paul.l.kehrer@gmail.com>2014-12-15 15:49:21 -0600
commitf83c749ceba71729c2ad9ae549bebdc5bdf63a29 (patch)
tree8c3bf38ad0e5fc2c828f9431717e943c089e1dd5 /src
parent9305287078bf1c15c469284c0a993c5c38e23bf5 (diff)
downloadcryptography-f83c749ceba71729c2ad9ae549bebdc5bdf63a29.tar.gz
cryptography-f83c749ceba71729c2ad9ae549bebdc5bdf63a29.tar.bz2
cryptography-f83c749ceba71729c2ad9ae549bebdc5bdf63a29.zip
initial x509 openssl implementation
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py20
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py97
-rw-r--r--src/cryptography/hazmat/primitives/serialization.py4
3 files changed, 120 insertions, 1 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index ebe38e20..ceb10cfc 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -19,7 +19,7 @@ from cryptography.hazmat.backends.interfaces import (
CMACBackend, CipherBackend, DSABackend, EllipticCurveBackend, HMACBackend,
HashBackend, PBKDF2HMACBackend, PEMSerializationBackend,
PKCS8SerializationBackend, RSABackend,
- TraditionalOpenSSLSerializationBackend
+ TraditionalOpenSSLSerializationBackend, X509Backend
)
from cryptography.hazmat.backends.openssl.ciphers import (
_AESCTRCipherContext, _CipherContext
@@ -36,6 +36,7 @@ from cryptography.hazmat.backends.openssl.hmac import _HMACContext
from cryptography.hazmat.backends.openssl.rsa import (
_RSAPrivateKey, _RSAPublicKey
)
+from cryptography.hazmat.backends.openssl.x509 import _X509Certificate
from cryptography.hazmat.bindings.openssl.binding import Binding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
@@ -66,6 +67,7 @@ _OpenSSLError = collections.namedtuple("_OpenSSLError",
@utils.register_interface(RSABackend)
@utils.register_interface(TraditionalOpenSSLSerializationBackend)
@utils.register_interface(PEMSerializationBackend)
+@utils.register_interface(X509Backend)
class Backend(object):
"""
OpenSSL API binding interfaces.
@@ -675,6 +677,22 @@ class Backend(object):
None,
)
+ def load_pem_x509_certificate(self, data):
+ mem_bio = self._bytes_to_bio(data)
+ x509 = self._lib.PEM_read_bio_X509(
+ mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL
+ )
+ assert x509 != self._ffi.NULL
+ x509 = self._ffi.gc(x509, self._lib.X509_free)
+ return _X509Certificate(self, x509)
+
+ def load_der_x509_certificate(self, data):
+ mem_bio = self._bytes_to_bio(data)
+ x509 = self._lib.d2i_X509_bio(mem_bio.bio, self._ffi.NULL)
+ assert x509 != self._ffi.NULL
+ x509 = self._ffi.gc(x509, self._lib.X509_free)
+ return _X509Certificate(self, x509)
+
def load_traditional_openssl_pem_private_key(self, data, password):
warnings.warn(
"load_traditional_openssl_pem_private_key is deprecated and will "
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
new file mode 100644
index 00000000..8dced83b
--- /dev/null
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -0,0 +1,97 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import, division, print_function
+
+import datetime
+
+from cryptography import utils
+from cryptography.hazmat.primitives import hashes, interfaces
+
+
+@utils.register_interface(interfaces.X509Certificate)
+class _X509Certificate(object):
+ def __init__(self, backend, x509):
+ self._backend = backend
+ self._x509 = x509
+
+ def _create_bio(self):
+ bio_method = self._backend._lib.BIO_s_mem()
+ assert bio_method != self._backend._ffi.NULL
+ bio = self._backend._lib.BIO_new(bio_method)
+ assert bio != self._backend._ffi.NULL
+ bio = self._backend._ffi.gc(bio, self._backend._lib.BIO_free)
+ return bio
+
+ def _read_bio(self, bio):
+ buf = self._backend._ffi.new("char **")
+ buf_len = self._backend._lib.BIO_get_mem_data(bio, buf)
+ assert buf_len > 0
+ assert buf[0] != self._backend._ffi.NULL
+ bio_data = self._backend._ffi.buffer(buf[0], buf_len)[:]
+ return bio_data
+
+ def fingerprint(self, algorithm):
+ h = hashes.Hash(algorithm, self._backend)
+ bio = self._create_bio()
+ res = self._backend._lib.i2d_X509_bio(
+ bio, self._x509
+ )
+ assert res == 1
+ der = self._read_bio(bio)
+ h.update(der)
+ return h.finalize()
+
+ @property
+ def serial(self):
+ asn1_int = self._backend._lib.X509_get_serialNumber(self._x509)
+ assert asn1_int != self._backend._ffi.NULL
+ bn = self._backend._lib.ASN1_INTEGER_to_BN(
+ asn1_int, self._backend._ffi.NULL
+ )
+ assert bn != self._backend._ffi.NULL
+ serial = self._backend._lib.BN_bn2hex(bn)
+ assert serial != self._backend._ffi.NULL
+ return int(self._backend._ffi.string(serial), 16)
+
+ def public_key(self):
+ pkey = self._backend._lib.X509_get_pubkey(self._x509)
+ assert pkey != self._backend._ffi.NULL
+ pkey = self._backend._ffi.gc(pkey, self._backend._lib.EVP_PKEY_free)
+ return self._backend._evp_pkey_to_public_key(pkey)
+
+ @property
+ def not_before(self):
+ asn1_time = self._backend._lib.X509_get_notBefore(self._x509)
+ return self._parse_asn1_time(asn1_time)
+
+ @property
+ def not_after(self):
+ asn1_time = self._backend._lib.X509_get_notAfter(self._x509)
+ return self._parse_asn1_time(asn1_time)
+
+ def _parse_asn1_time(self, asn1_time):
+ assert asn1_time != self._backend._ffi.NULL
+ generalized_time = self._backend._lib.ASN1_TIME_to_generalizedtime(
+ asn1_time, self._backend._ffi.NULL
+ )
+ assert generalized_time != self._backend._ffi.NULL
+ generalized_time = self._backend._ffi.gc(
+ generalized_time, self._backend._lib.ASN1_GENERALIZEDTIME_free
+ )
+ time = self._backend._ffi.string(
+ self._backend._lib.ASN1_STRING_data(
+ self._backend._ffi.cast("ASN1_STRING *", generalized_time)
+ )
+ )
+ return datetime.datetime.strptime(time, "%Y%m%d%H%M%SZ")
diff --git a/src/cryptography/hazmat/primitives/serialization.py b/src/cryptography/hazmat/primitives/serialization.py
index 0dbbc85c..077d56a5 100644
--- a/src/cryptography/hazmat/primitives/serialization.py
+++ b/src/cryptography/hazmat/primitives/serialization.py
@@ -116,3 +116,7 @@ else:
data = data[4:]
return result
+
+
+def load_pem_x509_certificate(data, backend):
+ return backend.load_pem_x509_certificate(data)