diff options
-rw-r--r-- | cryptography/exceptions.py | 4 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/backend.py | 22 | ||||
-rw-r--r-- | cryptography/hazmat/bindings/openssl/err.py | 7 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_block.py | 20 |
4 files changed, 50 insertions, 3 deletions
diff --git a/cryptography/exceptions.py b/cryptography/exceptions.py index c2e71493..a39674f9 100644 --- a/cryptography/exceptions.py +++ b/cryptography/exceptions.py @@ -18,3 +18,7 @@ class UnsupportedAlgorithm(Exception): class AlreadyFinalized(Exception): pass + + +class IncorrectPadding(Exception): + pass diff --git a/cryptography/hazmat/bindings/openssl/backend.py b/cryptography/hazmat/bindings/openssl/backend.py index db4d18e7..0071da5d 100644 --- a/cryptography/hazmat/bindings/openssl/backend.py +++ b/cryptography/hazmat/bindings/openssl/backend.py @@ -19,7 +19,7 @@ import sys import cffi from cryptography import utils -from cryptography.exceptions import UnsupportedAlgorithm +from cryptography.exceptions import UnsupportedAlgorithm, IncorrectPadding from cryptography.hazmat.bindings.interfaces import ( CipherBackend, HashBackend, HMACBackend ) @@ -193,6 +193,22 @@ class Backend(object): def create_symmetric_decryption_ctx(self, cipher, mode): return _CipherContext(self, cipher, mode, _CipherContext._DECRYPT) + def _handle_error(self): + code = self.lib.ERR_get_error() + assert code != 0 + 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 IncorrectPadding + elif func == self.lib.EVP_F_EVP_DECRYPTFINAL_EX: + if reason == self.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH: + raise IncorrectPadding + assert False + class GetCipherByName(object): def __init__(self, fmt): @@ -268,7 +284,9 @@ class _CipherContext(object): buf = self._backend.ffi.new("unsigned char[]", self._cipher.block_size) outlen = self._backend.ffi.new("int *") res = self._backend.lib.EVP_CipherFinal_ex(self._ctx, buf, outlen) - assert res != 0 + if res == 0: + self._backend._handle_error() + res = self._backend.lib.EVP_CIPHER_CTX_cleanup(self._ctx) assert res == 1 return self._backend.ffi.buffer(buf)[:outlen[0]] diff --git a/cryptography/hazmat/bindings/openssl/err.py b/cryptography/hazmat/bindings/openssl/err.py index 6a36dee0..3dac6948 100644 --- a/cryptography/hazmat/bindings/openssl/err.py +++ b/cryptography/hazmat/bindings/openssl/err.py @@ -21,6 +21,13 @@ struct ERR_string_data_st { const char *string; }; typedef struct ERR_string_data_st ERR_STRING_DATA; + +static const int ERR_LIB_EVP; + +static const int EVP_F_EVP_ENCRYPTFINAL_EX; +static const int EVP_F_EVP_DECRYPTFINAL_EX; + +static const int EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH; """ FUNCTIONS = """ diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index 9460c53d..4c756203 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -18,7 +18,9 @@ import binascii import pytest from cryptography import utils -from cryptography.exceptions import UnsupportedAlgorithm, AlreadyFinalized +from cryptography.exceptions import ( + UnsupportedAlgorithm, AlreadyFinalized, IncorrectPadding +) from cryptography.hazmat.primitives import interfaces from cryptography.hazmat.primitives.ciphers import ( Cipher, algorithms, modes @@ -108,3 +110,19 @@ class TestCipherContext(object): with pytest.raises(UnsupportedAlgorithm): cipher.decryptor() + + def test_incorrectly_padded(self, backend): + cipher = Cipher( + algorithms.AES(b"\x00" * 16), + modes.CBC(b"\x00" * 16), + backend + ) + encryptor = cipher.encryptor() + encryptor.update(b"1") + with pytest.raises(IncorrectPadding): + encryptor.finalize() + + decryptor = cipher.decryptor() + decryptor.update(b"1") + with pytest.raises(IncorrectPadding): + decryptor.finalize() |