summaryrefslogtreecommitdiff
path: root/src/add_python/lilliput/ae_common.py
blob: 033b5b085c574c4c2b2f65148a96bd45a4675d06 (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
from .constants import BLOCK_BITS, BLOCK_BYTES
from .helpers import xor
from . import tbc


def bytes_to_block_matrix(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 block_matrix_to_bytes(matrix):
    return bytes(byte for block in matrix for byte in block)


def pad10(X):
    zeroes = [0] * (BLOCK_BYTES-len(X)-1)
    return zeroes + [0b10000000] + X


def _tweak_associated_data(t, i, padded):
    tweak = list(i.to_bytes(t//8, 'little'))

    prefix = 0b0110 if padded else 0b0010

    # Clear upper 4 bits and set them to prefix.
    tweak[-1] &= 0b00001111
    tweak[-1] = prefix << 4

    return tweak


def build_auth(t, A, key):
    Auth = [0]*BLOCK_BYTES

    l_a = len(A)//BLOCK_BYTES
    need_padding = len(A)%BLOCK_BYTES > 0

    A = bytes_to_block_matrix(A)

    for i in range(l_a):
        tweak = _tweak_associated_data(t, i, padded=False)
        enc = tbc.encrypt(tweak, key, A[i])
        Auth = xor(Auth, enc)

    if not need_padding:
        return Auth

    tweak = _tweak_associated_data(t, l_a, padded=True)
    ad_padded = pad10(A[l_a])
    enc = tbc.encrypt(tweak, key, ad_padded)
    Auth = xor(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