summaryrefslogtreecommitdiff
path: root/src/cryptography
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2018-11-29 11:51:38 +0800
committerAlex Gaynor <alex.gaynor@gmail.com>2018-11-28 22:51:38 -0500
commite4e7b89fb627b372cde4158ceb7078d8769497cb (patch)
tree9dc87beda0cf2d1a948feea01c87361feb1a32af /src/cryptography
parent2f2f3d2e414a0167ae3a98b9b608904b2c76a35f (diff)
downloadcryptography-e4e7b89fb627b372cde4158ceb7078d8769497cb.tar.gz
PKCS12 Basic Parsing (#4553)
* PKCS12 parsing support * running all the tests is so gauche * rename func * various significant fixes * dangerous idiot here * move pkcs12 * docs updates * a bit more prose
Diffstat (limited to 'src/cryptography')
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py46
-rw-r--r--src/cryptography/hazmat/primitives/serialization/pkcs12.py9
2 files changed, 55 insertions, 0 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 44c2e3cd3..5a22a555d 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -2129,6 +2129,52 @@ class Backend(object):
self._lib.EVP_get_cipherbyname(cipher_name) != self._ffi.NULL
)
+ def load_key_and_certificates_from_pkcs12(self, data, password):
+ if password is None:
+ password = self._ffi.NULL
+ elif not isinstance(password, bytes):
+ raise TypeError("Password must be a byte string or None")
+
+ bio = self._bytes_to_bio(data)
+ p12 = self._lib.d2i_PKCS12_bio(bio.bio, self._ffi.NULL)
+ if p12 == self._ffi.NULL:
+ self._consume_errors()
+ raise ValueError("Could not deserialize PKCS12 data")
+
+ p12 = self._ffi.gc(p12, self._lib.PKCS12_free)
+ evp_pkey_ptr = self._ffi.new("EVP_PKEY **")
+ x509_ptr = self._ffi.new("X509 **")
+ sk_x509_ptr = self._ffi.new("Cryptography_STACK_OF_X509 **")
+ res = self._lib.PKCS12_parse(
+ p12, password, evp_pkey_ptr, x509_ptr, sk_x509_ptr
+ )
+ if res == 0:
+ self._consume_errors()
+ raise ValueError("Invalid password or PKCS12 data")
+
+ cert = None
+ key = None
+ additional_certificates = []
+
+ if evp_pkey_ptr[0] != self._ffi.NULL:
+ evp_pkey = self._ffi.gc(evp_pkey_ptr[0], self._lib.EVP_PKEY_free)
+ key = self._evp_pkey_to_private_key(evp_pkey)
+
+ if x509_ptr[0] != self._ffi.NULL:
+ x509 = self._ffi.gc(x509_ptr[0], self._lib.X509_free)
+ cert = _Certificate(self, x509)
+
+ if sk_x509_ptr[0] != self._ffi.NULL:
+ sk_x509 = self._ffi.gc(sk_x509_ptr[0], self._lib.sk_X509_free)
+ num = self._lib.sk_X509_num(sk_x509_ptr[0])
+ for i in range(num):
+ x509 = self._lib.sk_X509_value(sk_x509, i)
+ x509 = self._ffi.gc(x509, self._lib.X509_free)
+ self.openssl_assert(x509 != self._ffi.NULL)
+ additional_certificates.append(_Certificate(self, x509))
+
+ return (key, cert, additional_certificates)
+
class GetCipherByName(object):
def __init__(self, fmt):
diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py
new file mode 100644
index 000000000..98161d57a
--- /dev/null
+++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py
@@ -0,0 +1,9 @@
+# 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
+
+
+def load_key_and_certificates(data, password, backend):
+ return backend.load_key_and_certificates_from_pkcs12(data, password)