internal-forkskinny.c 28.7 KB
Newer Older
Arne Deprez 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
/*
 * Copyright (C) 2020 Southern Storm Software, Pty Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "internal-forkskinny.h"
#include "internal-skinnyutil.h"

/**
 * \brief 7-bit round constants for all ForkSkinny block ciphers.
 */
Arne Deprez committed
29 30 31 32 33 34 35 36 37 38 39 40 41
static unsigned char const RC[87] = {
    0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7e, 0x7d,
    0x7b, 0x77, 0x6f, 0x5f, 0x3e, 0x7c, 0x79, 0x73,
    0x67, 0x4f, 0x1e, 0x3d, 0x7a, 0x75, 0x6b, 0x57,
    0x2e, 0x5c, 0x38, 0x70, 0x61, 0x43, 0x06, 0x0d,
    0x1b, 0x37, 0x6e, 0x5d, 0x3a, 0x74, 0x69, 0x53,
    0x26, 0x4c, 0x18, 0x31, 0x62, 0x45, 0x0a, 0x15,
    0x2b, 0x56, 0x2c, 0x58, 0x30, 0x60, 0x41, 0x02,
    0x05, 0x0b, 0x17, 0x2f, 0x5e, 0x3c, 0x78, 0x71,
    0x63, 0x47, 0x0e, 0x1d, 0x3b, 0x76, 0x6d, 0x5b,
    0x36, 0x6c, 0x59, 0x32, 0x64, 0x49, 0x12, 0x25,
    0x4a, 0x14, 0x29, 0x52, 0x24, 0x48, 0x10
};
Arne Deprez committed
42 43 44 45 46 47 48 49

