Source code for cascada.primitives.lea

"""LEA 128-bit cipher."""
import itertools

from cascada.bitvector.core import Constant
from cascada.bitvector.operation import RotateLeft as ROL
from cascada.bitvector.operation import RotateRight as ROR

from cascada.bitvector.ssa import RoundBasedFunction
from cascada.primitives.blockcipher import Encryption, Cipher


[docs]class LEAKeySchedule(RoundBasedFunction): """Key schedule function.""" num_rounds = 24 input_widths = [32, 32, 32, 32] output_widths = [32 for i in range(24 * 6)]
[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 * 6)]
[docs] @classmethod def eval(cls, k0, k1, k2, k3): round_keys = [None for _ in range(cls.num_rounds)] T0, T1, T2, T3 = k0, k1, k2, k3 delta = [ Constant(0xc3efe9db, 32), Constant(0x44626b02, 32), Constant(0x79e27c8a, 32), Constant(0x78df30ec, 32), ] for i in range(cls.num_rounds): T0 = ROL(T0 + ROL(delta[i % 4], i), 1) T1 = ROL(T1 + ROL(delta[i % 4], (i + 1)), 3) T2 = ROL(T2 + ROL(delta[i % 4], (i + 2)), 6) T3 = ROL(T3 + ROL(delta[i % 4], (i + 3)), 11) round_keys[i] = T0, T1, T2, T1, T3, T1 cls.add_round_outputs(*round_keys[i]) return tuple(itertools.chain(*round_keys)) # flatten
[docs]class LEAEncryption(Encryption, RoundBasedFunction): """Encryption function.""" num_rounds = 24 input_widths = [32, 32, 32, 32] output_widths = [32, 32, 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, p0, p1, p2, p3): x0, x1, x2, x3 = p0, p1, p2, p3 rk = [[None for _ in range(6)] for _ in range(cls.num_rounds)] for i, k in enumerate(cls.round_keys): rk[i // 6][i % 6] = k for i in range(cls.num_rounds): k0, k1, k2, k3, k4, k5 = rk[i] tmp = x0 x0 = ROL((x0 ^ k0) + (x1 ^ k1), 9) x1 = ROR((x1 ^ k2) + (x2 ^ k3), 5) x2 = ROR((x2 ^ k4) + (x3 ^ k5), 3) x3 = tmp cls.add_round_outputs(x0, x1, x2, x3) return x0, x1, x2, x3
[docs]class LEACipher(Cipher): """LEA-128 cipher.""" key_schedule = LEAKeySchedule encryption = LEAEncryption
[docs] @classmethod def set_num_rounds(cls, new_num_rounds): cls.key_schedule.set_num_rounds(new_num_rounds) cls.encryption.set_num_rounds(new_num_rounds)
@classmethod def test(cls): old_num_rounds = cls.num_rounds cls.set_num_rounds(24) key = [ Constant(0x3c2d1e0f, 32), Constant(0x78695a4b, 32), Constant(0xb4a59687, 32), Constant(0xf0e1d2c3, 32) ] pt = [ Constant(0x13121110, 32), Constant(0x17161514, 32), Constant(0x1b1a1918, 32), Constant(0x1f1e1d1c, 32) ] ct = [ Constant(0x354ec89f, 32), Constant(0x18c6c628, 32), Constant(0xa7c73255, 32), Constant(0xfd8b6404, 32) ] assert cls(pt, key) == tuple(ct) cls.set_num_rounds(old_num_rounds)