23 #include "skinny128-cipher.h"
24 #include "skinny-internal.h"
28 STATIC_INLINE uint64_t skinny128_LFSR2(uint64_t x)
30 return ((x << 1) & 0xFEFEFEFEFEFEFEFEULL) ^
31 (((x >> 7) ^ (x >> 5)) & 0x0101010101010101ULL);
34 STATIC_INLINE uint64_t skinny128_LFSR3(uint64_t x)
36 return ((x >> 1) & 0x7F7F7F7F7F7F7F7FULL) ^
37 (((x << 7) ^ (x << 1)) & 0x8080808080808080ULL);
42 STATIC_INLINE uint32_t skinny128_LFSR2(uint32_t x)
44 return ((x << 1) & 0xFEFEFEFEU) ^ (((x >> 7) ^ (x >> 5)) & 0x01010101U);
47 STATIC_INLINE uint32_t skinny128_LFSR3(uint32_t x)
49 return ((x >> 1) & 0x7F7F7F7FU) ^ (((x << 7) ^ (x << 1)) & 0x80808080U);
57 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
59 uint64_t x = tk->
lrow[1];
62 y = x & 0xFF0000FF00FF00FFULL;
63 tk->
lrow[0] = (y << 16) | (y >> 48) |
64 ((x & 0x00000000FF000000ULL) << 32) |
65 ((x & 0x0000FF0000000000ULL) >> 16) |
66 ((x & 0x00FF00000000FF00ULL) >> 8);
68 uint32_t row2 = tk->
row[2];
69 uint32_t row3 = tk->
row[3];
72 row3 = (row3 << 16) | (row3 >> 16);
73 tk->
row[0] = ((row2 >> 8) & 0x000000FFU) |
74 ((row2 << 16) & 0x00FF0000U) |
75 ( row3 & 0xFF00FF00U);
76 tk->
row[1] = ((row2 >> 16) & 0x000000FFU) |
77 (row2 & 0xFF000000U) |
78 ((row3 << 8) & 0x0000FF00U) |
79 ( row3 & 0x00FF0000U);
84 static void skinny128_set_tk1
85 (
Skinny128Key_t *ks,
const void *key,
unsigned key_size,
int tweaked)
94 tk.
row[0] = READ_WORD32(key, 0);
95 tk.
row[1] = READ_WORD32(key, 4);
96 tk.
row[2] = READ_WORD32(key, 8);
97 tk.
row[3] = READ_WORD32(key, 12);
99 for (index = 0; index < key_size; index += 4) {
100 if ((index + 4) <= key_size) {
101 word = READ_WORD32(key, index);
103 word = READ_BYTE(key, index);
104 if ((index + 1) < key_size)
105 word |= (READ_BYTE(key, index + 1) << 8);
106 if ((index + 2) < key_size)
107 word |= (READ_BYTE(key, index + 2) << 16);
109 tk.
row[index / 4] = word;
114 for (index = 0; index < ks->
rounds; ++index) {
126 rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01;
138 skinny128_permute_tk(&tk);
143 static void skinny128_xor_tk1(
Skinny128Key_t *ks,
const void *key)
149 tk.
row[0] = READ_WORD32(key, 0);
150 tk.
row[1] = READ_WORD32(key, 4);
151 tk.
row[2] = READ_WORD32(key, 8);
152 tk.
row[3] = READ_WORD32(key, 12);
155 for (index = 0; index < ks->
rounds; ++index) {
165 skinny128_permute_tk(&tk);
170 static void skinny128_set_tk2
179 tk.
row[0] = READ_WORD32(key, 0);
180 tk.
row[1] = READ_WORD32(key, 4);
181 tk.
row[2] = READ_WORD32(key, 8);
182 tk.
row[3] = READ_WORD32(key, 12);
184 for (index = 0; index < key_size; index += 4) {
185 if ((index + 4) <= key_size) {
186 word = READ_WORD32(key, index);
188 word = READ_BYTE(key, index);
189 if ((index + 1) < key_size)
190 word |= (READ_BYTE(key, index + 1) << 8);
191 if ((index + 2) < key_size)
192 word |= (READ_BYTE(key, index + 2) << 16);
194 tk.
row[index / 4] = word;
199 for (index = 0; index < ks->
rounds; ++index) {
209 skinny128_permute_tk(&tk);
213 tk.
lrow[0] = skinny128_LFSR2(tk.
lrow[0]);
215 tk.
row[0] = skinny128_LFSR2(tk.
row[0]);
216 tk.
row[1] = skinny128_LFSR2(tk.
row[1]);
222 static void skinny128_set_tk3
231 tk.
row[0] = READ_WORD32(key, 0);
232 tk.
row[1] = READ_WORD32(key, 4);
233 tk.
row[2] = READ_WORD32(key, 8);
234 tk.
row[3] = READ_WORD32(key, 12);
236 for (index = 0; index < key_size; index += 4) {
237 if ((index + 4) <= key_size) {
238 word = READ_WORD32(key, index);
240 word = READ_BYTE(key, index);
241 if ((index + 1) < key_size)
242 word |= (READ_BYTE(key, index + 1) << 8);
243 if ((index + 2) < key_size)
244 word |= (READ_BYTE(key, index + 2) << 16);
246 tk.
row[index / 4] = word;
251 for (index = 0; index < ks->
rounds; ++index) {
261 skinny128_permute_tk(&tk);
265 tk.
lrow[0] = skinny128_LFSR3(tk.
lrow[0]);
267 tk.
row[0] = skinny128_LFSR3(tk.
row[0]);
268 tk.
row[1] = skinny128_LFSR3(tk.
row[1]);
273 static void skinny128_set_key_inner
274 (
Skinny128Key_t *ks,
const void *key,
unsigned key_size,
const void *tweak)
280 skinny128_set_tk1(ks, key, key_size, 0);
299 skinny128_set_tk2(ks, key, key_size);
319 skinny128_set_key_inner(ks, key, size, 0);
336 skinny128_set_key_inner(&(ks->
ks), key, key_size, ks->
tweak);
351 memcpy(tk_prev, ks->
tweak,
sizeof(tk_prev));
352 memcpy(ks->
tweak, tweak, tweak_size);
353 memset(ks->
tweak + tweak_size, 0,
sizeof(ks->
tweak) - tweak_size);
356 skinny128_xor_tk1(&(ks->
ks), tk_prev);
359 skinny128_xor_tk1(&(ks->
ks), ks->
tweak);
363 STATIC_INLINE uint32_t skinny128_rotate_right(uint32_t x,
unsigned count)
368 return (x << count) | (x >> (32 - count));
373 STATIC_INLINE uint64_t skinny128_sbox(uint64_t x)
378 x ^= (((x >> 2) & (x >> 3)) & 0x1111111111111111ULL);
379 y = (((x << 5) & (x << 1)) & 0x2020202020202020ULL);
380 x ^= (((x << 5) & (x << 4)) & 0x4040404040404040ULL) ^ y;
381 y = (((x << 2) & (x << 1)) & 0x8080808080808080ULL);
382 x ^= (((x >> 2) & (x << 1)) & 0x0202020202020202ULL) ^ y;
383 y = (((x >> 5) & (x << 1)) & 0x0404040404040404ULL);
384 x ^= (((x >> 1) & (x >> 2)) & 0x0808080808080808ULL) ^ y;
386 return ((x & 0x0808080808080808ULL) << 1) |
387 ((x & 0x3232323232323232ULL) << 2) |
388 ((x & 0x0101010101010101ULL) << 5) |
389 ((x & 0x8080808080808080ULL) >> 6) |
390 ((x & 0x4040404040404040ULL) >> 4) |
391 ((x & 0x0404040404040404ULL) >> 2);
394 STATIC_INLINE uint64_t skinny128_inv_sbox(uint64_t x)
399 y = (((x >> 1) & (x >> 3)) & 0x0101010101010101ULL);
400 x ^= (((x >> 2) & (x >> 3)) & 0x1010101010101010ULL) ^ y;
401 y = (((x >> 6) & (x >> 1)) & 0x0202020202020202ULL);
402 x ^= (((x >> 1) & (x >> 2)) & 0x0808080808080808ULL) ^ y;
403 y = (((x << 2) & (x << 1)) & 0x8080808080808080ULL);
404 x ^= (((x >> 1) & (x << 2)) & 0x0404040404040404ULL) ^ y;
405 y = (((x << 5) & (x << 1)) & 0x2020202020202020ULL);
406 x ^= (((x << 4) & (x << 5)) & 0x4040404040404040ULL) ^ y;
408 return ((x & 0x0101010101010101ULL) << 2) |
409 ((x & 0x0404040404040404ULL) << 4) |
410 ((x & 0x0202020202020202ULL) << 6) |
411 ((x & 0x2020202020202020ULL) >> 5) |
412 ((x & 0xC8C8C8C8C8C8C8C8ULL) >> 2) |
413 ((x & 0x1010101010101010ULL) >> 1);
418 STATIC_INLINE uint32_t skinny128_sbox(uint32_t x)
457 x ^= (((x >> 2) & (x >> 3)) & 0x11111111U);
458 y = (((x << 5) & (x << 1)) & 0x20202020U);
459 x ^= (((x << 5) & (x << 4)) & 0x40404040U) ^ y;
460 y = (((x << 2) & (x << 1)) & 0x80808080U);
461 x ^= (((x >> 2) & (x << 1)) & 0x02020202U) ^ y;
462 y = (((x >> 5) & (x << 1)) & 0x04040404U);
463 x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y;
468 return ((x & 0x08080808U) << 1) |
469 ((x & 0x32323232U) << 2) |
470 ((x & 0x01010101U) << 5) |
471 ((x & 0x80808080U) >> 6) |
472 ((x & 0x40404040U) >> 4) |
473 ((x & 0x04040404U) >> 2);
476 STATIC_INLINE uint32_t skinny128_inv_sbox(uint32_t x)
510 y = (((x >> 1) & (x >> 3)) & 0x01010101U);
511 x ^= (((x >> 2) & (x >> 3)) & 0x10101010U) ^ y;
512 y = (((x >> 6) & (x >> 1)) & 0x02020202U);
513 x ^= (((x >> 1) & (x >> 2)) & 0x08080808U) ^ y;
514 y = (((x << 2) & (x << 1)) & 0x80808080U);
515 x ^= (((x >> 1) & (x << 2)) & 0x04040404U) ^ y;
516 y = (((x << 5) & (x << 1)) & 0x20202020U);
517 x ^= (((x << 4) & (x << 5)) & 0x40404040U) ^ y;
522 return ((x & 0x01010101U) << 2) |
523 ((x & 0x04040404U) << 4) |
524 ((x & 0x02020202U) << 6) |
525 ((x & 0x20202020U) >> 5) |
526 ((x & 0xC8C8C8C8U) >> 2) |
527 ((x & 0x10101010U) >> 1);
541 state.
row[0] = READ_WORD32(input, 0);
542 state.
row[1] = READ_WORD32(input, 4);
543 state.
row[2] = READ_WORD32(input, 8);
544 state.
row[3] = READ_WORD32(input, 12);
548 for (index = ks->
rounds; index > 0; --index, ++schedule) {
551 state.
lrow[0] = skinny128_sbox(state.
lrow[0]);
552 state.
lrow[1] = skinny128_sbox(state.
lrow[1]);
554 state.
row[0] = skinny128_sbox(state.
row[0]);
555 state.
row[1] = skinny128_sbox(state.
row[1]);
556 state.
row[2] = skinny128_sbox(state.
row[2]);
557 state.
row[3] = skinny128_sbox(state.
row[3]);
563 state.
lrow[1] ^= 0x02;
565 state.
row[0] ^= schedule->
row[0];
566 state.
row[1] ^= schedule->
row[1];
567 state.
row[2] ^= 0x02;
571 state.
row[1] = skinny128_rotate_right(state.
row[1], 8);
572 state.
row[2] = skinny128_rotate_right(state.
row[2], 16);
573 state.
row[3] = skinny128_rotate_right(state.
row[3], 24);
576 state.
row[1] ^= state.
row[2];
577 state.
row[2] ^= state.
row[0];
578 temp = state.
row[3] ^ state.
row[2];
579 state.
row[3] = state.
row[2];
580 state.
row[2] = state.
row[1];
581 state.
row[1] = state.
row[0];
586 WRITE_WORD32(output, 0, state.
row[0]);
587 WRITE_WORD32(output, 4, state.
row[1]);
588 WRITE_WORD32(output, 8, state.
row[2]);
589 WRITE_WORD32(output, 12, state.
row[3]);
601 state.
row[0] = READ_WORD32(input, 0);
602 state.
row[1] = READ_WORD32(input, 4);
603 state.
row[2] = READ_WORD32(input, 8);
604 state.
row[3] = READ_WORD32(input, 12);
608 for (index = ks->
rounds; index > 0; --index, --schedule) {
611 state.
row[3] = state.
row[0];
612 state.
row[0] = state.
row[1];
613 state.
row[1] = state.
row[2];
614 state.
row[3] ^= temp;
615 state.
row[2] = temp ^ state.
row[0];
616 state.
row[1] ^= state.
row[2];
619 state.
row[1] = skinny128_rotate_right(state.
row[1], 24);
620 state.
row[2] = skinny128_rotate_right(state.
row[2], 16);
621 state.
row[3] = skinny128_rotate_right(state.
row[3], 8);
627 state.
row[0] ^= schedule->
row[0];
628 state.
row[1] ^= schedule->
row[1];
630 state.
row[2] ^= 0x02;
634 state.
lrow[0] = skinny128_inv_sbox(state.
lrow[0]);
635 state.
lrow[1] = skinny128_inv_sbox(state.
lrow[1]);
637 state.
row[0] = skinny128_inv_sbox(state.
row[0]);
638 state.
row[1] = skinny128_inv_sbox(state.
row[1]);
639 state.
row[2] = skinny128_inv_sbox(state.
row[2]);
640 state.
row[3] = skinny128_inv_sbox(state.
row[3]);
645 WRITE_WORD32(output, 0, state.
row[0]);
646 WRITE_WORD32(output, 4, state.
row[1]);
647 WRITE_WORD32(output, 8, state.
row[2]);
648 WRITE_WORD32(output, 12, state.
row[3]);
Union that describes a 64-bit 2x4 array of cells.
Skinny128HalfCells_t schedule[SKINNY128_MAX_ROUNDS]
Key schedule for Skinny128 block ciphers when a tweak is in use.
int skinny128_set_tweaked_key(Skinny128TweakedKey_t *ks, const void *key, unsigned key_size)
Sets the key schedule for a Skinny128 block cipher, and prepare for tweaked encryption.
void skinny128_ecb_encrypt(void *output, const void *input, const Skinny128Key_t *ks)
Encrypts a single block using the Skinny128 block cipher in ECB mode.
Key schedule for Skinny128 block ciphers.
Union that describes a 128-bit 4x4 array of cells.
void skinny128_ecb_decrypt(void *output, const void *input, const Skinny128Key_t *ks)
Decrypts a single block using the Skinny128 block cipher in ECB mode.
int skinny128_set_key(Skinny128Key_t *ks, const void *key, unsigned size)
Sets the key schedule for a Skinny128 block cipher.
#define SKINNY128_BLOCK_SIZE
Size of a block for Skinny128 block ciphers.
int skinny128_set_tweak(Skinny128TweakedKey_t *ks, const void *tweak, unsigned tweak_size)
Changes the tweak value for a previously-initialized key schedule.
uint8_t tweak[SKINNY128_BLOCK_SIZE]