static const uint32_t T[256] = {0x65656565, 0x4c4c4c4c, 0x6a6a6a6a, 0x42424242, 0x4b4b4b4b, 0x63636363, 0x43434343, 0x6b6b6b6b, 0x55555555, 0x75757575, 0x5a5a5a5a, 0x7a7a7a7a, 0x53535353, 0x73737373, 0x5b5b5b5b, 0x7b7b7b7b, 0x35353535, 0x8c8c8c8c, 0x3a3a3a3a, 0x81818181, 0x89898989, 0x33333333, 0x80808080, 0x3b3b3b3b, 0x95959595, 0x25252525, 0x98989898, 0x2a2a2a2a, 0x90909090, 0x23232323, 0x99999999, 0x2b2b2b2b, 0xe5e5e5e5, 0xcccccccc, 0xe8e8e8e8, 0xc1c1c1c1, 0xc9c9c9c9, 0xe0e0e0e0, 0xc0c0c0c0, 0xe9e9e9e9, 0xd5d5d5d5, 0xf5f5f5f5, 0xd8d8d8d8, 0xf8f8f8f8, 0xd0d0d0d0, 0xf0f0f0f0, 0xd9d9d9d9, 0xf9f9f9f9, 0xa5a5a5a5, 0x1c1c1c1c, 0xa8a8a8a8, 0x12121212, 0x1b1b1b1b, 0xa0a0a0a0, 0x13131313, 0xa9a9a9a9, 0x05050505, 0xb5b5b5b5, 0x0a0a0a0a, 0xb8b8b8b8, 0x03030303, 0xb0b0b0b0, 0x0b0b0b0b, 0xb9b9b9b9, 0x32323232, 0x88888888, 0x3c3c3c3c, 0x85858585, 0x8d8d8d8d, 0x34343434, 0x84848484, 0x3d3d3d3d, 0x91919191, 0x22222222, 0x9c9c9c9c, 0x2c2c2c2c, 0x94949494, 0x24242424, 0x9d9d9d9d, 0x2d2d2d2d, 0x62626262, 0x4a4a4a4a, 0x6c6c6c6c, 0x45454545, 0x4d4d4d4d, 0x64646464, 0x44444444, 0x6d6d6d6d, 0x52525252, 0x72727272, 0x5c5c5c5c, 0x7c7c7c7c, 0x54545454, 0x74747474, 0x5d5d5d5d, 0x7d7d7d7d, 0xa1a1a1a1, 0x1a1a1a1a, 0xacacacac, 0x15151515, 0x1d1d1d1d, 0xa4a4a4a4, 0x14141414, 0xadadadad, 0x02020202, 0xb1b1b1b1, 0x0c0c0c0c, 0xbcbcbcbc, 0x04040404, 0xb4b4b4b4, 0x0d0d0d0d, 0xbdbdbdbd, 0xe1e1e1e1, 0xc8c8c8c8, 0xecececec, 0xc5c5c5c5, 0xcdcdcdcd, 0xe4e4e4e4, 0xc4c4c4c4, 0xedededed, 0xd1d1d1d1, 0xf1f1f1f1, 0xdcdcdcdc, 0xfcfcfcfc, 0xd4d4d4d4, 0xf4f4f4f4, 0xdddddddd, 0xfdfdfdfd, 0x36363636, 0x8e8e8e8e, 0x38383838, 0x82828282, 0x8b8b8b8b, 0x30303030, 0x83838383, 0x39393939, 0x96969696, 0x26262626, 0x9a9a9a9a, 0x28282828, 0x93939393, 0x20202020, 0x9b9b9b9b, 0x29292929, 0x66666666, 0x4e4e4e4e, 0x68686868, 0x41414141, 0x49494949, 0x60606060, 0x40404040, 0x69696969, 0x56565656, 0x76767676, 0x58585858, 0x78787878, 0x50505050, 0x70707070, 0x59595959, 0x79797979, 0xa6a6a6a6, 0x1e1e1e1e, 0xaaaaaaaa, 0x11111111, 0x19191919, 0xa3a3a3a3, 0x10101010, 0xabababab, 0x06060606, 0xb6b6b6b6, 0x08080808, 0xbabababa, 0x00000000, 0xb3b3b3b3, 0x09090909, 0xbbbbbbbb, 0xe6e6e6e6, 0xcececece, 0xeaeaeaea, 0xc2c2c2c2, 0xcbcbcbcb, 0xe3e3e3e3, 0xc3c3c3c3, 0xebebebeb, 0xd6d6d6d6, 0xf6f6f6f6, 0xdadadada, 0xfafafafa, 0xd3d3d3d3, 0xf3f3f3f3, 0xdbdbdbdb, 0xfbfbfbfb, 0x31313131, 0x8a8a8a8a, 0x3e3e3e3e, 0x86868686, 0x8f8f8f8f, 0x37373737, 0x87878787, 0x3f3f3f3f, 0x92929292, 0x21212121, 0x9e9e9e9e, 0x2e2e2e2e, 0x97979797, 0x27272727, 0x9f9f9f9f, 0x2f2f2f2f, 0x61616161, 0x48484848, 0x6e6e6e6e, 0x46464646, 0x4f4f4f4f, 0x67676767, 0x47474747, 0x6f6f6f6f, 0x51515151, 0x71717171, 0x5e5e5e5e, 0x7e7e7e7e, 0x57575757, 0x77777777, 0x5f5f5f5f, 0x7f7f7f7f, 0xa2a2a2a2, 0x18181818, 0xaeaeaeae, 0x16161616, 0x1f1f1f1f, 0xa7a7a7a7, 0x17171717, 0xafafafaf, 0x01010101, 0xb2b2b2b2, 0x0e0e0e0e, 0xbebebebe, 0x07070707, 0xb7b7b7b7, 0x0f0f0f0f, 0xbfbfbfbf, 0xe2e2e2e2, 0xcacacaca, 0xeeeeeeee, 0xc6c6c6c6, 0xcfcfcfcf, 0xe7e7e7e7, 0xc7c7c7c7, 0xefefefef, 0xd2d2d2d2, 0xf2f2f2f2, 0xdededede, 0xfefefefe, 0xd7d7d7d7, 0xf7f7f7f7, 0xdfdfdfdf, 0xffffffff};
static const uint32_t T_inv[256] = {0xacacacac, 0xe8e8e8e8, 0x68686868, 0x3c3c3c3c, 0x6c6c6c6c, 0x38383838, 0xa8a8a8a8, 0xecececec, 0xaaaaaaaa, 0xaeaeaeae, 0x3a3a3a3a, 0x3e3e3e3e, 0x6a6a6a6a, 0x6e6e6e6e, 0xeaeaeaea, 0xeeeeeeee, 0xa6a6a6a6, 0xa3a3a3a3, 0x33333333, 0x36363636, 0x66666666, 0x63636363, 0xe3e3e3e3, 0xe6e6e6e6, 0xe1e1e1e1, 0xa4a4a4a4, 0x61616161, 0x34343434, 0x31313131, 0x64646464, 0xa1a1a1a1, 0xe4e4e4e4, 0x8d8d8d8d, 0xc9c9c9c9, 0x49494949, 0x1d1d1d1d, 0x4d4d4d4d, 0x19191919, 0x89898989, 0xcdcdcdcd, 0x8b8b8b8b, 0x8f8f8f8f, 0x1b1b1b1b, 0x1f1f1f1f, 0x4b4b4b4b, 0x4f4f4f4f, 0xcbcbcbcb, 0xcfcfcfcf, 0x85858585, 0xc0c0c0c0, 0x40404040, 0x15151515, 0x45454545, 0x10101010, 0x80808080, 0xc5c5c5c5, 0x82828282, 0x87878787, 0x12121212, 0x17171717, 0x42424242, 0x47474747, 0xc2c2c2c2, 0xc7c7c7c7, 0x96969696, 0x93939393, 0x03030303, 0x06060606, 0x56565656, 0x53535353, 0xd3d3d3d3, 0xd6d6d6d6, 0xd1d1d1d1, 0x94949494, 0x51515151, 0x04040404, 0x01010101, 0x54545454, 0x91919191, 0xd4d4d4d4, 0x9c9c9c9c, 0xd8d8d8d8, 0x58585858, 0x0c0c0c0c, 0x5c5c5c5c, 0x08080808, 0x98989898, 0xdcdcdcdc, 0x9a9a9a9a, 0x9e9e9e9e, 0x0a0a0a0a, 0x0e0e0e0e, 0x5a5a5a5a, 0x5e5e5e5e, 0xdadadada, 0xdededede, 0x95959595, 0xd0d0d0d0, 0x50505050, 0x05050505, 0x55555555, 0x00000000, 0x90909090, 0xd5d5d5d5, 0x92929292, 0x97979797, 0x02020202, 0x07070707, 0x52525252, 0x57575757, 0xd2d2d2d2, 0xd7d7d7d7, 0x9d9d9d9d, 0xd9d9d9d9, 0x59595959, 0x0d0d0d0d, 0x5d5d5d5d, 0x09090909, 0x99999999, 0xdddddddd, 0x9b9b9b9b, 0x9f9f9f9f, 0x0b0b0b0b, 0x0f0f0f0f, 0x5b5b5b5b, 0x5f5f5f5f, 0xdbdbdbdb, 0xdfdfdfdf, 0x16161616, 0x13131313, 0x83838383, 0x86868686, 0x46464646, 0x43434343, 0xc3c3c3c3, 0xc6c6c6c6, 0x41414141, 0x14141414, 0xc1c1c1c1, 0x84848484, 0x11111111, 0x44444444, 0x81818181, 0xc4c4c4c4, 0x1c1c1c1c, 0x48484848, 0xc8c8c8c8, 0x8c8c8c8c, 0x4c4c4c4c, 0x18181818, 0x88888888, 0xcccccccc, 0x1a1a1a1a, 0x1e1e1e1e, 0x8a8a8a8a, 0x8e8e8e8e, 0x4a4a4a4a, 0x4e4e4e4e, 0xcacacaca, 0xcececece, 0x35353535, 0x60606060, 0xe0e0e0e0, 0xa5a5a5a5, 0x65656565, 0x30303030, 0xa0a0a0a0, 0xe5e5e5e5, 0x32323232, 0x37373737, 0xa2a2a2a2, 0xa7a7a7a7, 0x62626262, 0x67676767, 0xe2e2e2e2, 0xe7e7e7e7, 0x3d3d3d3d, 0x69696969, 0xe9e9e9e9, 0xadadadad, 0x6d6d6d6d, 0x39393939, 0xa9a9a9a9, 0xedededed, 0x3b3b3b3b, 0x3f3f3f3f, 0xabababab, 0xafafafaf, 0x6b6b6b6b, 0x6f6f6f6f, 0xebebebeb, 0xefefefef, 0x26262626, 0x23232323, 0xb3b3b3b3, 0xb6b6b6b6, 0x76767676, 0x73737373, 0xf3f3f3f3, 0xf6f6f6f6, 0x71717171, 0x24242424, 0xf1f1f1f1, 0xb4b4b4b4, 0x21212121, 0x74747474, 0xb1b1b1b1, 0xf4f4f4f4, 0x2c2c2c2c, 0x78787878, 0xf8f8f8f8, 0xbcbcbcbc, 0x7c7c7c7c, 0x28282828, 0xb8b8b8b8, 0xfcfcfcfc, 0x2a2a2a2a, 0x2e2e2e2e, 0xbabababa, 0xbebebebe, 0x7a7a7a7a, 0x7e7e7e7e, 0xfafafafa, 0xfefefefe, 0x25252525, 0x70707070, 0xf0f0f0f0, 0xb5b5b5b5, 0x75757575, 0x20202020, 0xb0b0b0b0, 0xf5f5f5f5, 0x22222222, 0x27272727, 0xb2b2b2b2, 0xb7b7b7b7, 0x72727272, 0x77777777, 0xf2f2f2f2, 0xf7f7f7f7, 0x2d2d2d2d, 0x79797979, 0xf9f9f9f9, 0xbdbdbdbd, 0x7d7d7d7d, 0x29292929, 0xb9b9b9b9, 0xfdfdfdfd, 0x2b2b2b2b, 0x2f2f2f2f, 0xbbbbbbbb, 0xbfbfbfbf, 0x7b7b7b7b, 0x7f7f7f7f, 0xfbfbfbfb, 0xffffffff};

