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
|
# 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 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
elif len(iv) == 0:
with pytest.raises(ValueError):
Cipher(algorithms.AES(key), modes.GCM(iv), backend)
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"])
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
elif len(iv) == 0:
with pytest.raises(ValueError):
aesgcm.encrypt(iv, msg, aad)
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)
|