lilliput-ae-reference-implementation

Implementations of Lilliput-AE submitted to the NIST LWC standardization process
git clone https://git.kevinlegouguec.net/lilliput-ae-reference-implementation
Log | Files | Refs | README

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 */