From 235d3ce2b7ae13cf94c97c00f5aa89c40bc6763c Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Sat, 1 Mar 2014 20:54:13 +0000 Subject: Get rid of handle_errors --- cryptography/hazmat/backends/openssl/backend.py | 73 +++++++++++++------------ tests/hazmat/backends/test_openssl.py | 39 ++----------- 2 files changed, 42 insertions(+), 70 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 0dc6803e..b14ec2d9 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -228,43 +228,25 @@ class Backend(object): self._lib.ERR_error_string_n(code, err_buf, 256) return self._ffi.string(err_buf, 256)[:] - def _handle_error(self, mode): - code = self._lib.ERR_get_error() - if not code and isinstance(mode, GCM): - raise InvalidTag - assert code != 0 - - # consume any remaining errors on the stack - ignored_code = None - while ignored_code != 0: - ignored_code = self._lib.ERR_get_error() - - # raise the first error we found - return self._handle_error_code(code) - - def _handle_error_code(self, code): - lib = self._lib.ERR_GET_LIB(code) - func = self._lib.ERR_GET_FUNC(code) - reason = self._lib.ERR_GET_REASON(code) - - if lib == self._lib.ERR_LIB_EVP: - if func == self._lib.EVP_F_EVP_ENCRYPTFINAL_EX: - if reason == self._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH: - raise ValueError( - "The length of the provided data is not a multiple of " - "the block length" - ) - elif func == self._lib.EVP_F_EVP_DECRYPTFINAL_EX: - if reason == self._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH: - raise ValueError( - "The length of the provided data is not a multiple of " - "the block length" - ) - - raise InternalError( + def _consume_errors(self): + errors = [] + while 1: + code = self._lib.ERR_get_error() + if code == 0: + break + + lib = self._lib.ERR_GET_LIB(code) + func = self._lib.ERR_GET_FUNC(code) + reason = self._lib.ERR_GET_REASON(code) + + errors.append((code, lib, func, reason)) + return errors + + def _unknown_error(self, error): + return InternalError( "Unknown error code {0} from OpenSSL, " "you should probably file a bug. {1}".format( - code, self._err_string(code) + error[0], self._err_string(error[0]) ) ) @@ -464,7 +446,26 @@ class _CipherContext(object): outlen = self._backend._ffi.new("int *") res = self._backend._lib.EVP_CipherFinal_ex(self._ctx, buf, outlen) if res == 0: - self._backend._handle_error(self._mode) + errors = self._backend._consume_errors() + + if not errors and isinstance(self._mode, GCM): + raise InvalidTag + else: + assert errors + + if errors[0][1:] == ( + self._backend._lib.ERR_LIB_EVP, + self._backend._lib.EVP_F_EVP_ENCRYPTFINAL_EX, + self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH + ) or errors[0][1:] == ( + self._backend._lib.ERR_LIB_EVP, + self._backend._lib.EVP_F_EVP_DECRYPTFINAL_EX, + self._backend._lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH + ): + raise ValueError( + "The length of the provided data is not a multiple of " + "the block length." + ) if (isinstance(self._mode, GCM) and self._operation == self._ENCRYPT): diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index b24808df..fb9b978d 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -71,46 +71,17 @@ class TestOpenSSL(object): with pytest.raises(UnsupportedAlgorithm): cipher.encryptor() - def test_handle_unknown_error(self): - with pytest.raises(InternalError): - backend._handle_error_code(0) - - backend._lib.ERR_put_error(backend._lib.ERR_LIB_EVP, 0, 0, - b"test_openssl.py", -1) - with pytest.raises(InternalError): - backend._handle_error(None) - - backend._lib.ERR_put_error( - backend._lib.ERR_LIB_EVP, - backend._lib.EVP_F_EVP_ENCRYPTFINAL_EX, - 0, - b"test_openssl.py", - -1 - ) - with pytest.raises(InternalError): - backend._handle_error(None) - - backend._lib.ERR_put_error( - backend._lib.ERR_LIB_EVP, - backend._lib.EVP_F_EVP_DECRYPTFINAL_EX, - 0, - b"test_openssl.py", - -1 - ) - with pytest.raises(InternalError): - backend._handle_error(None) - - def test_handle_multiple_errors(self): + def test_consume_errors(self): for i in range(10): backend._lib.ERR_put_error(backend._lib.ERR_LIB_EVP, 0, 0, b"test_openssl.py", -1) assert backend._lib.ERR_peek_error() != 0 - with pytest.raises(InternalError): - backend._handle_error(None) + errors = backend._consume_errors() assert backend._lib.ERR_peek_error() == 0 + assert len(errors) == 10 def test_openssl_error_string(self): backend._lib.ERR_put_error( @@ -121,8 +92,8 @@ class TestOpenSSL(object): -1 ) - with pytest.raises(InternalError) as exc: - backend._handle_error(None) + errors = backend._consume_errors() + exc = backend._unknown_error(errors[0]) assert ( "digital envelope routines:" -- cgit v1.2.3 From 151cede33ca6e00a6ffd48851ca43d615e8920e4 Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Sat, 1 Mar 2014 21:04:08 +0000 Subject: Use a namedtuple to keep errors in --- cryptography/hazmat/backends/openssl/backend.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index b14ec2d9..318edec1 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -13,6 +13,7 @@ from __future__ import absolute_import, division, print_function +import collections import itertools from cryptography import utils @@ -34,6 +35,10 @@ from cryptography.hazmat.primitives.ciphers.modes import ( ) +_OpenSSLError = collections.namedtuple("_OpenSSLError", + ["code", "lib", "func", "reason"]) + + @utils.register_interface(CipherBackend) @utils.register_interface(HashBackend) @utils.register_interface(HMACBackend) @@ -239,14 +244,14 @@ class Backend(object): func = self._lib.ERR_GET_FUNC(code) reason = self._lib.ERR_GET_REASON(code) - errors.append((code, lib, func, reason)) + errors.append(_OpenSSLError(code, lib, func, reason)) return errors def _unknown_error(self, error): return InternalError( "Unknown error code {0} from OpenSSL, " "you should probably file a bug. {1}".format( - error[0], self._err_string(error[0]) + error.code, self._err_string(error.code) ) ) -- cgit v1.2.3 From 9ed28547a72fab4efa30eef3cb867b1f2165e143 Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Sat, 1 Mar 2014 21:07:23 +0000 Subject: Style tweaks --- cryptography/hazmat/backends/openssl/backend.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 318edec1..d4aaad76 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -235,7 +235,7 @@ class Backend(object): def _consume_errors(self): errors = [] - while 1: + while True: code = self._lib.ERR_get_error() if code == 0: break @@ -455,8 +455,8 @@ class _CipherContext(object): if not errors and isinstance(self._mode, GCM): raise InvalidTag - else: - assert errors + + assert errors if errors[0][1:] == ( self._backend._lib.ERR_LIB_EVP, -- cgit v1.2.3 From 1c979c6a28385e8c2f92ecd457fc0ebe48819536 Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Sat, 1 Mar 2014 21:29:28 +0000 Subject: pep8 --- tests/hazmat/backends/test_openssl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index fb9b978d..9d48f4e8 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -14,7 +14,7 @@ import pytest from cryptography import utils -from cryptography.exceptions import UnsupportedAlgorithm, InternalError +from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.openssl.backend import backend, Backend from cryptography.hazmat.primitives import interfaces, hashes from cryptography.hazmat.primitives.ciphers import Cipher -- cgit v1.2.3 From 94ee8b5c8570a330f9e3d30ae8313ec41b10b470 Mon Sep 17 00:00:00 2001 From: Alex Stapleton Date: Sat, 1 Mar 2014 22:08:49 +0000 Subject: raise InternalError --- cryptography/hazmat/backends/openssl/backend.py | 2 ++ tests/hazmat/backends/test_openssl.py | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index d4aaad76..1fcd7ef2 100644 --- a/cryptography/hazmat/backends/openssl/backend.py +++ b/cryptography/hazmat/backends/openssl/backend.py @@ -471,6 +471,8 @@ class _CipherContext(object): "The length of the provided data is not a multiple of " "the block length." ) + else: + raise self._backend._unknown_error(errors[0]) if (isinstance(self._mode, GCM) and self._operation == self._ENCRYPT): diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 9d48f4e8..42c1b395 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -14,7 +14,7 @@ import pytest from cryptography import utils -from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.exceptions import UnsupportedAlgorithm, InternalError from cryptography.hazmat.backends.openssl.backend import backend, Backend from cryptography.hazmat.primitives import interfaces, hashes from cryptography.hazmat.primitives.ciphers import Cipher @@ -118,6 +118,15 @@ class TestOpenSSL(object): b"data not multiple of block length" ) + def test_unknown_error_in_cipher_finalize(self): + cipher = Cipher(AES(b"\0" * 16), CBC(b"\0" * 16), backend=backend) + enc = cipher.encryptor() + enc.update(b"\0") + backend._lib.ERR_put_error(0, 0, 1, + b"test_openssl.py", -1) + with pytest.raises(InternalError): + enc.finalize() + def test_derive_pbkdf2_raises_unsupported_on_old_openssl(self): if backend.pbkdf2_hmac_supported(hashes.SHA256()): pytest.skip("Requires an older OpenSSL") -- cgit v1.2.3