multiplications.py 6.34 KB
Newer Older
lwc-tester committed
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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
# Implementation of the Lilliput-AE tweakable block cipher.
#
# Authors, hereby denoted as "the implementer":
#     Kévin Le Gouguec,
#     Léo Reynaud
#     2019.
#
# For more information, feedback or questions, refer to our website:
# https://paclido.fr/lilliput-ae
#
# To the extent possible under law, the implementer has waived all copyright
# and related or neighboring rights to the source code in this file.
# http://creativecommons.org/publicdomain/zero/1.0/

"""Multiplications for Lilliput-TBC's tweakey schedule.

This module provides a list of functions implementing lane multiplications,
from ALPHAS[0] = α₀ = I to ALPHAS[6] = α₆ = M_R³.
"""


def _multiply_M(lane):
    multiplied_lane = [lane[(byte-1) % 8] for byte in range(0, 8)]

    multiplied_lane[2] ^= ((lane[6] << 2) & 0xff)
    multiplied_lane[4] ^= ((lane[4] >> 3) & 0xff)
    multiplied_lane[5] ^= ((lane[5] << 3) & 0xff)

    return multiplied_lane


def _multiply_M2(lane):
    multiplied_lane = [lane[(byte-2) % 8] for byte in range(0, 8)]

    multiplied_lane[2] ^= ((lane[5] << 2) & 0xff)
    multiplied_lane[3] ^= ((lane[6] << 2) & 0xff)
    multiplied_lane[4] ^= ((lane[3] >> 3) & 0xff) ^ ((lane[4] >> 6) & 0xff)
    multiplied_lane[5] ^= ((lane[5] << 6) & 0xff)
    multiplied_lane[6] ^= ((lane[5] << 3) & 0xff)

    # binary matrix M1
    multi_mat_l4_m1 = 0
    l4 = lane[4]
    multi_mat_l4_m1 ^= ((l4 & 0x8) >> 3)
    multi_mat_l4_m1 ^= ((l4 & 0x10) >> 3)
    multi_mat_l4_m1 ^= ((l4 & 0x20) >> 3)
    multi_mat_l4_m1 ^= ((l4 & 0x40) >> 3) ^ ((l4 & 0x1) << 3)
    multi_mat_l4_m1 ^= ((l4 & 0x80) >> 3) ^ ((l4 & 0x2) << 3)
    multi_mat_l4_m1 ^= ((l4 & 0x04) << 3)
    multi_mat_l4_m1 ^= ((l4 & 0x08) << 3)
    multi_mat_l4_m1 ^= ((l4 & 0x10) << 3)

    multiplied_lane[5] ^= multi_mat_l4_m1

    return multiplied_lane


def _multiply_M3(lane):
    multiplied_lane = [lane[(byte-3) % 8] for byte in range(0, 8)]

    multiplied_lane[2] ^= ((lane[4] << 2) & 0xff) ^ ((lane[5] << 5) & 0xff)
    multiplied_lane[3] ^= ((lane[5] << 2) & 0xff)
    multiplied_lane[4] ^= ((lane[2] >> 3) & 0xff) ^ ((lane[3] >> 6) & 0xff) ^ ((lane[6] << 2) & 0xff)
    multiplied_lane[6] ^= ((lane[5] << 6) & 0xff)
    multiplied_lane[7] ^= ((lane[5] << 3) & 0xff)

    # binary matrix M1
    multi_mat_l3_m1 = 0
    l3 = lane[3]
    multi_mat_l3_m1 ^= ((l3 & 0x8) >> 3)
    multi_mat_l3_m1 ^= ((l3 & 0x10) >> 3)
    multi_mat_l3_m1 ^= ((l3 & 0x20) >> 3)
    multi_mat_l3_m1 ^= ((l3 & 0x40) >> 3) ^ ((l3 & 0x1) << 3)
    multi_mat_l3_m1 ^= ((l3 & 0x80) >> 3) ^ ((l3 & 0x2) << 3)
    multi_mat_l3_m1 ^= ((l3 & 0x04) << 3)
    multi_mat_l3_m1 ^= ((l3 & 0x08) << 3)
    multi_mat_l3_m1 ^= ((l3 & 0x10) << 3)

    # binary matrix M1
    multi_mat_l4_m1 = 0
    l4 = lane[4]
    multi_mat_l4_m1 ^= ((l4 & 0x8) >> 3)
    multi_mat_l4_m1 ^= ((l4 & 0x10) >> 3)
    multi_mat_l4_m1 ^= ((l4 & 0x20) >> 3)
    multi_mat_l4_m1 ^= ((l4 & 0x40) >> 3) ^ ((l4 & 0x1) << 3)
    multi_mat_l4_m1 ^= ((l4 & 0x80) >> 3) ^ ((l4 & 0x2) << 3)
    multi_mat_l4_m1 ^= ((l4 & 0x04) << 3)
    multi_mat_l4_m1 ^= ((l4 & 0x08) << 3)
    multi_mat_l4_m1 ^= ((l4 & 0x10) << 3)

    # binary matrix M2
    multi_mat_l4_m2 = 0
    l4 = lane[4]
    multi_mat_l4_m2 ^= ((l4 & 0x40) >> 6)
    multi_mat_l4_m2 ^= ((l4 & 0x80) >> 6)
    multi_mat_l4_m2 ^= (l4 & 0x08)
    multi_mat_l4_m2 ^= (l4 & 0x10)
    multi_mat_l4_m2 ^= (l4 & 0x20)
    multi_mat_l4_m2 ^= (l4 & 0x40) ^ ((l4 & 0x1) << 6)
    multi_mat_l4_m2 ^= (l4 & 0x80) ^ ((l4 & 0x2) << 6)


    multiplied_lane[5] ^= multi_mat_l3_m1 ^ multi_mat_l4_m2
    multiplied_lane[6] ^= multi_mat_l4_m1

    return multiplied_lane


