lilliput-ae-utils.h (3900B)
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 provides functions used by both authenticated encryption modes. 18 */ 19 20 #ifndef LILLIPUT_AE_UTILS_H 21 #define LILLIPUT_AE_UTILS_H 22 23 #include <stddef.h> 24 #include <stdint.h> 25 #include <string.h> 26 27 #include "cipher.h" 28 #include "constants.h" 29 30 31 static inline void encrypt(const uint8_t K[KEY_BYTES], 32 const uint8_t T[TWEAK_BYTES], 33 const uint8_t M[BLOCK_BYTES], 34 uint8_t C[BLOCK_BYTES]) 35 { 36 lilliput_tbc_encrypt(K, T, M, C); 37 } 38 39 static inline void decrypt(const uint8_t K[KEY_BYTES], 40 const uint8_t T[TWEAK_BYTES], 41 const uint8_t C[BLOCK_BYTES], 42 uint8_t M[BLOCK_BYTES]) 43 { 44 lilliput_tbc_decrypt(K, T, C, M); 45 } 46 47 static inline void xor_into(uint8_t dest[BLOCK_BYTES], const uint8_t src[BLOCK_BYTES]) 48 { 49 for (size_t i=0; i<BLOCK_BYTES; i++) 50 dest[i] ^= src[i]; 51 } 52 53 static inline void xor_arrays(size_t len, uint8_t out[len], const uint8_t a[len], const uint8_t b[len]) 54 { 55 for (size_t i=0; i<len; i++) 56 out[i] = a[i] ^ b[i]; 57 } 58 59 static inline void pad10(size_t X_len, const uint8_t X[X_len], uint8_t padded[BLOCK_BYTES]) 60 { 61 /* Assuming 0 < |X| < n: 62 * 63 * pad10*(X) = X || 1 || 0^{n-|X|-1} 64 * 65 * For example, with uint8_t X[3] = { [0]=0x01, [1]=0x02, [2]=0x03 } 66 * 67 * pad10*(X) = 68 * X[0] X[1] X[2] 1 0* 69 * 00000001 00000010 00000011 1 0000000 00000000... 70 * 71 * - padded[0, 2]: X[0, 2] 72 * - padded[3]: 10000000 73 * - padded[4, 15]: zeroes 74 */ 75 76 memcpy(padded, X, X_len); 77 padded[X_len] = 0x80; 78 79 /* memset(&padded[BLOCK_BYTES], 0, 0) may or may not constitute 80 * undefined behaviour; use a straight loop instead. */ 81 82 for (size_t i=X_len+1; i<BLOCK_BYTES; i++) 83 { 84 padded[i] = 0; 85 } 86 } 87 88 static inline void copy_block_index(size_t index, uint8_t tweak[TWEAK_BYTES]) 89 { 90 size_t s = sizeof(index); 91 uint8_t *dest = &tweak[TWEAK_BYTES-s]; 92 93 for (size_t i=0; i<s; i++) 94 { 95 dest[i] = index >> 8*(s-1-i); 96 } 97 } 98 99 static inline void fill_index_tweak( 100 uint8_t prefix, 101 size_t block_index, 102 uint8_t tweak[TWEAK_BYTES] 103 ) 104 { 105 /* The t-bit tweak is filled as follows: 106 * 107 * 1 4 5 t 108 * [ prefix || block index ] 109 * 110 * The s-bit block index is encoded as follows: 111 * 112 * 5 t-s t-s+1 t 113 * [ zero padding || block index, MSB first ] 114 */ 115 116 tweak[0] = prefix<<4; 117 118 /* Assume padding bytes have already been set to 0. */ 119 120 copy_block_index(block_index, tweak); 121 } 122 123 static void process_associated_data( 124 const uint8_t key[KEY_BYTES], 125 size_t A_len, 126 const uint8_t A[A_len], 127 uint8_t Auth[BLOCK_BYTES] 128 ) 129 { 130 uint8_t Ek_Ai[BLOCK_BYTES]; 131 uint8_t tweak[TWEAK_BYTES]; 132 133 memset(tweak, 0, TWEAK_BYTES); 134 memset(Auth, 0, BLOCK_BYTES); 135 136 size_t l_a = A_len / BLOCK_BYTES; 137 size_t rest = A_len % BLOCK_BYTES; 138 139 for (size_t i=0; i<l_a; i++) 140 { 141 fill_index_tweak(0x2, i, tweak); 142 encrypt(key, tweak, &A[i*BLOCK_BYTES], Ek_Ai); 143 xor_into(Auth, Ek_Ai); 144 } 145 146 if (rest != 0) 147 { 148 uint8_t A_rest[BLOCK_BYTES]; 149 pad10(rest, &A[l_a*BLOCK_BYTES], A_rest); 150 fill_index_tweak(0x6, l_a, tweak); 151 encrypt(key, tweak, A_rest, Ek_Ai); 152 xor_into(Auth, Ek_Ai); 153 } 154 } 155 156 157 #endif /* LILLIPUT_AE_UTILS_H */