static const uint32_t AC_column0[87] = {0x1000101, 0x3000303, 0x7000707, 0xf000f0f, 0xf000f0f, 0xf000f0f, 0xe000e0e, 0xd000d0d, 0xb000b0b, 0x7000707, 0xf000f0f, 0xf000f0f, 0xe000e0e, 0xc000c0c, 0x9000909, 0x3000303, 0x7000707, 0xf000f0f, 0xe000e0e, 0xd000d0d, 0xa000a0a, 0x5000505, 0xb000b0b, 0x7000707, 0xe000e0e, 0xc000c0c, 0x8000808, 0x0, 0x1000101, 0x3000303, 0x6000606, 0xd000d0d, 0xb000b0b, 0x7000707, 0xe000e0e, 0xd000d0d, 0xa000a0a, 0x4000404, 0x9000909, 0x3000303, 0x6000606, 0xc000c0c, 0x8000808, 0x1000101, 0x2000202, 0x5000505, 0xa000a0a, 0x5000505, 0xb000b0b, 0x6000606, 0xc000c0c, 0x8000808, 0x0, 0x0, 0x1000101, 0x2000202, 0x5000505, 0xb000b0b, 0x7000707, 0xf000f0f, 0xe000e0e, 0xc000c0c, 0x8000808, 0x1000101, 0x3000303, 0x7000707, 0xe000e0e, 0xd000d0d, 0xb000b0b, 0x6000606, 0xd000d0d, 0xb000b0b, 0x6000606, 0xc000c0c, 0x9000909, 0x2000202, 0x4000404, 0x9000909, 0x2000202, 0x5000505, 0xa000a0a, 0x4000404, 0x9000909, 0x2000202, 0x4000404, 0x8000808, 0x0};
static const uint32_t AC_column1[87] = {0x0, 0x0, 0x0, 0x0, 0x10000, 0x30000, 0x70000, 0x70000, 0x70000, 0x70000, 0x60000, 0x50000, 0x30000, 0x70000, 0x70000, 0x70000, 0x60000, 0x40000, 0x10000, 0x30000, 0x70000, 0x70000, 0x60000, 0x50000, 0x20000, 0x50000, 0x30000, 0x70000, 0x60000, 0x40000, 0x0, 0x0, 0x10000, 0x30000, 0x60000, 0x50000, 0x30000, 0x70000, 0x60000, 0x50000, 0x20000, 0x40000, 0x10000, 0x30000, 0x60000, 0x40000, 0x0, 0x10000, 0x20000, 0x50000, 0x20000, 0x50000, 0x30000, 0x60000, 0x40000, 0x0, 0x0, 0x0, 0x10000, 0x20000, 0x50000, 0x30000, 0x70000, 0x70000, 0x60000, 0x40000, 0x0, 0x10000, 0x30000, 0x70000, 0x60000, 0x50000, 0x30000, 0x60000, 0x50000, 0x30000, 0x60000, 0x40000, 0x10000, 0x20000, 0x40000, 0x10000, 0x20000, 0x50000, 0x20000, 0x40000, 0x10000};


Arne Deprez committed
50
#if !defined(__AVR__)
Arne Deprez committed
51

Arne Deprez committed
52 53
void forkskinny_128_256_rounds
    (forkskinny_128_256_state_t *state, unsigned first, unsigned last)
