Skip to content

disallow implicit tag truncation with finalize_with_tag #4342

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
disallow implicit tag truncation with finalize_with_tag
  • Loading branch information
reaperhulk committed Jul 17, 2018
commit 688e0f673bfbf43fa898994326c6877f00ab19ef
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")