/* Implementation of the Lilliput-AE tweakable block cipher. Authors, hereby denoted as "the implementer": Kévin Le Gouguec, 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/ --- This file implements Lilliput-AE's nonce-misuse-resistant mode based on SCT-2. */ #include #include #include #include "cipher.h" #include "lilliput-ae.h" #include "lilliput-ae-utils.h" static void _init_msg_tweak(const uint8_t tag[TAG_BYTES], uint8_t tweak[TWEAK_BYTES]) { /* The t-bit tweak is filled as follows: * * - bits [ 1, t-1]: tag + block index * [ 1, 64]: tag[ 1.. 64] XOR block index * [ 65, t-1]: tag[65..t-1] * - bit t: 1 * * This function sets bits 65 to t once and for all. */ memcpy(tweak+sizeof(uint64_t), tag+sizeof(uint64_t), TAG_BYTES-sizeof(uint64_t)); tweak[TWEAK_BYTES-1] |= 0x80; } static void _fill_msg_tweak(const uint8_t tag[TAG_BYTES], uint64_t block_index, uint8_t tweak[TWEAK_BYTES]) { /* The t-bit tweak is filled as follows: * * - bits [ 1, t-1]: tag + block index * [ 1, 64]: tag[ 1.. 64] XOR block index * [ 65, t-1]: tag[65..t-1] * - bit t: 1 * * This function assumes bits 65 to t have already been set, and * only sets bits 1 to 64. */ for (size_t i=0; i> i*8 & 0xff; tweak[i] = tag[i] ^ index_i; } } static void _fill_tag_tweak(const uint8_t N[NONCE_BYTES], uint8_t tweak[TWEAK_BYTES]) { /* The t-bit tweak is filled as follows: * * - bits [ 1, t-7]: N * - bits [t-7, t]: 0001||0^4 */ memcpy(tweak, N, TWEAK_BYTES-1); tweak[TWEAK_BYTES-1] = 0x10; } static void _generate_tag( const uint8_t key[KEY_BYTES], size_t M_len, const uint8_t M[M_len], const uint8_t N[NONCE_BYTES], const uint8_t Auth[BLOCK_BYTES], uint8_t tag[TAG_BYTES] ) { uint8_t Ek_Mj[BLOCK_BYTES]; uint8_t tag_tmp[TAG_BYTES]; uint8_t tweak[TWEAK_BYTES]; memset(tweak, 0, TWEAK_BYTES); memcpy(tag_tmp, Auth, TAG_BYTES); size_t l = M_len / BLOCK_BYTES; size_t rest = M_len % BLOCK_BYTES; for (size_t j=0; j