23 #include "mantis-cipher.h"
24 #include "skinny-internal.h"
26 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
29 #define RC_ROW_SIZE 64
33 (((((uint64_t)((x) >> 56)) & 0xFF)) | \
34 ((((uint64_t)((x) >> 48)) & 0xFF) << 8) | \
35 ((((uint64_t)((x) >> 40)) & 0xFF) << 16) | \
36 ((((uint64_t)((x) >> 32)) & 0xFF) << 24) | \
37 ((((uint64_t)((x) >> 24)) & 0xFF) << 32) | \
38 ((((uint64_t)((x) >> 16)) & 0xFF) << 40) | \
39 ((((uint64_t)((x) >> 8)) & 0xFF) << 48) | \
40 ((((uint64_t)((x) )) & 0xFF) << 56))
43 #define ALPHA (RC(0x243F6A8885A308D3ULL))
47 RC(0x13198A2E03707344ULL),
48 RC(0xA4093822299F31D0ULL),
49 RC(0x082EFA98EC4E6C89ULL),
50 RC(0x452821E638D01377ULL),
51 RC(0xBE5466CF34E90C6CULL),
52 RC(0xC0AC29B7C97C50DDULL),
53 RC(0x3F84D5B5B5470917ULL),
54 RC(0x9216D5D98979FB1BULL)
57 #elif SKINNY_LITTLE_ENDIAN
60 #define RC_ROW_SIZE 32
63 #define RC_EXTRACT_ROW(x,shift) \
64 (((((uint32_t)((x) >> ((shift) + 24))) & 0xFF)) | \
65 ((((uint32_t)((x) >> ((shift) + 16))) & 0xFF) << 8) | \
66 ((((uint32_t)((x) >> ((shift) + 8))) & 0xFF) << 16) | \
67 ((((uint32_t)((x) >> ((shift)))) & 0xFF) << 24))
71 {RC_EXTRACT_ROW((x), 32), RC_EXTRACT_ROW((x), 0)}
74 #define ALPHA 0x243F6A8885A308D3ULL
75 #define ALPHA_ROW0 (RC_EXTRACT_ROW(ALPHA, 32))
76 #define ALPHA_ROW1 (RC_EXTRACT_ROW(ALPHA, 0))
80 RC(0x13198A2E03707344ULL),
81 RC(0xA4093822299F31D0ULL),
82 RC(0x082EFA98EC4E6C89ULL),
83 RC(0x452821E638D01377ULL),
84 RC(0xBE5466CF34E90C6CULL),
85 RC(0xC0AC29B7C97C50DDULL),
86 RC(0x3F84D5B5B5470917ULL),
87 RC(0x9216D5D98979FB1BULL)
93 #define RC_ROW_SIZE 16
96 #define RC_EXTRACT_ROW(x,shift) \
97 (((((uint16_t)((x) >> ((shift) + 8))) & 0xFF)) | \
98 ((((uint16_t)((x) >> ((shift)))) & 0xFF) << 8))
102 {RC_EXTRACT_ROW((x), 48), RC_EXTRACT_ROW((x), 32), \
103 RC_EXTRACT_ROW((x), 16), RC_EXTRACT_ROW((x), 0)}
106 #define ALPHA 0x243F6A8885A308D3ULL
107 #define ALPHA_ROW0 (RC_EXTRACT_ROW(ALPHA, 48))
108 #define ALPHA_ROW1 (RC_EXTRACT_ROW(ALPHA, 32))
109 #define ALPHA_ROW2 (RC_EXTRACT_ROW(ALPHA, 16))
110 #define ALPHA_ROW3 (RC_EXTRACT_ROW(ALPHA, 0))
114 RC(0x13198A2E03707344ULL),
115 RC(0xA4093822299F31D0ULL),
116 RC(0x082EFA98EC4E6C89ULL),
117 RC(0x452821E638D01377ULL),
118 RC(0xBE5466CF34E90C6CULL),
119 RC(0xC0AC29B7C97C50DDULL),
120 RC(0x3F84D5B5B5470917ULL),
121 RC(0x9216D5D98979FB1BULL)
126 STATIC_INLINE
void mantis_unpack_block
129 #if SKINNY_LITTLE_ENDIAN
130 block->
lrow[0] = READ_WORD32(buf, offset);
131 block->
lrow[1] = READ_WORD32(buf, offset + 4);
133 block->
row[0] = READ_WORD16(buf, offset);
134 block->
row[1] = READ_WORD16(buf, offset + 2);
135 block->
row[2] = READ_WORD16(buf, offset + 4);
136 block->
row[3] = READ_WORD16(buf, offset + 6);
140 STATIC_INLINE
void mantis_unpack_rotated_block
149 rotated[index] = (carry << 7) | (next >> 1);
152 rotated[MANTIS_BLOCK_SIZE - 1] ^= (buf[0] >> 7);
153 mantis_unpack_block(block, rotated, 0);
158 unsigned rounds,
int mode)
172 mantis_unpack_block(&(ks->
k0), key, 0);
173 mantis_unpack_block(&(ks->
k1), key, 8);
174 mantis_unpack_rotated_block(&(ks->
k0prime), key);
177 mantis_unpack_rotated_block(&(ks->
k0), key);
178 mantis_unpack_block(&(ks->
k0prime), key, 0);
179 mantis_unpack_block(&(ks->
k1), key, 8);
180 #if RC_ROW_SIZE == 64
182 #elif RC_ROW_SIZE == 32
183 ks->
k1.
lrow[0] ^= ALPHA_ROW0;
184 ks->
k1.
lrow[1] ^= ALPHA_ROW1;
186 ks->
k1.
row[0] ^= ALPHA_ROW0;
187 ks->
k1.
row[1] ^= ALPHA_ROW1;
188 ks->
k1.
row[2] ^= ALPHA_ROW2;
189 ks->
k1.
row[3] ^= ALPHA_ROW3;
213 mantis_unpack_block(&(ks->
tweak), tweak, 0);
233 #if RC_ROW_SIZE == 64
235 #elif RC_ROW_SIZE == 32
236 ks->
k1.
lrow[0] ^= ALPHA_ROW0;
237 ks->
k1.
lrow[1] ^= ALPHA_ROW1;
239 ks->
k1.
row[0] ^= ALPHA_ROW0;
240 ks->
k1.
row[1] ^= ALPHA_ROW1;
241 ks->
k1.
row[2] ^= ALPHA_ROW2;
242 ks->
k1.
row[3] ^= ALPHA_ROW3;
248 STATIC_INLINE uint64_t mantis_sbox(uint64_t d)
260 uint64_t a = (d >> 3);
261 uint64_t b = (d >> 2);
262 uint64_t c = (d >> 1);
264 uint64_t ab = not_a | (~b);
265 uint64_t ad = not_a & (~d);
266 uint64_t aout = (((~c) & ab) | ad);
267 uint64_t bout = ad | (b & c) | (a & c & d);
268 uint64_t cout = (b & d) | ((b | d) & not_a);
269 uint64_t dout = (a | b | c) & ab & (c | d);
270 return ((aout & 0x1111111111111111U) << 3) |
271 ((bout & 0x1111111111111111U) << 2) |
272 ((cout & 0x1111111111111111U) << 1) |
273 (dout & 0x1111111111111111U);
278 STATIC_INLINE uint32_t mantis_sbox(uint32_t d)
290 uint32_t a = (d >> 3);
291 uint32_t b = (d >> 2);
292 uint32_t c = (d >> 1);
294 uint32_t ab = not_a | (~b);
295 uint32_t ad = not_a & (~d);
296 uint32_t aout = (((~c) & ab) | ad);
297 uint32_t bout = ad | (b & c) | (a & c & d);
298 uint32_t cout = (b & d) | ((b | d) & not_a);
299 uint32_t dout = (a | b | c) & ab & (c | d);
300 return ((aout & 0x11111111U) << 3) | ((bout & 0x11111111U) << 2) |
301 ((cout & 0x11111111U) << 1) | (dout & 0x11111111U);
309 uint16_t row1 = tweak->
row[1];
310 uint16_t row3 = tweak->
row[3];
311 tweak->
row[1] = tweak->
row[0];
312 tweak->
row[3] = tweak->
row[2];
313 tweak->
row[0] = ((row1 >> 8) & 0x00F0U) |
316 tweak->
row[2] = ((row1 << 4) & 0x0F00U) |
317 ((row1 >> 4) & 0x00F0U) |
318 ((row3 >> 4) & 0x000FU) |
319 ((row3 << 12) & 0xF000U);
322 STATIC_INLINE
void mantis_update_tweak_inverse(
MantisCells_t *tweak)
325 uint16_t row0 = tweak->
row[0];
326 uint16_t row2 = tweak->
row[2];
327 tweak->
row[0] = tweak->
row[1];
328 tweak->
row[2] = tweak->
row[3];
329 tweak->
row[1] = ((row2 >> 4) & 0x00F0U) |
330 ((row2 << 4) & 0x0F00U) |
332 ((row0 << 8) & 0xF000U);
333 tweak->
row[3] = (row0 & 0xFF00U) |
334 ((row2 << 4) & 0x00F0U) |
335 ((row2 >> 12) & 0x000FU);
341 uint16_t row0 = state->
row[0];
342 uint16_t row1 = state->
row[1];
343 uint16_t row2 = state->
row[2];
344 uint16_t row3 = state->
row[3];
345 state->
row[0] = (row0 & 0x00F0U) |
347 ((row2 >> 8) & 0x000FU) |
348 ((row3 << 8) & 0x0F00U);
349 state->
row[1] = (row0 & 0x000FU) |
351 ((row2 >> 8) & 0x00F0U) |
352 ((row3 << 8) & 0xF000U);
353 state->
row[2] = ((row0 << 4) & 0xF000U) |
354 ((row1 << 4) & 0x00F0U) |
355 ((row2 << 4) & 0x0F00U) |
356 ((row3 >> 12) & 0x000FU);
357 state->
row[3] = ((row0 >> 4) & 0x0F00U) |
358 ((row1 >> 4) & 0x000FU) |
359 ((row2 << 12) & 0xF000U) |
360 ((row3 >> 4) & 0x00F0U);
363 STATIC_INLINE
void mantis_shift_rows_inverse(
MantisCells_t *state)
366 uint16_t row0 = state->
row[0];
367 uint16_t row1 = state->
row[1];
368 uint16_t row2 = state->
row[2];
369 uint16_t row3 = state->
row[3];
370 state->
row[0] = (row0 & 0x00F0U) |
372 ((row2 >> 4) & 0x0F00U) |
373 ((row3 << 4) & 0xF000U);
374 state->
row[1] = (row0 & 0xF000U) |
376 ((row2 >> 4) & 0x000FU) |
377 ((row3 << 4) & 0x00F0U);
378 state->
row[2] = ((row0 << 8) & 0x0F00U) |
379 ((row1 << 8) & 0xF000U) |
380 ((row2 >> 4) & 0x00F0U) |
381 ((row3 >> 12) & 0x000FU);
382 state->
row[3] = ((row0 >> 8) & 0x000FU) |
383 ((row1 >> 8) & 0x00F0U) |
384 ((row2 << 12) & 0xF000U) |
385 ((row3 << 4) & 0x0F00U);
390 uint16_t t0 = state->
row[0];
391 uint16_t t1 = state->
row[1];
392 uint16_t t2 = state->
row[2];
393 uint16_t t3 = state->
row[3];
394 state->
row[0] = t1 ^ t2 ^ t3;
395 state->
row[1] = t0 ^ t2 ^ t3;
396 state->
row[2] = t0 ^ t1 ^ t3;
397 state->
row[3] = t0 ^ t1 ^ t2;
402 #if RC_ROW_SIZE == 64
403 const uint64_t *r = &(rc[0]);
404 #elif RC_ROW_SIZE == 32
405 const uint32_t *r = rc[0];
407 const uint16_t *r = rc[0];
415 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
416 state.
llrow = READ_WORD64(input, 0);
417 #elif SKINNY_LITTLE_ENDIAN
418 state.
lrow[0] = READ_WORD32(input, 0);
419 state.
lrow[1] = READ_WORD32(input, 4);
421 state.
row[0] = READ_WORD16(input, 0);
422 state.
row[1] = READ_WORD16(input, 2);
423 state.
row[2] = READ_WORD16(input, 4);
424 state.
row[3] = READ_WORD16(input, 6);
437 for (index = ks->
rounds; index > 0; --index) {
439 mantis_update_tweak(&tweak);
445 state.
lrow[0] = mantis_sbox(state.
lrow[0]);
446 state.
lrow[1] = mantis_sbox(state.
lrow[1]);
450 #if RC_ROW_SIZE == 64
453 #elif RC_ROW_SIZE == 32
454 state.
lrow[0] ^= r[0];
455 state.
lrow[1] ^= r[1];
458 state.
row[0] ^= r[0];
459 state.
row[1] ^= r[1];
460 state.
row[2] ^= r[2];
461 state.
row[3] ^= r[3];
474 mantis_shift_rows(&state);
477 mantis_mix_columns(&state);
483 mantis_mix_columns(&state);
486 state.
lrow[0] = mantis_sbox(state.
lrow[0]);
487 state.
lrow[1] = mantis_sbox(state.
lrow[1]);
488 mantis_mix_columns(&state);
489 state.
lrow[0] = mantis_sbox(state.
lrow[0]);
490 state.
lrow[1] = mantis_sbox(state.
lrow[1]);
494 #if RC_ROW_SIZE == 64
496 #elif RC_ROW_SIZE == 32
497 k1.
lrow[0] ^= ALPHA_ROW0;
498 k1.
lrow[1] ^= ALPHA_ROW1;
500 k1.
row[0] ^= ALPHA_ROW0;
501 k1.
row[1] ^= ALPHA_ROW1;
502 k1.
row[2] ^= ALPHA_ROW2;
503 k1.
row[3] ^= ALPHA_ROW3;
507 for (index = ks->
rounds; index > 0; --index) {
509 mantis_mix_columns(&state);
512 mantis_shift_rows_inverse(&state);
523 #if RC_ROW_SIZE == 64
526 #elif RC_ROW_SIZE == 32
528 state.
lrow[0] ^= r[0];
529 state.
lrow[1] ^= r[1];
532 state.
row[0] ^= r[0];
533 state.
row[1] ^= r[1];
534 state.
row[2] ^= r[2];
535 state.
row[3] ^= r[3];
542 state.
lrow[0] = mantis_sbox(state.
lrow[0]);
543 state.
lrow[1] = mantis_sbox(state.
lrow[1]);
547 mantis_update_tweak_inverse(&tweak);
560 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
561 WRITE_WORD64(output, 0, state.
llrow);
562 #elif SKINNY_LITTLE_ENDIAN
563 WRITE_WORD32(output, 0, state.
lrow[0]);
564 WRITE_WORD32(output, 4, state.
lrow[1]);
566 WRITE_WORD16(output, 0, state.
row[0]);
567 WRITE_WORD16(output, 2, state.
row[1]);
568 WRITE_WORD16(output, 4, state.
row[2]);
569 WRITE_WORD16(output, 6, state.
row[3]);
574 (
void *output,
const void *input,
const void *tweak,
const MantisKey_t *ks)
576 #if RC_ROW_SIZE == 64
577 const uint64_t *r = &(rc[0]);
578 #elif RC_ROW_SIZE == 32
579 const uint32_t *r = rc[0];
581 const uint16_t *r = rc[0];
589 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
590 state.
llrow = READ_WORD64(input, 0);
591 tk.
llrow = READ_WORD64(tweak, 0);
592 #elif SKINNY_LITTLE_ENDIAN
593 state.
lrow[0] = READ_WORD32(input, 0);
594 state.
lrow[1] = READ_WORD32(input, 4);
595 tk.
lrow[0] = READ_WORD32(tweak, 0);
596 tk.
lrow[1] = READ_WORD32(tweak, 4);
598 state.
row[0] = READ_WORD16(input, 0);
599 state.
row[1] = READ_WORD16(input, 2);
600 state.
row[2] = READ_WORD16(input, 4);
601 state.
row[3] = READ_WORD16(input, 6);
602 tk.
row[0] = READ_WORD16(tweak, 0);
603 tk.
row[1] = READ_WORD16(tweak, 2);
604 tk.
row[2] = READ_WORD16(tweak, 4);
605 tk.
row[3] = READ_WORD16(tweak, 6);
618 for (index = ks->
rounds; index > 0; --index) {
620 mantis_update_tweak(&tk);
626 state.
lrow[0] = mantis_sbox(state.
lrow[0]);
627 state.
lrow[1] = mantis_sbox(state.
lrow[1]);
631 #if RC_ROW_SIZE == 64
634 #elif RC_ROW_SIZE == 32
635 state.
lrow[0] ^= r[0];
636 state.
lrow[1] ^= r[1];
639 state.
row[0] ^= r[0];
640 state.
row[1] ^= r[1];
641 state.
row[2] ^= r[2];
642 state.
row[3] ^= r[3];
655 mantis_shift_rows(&state);
658 mantis_mix_columns(&state);
664 mantis_mix_columns(&state);
667 state.
lrow[0] = mantis_sbox(state.
lrow[0]);
668 state.
lrow[1] = mantis_sbox(state.
lrow[1]);
669 mantis_mix_columns(&state);
670 state.
lrow[0] = mantis_sbox(state.
lrow[0]);
671 state.
lrow[1] = mantis_sbox(state.
lrow[1]);
675 #if RC_ROW_SIZE == 64
677 #elif RC_ROW_SIZE == 32
678 k1.
lrow[0] ^= ALPHA_ROW0;
679 k1.
lrow[1] ^= ALPHA_ROW1;
681 k1.
row[0] ^= ALPHA_ROW0;
682 k1.
row[1] ^= ALPHA_ROW1;
683 k1.
row[2] ^= ALPHA_ROW2;
684 k1.
row[3] ^= ALPHA_ROW3;
688 for (index = ks->
rounds; index > 0; --index) {
690 mantis_mix_columns(&state);
693 mantis_shift_rows_inverse(&state);
704 #if RC_ROW_SIZE == 64
707 #elif RC_ROW_SIZE == 32
709 state.
lrow[0] ^= r[0];
710 state.
lrow[1] ^= r[1];
713 state.
row[0] ^= r[0];
714 state.
row[1] ^= r[1];
715 state.
row[2] ^= r[2];
716 state.
row[3] ^= r[3];
723 state.
lrow[0] = mantis_sbox(state.
lrow[0]);
724 state.
lrow[1] = mantis_sbox(state.
lrow[1]);
728 mantis_update_tweak_inverse(&tk);
741 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
742 WRITE_WORD64(output, 0, state.
llrow);
743 #elif SKINNY_LITTLE_ENDIAN
744 WRITE_WORD32(output, 0, state.
lrow[0]);
745 WRITE_WORD32(output, 4, state.
lrow[1]);
747 WRITE_WORD16(output, 0, state.
row[0]);
748 WRITE_WORD16(output, 2, state.
row[1]);
749 WRITE_WORD16(output, 4, state.
row[2]);
750 WRITE_WORD16(output, 6, state.
row[3]);
void mantis_swap_modes(MantisKey_t *ks)
Swaps the encryption and decryption modes on a Mantis key schedule.
#define MANTIS_ENCRYPT
Mode that selects Mantis encryption when the key schedule is setup.
void mantis_ecb_crypt(void *output, const void *input, const MantisKey_t *ks)
Encrypts or decrypts a single block using the Mantis block cipher in ECB mode.
int mantis_set_tweak(MantisKey_t *ks, const void *tweak, unsigned size)
Sets the tweak value for a previously-initialized key schedule.
#define MANTIS_MAX_ROUNDS
Maximum number of rounds for Mantis block ciphers.
#define MANTIS_BLOCK_SIZE
Size of a block for Mantis block ciphers.
int mantis_set_key(MantisKey_t *ks, const void *key, unsigned size, unsigned rounds, int mode)
Sets the key schedule for a Mantis block cipher.
Key schedule for Mantis block ciphers.
#define MANTIS_KEY_SIZE
Size of a Mantis block cipher key.
#define MANTIS_TWEAK_SIZE
Size of a Mantis block cipher tweak.
void mantis_ecb_crypt_tweaked(void *output, const void *input, const void *tweak, const MantisKey_t *ks)
Encrypts or decrypts a single block using the Mantis block cipher in ECB mode, with the tweak supplie...
#define MANTIS_MIN_ROUNDS
Minimum number of rounds for Mantis block ciphers.
Union that describes a 64-bit 4x4 array of cells.