lilliput-ii.c (5339B)
1 /* 2 Implementation of the Lilliput-AE tweakable block cipher. 3 4 Authors, hereby denoted as "the implementer": 5 Kévin Le Gouguec, 6 2019. 7 8 For more information, feedback or questions, refer to our website: 9 https://paclido.fr/lilliput-ae 10 11 To the extent possible under law, the implementer has waived all copyright 12 and related or neighboring rights to the source code in this file. 13 http://creativecommons.org/publicdomain/zero/1.0/ 14 15 --- 16 17 This file implements Lilliput-AE's nonce-misuse-resistant mode based on SCT-2. 18 */ 19 20 #include <stdbool.h> 21 #include <stdint.h> 22 #include <string.h> 23 24 #include "cipher.h" 25 #include "lilliput-ae.h" 26 #include "lilliput-ae-utils.h" 27 28 29 static void _init_msg_tweak(const uint8_t tag[TAG_BYTES], uint8_t tweak[TWEAK_BYTES]) 30 { 31 /* The t-bit tweak is filled as follows: 32 * 33 * 1 2 t 34 * [ 1 || tag[2,t] XOR block index ] 35 * 36 * The s-bit block index is XORed to the tag as follows: 37 * 38 * 2 t-s t-s+1 t 39 * [ tag[2, t-s] || tag[t-s+1, t] XOR block index, MSB first ] 40 * 41 * This function sets bits 1 to t-s once and for all. 42 */ 43 44 memcpy(tweak, tag, TAG_BYTES-sizeof(size_t)); 45 tweak[0] |= 0x80; 46 } 47 48 static void _fill_msg_tweak(const uint8_t tag[TAG_BYTES], size_t block_index, uint8_t tweak[TWEAK_BYTES]) 49 { 50 /* The t-bit tweak is filled as follows: 51 * 52 * 1 2 t 53 * [ 1 || tag[2,t] XOR block index ] 54 * 55 * The s-bit block index is XORed to the tag as follows: 56 * 57 * 2 t-s t-s+1 t 58 * [ tag[2, t-s] || tag[t-s+1, t] XOR block index, MSB first ] 59 * 60 * This function assumes bits 1 to t-s have already been set, and 61 * only sets bits t-s+1 to t. 62 */ 63 64 copy_block_index(block_index, tweak); 65 66 for (size_t i=TWEAK_BYTES-sizeof(size_t); i<TWEAK_BYTES; i++) 67 { 68 tweak[i] ^= tag[i]; 69 } 70 } 71 72 static void _fill_tag_tweak(const uint8_t N[NONCE_BYTES], uint8_t tweak[TWEAK_BYTES]) 73 { 74 /* The t-bit tweak is filled as follows: 75 * 76 * 1 4 5 8 t-|N|+1 t 77 * [ 0001 || 0^4 || nonce ] 78 */ 79 80 tweak[0] = 0x10; 81 memcpy(&tweak[1], N, TWEAK_BYTES-1); 82 } 83 84 static void _generate_tag( 85 const uint8_t key[KEY_BYTES], 86 size_t M_len, 87 const uint8_t M[M_len], 88 const uint8_t N[NONCE_BYTES], 89 const uint8_t Auth[BLOCK_BYTES], 90 uint8_t tag[TAG_BYTES] 91 ) 92 { 93 uint8_t Ek_Mj[BLOCK_BYTES]; 94 uint8_t tag_tmp[TAG_BYTES]; 95 uint8_t tweak[TWEAK_BYTES]; 96 97 memset(tweak, 0, TWEAK_BYTES); 98 memcpy(tag_tmp, Auth, TAG_BYTES); 99 100 size_t l = M_len / BLOCK_BYTES; 101 size_t rest = M_len % BLOCK_BYTES; 102 103 for (size_t j=0; j<l; j++) 104 { 105 fill_index_tweak(0x0, j, tweak); 106 encrypt(key, tweak, &M[j*BLOCK_BYTES], Ek_Mj); 107 xor_into(tag_tmp, Ek_Mj); 108 } 109 110 if (rest != 0) 111 { 112 uint8_t M_rest[BLOCK_BYTES]; 113 pad10(rest, &M[l*BLOCK_BYTES], M_rest); 114 fill_index_tweak(0x4, l, tweak); 115 encrypt(key, tweak, M_rest, Ek_Mj); 116 xor_into(tag_tmp, Ek_Mj); 117 } 118 119 _fill_tag_tweak(N, tweak); 120 encrypt(key, tweak, tag_tmp, tag); 121 } 122 123 static void _encrypt_message( 124 const uint8_t key[KEY_BYTES], 125 size_t M_len, 126 const uint8_t M[M_len], 127 const uint8_t N[NONCE_BYTES], 128 const uint8_t tag[TAG_BYTES], 129 uint8_t C[M_len] 130 ) 131 { 132 uint8_t Ek_N[BLOCK_BYTES]; 133 134 uint8_t tweak[TWEAK_BYTES]; 135 _init_msg_tweak(tag, tweak); 136 137 uint8_t padded_N[BLOCK_BYTES]; 138 padded_N[0] = 0; 139 memcpy(&padded_N[1], N, NONCE_BYTES); 140 141 size_t l = M_len / BLOCK_BYTES; 142 size_t rest = M_len % BLOCK_BYTES; 143 144 for (size_t j=0; j<l; j++) 145 { 146 _fill_msg_tweak(tag, j, tweak); 147 encrypt(key, tweak, padded_N, Ek_N); 148 xor_arrays(BLOCK_BYTES, &C[j*BLOCK_BYTES], &M[j*BLOCK_BYTES], Ek_N); 149 } 150 151 if (rest != 0) 152 { 153 _fill_msg_tweak(tag, l, tweak); 154 encrypt(key, tweak, padded_N, Ek_N); 155 xor_arrays(rest, &C[l*BLOCK_BYTES], &M[l*BLOCK_BYTES], Ek_N); 156 } 157 } 158 159 void lilliput_ae_encrypt( 160 size_t message_len, 161 const uint8_t message[message_len], 162 size_t auth_data_len, 163 const uint8_t auth_data[auth_data_len], 164 const uint8_t key[KEY_BYTES], 165 const uint8_t nonce[NONCE_BYTES], 166 uint8_t ciphertext[message_len], 167 uint8_t tag[TAG_BYTES] 168 ) 169 { 170 uint8_t auth[BLOCK_BYTES]; 171 process_associated_data(key, auth_data_len, auth_data, auth); 172 173 _generate_tag(key, message_len, message, nonce, auth, tag); 174 175 _encrypt_message(key, message_len, message, nonce, tag, ciphertext); 176 } 177 178 bool lilliput_ae_decrypt( 179 size_t ciphertext_len, 180 const uint8_t ciphertext[ciphertext_len], 181 size_t auth_data_len, 182 const uint8_t auth_data[auth_data_len], 183 const uint8_t key[KEY_BYTES], 184 const uint8_t nonce[NONCE_BYTES], 185 const uint8_t tag[TAG_BYTES], 186 uint8_t message[ciphertext_len] 187 ) 188 { 189 _encrypt_message(key, ciphertext_len, ciphertext, nonce, tag, message); 190 191 uint8_t auth[BLOCK_BYTES]; 192 process_associated_data(key, auth_data_len, auth_data, auth); 193 194 uint8_t effective_tag[TAG_BYTES]; 195 _generate_tag(key, ciphertext_len, message, nonce, auth, effective_tag); 196 197 return memcmp(tag, effective_tag, TAG_BYTES) == 0; 198 }