aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography/hazmat
diff options
context:
space:
mode:
Diffstat (limited to 'cryptography/hazmat')
-rw-r--r--cryptography/hazmat/backends/interfaces.py10
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py59
-rw-r--r--cryptography/hazmat/bindings/openssl/err.py2
-rw-r--r--cryptography/hazmat/primitives/serialization.py6
4 files changed, 67 insertions, 10 deletions
diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py
index 97a7a4fd..55d5cd78 100644
--- a/cryptography/hazmat/backends/interfaces.py
+++ b/cryptography/hazmat/backends/interfaces.py
@@ -196,6 +196,16 @@ class TraditionalOpenSSLSerializationBackend(object):
@six.add_metaclass(abc.ABCMeta)
+class PKCS8SerializationBackend(object):
+ @abc.abstractmethod
+ def load_pkcs8_pem_private_key(self, data, password):
+ """
+ Load a private key from PEM encoded data, using password if the data
+ is encrypted.
+ """
+
+
+@six.add_metaclass(abc.ABCMeta)
class CMACBackend(object):
@abc.abstractmethod
def cmac_algorithm_supported(self, algorithm):
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 8d76160d..a5f21787 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -26,7 +26,8 @@ from cryptography.exceptions import (
)
from cryptography.hazmat.backends.interfaces import (
CMACBackend, CipherBackend, DSABackend, HMACBackend, HashBackend,
- PBKDF2HMACBackend, RSABackend, TraditionalOpenSSLSerializationBackend
+ PBKDF2HMACBackend, PKCS8SerializationBackend, RSABackend,
+ TraditionalOpenSSLSerializationBackend
)
from cryptography.hazmat.bindings.openssl.binding import Binding
from cryptography.hazmat.primitives import hashes, interfaces
@@ -55,6 +56,7 @@ _OpenSSLError = collections.namedtuple("_OpenSSLError",
@utils.register_interface(PBKDF2HMACBackend)
@utils.register_interface(RSABackend)
@utils.register_interface(TraditionalOpenSSLSerializationBackend)
+@utils.register_interface(PKCS8SerializationBackend)
class Backend(object):
"""
OpenSSL API binding interfaces.
@@ -777,6 +779,12 @@ class Backend(object):
return _CMACContext(self, algorithm)
def load_traditional_openssl_pem_private_key(self, data, password):
+ # OpenSSLs API for loading PKCS#8 certs can also load the traditional
+ # format so we just use that for both of them.
+
+ return self.load_pkcs8_pem_private_key(data, password)
+
+ def load_pkcs8_pem_private_key(self, data, password):
mem_bio = self._bytes_to_bio(data)
password_callback, password_func = self._pem_password_cb(password)
@@ -793,10 +801,18 @@ class Backend(object):
if not errors:
raise ValueError("Could not unserialize key data.")
- if errors[0][1:] == (
- self._lib.ERR_LIB_PEM,
- self._lib.PEM_F_PEM_DO_HEADER,
- self._lib.PEM_R_BAD_PASSWORD_READ
+ if (
+ errors[0][1:] == (
+ self._lib.ERR_LIB_PEM,
+ self._lib.PEM_F_PEM_DO_HEADER,
+ self._lib.PEM_R_BAD_PASSWORD_READ
+ )
+ ) or (
+ errors[0][1:] == (
+ self._lib.ERR_LIB_PEM,
+ self._lib.PEM_F_PEM_READ_BIO_PRIVATEKEY,
+ self._lib.PEM_R_BAD_PASSWORD_READ
+ )
):
assert not password
raise TypeError(
@@ -811,13 +827,36 @@ class Backend(object):
"Bad decrypt. Incorrect password?"
)
- elif errors[0][1:] == (
- self._lib.ERR_LIB_PEM,
- self._lib.PEM_F_PEM_GET_EVP_CIPHER_INFO,
- self._lib.PEM_R_UNSUPPORTED_ENCRYPTION
+ elif errors[0][1:] in (
+ (
+ self._lib.ERR_LIB_PEM,
+ self._lib.PEM_F_PEM_GET_EVP_CIPHER_INFO,
+ self._lib.PEM_R_UNSUPPORTED_ENCRYPTION
+ ),
+
+ (
+ self._lib.ERR_LIB_EVP,
+ self._lib.EVP_F_EVP_PBE_CIPHERINIT,
+ self._lib.EVP_R_UNKNOWN_PBE_ALGORITHM
+ )
+ ):
+ raise UnsupportedAlgorithm(
+ "PEM data is encrypted with an unsupported cipher",
+ _Reasons.UNSUPPORTED_CIPHER
+ )
+
+ elif any(
+ error[1:] == (
+ self._lib.ERR_LIB_EVP,
+ self._lib.EVP_F_EVP_PKCS82PKEY,
+ self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM
+ )
+ for error in errors
):
raise UnsupportedAlgorithm(
- "PEM data is encrypted with an unsupported cipher")
+ "Unsupported public key algorithm.",
+ _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM
+ )
else:
assert errors[0][1] in (
diff --git a/cryptography/hazmat/bindings/openssl/err.py b/cryptography/hazmat/bindings/openssl/err.py
index f6456d66..f685e494 100644
--- a/cryptography/hazmat/bindings/openssl/err.py
+++ b/cryptography/hazmat/bindings/openssl/err.py
@@ -135,6 +135,7 @@ static const int EVP_F_PKCS5_V2_PBE_KEYIVGEN;
static const int EVP_F_PKCS8_SET_BROKEN;
static const int EVP_F_RC2_MAGIC_TO_METH;
static const int EVP_F_RC5_CTRL;
+
static const int EVP_R_AES_KEY_SETUP_FAILED;
static const int EVP_R_ASN1_LIB;
static const int EVP_R_BAD_BLOCK_LENGTH;
@@ -168,6 +169,7 @@ static const int EVP_R_UNSUPPORTED_CIPHER;
static const int EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION;
static const int EVP_R_UNSUPPORTED_KEYLENGTH;
static const int EVP_R_UNSUPPORTED_SALT_TYPE;
+static const int EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM;
static const int EVP_R_WRONG_FINAL_BLOCK_LENGTH;
static const int EVP_R_WRONG_PUBLIC_KEY_TYPE;
diff --git a/cryptography/hazmat/primitives/serialization.py b/cryptography/hazmat/primitives/serialization.py
index 38937508..ed73c4c4 100644
--- a/cryptography/hazmat/primitives/serialization.py
+++ b/cryptography/hazmat/primitives/serialization.py
@@ -18,3 +18,9 @@ def load_pem_traditional_openssl_private_key(data, password, backend):
return backend.load_traditional_openssl_pem_private_key(
data, password
)
+
+
+def load_pem_pkcs8_private_key(data, password, backend):
+ return backend.load_pkcs8_pem_private_key(
+ data, password
+ )