Arne Deprez committed
54
{
Arne Deprez committed
55
    uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
Arne Deprez committed
56 57 58 59 60 61 62 63
    uint32_t tk_columns[4];

    /* Load the state into local variables */
    s0 = state->S[0];
    s1 = state->S[1];
    s2 = state->S[2];
    s3 = state->S[3];

Arne Deprez committed
64 65
    /* Perform all requested rounds */
    for (; first < last; ++first) {
Arne Deprez committed
66

Arne Deprez committed
67
        TK_to_column_256(tk_columns, state);
Arne Deprez committed
68

Arne Deprez committed
69 70 71 72
        t0 = (T[s0 & 0xff]&0xff00ffff) ^ (T[(s3>>8) & 0xff]&0x00ff0000) ^ (T[(s2>>16) & 0xff]&0xffff00ff) ^ (T[(s1>>24)]&0xff) ^ tk_columns[0] ^ AC_column0[first];
        t1 = (T[s1 & 0xff]&0xff00ffff) ^ (T[(s0>>8) & 0xff]&0x00ff0000) ^ (T[(s3>>16) & 0xff]&0xffff00ff) ^ (T[(s2>>24)]&0xff) ^ tk_columns[1] ^ AC_column1[first];
        t2 = (T[s2 & 0xff]&0xff00ffff) ^ (T[(s1>>8) & 0xff]&0x00ff0000) ^ (T[(s0>>16) & 0xff]&0xffff00ff) ^ (T[(s3>>24)]&0xff) ^ tk_columns[2] ^ 0x00020200;
        t3 = (T[s3 & 0xff]&0xff00ffff) ^ (T[(s2>>8) & 0xff]&0x00ff0000) ^ (T[(s1>>16) & 0xff]&0xffff00ff) ^ (T[(s0>>24)]&0xff) ^ tk_columns[3];
Arne Deprez committed
73

Arne Deprez committed
74 75 76 77 78
        /* Permute TK1 and TK2 for the next round */
        skinny128_permute_tk(state->TK1);
        skinny128_permute_tk(state->TK2);
        skinny128_LFSR2(state->TK2[0]);
        skinny128_LFSR2(state->TK2[1]);
Arne Deprez committed
79

Arne Deprez committed
80
        s0 = t0; s1 = t1; s2 = t2; s3 = t3;
Arne Deprez committed
81 82
    }

Arne Deprez committed
83 84 85 86 87
    /* Save the local variables back to the state */
    state->S[0] = s0;
    state->S[1] = s1;
    state->S[2] = s2;
    state->S[3] = s3;
Arne Deprez committed
88 89
}

Arne Deprez committed
90 91 92 93 94
void forkskinny_128_256_inv_rounds
    (forkskinny_128_256_state_t *state, unsigned first, unsigned last)
{
    uint32_t s0, s1, s2, s3, t0, t1, t2, t3, tk0, tk1;
    uint8_t rc;
Arne Deprez committed
95 96

    /* Load the state into local variables */
Arne Deprez committed
97 98 99 100 101 102
    t0 = state->S[0];
    t1 = state->S[1];
    t2 = state->S[2];
    t3 = state->S[3];

    // FIRST ROUND
Arne Deprez committed
103 104 105 106 107 108 109 110

    /* Permute TK1 and TK2 for the next round */
    skinny128_inv_LFSR2(state->TK2[0]);
    skinny128_inv_LFSR2(state->TK2[1]);
    skinny128_inv_permute_tk(state->TK1);
    skinny128_inv_permute_tk(state->TK2);

    /* Inverse mix of the columns */
Arne Deprez committed
111 112 113 114 115 116 117
    s0 = t0;
    t0 = t1;
    t1 = t2;
    t2 = t3;
    t3 = s0 ^ t2;
    t2 ^= t0;
    t1 ^= t2;
Arne Deprez committed
118 119

    /* XOR the shifted round constant and the shifted subkey for this round */
Arne Deprez committed
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
    rc = RC[--first];
    t0 ^= state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000;
    t1 ^= leftRotate8((state->TK1[1] ^ state->TK2[1] ^ (rc >> 4)));
    t2 ^= 0x020000;

    /* Save the local variables in temp but first convert them to columns*/
    rows_to_columns_32(s0, s1, s2, s3, t0, t1, t2, t3);


    /* Perform all requested rounds */
    while (first > last) {
        /* Permute TK1 and TK2 for the next round */
        skinny128_inv_LFSR2(state->TK2[0]);
        skinny128_inv_LFSR2(state->TK2[1]);
        skinny128_inv_permute_tk(state->TK1);
        skinny128_inv_permute_tk(state->TK2);

        t0 = (T_inv[s0 & 0xff]&0xff000000) ^ (T_inv[(s1>>8) & 0xff]&0x00ffffff) ^ (T_inv[(s2>>16) & 0xff]&0x0000ff00) ^ (T_inv[(s3>>24)]&0xffffff00);
        t1 = (T_inv[s1 & 0xff]&0xff000000) ^ (T_inv[(s2>>8) & 0xff]&0x00ffffff) ^ (T_inv[(s3>>16) & 0xff]&0x0000ff00) ^ (T_inv[(s0>>24)]&0xffffff00);
        t2 = (T_inv[s2 & 0xff]&0xff000000) ^ (T_inv[(s3>>8) & 0xff]&0x00ffffff) ^ (T_inv[(s0>>16) & 0xff]&0x0000ff00) ^ (T_inv[(s1>>24)]&0xffffff00);
        t3 = (T_inv[s3 & 0xff]&0xff000000) ^ (T_inv[(s0>>8) & 0xff]&0x00ffffff) ^ (T_inv[(s1>>16) & 0xff]&0x0000ff00) ^ (T_inv[(s2>>24)]&0xffffff00);

        /* XOR the shifted round constant and the shifted subkey for this round */
        rc = RC[--first];
        tk0 = state->TK1[0] ^ state->TK2[0] ^ (rc & 0x0F) ^ 0x00020000;
        tk1 = leftRotate8((state->TK1[1] ^ state->TK2[1] ^ (rc >> 4)));

        s0 = t0 ^ (((tk0)    &0xff) | ((tk1<<8)&0xff00));
        s1 = t1 ^ (((tk0>>8) &0xff) | ((tk1)&0xff00));
        s2 = t2 ^ (((tk0>>16)&0xff) | ((tk1>>8)&0xff00)) ^ 0x020000;
        s3 = t3 ^ (((tk0>>24)&0xff) | ((tk1>>16)&0xff00));
    }
Arne Deprez committed
152

Arne Deprez committed
153
    // FINAL ROUND
Arne Deprez committed
154

Arne Deprez committed
155
    /* Apply the inverse of the S-box to all cells in the state */
Arne Deprez committed
156 157 158 159 160 161
	skinny128_inv_sbox(s0);
	skinny128_inv_sbox(s1);
	skinny128_inv_sbox(s2);
	skinny128_inv_sbox(s3);

    /* Save the local variables back to the state but first convert them back to rows*/
Arne Deprez committed
162
	columns_to_rows_32(t0, t1, t2, t3, s0, s1, s2, s3);
Arne Deprez committed
163 164 165 166

	/* Shift the cells in the rows left, which moves the cell
	 * values down closer to the LSB.  That is, we do a right
	 * rotate on the word to rotate the cells in the word left */
Arne Deprez committed
167 168 169 170
    state->S[0] = t0;
	state->S[1] = rightRotate8(t1);
	state->S[2] = rightRotate16(t2);
	state->S[3] = rightRotate24(t3);
Arne Deprez committed
171 172
}

