# 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)
