diff options
author | Alex Stapleton <alexs@prol.etari.at> | 2014-07-10 21:52:40 +0100 |
---|---|---|
committer | Alex Stapleton <alex@ly.st> | 2014-07-11 09:51:19 +0100 |
commit | 953fedbbf00700491aef0e68e0fd74b7e8011de7 (patch) | |
tree | 156651783171ca4e39e0547751b1e31212fd7356 | |
parent | 3be364eb24dc31c0a90019f71edc72f9babebb98 (diff) | |
download | cryptography-953fedbbf00700491aef0e68e0fd74b7e8011de7.tar.gz cryptography-953fedbbf00700491aef0e68e0fd74b7e8011de7.tar.bz2 cryptography-953fedbbf00700491aef0e68e0fd74b7e8011de7.zip |
Raise ValueError if the password doesn't fit
Fixes #1235. OpenSSL only allows password up to 1024 bytes.
-rw-r--r-- | cryptography/hazmat/backends/openssl/backend.py | 41 | ||||
-rw-r--r-- | tests/hazmat/backends/test_openssl.py | 21 |
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): |