lilliput-ae-utils.h 3.63 KB
Newer Older
lwc-tester committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
/*
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 provides functions used by both authenticated encryption modes.
*/

#ifndef LILLIPUT_AE_UTILS_H
#define LILLIPUT_AE_UTILS_H

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include "cipher.h"
#include "constants.h"


static inline uint8_t upper_nibble(uint8_t i)
{
    return i >> 4;
}

static inline uint8_t lower_nibble(uint8_t i)
{
    return i & 0x0f;
}

static inline void encrypt(const uint8_t K[KEY_BYTES],
                           const uint8_t T[TWEAK_BYTES],
                           const uint8_t M[BLOCK_BYTES],
                           uint8_t C[BLOCK_BYTES])
{
    lilliput_tbc_encrypt(K, T, M, C);
}

static inline void decrypt(const uint8_t K[KEY_BYTES],
                           const uint8_t T[TWEAK_BYTES],
                           const uint8_t C[BLOCK_BYTES],
                           uint8_t M[BLOCK_BYTES])
{
    lilliput_tbc_decrypt(K, T, C, M);
}

static inline void xor_into(uint8_t dest[BLOCK_BYTES], const uint8_t src[BLOCK_BYTES])
{
    for (size_t i=0; i<BLOCK_BYTES; i++)
        dest[i] ^= src[i];
}

static inline void xor_arrays(size_t len, uint8_t out[len], const uint8_t a[len], const uint8_t b[len])
{
    for (size_t i=0; i<len; i++)
        out[i] = a[i] ^ b[i];
}

static inline void pad10(size_t X_len, const uint8_t X[X_len], uint8_t padded[BLOCK_BYTES])
{
    /* pad10*(X) = X || 1 || 0^{n-|X|-1} */

    /* For example, with uint8_t X[3] = { [0]=0x01, [1]=0x02, [2]=0x03 }
     *
     * pad10*(X) =
     *       X[2]     X[1]     X[0]   1 0*
     *     00000011 00000010 00000001 1 0000000 00000000...
     *
     * - padded[0, 11]:  zeroes
     * - padded[12]:     10000000
     * - padded[13, 15]: X[0, 2]
     */

    /* Assume that X_len<BLOCK_BYTES. */

    size_t pad_len = BLOCK_BYTES-X_len;

    memset(padded, 0, pad_len-1);
    padded[pad_len-1] = 0x80;
    memcpy(padded+pad_len, X, X_len);
}

static inline void fill_index_tweak(
    uint8_t  prefix,
    uint64_t block_index,
    uint8_t  tweak[TWEAK_BYTES]
)
{
    /* The t-bit tweak is filled as follows:
     *
     * - bits [  1, t-4]: block index
     *        [  1,  64]: actual 64-bit block index
     *        [ 65, t-4]: 0-padding
     * - bits [t-3,   t]: constant 4-bit prefix
     */

    for (size_t i=0; i<sizeof(block_index); i++)
    {
        tweak[i] = block_index >> 8*i & 0xff;
    }

    /* Assume padding bytes have already been set to 0. */

    tweak[TWEAK_BYTES-1] |= prefix << 4;
}

static void process_associated_data(
    const uint8_t key[KEY_BYTES],
    size_t        A_len,
    const uint8_t A[A_len],
    uint8_t       Auth[BLOCK_BYTES]
)
{
    uint8_t Ek_Ai[BLOCK_BYTES];
    uint8_t tweak[TWEAK_BYTES];

    memset(tweak, 0, TWEAK_BYTES);
    memset(Auth, 0, BLOCK_BYTES);

    size_t l_a = A_len / BLOCK_BYTES;
    size_t rest = A_len % BLOCK_BYTES;

    for (size_t i=0; i<l_a; i++)
    {
        fill_index_tweak(0x2, i, tweak);
        encrypt(key, tweak, &A[i*BLOCK_BYTES], Ek_Ai);
        xor_into(Auth, Ek_Ai);
    }

    if (rest != 0)
    {
        uint8_t A_rest[BLOCK_BYTES];
        pad10(rest, &A[l_a*BLOCK_BYTES], A_rest);
        fill_index_tweak(0x6, l_a, tweak);
        encrypt(key, tweak, A_rest, Ek_Ai);
        xor_into(Auth, Ek_Ai);
    }
}


#endif /* LILLIPUT_AE_UTILS_H */