Arne Deprez committed
173 174
void forkskinny_128_256_forward_tk
    (forkskinny_128_256_state_t *state, unsigned rounds)
Arne Deprez committed
175
{
Arne Deprez committed
176 177 178 179 180 181 182 183 184 185 186 187 188
    unsigned temp;

    /* The tweak permutation repeats every 16 rounds so we can avoid
     * some skinny128_permute_tk() calls in the early stages.  During
     * the 16 rounds, the LFSR will be applied 8 times to every word */
    while (rounds >= 16) {
        for (temp = 0; temp < 8; ++temp) {
            skinny128_LFSR2(state->TK2[0]);
            skinny128_LFSR2(state->TK2[1]);
            skinny128_LFSR2(state->TK2[2]);
            skinny128_LFSR2(state->TK2[3]);
        }
        rounds -= 16;
Arne Deprez committed
189 190
    }

Arne Deprez committed
191 192 193 194 195 196 197
    /* Handle the left-over rounds */
    while (rounds > 0) {
        skinny128_permute_tk(state->TK1);
        skinny128_permute_tk(state->TK2);
        skinny128_LFSR2(state->TK2[0]);
        skinny128_LFSR2(state->TK2[1]);
        --rounds;
Arne Deprez committed
198
    }
Arne Deprez committed
199
}
Arne Deprez committed
200

Arne Deprez committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
void forkskinny_128_256_reverse_tk
    (forkskinny_128_256_state_t *state, unsigned rounds)
{
    unsigned temp;

    /* The tweak permutation repeats every 16 rounds so we can avoid
     * some skinny128_inv_permute_tk() calls in the early stages.  During
     * the 16 rounds, the LFSR will be applied 8 times to every word */
    while (rounds >= 16) {
        for (temp = 0; temp < 8; ++temp) {
            skinny128_inv_LFSR2(state->TK2[0]);
            skinny128_inv_LFSR2(state->TK2[1]);
            skinny128_inv_LFSR2(state->TK2[2]);
            skinny128_inv_LFSR2(state->TK2[3]);
        }
        rounds -= 16;
Arne Deprez committed
217 218
    }

Arne Deprez committed
219 220 221 222 223 224 225
    /* Handle the left-over rounds */
    while (rounds > 0) {
        skinny128_inv_LFSR2(state->TK2[0]);
        skinny128_inv_LFSR2(state->TK2[1]);
        skinny128_inv_permute_tk(state->TK1);
        skinny128_inv_permute_tk(state->TK2);
        --rounds;
Arne Deprez committed
226 227 228
    }
}

Arne Deprez committed
229 230
void forkskinny_128_384_rounds
    (forkskinny_128_384_state_t *state, unsigned first, unsigned last)
Arne Deprez committed
231
{
Arne Deprez committed
232
    uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
Arne Deprez committed
233 234 235 236 237 238 239 240
    uint32_t tk_columns[4];

    /* Load the state into local variables */
    s0 = state->S[0];
    s1 = state->S[1];
    s2 = state->S[2];
    s3 = state->S[3];

Arne Deprez committed
241 242
    /* Perform all requested rounds */
    for (; first < last; ++first) {
Arne Deprez committed
243

Arne Deprez committed
244
        TK_to_column_384(tk_columns, state);
Arne Deprez committed
245

Arne Deprez committed
246 247 248 249
        t0 = (T[s0 & 0xff]&0xff00ffff) ^ (T[(s3>>8) & 0xff]&0x00ff0000) ^ (T[(s2>>16) & 0xff]&0xffff00ff) ^ (T[(s1>>24)]&0xff) ^ tk_columns[0] ^ AC_column0[first];
        t1 = (T[s1 & 0xff]&0xff00ffff) ^ (T[(s0>>8) & 0xff]&0x00ff0000) ^ (T[(s3>>16) & 0xff]&0xffff00ff) ^ (T[(s2>>24)]&0xff) ^ tk_columns[1] ^ AC_column1[first];
        t2 = (T[s2 & 0xff]&0xff00ffff) ^ (T[(s1>>8) & 0xff]&0x00ff0000) ^ (T[(s0>>16) & 0xff]&0xffff00ff) ^ (T[(s3>>24)]&0xff) ^ tk_columns[2] ^ 0x00020200;
        t3 = (T[s3 & 0xff]&0xff00ffff) ^ (T[(s2>>8) & 0xff]&0x00ff0000) ^ (T[(s1>>16) & 0xff]&0xffff00ff) ^ (T[(s0>>24)]&0xff) ^ tk_columns[3];
Arne Deprez committed
250

Arne Deprez committed
251 252 253 254 255 256 257 258 259 260
        /* Permute TK1, TK2, and TK3 for the next round */
        skinny128_permute_tk(state->TK1);
        skinny128_permute_tk(state->TK2);
        skinny128_permute_tk(state->TK3);
        skinny128_LFSR2(state->TK2[0]);
        skinny128_LFSR2(state->TK2[1]);
        skinny128_LFSR3(state->TK3[0]);
        skinny128_LFSR3(state->TK3[1]);

        s0 = t0; s1 = t1; s2 = t2; s3 = t3;
Arne Deprez committed
261 262
    }

Arne Deprez committed
263 264 265 266 267 268
    /* Save the local variables back to the state */
    state->S[0] = s0;
    state->S[1] = s1;
    state->S[2] = s2;
    state->S[3] = s3;
}
Arne Deprez committed
269

