diff options
Diffstat (limited to 'tests/hazmat/primitives/test_aes_gcm.py')
-rw-r--r-- | tests/hazmat/primitives/test_aes_gcm.py | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/tests/hazmat/primitives/test_aes_gcm.py b/tests/hazmat/primitives/test_aes_gcm.py new file mode 100644 index 000000000..8b71d1230 --- /dev/null +++ b/tests/hazmat/primitives/test_aes_gcm.py @@ -0,0 +1,219 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import absolute_import, division, print_function + +import binascii +import os + +import pytest + +from cryptography.hazmat.backends.interfaces import CipherBackend +from cryptography.hazmat.primitives.ciphers import algorithms, base, modes + +from .utils import generate_aead_test +from ...utils import load_nist_vectors + + +@pytest.mark.supported( + only_if=lambda backend: backend.cipher_supported( + algorithms.AES(b"\x00" * 16), modes.GCM(b"\x00" * 12) + ), + skip_message="Does not support AES GCM", +) +@pytest.mark.requires_backend_interface(interface=CipherBackend) +class TestAESModeGCM(object): + test_gcm = generate_aead_test( + load_nist_vectors, + os.path.join("ciphers", "AES", "GCM"), + [ + "gcmDecrypt128.rsp", + "gcmDecrypt192.rsp", + "gcmDecrypt256.rsp", + "gcmEncryptExtIV128.rsp", + "gcmEncryptExtIV192.rsp", + "gcmEncryptExtIV256.rsp", + ], + algorithms.AES, + modes.GCM, + ) + + def test_gcm_tag_with_only_aad(self, backend): + key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3") + iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d") + aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193") + tag = binascii.unhexlify(b"0f247e7f9c2505de374006738018493b") + + cipher = base.Cipher( + algorithms.AES(key), modes.GCM(iv), backend=backend + ) + encryptor = cipher.encryptor() + encryptor.authenticate_additional_data(aad) + encryptor.finalize() + assert encryptor.tag == tag + + def test_gcm_ciphertext_with_no_aad(self, backend): + key = binascii.unhexlify(b"e98b72a9881a84ca6b76e0f43e68647a") + iv = binascii.unhexlify(b"8b23299fde174053f3d652ba") + ct = binascii.unhexlify(b"5a3c1cf1985dbb8bed818036fdd5ab42") + tag = binascii.unhexlify(b"23c7ab0f952b7091cd324835043b5eb5") + pt = binascii.unhexlify(b"28286a321293253c3e0aa2704a278032") + + cipher = base.Cipher( + algorithms.AES(key), modes.GCM(iv), backend=backend + ) + encryptor = cipher.encryptor() + computed_ct = encryptor.update(pt) + encryptor.finalize() + assert computed_ct == ct + assert encryptor.tag == tag + + def test_gcm_ciphertext_limit(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend, + ).encryptor() + encryptor._bytes_processed = modes.GCM._MAX_ENCRYPTED_BYTES - 16 + encryptor.update(b"0" * 16) + assert encryptor._bytes_processed == modes.GCM._MAX_ENCRYPTED_BYTES + with pytest.raises(ValueError): + encryptor.update(b"0") + + def test_gcm_aad_limit(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend, + ).encryptor() + encryptor._aad_bytes_processed = modes.GCM._MAX_AAD_BYTES - 16 + encryptor.authenticate_additional_data(b"0" * 16) + assert encryptor._aad_bytes_processed == modes.GCM._MAX_AAD_BYTES + with pytest.raises(ValueError): + encryptor.authenticate_additional_data(b"0") + + def test_gcm_ciphertext_increments(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend, + ).encryptor() + encryptor.update(b"0" * 8) + assert encryptor._bytes_processed == 8 + encryptor.update(b"0" * 7) + assert encryptor._bytes_processed == 15 + encryptor.update(b"0" * 18) + assert encryptor._bytes_processed == 33 + + def test_gcm_aad_increments(self, backend): + encryptor = base.Cipher( + algorithms.AES(b"\x00" * 16), + modes.GCM(b"\x01" * 16), + backend=backend, + ).encryptor() + encryptor.authenticate_additional_data(b"0" * 8) + assert encryptor._aad_bytes_processed == 8 + encryptor.authenticate_additional_data(b"0" * 18) + assert encryptor._aad_bytes_processed == 26 + + def test_gcm_tag_decrypt_none(self, backend): + key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3") + iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d") + aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193") + + encryptor = base.Cipher( + algorithms.AES(key), modes.GCM(iv), backend=backend + ).encryptor() + encryptor.authenticate_additional_data(aad) + encryptor.finalize() + + decryptor = base.Cipher( + algorithms.AES(key), modes.GCM(iv), backend=backend + ).decryptor() + decryptor.authenticate_additional_data(aad) + with pytest.raises(ValueError): + decryptor.finalize() + + def test_gcm_tag_decrypt_mode(self, backend): + key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3") + iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d") + aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193") + + encryptor = base.Cipher( + algorithms.AES(key), modes.GCM(iv), backend=backend + ).encryptor() + encryptor.authenticate_additional_data(aad) + encryptor.finalize() + tag = encryptor.tag + + decryptor = base.Cipher( + algorithms.AES(key), modes.GCM(iv, tag), backend=backend + ).decryptor() + decryptor.authenticate_additional_data(aad) + decryptor.finalize() + + def test_gcm_tag_decrypt_finalize(self, backend): + key = binascii.unhexlify(b"5211242698bed4774a090620a6ca56f3") + iv = binascii.unhexlify(b"b1e1349120b6e832ef976f5d") + aad = binascii.unhexlify(b"b6d729aab8e6416d7002b9faa794c410d8d2f193") + + encryptor = base.Cipher( + algorithms.AES(key), modes.GCM(iv), backend=backend + ).encryptor() + encryptor.authenticate_additional_data(aad) + encryptor.finalize() + tag = encryptor.tag + + decryptor = base.Cipher( + algorithms.AES(key), modes.GCM(iv), backend=backend + ).decryptor() + decryptor.authenticate_additional_data(aad) + + decryptor.finalize_with_tag(tag) + + 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") + + def test_buffer_protocol(self, backend): + data = bytearray(b"helloworld") + enc = base.Cipher( + algorithms.AES(bytearray(b"\x00" * 16)), + modes.GCM(bytearray(b"\x00" * 12)), + backend, + ).encryptor() + enc.authenticate_additional_data(bytearray(b"foo")) + ct = enc.update(data) + enc.finalize() + dec = base.Cipher( + algorithms.AES(bytearray(b"\x00" * 16)), + modes.GCM(bytearray(b"\x00" * 12), enc.tag), + backend, + ).decryptor() + dec.authenticate_additional_data(bytearray(b"foo")) + pt = dec.update(ct) + dec.finalize() + assert pt == data + + @pytest.mark.parametrize("size", [8, 128]) + def test_gcm_min_max_iv(self, size, backend): + if backend._fips_enabled: + # Red Hat disables non-96-bit IV support as part of its FIPS + # patches. + pytest.skip("Non-96-bit IVs unsupported in FIPS mode.") + + key = os.urandom(16) + iv = b"\x00" * size + + payload = b"data" + encryptor = base.Cipher(algorithms.AES(key), modes.GCM(iv)).encryptor() + ct = encryptor.update(payload) + encryptor.finalize() + tag = encryptor.tag + + decryptor = base.Cipher(algorithms.AES(key), modes.GCM(iv)).decryptor() + pt = decryptor.update(ct) + + decryptor.finalize_with_tag(tag) + assert pt == payload |