def _multiply_MR(lane):
    multiplied_lane = [lane[(byte+1) % 8] for byte in range(0, 8)]

    multiplied_lane[2] ^= ((lane[4] >> 3) & 0xff)
    multiplied_lane[4] ^= ((lane[6] << 3) & 0xff)
    multiplied_lane[5] ^= ((lane[3] << 2) & 0xff)

    return multiplied_lane


def _multiply_MR2(lane):
    multiplied_lane = [lane[(byte+2) % 8] for byte in range(0, 8)]

    multiplied_lane[1] ^= ((lane[4] >> 3) & 0xff)
    multiplied_lane[2] ^= ((lane[5] >> 3) & 0xff)
    multiplied_lane[3] ^= ((lane[6] << 3) & 0xff)
    multiplied_lane[4] ^= ((lane[3] << 2) & 0xff) ^ ((lane[7] << 3) & 0xff)
    multiplied_lane[5] ^= ((lane[4] << 2) & 0xff)


    # binary matrix m3
    multi_mat_l6_m3 = 0
    l6 = lane[6]
    multi_mat_l6_m3 ^= (l6 & 0x1)
    multi_mat_l6_m3 ^= (l6 & 0x2)
    multi_mat_l6_m3 ^= (l6 & 0x4)
    multi_mat_l6_m3 ^= (l6 & 0x8)
    multi_mat_l6_m3 ^= (l6 & 0x10)


    multiplied_lane[2] ^= multi_mat_l6_m3

    return multiplied_lane


def _multiply_MR3(lane):
    multiplied_lane = [lane[(byte+3) % 8] for byte in range(0, 8)]

    multiplied_lane[0] ^= ((lane[4] >> 3) & 0xff)
    multiplied_lane[1] ^= ((lane[5] >> 3) & 0xff)
    multiplied_lane[3] ^= ((lane[3] << 2) & 0xff) ^ ((lane[7] << 3) & 0xff)
    multiplied_lane[4] ^= ((lane[0] << 3) & 0xff) ^ ((lane[4] << 2) & 0xff)
    multiplied_lane[5] ^= ((lane[5] << 2) & 0xff) ^ ((lane[6] << 5) & 0xff)

    # binary matrix m3
    multi_mat_l6_m3 = 0
    l6 = lane[6]
    multi_mat_l6_m3 ^= (l6 & 0x1)
    multi_mat_l6_m3 ^= (l6 & 0x2)
    multi_mat_l6_m3 ^= (l6 & 0x4)
    multi_mat_l6_m3 ^= (l6 & 0x8)
    multi_mat_l6_m3 ^= (l6 & 0x10)

    # binary matrix m3
    multi_mat_l7_m3 = 0
    l7 = lane[7]
    multi_mat_l7_m3 ^= (l7 & 0x1)
    multi_mat_l7_m3 ^= (l7 & 0x2)
    multi_mat_l7_m3 ^= (l7 & 0x4)
    multi_mat_l7_m3 ^= (l7 & 0x8)
    multi_mat_l7_m3 ^= (l7 & 0x10)

    # binary matrix m4
    multi_mat_l3_m4 = 0
    l3 = lane[3]
    multi_mat_l3_m4 ^= ((l3 & 0x2) >> 1)
    multi_mat_l3_m4 ^= ((l3 & 0x4) >> 1)
    multi_mat_l3_m4 ^= ((l3 & 0x8) >> 1)
    multi_mat_l3_m4 ^= ((l3 & 0x10) >> 1)
    multi_mat_l3_m4 ^= ((l3 & 0x20) >> 1)

    # binary matrix m1 for MR
    multi_mat_l6_m1 = 0
    l6 = lane[6]
    multi_mat_l6_m1 ^= ((l6 & 0x8) >> 3)
    multi_mat_l6_m1 ^= ((l6 & 0x10) >> 3)
    multi_mat_l6_m1 ^= ((l6 & 0x20) >> 3)
    multi_mat_l6_m1 ^= ((l6 & 0x40) >> 3) ^ ((l6 & 0x1) << 3)
    multi_mat_l6_m1 ^= ((l6 & 0x80) >> 3) ^ ((l6 & 0x2) << 3)
    multi_mat_l6_m1 ^= ((l6 & 0x4) << 3)
    multi_mat_l6_m1 ^= ((l6 & 0x8) << 3)
    multi_mat_l6_m1 ^= ((l6 & 0x10) << 3)


    multiplied_lane[1] ^= multi_mat_l6_m3
    multiplied_lane[2] ^= multi_mat_l3_m4 ^ multi_mat_l6_m1 ^ multi_mat_l7_m3

    return multiplied_lane


ALPHAS = (
    list,                       # Identity.
    _multiply_M,
    _multiply_M2,
    _multiply_M3,
    _multiply_MR,
    _multiply_MR2,
    _multiply_MR3
)