Skip to content

Commit

Permalink
disallow implicit tag truncation with finalize_with_tag (#4342)
Browse files Browse the repository at this point in the history
  • Loading branch information
reaperhulk authored and alex committed Jul 17, 2018
1 parent c574e75 commit d4378e4
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ Changelog

.. note:: This version is not yet released and is under active development.

* **SECURITY ISSUE:**
:meth:`~cryptography.hazmat.primitives.ciphers.AEADDecryptionContext.finalize_with_tag`
allowed tag truncation by default which can allow tag forgery in some cases.
The method now enforces the ``min_tag_length`` provided to the
:class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` constructor.
* Added support for Python 3.7.
* Added :meth:`~cryptography.fernet.Fernet.extract_timestamp` to get the
authenticated timestamp of a :doc:`Fernet </fernet>` token.
Expand Down
1 change: 1 addition & 0 deletions docs/hazmat/primitives/symmetric-encryption.rst
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@ Interfaces
:raises ValueError: This is raised when the data provided isn't
a multiple of the algorithm's block size, if ``min_tag_length`` is
less than 4, or if ``len(tag) < min_tag_length``.
``min_tag_length`` is an argument to the ``GCM`` constructor.
:raises NotImplementedError: This is raised if the version of the
OpenSSL backend used is 1.0.1 or earlier.

Expand Down
5 changes: 5 additions & 0 deletions src/cryptography/hazmat/backends/openssl/ciphers.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ def finalize_with_tag(self, tag):
"finalize_with_tag requires OpenSSL >= 1.0.2. To use this "
"method please update OpenSSL"
)
if len(tag) < self._mode._min_tag_length:
raise ValueError(
"Authentication tag must be {0} bytes or longer.".format(
self._mode._min_tag_length)
)
res = self._backend._lib.EVP_CIPHER_CTX_ctrl(
self._ctx, self._backend._lib.EVP_CTRL_AEAD_SET_TAG,
len(tag), tag
Expand Down
1 change: 1 addition & 0 deletions src/cryptography/hazmat/primitives/ciphers/modes.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ def __init__(self, initialization_vector, tag=None, min_tag_length=16):
min_tag_length)
)
self._tag = tag
self._min_tag_length = min_tag_length

tag = utils.read_only_property("_tag")
initialization_vector = utils.read_only_property("_initialization_vector")
Expand Down
16 changes: 16 additions & 0 deletions tests/hazmat/primitives/test_aes.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,3 +439,19 @@ def test_gcm_tag_decrypt_finalize(self, backend):
decryptor.finalize()
else:
decryptor.finalize_with_tag(tag)

@pytest.mark.supported(
only_if=lambda backend: (
not backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 or
backend._lib.CRYPTOGRAPHY_IS_LIBRESSL
),
skip_message="Not supported on OpenSSL 1.0.1",
)
def test_gcm_tag_decrypt_finalize_tag_length(self, backend):
decryptor = base.Cipher(
algorithms.AES(b"0" * 16),
modes.GCM(b"0" * 12),
backend=backend
).decryptor()
with pytest.raises(ValueError):
decryptor.finalize_with_tag(b"tagtooshort")

0 comments on commit d4378e4

Please sign in to comment.