aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst11
-rw-r--r--src/cryptography/exceptions.py4
-rw-r--r--src/cryptography/hazmat/backends/commoncrypto/backend.py3
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py17
-rw-r--r--src/cryptography/hazmat/backends/openssl/ciphers.py30
-rw-r--r--src/cryptography/hazmat/bindings/commoncrypto/binding.py3
-rw-r--r--src/cryptography/hazmat/bindings/openssl/binding.py9
-rw-r--r--tests/hazmat/backends/test_openssl.py20
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)