23 #include "skinny64-cipher.h"
24 #include "skinny-internal.h"
26 STATIC_INLINE uint32_t skinny64_LFSR2(uint32_t x)
28 return ((x << 1) & 0xEEEEEEEEU) ^ (((x >> 3) ^ (x >> 2)) & 0x11111111U);
31 STATIC_INLINE uint32_t skinny64_LFSR3(uint32_t x)
33 return ((x >> 1) & 0x77777777U) ^ ((x ^ (x << 3)) & 0x88888888U);
39 #if SKINNY_LITTLE_ENDIAN
41 uint32_t x = tk->
lrow[1];
43 tk->
lrow[0] = ((x & 0x0000000FU) << 4) |
44 ((x & 0x00F0F0F0U) << 8) |
45 ((x & 0x0F000000U) >> 24) |
46 ((x & 0x00000F00U) << 16) |
47 ((x & 0xF0000000U) >> 12) |
48 ((x & 0x000F0000U) >> 8);
50 uint16_t row2 = tk->
row[2];
51 uint16_t row3 = tk->
row[3];
54 row3 = (row3 << 8) | (row3 >> 8);
55 tk->
row[0] = ((row2 << 4) & 0x00F0U) |
56 ((row2 << 8) & 0xF000U) |
58 tk->
row[1] = ((row2 >> 8) & 0x00F0U) |
60 ((row3 >> 4) & 0x000FU) |
66 static void skinny64_set_tk1
67 (
Skinny64Key_t *ks,
const void *key,
unsigned key_size,
int tweaked)
76 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
77 tk.
llrow = READ_WORD64(key, 0);
78 #elif SKINNY_LITTLE_ENDIAN
79 tk.
lrow[0] = READ_WORD32(key, 0);
80 tk.
lrow[1] = READ_WORD32(key, 4);
82 tk.
row[0] = READ_WORD16(key, 0);
83 tk.
row[1] = READ_WORD16(key, 2);
84 tk.
row[2] = READ_WORD16(key, 4);
85 tk.
row[3] = READ_WORD16(key, 6);
88 for (index = 0; index < key_size; index += 2) {
89 if ((index + 2) <= key_size) {
90 word = READ_WORD16(key, index);
92 word = READ_BYTE(key, index);
94 tk.
row[index / 2] = word;
99 for (index = 0; index < ks->
rounds; ++index) {
106 rc = (rc << 1) ^ ((rc >> 5) & 0x01) ^ ((rc >> 4) & 0x01) ^ 0x01;
118 skinny64_permute_tk(&tk);
123 static void skinny64_xor_tk1(
Skinny64Key_t *ks,
const void *key)
129 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
130 tk.
llrow = READ_WORD64(key, 0);
131 #elif SKINNY_LITTLE_ENDIAN
132 tk.
lrow[0] = READ_WORD32(key, 0);
133 tk.
lrow[1] = READ_WORD32(key, 4);
135 tk.
row[0] = READ_WORD16(key, 0);
136 tk.
row[1] = READ_WORD16(key, 2);
137 tk.
row[2] = READ_WORD16(key, 4);
138 tk.
row[3] = READ_WORD16(key, 6);
142 for (index = 0; index < ks->
rounds; ++index) {
147 skinny64_permute_tk(&tk);
152 static void skinny64_set_tk2
161 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
162 tk.
llrow = READ_WORD64(key, 0);
163 #elif SKINNY_LITTLE_ENDIAN
164 tk.
lrow[0] = READ_WORD32(key, 0);
165 tk.
lrow[1] = READ_WORD32(key, 4);
167 tk.
row[0] = READ_WORD16(key, 0);
168 tk.
row[1] = READ_WORD16(key, 2);
169 tk.
row[2] = READ_WORD16(key, 4);
170 tk.
row[3] = READ_WORD16(key, 6);
173 for (index = 0; index < key_size; index += 2) {
174 if ((index + 2) <= key_size) {
175 word = READ_WORD16(key, index);
177 word = READ_BYTE(key, index);
179 tk.
row[index / 2] = word;
184 for (index = 0; index < ks->
rounds; ++index) {
189 skinny64_permute_tk(&tk);
192 tk.
lrow[0] = skinny64_LFSR2(tk.
lrow[0]);
197 static void skinny64_set_tk3
206 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
207 tk.
llrow = READ_WORD64(key, 0);
208 #elif SKINNY_LITTLE_ENDIAN
209 tk.
lrow[0] = READ_WORD32(key, 0);
210 tk.
lrow[1] = READ_WORD32(key, 4);
212 tk.
row[0] = READ_WORD16(key, 0);
213 tk.
row[1] = READ_WORD16(key, 2);
214 tk.
row[2] = READ_WORD16(key, 4);
215 tk.
row[3] = READ_WORD16(key, 6);
218 for (index = 0; index < key_size; index += 2) {
219 if ((index + 2) <= key_size) {
220 word = READ_WORD16(key, index);
222 word = READ_BYTE(key, index);
224 tk.
row[index / 2] = word;
229 for (index = 0; index < ks->
rounds; ++index) {
234 skinny64_permute_tk(&tk);
237 tk.
lrow[0] = skinny64_LFSR3(tk.
lrow[0]);
241 static void skinny64_set_key_inner
242 (
Skinny64Key_t *ks,
const void *key,
unsigned key_size,
const void *tweak)
248 skinny64_set_tk1(ks, key, key_size, 0);
267 skinny64_set_tk2(ks, key, key_size);
287 skinny64_set_key_inner(ks, key, size, 0);
304 skinny64_set_key_inner(&(ks->
ks), key, key_size, ks->
tweak);
319 memcpy(tk_prev, ks->
tweak,
sizeof(tk_prev));
320 memcpy(ks->
tweak, tweak, tweak_size);
321 memset(ks->
tweak + tweak_size, 0,
sizeof(ks->
tweak) - tweak_size);
324 skinny64_xor_tk1(&(ks->
ks), tk_prev);
327 skinny64_xor_tk1(&(ks->
ks), ks->
tweak);
331 STATIC_INLINE uint16_t skinny64_rotate_right(uint16_t x,
unsigned count)
333 return (x >> count) | (x << (16 - count));
338 STATIC_INLINE uint64_t skinny64_sbox(uint64_t x)
345 uint64_t bit1 = bit0 >> 1;
346 uint64_t bit2 = bit0 >> 2;
347 uint64_t bit3 = bit0 >> 3;
352 x = ((bit0 << 3) & 0x8888888888888888ULL) |
353 ( bit1 & 0x1111111111111111ULL) |
354 ((bit2 << 1) & 0x2222222222222222ULL) |
355 ((bit3 << 2) & 0x4444444444444444ULL);
359 STATIC_INLINE uint64_t skinny64_inv_sbox(uint64_t x)
362 uint64_t bit1 = bit0 >> 1;
363 uint64_t bit2 = bit0 >> 2;
364 uint64_t bit3 = bit0 >> 3;
369 x = ((bit0 << 1) & 0x2222222222222222ULL) |
370 ((bit1 << 2) & 0x4444444444444444ULL) |
371 ((bit2 << 3) & 0x8888888888888888ULL) |
372 ( bit3 & 0x1111111111111111ULL);
378 STATIC_INLINE uint32_t skinny64_sbox(uint32_t x)
411 x = (((x >> 3) & (x >> 2)) & 0x11111111U) ^ x;
412 x = (((x << 1) & (x << 2)) & 0x88888888U) ^ x;
413 x = (((x << 1) & (x << 2)) & 0x44444444U) ^ x;
414 x = (((x >> 2) & (x << 1)) & 0x22222222U) ^ x;
416 return ((x >> 1) & 0x77777777U) | ((x << 3) & 0x88888888U);
419 STATIC_INLINE uint32_t skinny64_inv_sbox(uint32_t x)
437 x = (((x >> 3) & (x >> 2)) & 0x11111111U) ^ x;
438 x = (((x << 1) & (x >> 2)) & 0x22222222U) ^ x;
439 x = (((x << 1) & (x << 2)) & 0x44444444U) ^ x;
440 x = (((x << 1) & (x << 2)) & 0x88888888U) ^ x;
442 return ((x << 1) & 0xEEEEEEEEU) | ((x >> 3) & 0x11111111U);
456 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
457 state.
llrow = READ_WORD64(input, 0);
458 #elif SKINNY_LITTLE_ENDIAN
459 state.
lrow[0] = READ_WORD32(input, 0);
460 state.
lrow[1] = READ_WORD32(input, 4);
462 state.
row[0] = READ_WORD16(input, 0);
463 state.
row[1] = READ_WORD16(input, 2);
464 state.
row[2] = READ_WORD16(input, 4);
465 state.
row[3] = READ_WORD16(input, 6);
470 for (index = ks->
rounds; index > 0; --index, ++schedule) {
475 state.
lrow[0] = skinny64_sbox(state.
lrow[0]);
476 state.
lrow[1] = skinny64_sbox(state.
lrow[1]);
480 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
481 state.
llrow ^= schedule->
lrow | 0x2000000000ULL;
484 state.
row[2] ^= 0x20;
488 state.
row[1] = skinny64_rotate_right(state.
row[1], 4);
489 state.
row[2] = skinny64_rotate_right(state.
row[2], 8);
490 state.
row[3] = skinny64_rotate_right(state.
row[3], 12);
493 state.
row[1] ^= state.
row[2];
494 state.
row[2] ^= state.
row[0];
495 temp = state.
row[3] ^ state.
row[2];
496 state.
row[3] = state.
row[2];
497 state.
row[2] = state.
row[1];
498 state.
row[1] = state.
row[0];
503 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
504 WRITE_WORD64(output, 0, state.
llrow);
505 #elif SKINNY_LITTLE_ENDIAN
506 WRITE_WORD32(output, 0, state.
lrow[0]);
507 WRITE_WORD32(output, 4, state.
lrow[1]);
509 WRITE_WORD16(output, 0, state.
row[0]);
510 WRITE_WORD16(output, 2, state.
row[1]);
511 WRITE_WORD16(output, 4, state.
row[2]);
512 WRITE_WORD16(output, 6, state.
row[3]);
525 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
526 state.
llrow = READ_WORD64(input, 0);
527 #elif SKINNY_LITTLE_ENDIAN
528 state.
lrow[0] = READ_WORD32(input, 0);
529 state.
lrow[1] = READ_WORD32(input, 4);
531 state.
row[0] = READ_WORD16(input, 0);
532 state.
row[1] = READ_WORD16(input, 2);
533 state.
row[2] = READ_WORD16(input, 4);
534 state.
row[3] = READ_WORD16(input, 6);
539 for (index = ks->
rounds; index > 0; --index, --schedule) {
542 state.
row[3] = state.
row[0];
543 state.
row[0] = state.
row[1];
544 state.
row[1] = state.
row[2];
545 state.
row[3] ^= temp;
546 state.
row[2] = temp ^ state.
row[0];
547 state.
row[1] ^= state.
row[2];
550 state.
row[1] = skinny64_rotate_right(state.
row[1], 12);
551 state.
row[2] = skinny64_rotate_right(state.
row[2], 8);
552 state.
row[3] = skinny64_rotate_right(state.
row[3], 4);
555 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
556 state.
llrow ^= schedule->
lrow | 0x2000000000ULL;
559 state.
row[2] ^= 0x20;
566 state.
lrow[0] = skinny64_inv_sbox(state.
lrow[0]);
567 state.
lrow[1] = skinny64_inv_sbox(state.
lrow[1]);
572 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
573 WRITE_WORD64(output, 0, state.
llrow);
574 #elif SKINNY_LITTLE_ENDIAN
575 WRITE_WORD32(output, 0, state.
lrow[0]);
576 WRITE_WORD32(output, 4, state.
lrow[1]);
578 WRITE_WORD16(output, 0, state.
row[0]);
579 WRITE_WORD16(output, 2, state.
row[1]);
580 WRITE_WORD16(output, 4, state.
row[2]);
581 WRITE_WORD16(output, 6, state.
row[3]);
int skinny64_set_tweak(Skinny64TweakedKey_t *ks, const void *tweak, unsigned tweak_size)
Changes the tweak value for a previously-initialized key schedule.
int skinny64_set_key(Skinny64Key_t *ks, const void *key, unsigned size)
Sets the key schedule for a Skinny64 block cipher.
int skinny64_set_tweaked_key(Skinny64TweakedKey_t *ks, const void *key, unsigned key_size)
Sets the key schedule for a Skinny64 block cipher, and prepare for tweaked encryption.
Key schedule for Skinny64 block ciphers when a tweak is in use.
void skinny64_ecb_decrypt(void *output, const void *input, const Skinny64Key_t *ks)
Decrypts a single block using the Skinny64 block cipher in ECB mode.
void skinny64_ecb_encrypt(void *output, const void *input, const Skinny64Key_t *ks)
Encrypts a single block using the Skinny64 block cipher in ECB mode.
Skinny64HalfCells_t schedule[SKINNY64_MAX_ROUNDS]
uint8_t tweak[SKINNY64_BLOCK_SIZE]
Key schedule for Skinny64 block ciphers.
Union that describes a 32-bit 2x4 array of cells.
#define SKINNY64_BLOCK_SIZE
Size of a block for Skinny64 block ciphers.
Union that describes a 64-bit 4x4 array of cells.