diff options
author | Paul Kehrer <paul.l.kehrer@gmail.com> | 2018-07-15 09:15:16 +0530 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2018-07-14 23:45:16 -0400 |
commit | bb23c6c7cbb3f62f1b1b2480f9dc07c6beba3398 (patch) | |
tree | 9e4fe9cecf15bd625558fcf32614ea3fbca5bbc8 | |
parent | 33db1c83b7ccb18e3319dedb5c7eb38edb74d8ab (diff) | |
download | cryptography-bb23c6c7cbb3f62f1b1b2480f9dc07c6beba3398.tar.gz cryptography-bb23c6c7cbb3f62f1b1b2480f9dc07c6beba3398.tar.bz2 cryptography-bb23c6c7cbb3f62f1b1b2480f9dc07c6beba3398.zip |
document one shot AEAD length restrictions (#4322)
* document one shot AEAD length restrictions
* write a test that won't consume infinity ram
continue to raise OverflowError since that's what cffi did.
* this applies to associated_data too
* remove unneeded arg
* review feedback on docs
-rw-r--r-- | docs/hazmat/primitives/aead.rst | 6 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/ciphers/aead.py | 24 | ||||
-rw-r--r-- | tests/hazmat/primitives/test_aead.py | 38 |
3 files changed, 68 insertions, 0 deletions
diff --git a/docs/hazmat/primitives/aead.rst b/docs/hazmat/primitives/aead.rst index ee4214a1..a54cc6fa 100644 --- a/docs/hazmat/primitives/aead.rst +++ b/docs/hazmat/primitives/aead.rst @@ -60,6 +60,8 @@ also support providing integrity for associated data which is not encrypted. authenticated with the key, but does not need to be encrypted. Can be ``None``. :returns bytes: The ciphertext bytes with the 16 byte tag appended. + :raises OverflowError: If ``data`` or ``associated_data`` is larger + than 2\ :sup:`32` bytes. .. method:: decrypt(nonce, data, associated_data) @@ -128,6 +130,8 @@ also support providing integrity for associated data which is not encrypted. :param bytes associated_data: Additional data that should be authenticated with the key, but is not encrypted. Can be ``None``. :returns bytes: The ciphertext bytes with the 16 byte tag appended. + :raises OverflowError: If ``data`` or ``associated_data`` is larger + than 2\ :sup:`32` bytes. .. method:: decrypt(nonce, data, associated_data) @@ -212,6 +216,8 @@ also support providing integrity for associated data which is not encrypted. :param bytes associated_data: Additional data that should be authenticated with the key, but is not encrypted. Can be ``None``. :returns bytes: The ciphertext bytes with the tag appended. + :raises OverflowError: If ``data`` or ``associated_data`` is larger + than 2\ :sup:`32` bytes. .. method:: decrypt(nonce, data, associated_data) diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py index 415a45a9..9794d768 100644 --- a/src/cryptography/hazmat/primitives/ciphers/aead.py +++ b/src/cryptography/hazmat/primitives/ciphers/aead.py @@ -12,6 +12,8 @@ from cryptography.hazmat.backends.openssl.backend import backend class ChaCha20Poly1305(object): + _MAX_SIZE = 2 ** 32 + def __init__(self, key): if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( @@ -33,6 +35,12 @@ class ChaCha20Poly1305(object): if associated_data is None: associated_data = b"" + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + self._check_params(nonce, data, associated_data) return aead._encrypt( backend, self, nonce, data, associated_data, 16 @@ -56,6 +64,8 @@ class ChaCha20Poly1305(object): class AESCCM(object): + _MAX_SIZE = 2 ** 32 + def __init__(self, key, tag_length=16): utils._check_bytes("key", key) if len(key) not in (16, 24, 32): @@ -90,6 +100,12 @@ class AESCCM(object): if associated_data is None: associated_data = b"" + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + self._check_params(nonce, data, associated_data) self._validate_lengths(nonce, len(data)) return aead._encrypt( @@ -121,6 +137,8 @@ class AESCCM(object): class AESGCM(object): + _MAX_SIZE = 2 ** 32 + def __init__(self, key): utils._check_bytes("key", key) if len(key) not in (16, 24, 32): @@ -142,6 +160,12 @@ class AESGCM(object): if associated_data is None: associated_data = b"" + if len(data) > self._MAX_SIZE or len(associated_data) > self._MAX_SIZE: + # This is OverflowError to match what cffi would raise + raise OverflowError( + "Data or associated data too long. Max 2**32 bytes" + ) + self._check_params(nonce, data, associated_data) return aead._encrypt( backend, self, nonce, data, associated_data, 16 diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py index dc2f357b..a0cc79e1 100644 --- a/tests/hazmat/primitives/test_aead.py +++ b/tests/hazmat/primitives/test_aead.py @@ -22,6 +22,11 @@ from ...utils import ( ) +class FakeData(object): + def __len__(self): + return 2 ** 32 + 1 + + def _aead_supported(cls): try: cls(b"0" * 32) @@ -46,6 +51,17 @@ def test_chacha20poly1305_unsupported_on_older_openssl(backend): ) @pytest.mark.requires_backend_interface(interface=CipherBackend) class TestChaCha20Poly1305(object): + def test_data_too_large(self): + key = ChaCha20Poly1305.generate_key() + chacha = ChaCha20Poly1305(key) + nonce = b"0" * 12 + + with pytest.raises(OverflowError): + chacha.encrypt(nonce, FakeData(), b"") + + with pytest.raises(OverflowError): + chacha.encrypt(nonce, b"", FakeData()) + def test_generate_key(self): key = ChaCha20Poly1305.generate_key() assert len(key) == 32 @@ -168,6 +184,17 @@ def test_aesccm_unsupported_on_older_openssl(backend): ) @pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESCCM(object): + def test_data_too_large(self): + key = AESCCM.generate_key(128) + aesccm = AESCCM(key) + nonce = b"0" * 12 + + with pytest.raises(OverflowError): + aesccm.encrypt(nonce, FakeData(), b"") + + with pytest.raises(OverflowError): + aesccm.encrypt(nonce, b"", FakeData()) + def test_default_tag_length(self, backend): key = AESCCM.generate_key(128) aesccm = AESCCM(key) @@ -309,6 +336,17 @@ def _load_gcm_vectors(): @pytest.mark.requires_backend_interface(interface=CipherBackend) class TestAESGCM(object): + def test_data_too_large(self): + key = AESGCM.generate_key(128) + aesgcm = AESGCM(key) + nonce = b"0" * 12 + + with pytest.raises(OverflowError): + aesgcm.encrypt(nonce, FakeData(), b"") + + with pytest.raises(OverflowError): + aesgcm.encrypt(nonce, b"", FakeData()) + @pytest.mark.parametrize("vector", _load_gcm_vectors()) def test_vectors(self, vector): key = binascii.unhexlify(vector["key"]) |