summaryrefslogtreecommitdiff
path: root/tests/hazmat/primitives/test_aes_gcm.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/hazmat/primitives/test_aes_gcm.py')
-rw-r--r--tests/hazmat/primitives/test_aes_gcm.py219
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