1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
# 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.
import binascii
import pytest
from cryptography.exceptions import InvalidTag
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
from .utils import wycheproof_tests
@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()
@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()
@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",
)
@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)
|