text: # 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 pytest
  
  from cryptography.exceptions import InvalidTag
  from cryptography.hazmat.backends.interfaces import CipherBackend
  from cryptography.hazmat.primitives import padding
  from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
  from cryptography.hazmat.primitives.ciphers.aead import AESCCM, AESGCM
  
  from ..hazmat.primitives.test_aead import _aead_supported
  
  
  @pytest.mark.requires_backend_interface(interface=CipherBackend)
  @pytest.mark.wycheproof_tests("aes_cbc_pkcs5_test.json")
  def test_aes_cbc_pkcs5(backend, wycheproof):
      key = binascii.unhexlify(wycheproof.testcase["key"])
      iv = binascii.unhexlify(wycheproof.testcase["iv"])
      msg = binascii.unhexlify(wycheproof.testcase["msg"])
      ct = binascii.unhexlify(wycheproof.testcase["ct"])
  
      padder = padding.PKCS7(128).padder()
  
      cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend)
      enc = cipher.encryptor()
      computed_ct = (
          enc.update(padder.update(msg) + padder.finalize()) + enc.finalize()
      )
      dec = cipher.decryptor()
      padded_msg = dec.update(ct) + dec.finalize()
      unpadder = padding.PKCS7(128).unpadder()
      if wycheproof.valid or wycheproof.acceptable:
          assert computed_ct == ct
          computed_msg = unpadder.update(padded_msg) + unpadder.finalize()
          assert computed_msg == msg
      else:
          assert computed_ct != ct
          with pytest.raises(ValueError):
              unpadder.update(padded_msg) + unpadder.finalize()
  
  
  @pytest.mark.requires_backend_interface(interface=CipherBackend)
  @pytest.mark.wycheproof_tests("aes_gcm_test.json")
  def test_aes_gcm(backend, wycheproof):
      key = binascii.unhexlify(wycheproof.testcase["key"])
      iv = binascii.unhexlify(wycheproof.testcase["iv"])
      aad = binascii.unhexlify(wycheproof.testcase["aad"])
      msg = binascii.unhexlify(wycheproof.testcase["msg"])
      ct = binascii.unhexlify(wycheproof.testcase["ct"])
      tag = binascii.unhexlify(wycheproof.testcase["tag"])
      if len(iv) < 8 or len(iv) > 128:
          pytest.skip(
              "Less than 64-bit IVs (and greater than 1024-bit) are no longer "
              "supported"
          )
      if backend._fips_enabled and len(iv) != 12:
          # Red Hat disables non-96-bit IV support as part of its FIPS
          # patches.
          pytest.skip("Non-96-bit IVs unsupported in FIPS mode.")
      if wycheproof.valid or wycheproof.acceptable:
          enc = Cipher(algorithms.AES(key), modes.GCM(iv), backend).encryptor()
          enc.authenticate_additional_data(aad)
          computed_ct = enc.update(msg) + enc.finalize()
          computed_tag = enc.tag
          assert computed_ct == ct
          assert computed_tag == tag
          dec = Cipher(
              algorithms.AES(key),
              modes.GCM(iv, tag, min_tag_length=len(tag)),
              backend,
          ).decryptor()
          dec.authenticate_additional_data(aad)
          computed_msg = dec.update(ct) + dec.finalize()
          assert computed_msg == msg
      else:
          dec = Cipher(
              algorithms.AES(key),
              modes.GCM(iv, tag, min_tag_length=len(tag)),
              backend,
          ).decryptor()
          dec.authenticate_additional_data(aad)
          dec.update(ct)
          with pytest.raises(InvalidTag):
              dec.finalize()
  
  
  @pytest.mark.requires_backend_interface(interface=CipherBackend)
  @pytest.mark.wycheproof_tests("aes_gcm_test.json")
  def test_aes_gcm_aead_api(backend, wycheproof):
      key = binascii.unhexlify(wycheproof.testcase["key"])
      iv = binascii.unhexlify(wycheproof.testcase["iv"])
      aad = binascii.unhexlify(wycheproof.testcase["aad"])
      msg = binascii.unhexlify(wycheproof.testcase["msg"])
      ct = binascii.unhexlify(wycheproof.testcase["ct"])
      tag = binascii.unhexlify(wycheproof.testcase["tag"])
      if len(iv) < 8 or len(iv) > 128:
          pytest.skip(
              "Less than 64-bit IVs (and greater than 1024-bit) are no longer "
              "supported"
          )
  
      if backend._fips_enabled and len(iv) != 12:
          # Red Hat disables non-96-bit IV support as part of its FIPS
          # patches.
          pytest.skip("Non-96-bit IVs unsupported in FIPS mode.")
      aesgcm = AESGCM(key)
      if wycheproof.valid or wycheproof.acceptable:
          computed_ct = aesgcm.encrypt(iv, msg, aad)
          assert computed_ct == ct + tag
          computed_msg = aesgcm.decrypt(iv, ct + tag, aad)
          assert computed_msg == msg
      else:
          with pytest.raises(InvalidTag):
              aesgcm.decrypt(iv, ct + tag, aad)
  
  
  @pytest.mark.skipif(
      not _aead_supported(AESCCM),
      reason="Requires OpenSSL with AES-CCM support",
  )
  @pytest.mark.requires_backend_interface(interface=CipherBackend)
  @pytest.mark.wycheproof_tests("aes_ccm_test.json")
  def test_aes_ccm_aead_api(backend, wycheproof):
      key = binascii.unhexlify(wycheproof.testcase["key"])
      iv = binascii.unhexlify(wycheproof.testcase["iv"])
      aad = binascii.unhexlify(wycheproof.testcase["aad"])
      msg = binascii.unhexlify(wycheproof.testcase["msg"])
      ct = binascii.unhexlify(wycheproof.testcase["ct"])
      tag = binascii.unhexlify(wycheproof.testcase["tag"])
  
      if (
          wycheproof.invalid
          and wycheproof.testcase["comment"] == "Invalid tag size"
      ):
          with pytest.raises(ValueError):
              AESCCM(key, tag_length=wycheproof.testgroup["tagSize"] // 8)
          return
  
      aesccm = AESCCM(key, tag_length=wycheproof.testgroup["tagSize"] // 8)
      if wycheproof.valid or wycheproof.acceptable:
          computed_ct = aesccm.encrypt(iv, msg, aad)
          assert computed_ct == ct + tag
          computed_msg = aesccm.decrypt(iv, ct + tag, aad)
          assert computed_msg == msg
      elif not 7 <= len(iv) <= 13:
          with pytest.raises(ValueError):
              aesccm.decrypt(iv, ct + tag, aad)
      else:
          with pytest.raises(InvalidTag):
              aesccm.decrypt(iv, ct + tag, aad)
  