diff options
-rw-r--r-- | CHANGELOG.rst | 11 | ||||
-rw-r--r-- | src/cryptography/exceptions.py | 4 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/commoncrypto/backend.py | 3 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 17 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/ciphers.py | 30 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/commoncrypto/binding.py | 3 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/binding.py | 9 | ||||
-rw-r--r-- | tests/hazmat/backends/test_openssl.py | 20 |
8 files changed, 34 insertions, 63 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 705c09cd..fdea8c35 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,17 @@ Changelog * Added :class:`~cryptography.hazmat.primitives.kdf.x963kdf.X963KDF`. +1.0.2 - 2015-09-27 +~~~~~~~~~~~~~~~~~~ +* **SECURITY ISSUE**: The OpenSSL backend prior to 1.0.2 made extensive use + of assertions to check response codes where our tests could not trigger a + failure. However, when Python is run with ``-O`` these asserts are optimized + away. If a user ran Python with this flag and got an invalid response code + this could result in undefined behavior or worse. Accordingly, all response + checks from the OpenSSL backend have been converted from ``assert`` + to a true function call. Credit **Emilia Käsper (Google Security Team)** + for the report. + 1.0.1 - 2015-09-05 ~~~~~~~~~~~~~~~~~~ diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py index a4292eb8..29be22be 100644 --- a/src/cryptography/exceptions.py +++ b/src/cryptography/exceptions.py @@ -49,7 +49,9 @@ class InvalidSignature(Exception): class InternalError(Exception): - pass + def __init__(self, msg, err_code): + super(InternalError, self).__init__(msg) + self.err_code = err_code class InvalidKey(Exception): diff --git a/src/cryptography/hazmat/backends/commoncrypto/backend.py b/src/cryptography/hazmat/backends/commoncrypto/backend.py index 091fbb7c..315d67d8 100644 --- a/src/cryptography/hazmat/backends/commoncrypto/backend.py +++ b/src/cryptography/hazmat/backends/commoncrypto/backend.py @@ -227,7 +227,8 @@ class Backend(object): else: raise InternalError( "The backend returned an unknown error, consider filing a bug." - " Code: {0}.".format(response) + " Code: {0}.".format(response), + response ) def _release_cipher_ctx(self, ctx): diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index c4cac1a6..b45c8986 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -15,9 +15,7 @@ import idna import six from cryptography import utils, x509 -from cryptography.exceptions import ( - InternalError, UnsupportedAlgorithm, _Reasons -) +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.backends.interfaces import ( CMACBackend, CipherBackend, DERSerializationBackend, DSABackend, EllipticCurveBackend, HMACBackend, HashBackend, PBKDF2HMACBackend, @@ -738,22 +736,9 @@ class Backend(object): return self._ffi.buffer(buf)[:] - def _err_string(self, code): - err_buf = self._ffi.new("char[]", 256) - self._lib.ERR_error_string_n(code, err_buf, 256) - return self._ffi.string(err_buf, 256)[:] - def _consume_errors(self): return binding._consume_errors(self._lib) - def _unknown_error(self, error): - return InternalError( - "Unknown error code {0} from OpenSSL, " - "you should probably file a bug. {1}.".format( - error.code, self._err_string(error.code) - ) - ) - def _bn_to_int(self, bn): assert bn != self._ffi.NULL if six.PY3: diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 4c1c7bc9..a80708aa 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -136,23 +136,21 @@ class _CipherContext(object): if not errors and isinstance(self._mode, modes.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." + self._backend.openssl_assert( + 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 ) - else: - raise self._backend._unknown_error(errors[0]) + ) + raise ValueError( + "The length of the provided data is not a multiple of " + "the block length." + ) if (isinstance(self._mode, modes.GCM) and self._operation == self._ENCRYPT): diff --git a/src/cryptography/hazmat/bindings/commoncrypto/binding.py b/src/cryptography/hazmat/bindings/commoncrypto/binding.py index 1695c041..dfe046b5 100644 --- a/src/cryptography/hazmat/bindings/commoncrypto/binding.py +++ b/src/cryptography/hazmat/bindings/commoncrypto/binding.py @@ -13,6 +13,3 @@ class Binding(object): """ lib = lib ffi = ffi - - def __init__(self): - pass diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index a5635f7d..47b1d6e2 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -9,6 +9,7 @@ import os import threading import types +from cryptography.exceptions import InternalError from cryptography.hazmat.bindings._openssl import ffi, lib from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES @@ -17,12 +18,6 @@ _OpenSSLError = collections.namedtuple("_OpenSSLError", ["code", "lib", "func", "reason"]) -class UnhandledOpenSSLError(Exception): - def __init__(self, msg, errors): - super(UnhandledOpenSSLError, self).__init__(msg) - self.errors = errors - - def _consume_errors(lib): errors = [] while True: @@ -41,7 +36,7 @@ def _consume_errors(lib): def _openssl_assert(lib, ok): if not ok: errors = _consume_errors(lib) - raise UnhandledOpenSSLError( + raise InternalError( "Unknown OpenSSL error. Please file an issue at https://github.com" "/pyca/cryptography/issues with information on how to reproduce " "this.", diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index abd707ca..8fd0d711 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -20,7 +20,6 @@ from cryptography.hazmat.backends.openssl.backend import ( Backend, backend ) from cryptography.hazmat.backends.openssl.ec import _sn_to_elliptic_curve -from cryptography.hazmat.bindings.openssl.binding import UnhandledOpenSSLError from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import dsa, ec, padding from cryptography.hazmat.primitives.ciphers import ( @@ -125,7 +124,7 @@ class TestOpenSSL(object): def test_openssl_assert(self): backend.openssl_assert(True) - with pytest.raises(UnhandledOpenSSLError): + with pytest.raises(InternalError): backend.openssl_assert(False) def test_consume_errors(self): @@ -140,23 +139,6 @@ class TestOpenSSL(object): assert backend._lib.ERR_peek_error() == 0 assert len(errors) == 10 - def test_openssl_error_string(self): - backend._lib.ERR_put_error( - backend._lib.ERR_LIB_EVP, - backend._lib.EVP_F_EVP_DECRYPTFINAL_EX, - 0, - b"test_openssl.py", - -1 - ) - - errors = backend._consume_errors() - exc = backend._unknown_error(errors[0]) - - assert ( - "digital envelope routines:" - "EVP_DecryptFinal_ex:digital envelope routines" in str(exc) - ) - def test_ssl_ciphers_registered(self): meth = backend._lib.TLSv1_method() ctx = backend._lib.SSL_CTX_new(meth) |