#include #include #include "cipher.h" #include "constants.h" #include "parameters.h" #include "tweakey.h" enum permutation { PERMUTATION_ENCRYPTION = 0, PERMUTATION_DECRYPTION = 1, PERMUTATION_NONE }; typedef enum permutation permutation; const uint8_t PERMUTATIONS[2][BLOCK_BYTES] = { /* PI(i) */ [0] = { 13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6, 0, 7 }, /* PI^-1(i) */ [1] = { 14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7 } }; struct cipher_state { uint8_t X[BLOCK_BYTES]; }; typedef struct cipher_state cipher_state; static void _state_init(cipher_state *X, const uint8_t message[BLOCK_BYTES]) { memcpy(X->X, message, sizeof(X->X)); } static void _compute_round_tweakeys( const uint8_t key[KEY_BYTES], const uint8_t tweak[TWEAK_BYTES], uint8_t RTK[ROUNDS][ROUND_TWEAKEY_BYTES] ) { tweakey_state TK; tweakey_state_init(&TK, key, tweak); tweakey_state_extract(&TK, RTK[0], 0); for (uint8_t i=1; iX[j] ^ RTK[j]; } for (size_t j=0; jX[dest_j] ^= F[j]; } } static void _linear_layer(cipher_state *X) { X->X[15] ^= X->X[1]; X->X[15] ^= X->X[2]; X->X[15] ^= X->X[3]; X->X[15] ^= X->X[4]; X->X[15] ^= X->X[5]; X->X[15] ^= X->X[6]; X->X[15] ^= X->X[7]; X->X[14] ^= X->X[7]; X->X[13] ^= X->X[7]; X->X[12] ^= X->X[7]; X->X[11] ^= X->X[7]; X->X[10] ^= X->X[7]; X->X[9] ^= X->X[7]; } static void _permutation_layer(cipher_state *X, permutation p) { if (p == PERMUTATION_NONE) { return; } uint8_t X_old[BLOCK_BYTES]; memcpy(X_old, X, sizeof(X_old)); const uint8_t *pi = PERMUTATIONS[p]; for (size_t j=0; jX[pi[j]] = X_old[j]; } } static void _one_round_egfn(cipher_state *X, const uint8_t RTK[ROUND_TWEAKEY_BYTES], permutation p) { _nonlinear_layer(X, RTK); _linear_layer(X); _permutation_layer(X, p); } void lilliput_tbc_encrypt( const uint8_t key[KEY_BYTES], const uint8_t tweak[TWEAK_BYTES], const uint8_t message[BLOCK_BYTES], uint8_t ciphertext[BLOCK_BYTES] ) { cipher_state X; _state_init(&X, message); uint8_t RTK[ROUNDS][ROUND_TWEAKEY_BYTES]; _compute_round_tweakeys(key, tweak, RTK); for (uint8_t i=0; i