Arne Deprez committed
270 271 272 273 274
void forkskinny_128_384_inv_rounds
    (forkskinny_128_384_state_t *state, unsigned first, unsigned last)
{
   uint32_t s0, s1, s2, s3, t0, t1, t2, t3, tk0, tk1;
    uint8_t rc;
Arne Deprez committed
275 276

    /* Load the state into local variables */
Arne Deprez committed
277 278 279 280
    t0 = state->S[0];
    t1 = state->S[1];
    t2 = state->S[2];
    t3 = state->S[3];
Arne Deprez committed
281

Arne Deprez committed
282
    // FIRST ROUND
Arne Deprez committed
283 284 285 286 287 288 289 290 291 292

    /* Permute TK1 and TK2 for the next round */
    skinny128_inv_LFSR2(state->TK2[0]);
    skinny128_inv_LFSR2(state->TK2[1]);
    skinny128_inv_LFSR3(state->TK3[0]);
    skinny128_inv_LFSR3(state->TK3[1]);
    skinny128_inv_permute_tk(state->TK1);
    skinny128_inv_permute_tk(state->TK2);
    skinny128_inv_permute_tk(state->TK3);

Arne Deprez committed
293 294 295 296 297 298 299 300
    /* Inverse mix of the columns */
    s0 = t0;
    t0 = t1;
    t1 = t2;
    t2 = t3;
    t3 = s0 ^ t2;
    t2 ^= t0;
    t1 ^= t2;
Arne Deprez committed
301 302

    /* XOR the shifted round constant and the shifted subkey for this round */
Arne Deprez committed
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
    rc = RC[--first];
    t0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ (rc & 0x0F) ^ 0x00020000;
    t1 ^= leftRotate8((state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4)));
    t2 ^= 0x020000;

    /* Save the local variables in temp but first convert them to columns*/
    rows_to_columns_32(s0, s1, s2, s3, t0, t1, t2, t3);


    /* Perform all requested rounds */
    while (first > last) {
        /* Permute TK1 and TK2 for the next round */
        skinny128_inv_LFSR2(state->TK2[0]);
        skinny128_inv_LFSR2(state->TK2[1]);
        skinny128_inv_LFSR3(state->TK3[0]);
        skinny128_inv_LFSR3(state->TK3[1]);
        skinny128_inv_permute_tk(state->TK1);
        skinny128_inv_permute_tk(state->TK2);
        skinny128_inv_permute_tk(state->TK3);

        t0 = (T_inv[s0 & 0xff]&0xff000000) ^ (T_inv[(s1>>8) & 0xff]&0x00ffffff) ^ (T_inv[(s2>>16) & 0xff]&0x0000ff00) ^ (T_inv[(s3>>24)]&0xffffff00);
        t1 = (T_inv[s1 & 0xff]&0xff000000) ^ (T_inv[(s2>>8) & 0xff]&0x00ffffff) ^ (T_inv[(s3>>16) & 0xff]&0x0000ff00) ^ (T_inv[(s0>>24)]&0xffffff00);
        t2 = (T_inv[s2 & 0xff]&0xff000000) ^ (T_inv[(s3>>8) & 0xff]&0x00ffffff) ^ (T_inv[(s0>>16) & 0xff]&0x0000ff00) ^ (T_inv[(s1>>24)]&0xffffff00);
        t3 = (T_inv[s3 & 0xff]&0xff000000) ^ (T_inv[(s0>>8) & 0xff]&0x00ffffff) ^ (T_inv[(s1>>16) & 0xff]&0x0000ff00) ^ (T_inv[(s2>>24)]&0xffffff00);

        /* XOR the shifted round constant and the shifted subkey for this round */
        rc = RC[--first];
        tk0 = state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^ (rc & 0x0F) ^ 0x00020000;
        tk1 = leftRotate8((state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^ (rc >> 4)));

        s0 = t0 ^ (((tk0)    &0xff) | ((tk1<<8)&0xff00));
        s1 = t1 ^ (((tk0>>8) &0xff) | ((tk1)&0xff00));
        s2 = t2 ^ (((tk0>>16)&0xff) | ((tk1>>8)&0xff00)) ^ 0x020000;
        s3 = t3 ^ (((tk0>>24)&0xff) | ((tk1>>16)&0xff00));
    }
Arne Deprez committed
338

Arne Deprez committed
339
    // FINAL ROUND
Arne Deprez committed
340

Arne Deprez committed
341
    /* Apply the inverse of the S-box to all cells in the state */
Arne Deprez committed
342 343 344 345 346 347
	skinny128_inv_sbox(s0);
	skinny128_inv_sbox(s1);
	skinny128_inv_sbox(s2);
	skinny128_inv_sbox(s3);

    /* Save the local variables back to the state but first convert them back to rows*/
