aboutsummaryrefslogtreecommitdiffstats
path: root/cryptography
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2014-03-01 14:58:46 -0800
committerAlex Gaynor <alex.gaynor@gmail.com>2014-03-01 14:58:46 -0800
commit09cd8e6cd8103870543d1cc72fe9d404e2bd062c (patch)
tree73ee261656d483af7ee1c288c63396577e69fb45 /cryptography
parente5dadb2d3c6c0e7062dc73f8a50aa6f7b457b64f (diff)
parent94ee8b5c8570a330f9e3d30ae8313ec41b10b470 (diff)
downloadcryptography-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.py80
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):