summaryrefslogtreecommitdiff
path: root/python/helpers.py
blob: 07affa92059cc484fffa5a71b89c37e55209da1c (plain)
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
from constants import BLOCK_BITS, BLOCK_BYTES
from lilliput_tbc import LilliputTBCEnc


def ArrayToBlockbytesMatrix(array):
    vector = list(array)

    blocks_nb = len(vector)//BLOCK_BYTES

    block_starts = (
        i*BLOCK_BYTES for i in range(blocks_nb)
    )

    matrix = [
        vector[start:start+BLOCK_BYTES] for start in block_starts
    ]

    padding_len = len(vector)%BLOCK_BYTES

    if padding_len > 0:
        padding = vector[-padding_len:]
        matrix.append(padding)

    return matrix


def BlockbytesMatrixToBytes(matrix):
    return bytes(byte for block in matrix for byte in block)


def XorState(state1, state2):
    return [s1^s2 for (s1, s2) in zip(state1, state2)]


def Padding10LSB(array, number_bits):
    shifted = 0
    for byte in range(0, len(array)):
        shifted |= (array[byte] << (8 * byte))
    shifted = (shifted << (BLOCK_BITS - number_bits)) & 0xffffffffffffffffffffffffffffffff

    padded = shifted | (0x1 << (BLOCK_BITS - number_bits - 1))

    array_padded = [0 for byte in range(0, BLOCK_BYTES)]
    for byte in range(0, BLOCK_BYTES):
        array_padded[byte] = (padded & (0xff << (8 * byte))) >> (8 * byte)

    return array_padded


def _tweakAssociatedData(t, i, padded):
    t_bytes = t//8
    tweak = [0]*(t_bytes)

    mask = 0xff
    for byte in range(t_bytes-1):
        tweak[byte] = (i & mask) >> (byte * 8)
        mask = mask << 8

    mask = (0xf << (8 * t_bytes-1))
    tweak[-1] = (i & mask) >> ((t_bytes-1)*8)
    if not padded:
        tweak[-1] |= 0x20
    else:
        tweak[-1] |= 0x60

    return tweak


def BuildAuth(t, A, key):
    Auth = [0 for byte in range(0, BLOCK_BYTES)]
    l_a = len(A)//BLOCK_BYTES

    padding_bytes = len(A)%BLOCK_BYTES

    A = ArrayToBlockbytesMatrix(A)

    for i in range(0, l_a):
        tweak = _tweakAssociatedData(t, i, padded=False)
        enc = LilliputTBCEnc(tweak, key, A[i])
        Auth = XorState(Auth, enc)

    if padding_bytes == 0:
        return Auth

    tweak = _tweakAssociatedData(t, l_a, padded=True)
    ad_padded = Padding10LSB(A[l_a], padding_bytes*8)
    enc = LilliputTBCEnc(tweak, key, ad_padded)
    Auth = XorState(Auth, enc)

    return Auth


class TagValidationError(Exception):
    def __init__(self, announced, computed):
        msg = '\n'.join((
            'Invalid tag:',
            announced.hex().upper()+' (announced)',
            computed.hex().upper()+' (computed)'
        ))

        super().__init__(msg)
        self._announced = announced
        self._computed = computed