aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cryptography/hazmat/backends/openssl/backend.py41
-rw-r--r--tests/hazmat/backends/test_openssl.py21
2 files changed, 39 insertions, 23 deletions
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 0d71818f..01e61283 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -490,14 +490,24 @@ class Backend(object):
def pem_password_cb(buf, size, writing, userdata):
pem_password_cb.called += 1
- if not password or len(password) >= size:
+ if not password:
+ pem_password_cb.exception = TypeError(
+ "Password was not given but private key is encrypted."
+ )
return 0
- else:
+ elif len(password) < size:
pw_buf = self._ffi.buffer(buf, size)
pw_buf[:len(password)] = password
return len(password)
+ else:
+ pem_password_cb.exception = ValueError(
+ "Passwords longer than {0} bytes are not supported "
+ "by this backend.".format(size - 1)
+ )
+ return 0
pem_password_cb.called = 0
+ pem_password_cb.exception = None
return (
self._ffi.callback("int (char *, int, int, void *)",
@@ -786,7 +796,12 @@ class Backend(object):
)
if evp_pkey == self._ffi.NULL:
- self._handle_key_loading_error(password)
+ if password_func.exception is not None:
+ errors = self._consume_errors()
+ assert errors
+ raise password_func.exception
+ else:
+ self._handle_key_loading_error()
evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
@@ -801,28 +816,12 @@ class Backend(object):
return convert_func(evp_pkey)
- def _handle_key_loading_error(self, password):
+ def _handle_key_loading_error(self):
errors = self._consume_errors()
+
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
- )
- ) 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(
- "Password was not given but private key is encrypted.")
-
elif errors[0][1:] == (
self._lib.ERR_LIB_EVP,
self._lib.EVP_F_EVP_DECRYPTFINAL_EX,
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 696a0f73..cf70f109 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -13,6 +13,7 @@
from __future__ import absolute_import, division, print_function
+import os
import subprocess
import sys
import textwrap
@@ -33,7 +34,7 @@ from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.modes import CBC, CTR
from cryptography.hazmat.primitives.interfaces import BlockCipherAlgorithm
-from ...utils import raises_unsupported_algorithm
+from ...utils import load_vectors_from_file, raises_unsupported_algorithm
@utils.register_interface(interfaces.Mode)
@@ -464,7 +465,7 @@ class TestOpenSSLCMAC(object):
class TestOpenSSLSerialisationWithOpenSSL(object):
- def test_password_too_long(self):
+ def test_pem_password_cb_buffer_too_small(self):
ffi_cb, cb = backend._pem_password_cb(b"aa")
assert cb(None, 1, False, None) == 0
@@ -473,6 +474,22 @@ class TestOpenSSLSerialisationWithOpenSSL(object):
with raises_unsupported_algorithm(None):
backend._evp_pkey_to_private_key(key)
+ def test_very_long_pem_serialization_password(self):
+ password = "x" * 1024
+
+ with pytest.raises(ValueError):
+ load_vectors_from_file(
+ os.path.join(
+ "asymmetric", "Traditional_OpenSSL_Serialization",
+ "key1.pem"
+ ),
+ lambda pemfile: (
+ backend.load_traditional_openssl_pem_private_key(
+ pemfile.read().encode(), password
+ )
+ )
+ )
+
class TestOpenSSLNoEllipticCurve(object):
def test_elliptic_curve_supported(self, monkeypatch):