summaryrefslogtreecommitdiff
path: root/src/add_python/lilliput/ae_common.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/add_python/lilliput/ae_common.py')
-rw-r--r--src/add_python/lilliput/ae_common.py104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/add_python/lilliput/ae_common.py b/src/add_python/lilliput/ae_common.py
new file mode 100644
index 0000000..b94be1b
--- /dev/null
+++ b/src/add_python/lilliput/ae_common.py
@@ -0,0 +1,104 @@
+# 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/
+
+"""Helper functions used in both Lilliput-I and Lilliput-II."""
+
+
+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 integer_to_byte_array(i, n):
+ return list(i.to_bytes(n, 'little'))
+
+
+def _tweak_associated_data(t, i, padded):
+ tweak = integer_to_byte_array(i, t//8)
+
+ 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