"""XTEA cipher."""
from cascada.bitvector.core import Constant
from cascada.bitvector.ssa import RoundBasedFunction
from cascada.primitives.blockcipher import Encryption, Cipher
[docs]class XTEAKeySchedule(RoundBasedFunction):
"""Key schedule function."""
num_rounds = 64
input_widths = [32, 32, 32, 32]
output_widths = [32 for i in range(64)]
[docs] @classmethod
def set_num_rounds(cls, new_num_rounds):
cls.num_rounds = new_num_rounds
cls.output_widths = [32 for _ in range(new_num_rounds)]
[docs] @classmethod
def eval(cls, *master_key):
mk = list(master_key)
s = Constant(0, 32)
delta = Constant(0x9E3779B9, 32)
k = []
for i in range(cls.num_rounds):
if i % 2 == 0:
k.append(s + mk[int(s & Constant(3, 32))])
# s += delta
else:
k.append(s + mk[int((s >> Constant(11, 32)) & Constant(3, 32))])
if i % 2 == 0:
s += delta
cls.add_round_outputs(k[-1])
return k
[docs]class XTEAEncryption(Encryption, RoundBasedFunction):
"""Encryption function."""
num_rounds = 64
input_widths = [32, 32]
output_widths = [32, 32]
round_keys = None
[docs] @classmethod
def set_num_rounds(cls, new_num_rounds):
cls.num_rounds = new_num_rounds
[docs] @classmethod
def eval(cls, x, y):
v0 = x
v1 = y
k = cls.round_keys
for i in range(cls.num_rounds):
v0, v1 = v1, v0 + ((((v1 << Constant(4, 32)) ^ (v1 >> Constant(5, 32))) + v1) ^ k[i])
cls.add_round_outputs(v0, v1)
return v0, v1
[docs]class XTEACipher(Cipher):
"""XTEA cipher."""
key_schedule = XTEAKeySchedule
encryption = XTEAEncryption
[docs] @classmethod
def set_num_rounds(cls, new_num_rounds):
cls.encryption.set_num_rounds(new_num_rounds)
cls.key_schedule.set_num_rounds(new_num_rounds)
[docs] @classmethod
def test(cls):
"""Test XTEA with test vectors."""
# https://go.googlesource.com/crypto/+/master/xtea/xtea_test.go
old_num_rounds = cls.num_rounds
cls.set_num_rounds(64)
plaintext = (0x41424344, 0x45464748)
key = (0, 0, 0, 0)
assert cls(plaintext, key) == (0xa0390589, 0xf8b8efa5)
plaintext = (0x41424344, 0x45464748)
key = (0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)
assert cls(plaintext, key) == (0x497df3d0, 0x72612cb5)
cls.set_num_rounds(64)