Arne Deprez committed
348
	columns_to_rows_32(t0, t1, t2, t3, s0, s1, s2, s3);
Arne Deprez committed
349 350 351 352

	/* Shift the cells in the rows left, which moves the cell
	 * values down closer to the LSB.  That is, we do a right
	 * rotate on the word to rotate the cells in the word left */
Arne Deprez committed
353 354 355 356
    state->S[0] = t0;
	state->S[1] = rightRotate8(t1);
	state->S[2] = rightRotate16(t2);
	state->S[3] = rightRotate24(t3);
Arne Deprez committed
357 358
}

Arne Deprez committed
359 360
void forkskinny_128_384_forward_tk
    (forkskinny_128_384_state_t *state, unsigned rounds)
Arne Deprez committed
361
{
Arne Deprez committed
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
    unsigned temp;

    /* The tweak permutation repeats every 16 rounds so we can avoid
     * some skinny128_permute_tk() calls in the early stages.  During
     * the 16 rounds, the LFSR will be applied 8 times to every word */
    while (rounds >= 16) {
        for (temp = 0; temp < 8; ++temp) {
            skinny128_LFSR2(state->TK2[0]);
            skinny128_LFSR2(state->TK2[1]);
            skinny128_LFSR2(state->TK2[2]);
            skinny128_LFSR2(state->TK2[3]);
            skinny128_LFSR3(state->TK3[0]);
            skinny128_LFSR3(state->TK3[1]);
            skinny128_LFSR3(state->TK3[2]);
            skinny128_LFSR3(state->TK3[3]);
        }
        rounds -= 16;
Arne Deprez committed
379 380
    }

Arne Deprez committed
381 382 383 384 385 386 387 388 389 390
    /* Handle the left-over rounds */
    while (rounds > 0) {
        skinny128_permute_tk(state->TK1);
        skinny128_permute_tk(state->TK2);
        skinny128_permute_tk(state->TK3);
        skinny128_LFSR2(state->TK2[0]);
        skinny128_LFSR2(state->TK2[1]);
        skinny128_LFSR3(state->TK3[0]);
        skinny128_LFSR3(state->TK3[1]);
        --rounds;
Arne Deprez committed
391 392 393
    }
}

Arne Deprez committed
394 395
void forkskinny_128_384_reverse_tk
    (forkskinny_128_384_state_t *state, unsigned rounds)
Arne Deprez committed
396
{
Arne Deprez committed
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
    unsigned temp;

    /* The tweak permutation repeats every 16 rounds so we can avoid
     * some skinny128_inv_permute_tk() calls in the early stages.  During
     * the 16 rounds, the LFSR will be applied 8 times to every word */
    while (rounds >= 16) {
        for (temp = 0; temp < 8; ++temp) {
            skinny128_inv_LFSR2(state->TK2[0]);
            skinny128_inv_LFSR2(state->TK2[1]);
            skinny128_inv_LFSR2(state->TK2[2]);
            skinny128_inv_LFSR2(state->TK2[3]);
            skinny128_inv_LFSR3(state->TK3[0]);
            skinny128_inv_LFSR3(state->TK3[1]);
            skinny128_inv_LFSR3(state->TK3[2]);
            skinny128_inv_LFSR3(state->TK3[3]);
        }
        rounds -= 16;
    }
Arne Deprez committed
415

Arne Deprez committed
416 417 418 419 420 421 422 423 424 425 426 427
    /* Handle the left-over rounds */
    while (rounds > 0) {
        skinny128_inv_LFSR2(state->TK2[0]);
        skinny128_inv_LFSR2(state->TK2[1]);
        skinny128_inv_LFSR3(state->TK3[0]);
        skinny128_inv_LFSR3(state->TK3[1]);
        skinny128_inv_permute_tk(state->TK1);
        skinny128_inv_permute_tk(state->TK2);
        skinny128_inv_permute_tk(state->TK3);
        --rounds;
    }
}
Arne Deprez committed
428

Arne Deprez committed
429 430
void forkskinny_64_192_rounds
    (forkskinny_64_192_state_t *state, unsigned first, unsigned last)
Arne Deprez committed
431 432 433 434 435 436 437 438 439 440
{
    uint16_t s0, s1, s2, s3, temp;
    uint8_t rc;

    /* Load the state into local variables */
    s0 = state->S[0];
    s1 = state->S[1];
    s2 = state->S[2];
    s3 = state->S[3];

Arne Deprez committed
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
    /* Perform all requested rounds */
    for (; first < last; ++first) {
        /* Apply the S-box to all cells in the state */
        skinny64_sbox(s0);
        skinny64_sbox(s1);
        skinny64_sbox(s2);
        skinny64_sbox(s3);

        /* XOR the round constant and the subkey for this round */
        rc = RC[first];
        s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^
              ((rc & 0x0F) << 12) ^ 0x0020;
        s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^
              ((rc & 0x70) << 8);
        s2 ^= 0x2000;

        /* Shift the cells in the rows right */
        s1 = rightRotate4_16(s1);
        s2 = rightRotate8_16(s2);
        s3 = rightRotate12_16(s3);

        /* Mix the columns */
        s1 ^= s2;
        s2 ^= s0;
        temp = s3 ^ s2;
        s3 = s2;
        s2 = s1;
        s1 = s0;
        s0 = temp;

        /* Permute TK1, TK2, and TK3 for the next round */
        skinny64_permute_tk(state->TK1);
        skinny64_permute_tk(state->TK2);
        skinny64_permute_tk(state->TK3);
        skinny64_LFSR2(state->TK2[0]);
        skinny64_LFSR2(state->TK2[1]);
        skinny64_LFSR3(state->TK3[0]);
        skinny64_LFSR3(state->TK3[1]);
    }
Arne Deprez committed
480 481 482 483 484 485 486 487

    /* Save the local variables back to the state */
    state->S[0] = s0;
    state->S[1] = s1;
    state->S[2] = s2;
    state->S[3] = s3;
}

