diff options
| author | Alex Gaynor <alex.gaynor@gmail.com> | 2014-03-01 14:58:46 -0800 | 
|---|---|---|
| committer | Alex Gaynor <alex.gaynor@gmail.com> | 2014-03-01 14:58:46 -0800 | 
| commit | 09cd8e6cd8103870543d1cc72fe9d404e2bd062c (patch) | |
| tree | 73ee261656d483af7ee1c288c63396577e69fb45 /cryptography | |
| parent | e5dadb2d3c6c0e7062dc73f8a50aa6f7b457b64f (diff) | |
| parent | 94ee8b5c8570a330f9e3d30ae8313ec41b10b470 (diff) | |
| download | cryptography-09cd8e6cd8103870543d1cc72fe9d404e2bd062c.tar.gz cryptography-09cd8e6cd8103870543d1cc72fe9d404e2bd062c.tar.bz2 cryptography-09cd8e6cd8103870543d1cc72fe9d404e2bd062c.zip | |
Merge pull request #707 from public/consume-errors
Get rid of handle_errors
Diffstat (limited to 'cryptography')
| -rw-r--r-- | cryptography/hazmat/backends/openssl/backend.py | 80 | 
1 files changed, 44 insertions, 36 deletions
| diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py index 0dc6803e..1fcd7ef2 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) @@ -228,43 +233,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 True: +            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(_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( -                code, self._err_string(code) +                error.code, self._err_string(error.code)              )          ) @@ -464,7 +451,28 @@ 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 + +            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." +                ) +            else: +                raise self._backend._unknown_error(errors[0])          if (isinstance(self._mode, GCM) and             self._operation == self._ENCRYPT): | 