Arne Deprez committed
488 489
void forkskinny_64_192_inv_rounds
    (forkskinny_64_192_state_t *state, unsigned first, unsigned last)
Arne Deprez committed
490 491 492 493 494 495 496 497 498 499
{
    uint16_t s0, s1, s2, s3, temp;
    uint8_t rc;

    /* Load the state into local variables */
    s0 = state->S[0];
    s1 = state->S[1];
    s2 = state->S[2];
    s3 = state->S[3];

Arne Deprez committed
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
    /* Perform all requested rounds */
    while (first > last) {
        /* Permute TK1, TK2, and TK3 for the next round */
        skinny64_inv_LFSR2(state->TK2[0]);
        skinny64_inv_LFSR2(state->TK2[1]);
        skinny64_inv_LFSR3(state->TK3[0]);
        skinny64_inv_LFSR3(state->TK3[1]);
        skinny64_inv_permute_tk(state->TK1);
        skinny64_inv_permute_tk(state->TK2);
        skinny64_inv_permute_tk(state->TK3);

        /* Inverse mix of the columns */
        temp = s0;
        s0 = s1;
        s1 = s2;
        s2 = s3;
        s3 = temp ^ s2;
        s2 ^= s0;
        s1 ^= s2;

        /* Shift the cells in the rows left */
        s1 = leftRotate4_16(s1);
        s2 = leftRotate8_16(s2);
        s3 = leftRotate12_16(s3);

        /* XOR the round constant and the subkey for this round */
        rc = RC[--first];
        s0 ^= state->TK1[0] ^ state->TK2[0] ^ state->TK3[0] ^
              ((rc & 0x0F) << 12) ^ 0x0020;
        s1 ^= state->TK1[1] ^ state->TK2[1] ^ state->TK3[1] ^
              ((rc & 0x70) << 8);
        s2 ^= 0x2000;

        /* Apply the inverse of the S-box to all cells in the state */
        skinny64_inv_sbox(s0);
        skinny64_inv_sbox(s1);
        skinny64_inv_sbox(s2);
        skinny64_inv_sbox(s3);
    }
Arne Deprez committed
539 540 541 542 543 544 545 546

    /* Save the local variables back to the state */
    state->S[0] = s0;
    state->S[1] = s1;
    state->S[2] = s2;
    state->S[3] = s3;
}

Arne Deprez committed
547 548
void forkskinny_64_192_forward_tk
    (forkskinny_64_192_state_t *state, unsigned rounds)
Arne Deprez committed
549
{
Arne Deprez committed
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
    unsigned temp;

    /* The tweak permutation repeats every 16 rounds so we can avoid
     * some skinny64_permute_tk() calls in the early stages.  During
     * the 16 rounds, the LFSR will be applied 8 times to every word */
    while (rounds >= 16) {
        for (temp = 0; temp < 8; ++temp) {
            skinny64_LFSR2(state->TK2[0]);
            skinny64_LFSR2(state->TK2[1]);
            skinny64_LFSR2(state->TK2[2]);
            skinny64_LFSR2(state->TK2[3]);
            skinny64_LFSR3(state->TK3[0]);
            skinny64_LFSR3(state->TK3[1]);
            skinny64_LFSR3(state->TK3[2]);
            skinny64_LFSR3(state->TK3[3]);
        }
        rounds -= 16;
Arne Deprez committed
567 568
    }

Arne Deprez committed
569 570 571 572 573 574 575 576 577 578
    /* Handle the left-over rounds */
    while (rounds > 0) {
        skinny64_permute_tk(state->TK1);
        skinny64_permute_tk(state->TK2);
        skinny64_permute_tk(state->TK3);
        skinny64_LFSR2(state->TK2[0]);
        skinny64_LFSR2(state->TK2[1]);
        skinny64_LFSR3(state->TK3[0]);
        skinny64_LFSR3(state->TK3[1]);
        --rounds;
Arne Deprez committed
579
    }
Arne Deprez committed
580
}
Arne Deprez committed
581

Arne Deprez committed
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
void forkskinny_64_192_reverse_tk
    (forkskinny_64_192_state_t *state, unsigned rounds)
{
    unsigned temp;

    /* The tweak permutation repeats every 16 rounds so we can avoid
     * some skinny64_inv_permute_tk() calls in the early stages.  During
     * the 16 rounds, the LFSR will be applied 8 times to every word */
    while (rounds >= 16) {
        for (temp = 0; temp < 8; ++temp) {
            skinny64_inv_LFSR2(state->TK2[0]);
            skinny64_inv_LFSR2(state->TK2[1]);
            skinny64_inv_LFSR2(state->TK2[2]);
            skinny64_inv_LFSR2(state->TK2[3]);
            skinny64_inv_LFSR3(state->TK3[0]);
            skinny64_inv_LFSR3(state->TK3[1]);
            skinny64_inv_LFSR3(state->TK3[2]);
            skinny64_inv_LFSR3(state->TK3[3]);
        }
        rounds -= 16;
Arne Deprez committed
602 603
    }

Arne Deprez committed
604 605 606 607 608 609 610 611 612 613
    /* Handle the left-over rounds */
    while (rounds > 0) {
        skinny64_inv_LFSR2(state->TK2[0]);
        skinny64_inv_LFSR2(state->TK2[1]);
        skinny64_inv_LFSR3(state->TK3[0]);
        skinny64_inv_LFSR3(state->TK3[1]);
        skinny64_inv_permute_tk(state->TK1);
        skinny64_inv_permute_tk(state->TK2);
        skinny64_inv_permute_tk(state->TK3);
        --rounds;
Arne Deprez committed
614 615 616
    }
}

Arne Deprez committed
617
#endif /* !__AVR__ */