Skinny-C
 All Data Structures Files Functions Variables Groups Pages
mantis-cipher.c
1 /*
2  * Copyright (C) 2017 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "mantis-cipher.h"
24 #include "skinny-internal.h"
25 
26 #if SKINNY_64BIT && SKINNY_LITTLE_ENDIAN
27 
28 /* Size of each RC row value in bits */
29 #define RC_ROW_SIZE 64
30 
31 /* Swap the bits in an RC constant to convert into host-endian */
32 #define RC(x) \
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))
41 
42 /* Alpha constant for adjusting k1 for the inverse rounds */
43 #define ALPHA (RC(0x243F6A8885A308D3ULL))
44 
45 /* Round constants for Mantis, split up into 64-bit row values */
46 static uint64_t const rc[MANTIS_MAX_ROUNDS] = {
47  RC(0x13198A2E03707344ULL),
48  RC(0xA4093822299F31D0ULL),
49  RC(0x082EFA98EC4E6C89ULL),
50  RC(0x452821E638D01377ULL),
51  RC(0xBE5466CF34E90C6CULL),
52  RC(0xC0AC29B7C97C50DDULL),
53  RC(0x3F84D5B5B5470917ULL),
54  RC(0x9216D5D98979FB1BULL)
55 };
56 
57 #elif SKINNY_LITTLE_ENDIAN
58 
59 /* Size of each RC row value in bits */
60 #define RC_ROW_SIZE 32
61 
62 /* Extract the 32 bits for a row from a 64-bit round constant */
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))
68 
69 /* Extract the rows from a 64-bit round constant */
70 #define RC(x) \
71  {RC_EXTRACT_ROW((x), 32), RC_EXTRACT_ROW((x), 0)}
72 
73 /* Alpha constant for adjusting k1 for the inverse rounds */
74 #define ALPHA 0x243F6A8885A308D3ULL
75 #define ALPHA_ROW0 (RC_EXTRACT_ROW(ALPHA, 32))
76 #define ALPHA_ROW1 (RC_EXTRACT_ROW(ALPHA, 0))
77 
78 /* Round constants for Mantis, split up into 32-bit row values */
79 static uint32_t const rc[MANTIS_MAX_ROUNDS][2] = {
80  RC(0x13198A2E03707344ULL),
81  RC(0xA4093822299F31D0ULL),
82  RC(0x082EFA98EC4E6C89ULL),
83  RC(0x452821E638D01377ULL),
84  RC(0xBE5466CF34E90C6CULL),
85  RC(0xC0AC29B7C97C50DDULL),
86  RC(0x3F84D5B5B5470917ULL),
87  RC(0x9216D5D98979FB1BULL)
88 };
89 
90 #else
91 
92 /* Size of each RC row value in bits */
93 #define RC_ROW_SIZE 16
94 
95 /* Extract the 16 bits for a row from a 64-bit round constant */
96 #define RC_EXTRACT_ROW(x,shift) \
97  (((((uint16_t)((x) >> ((shift) + 8))) & 0xFF)) | \
98  ((((uint16_t)((x) >> ((shift)))) & 0xFF) << 8))
99 
100 /* Extract the rows from a 64-bit round constant */
101 #define RC(x) \
102  {RC_EXTRACT_ROW((x), 48), RC_EXTRACT_ROW((x), 32), \
103  RC_EXTRACT_ROW((x), 16), RC_EXTRACT_ROW((x), 0)}
104 
105 /* Alpha constant for adjusting k1 for the inverse rounds */
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))
111 
112 /* Round constants for Mantis, split up into 16-bit row values */
113 static uint16_t const rc[MANTIS_MAX_ROUNDS][4] = {
114  RC(0x13198A2E03707344ULL),
115  RC(0xA4093822299F31D0ULL),
116  RC(0x082EFA98EC4E6C89ULL),
117  RC(0x452821E638D01377ULL),
118  RC(0xBE5466CF34E90C6CULL),
119  RC(0xC0AC29B7C97C50DDULL),
120  RC(0x3F84D5B5B5470917ULL),
121  RC(0x9216D5D98979FB1BULL)
122 };
123 
124 #endif
125 
126 STATIC_INLINE void mantis_unpack_block
127  (MantisCells_t *block, const uint8_t *buf, unsigned offset)
128 {
129 #if SKINNY_LITTLE_ENDIAN
130  block->lrow[0] = READ_WORD32(buf, offset);
131  block->lrow[1] = READ_WORD32(buf, offset + 4);
132 #else
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);
137 #endif
138 }
139 
140 STATIC_INLINE void mantis_unpack_rotated_block
141  (MantisCells_t *block, const uint8_t *buf)
142 {
143  uint8_t rotated[MANTIS_BLOCK_SIZE];
144  unsigned index;
145  uint8_t next;
146  uint8_t carry = buf[MANTIS_BLOCK_SIZE - 1];
147  for (index = 0; index < MANTIS_BLOCK_SIZE; ++index) {
148  next = buf[index];
149  rotated[index] = (carry << 7) | (next >> 1);
150  carry = next;
151  }
152  rotated[MANTIS_BLOCK_SIZE - 1] ^= (buf[0] >> 7);
153  mantis_unpack_block(block, rotated, 0);
154 }
155 
156 int mantis_set_key
157  (MantisKey_t *ks, const void *key, unsigned size,
158  unsigned rounds, int mode)
159 {
160  /* Validate the parameters */
161  if (!ks || !key || size != MANTIS_KEY_SIZE ||
162  rounds < MANTIS_MIN_ROUNDS ||
163  rounds > MANTIS_MAX_ROUNDS)
164  return 0;
165 
166  /* Set the round count */
167  ks->rounds = rounds;
168 
169  /* Set up the encryption or decryption key */
170  if (mode == MANTIS_ENCRYPT) {
171  /* Encryption */
172  mantis_unpack_block(&(ks->k0), key, 0);
173  mantis_unpack_block(&(ks->k1), key, 8);
174  mantis_unpack_rotated_block(&(ks->k0prime), key);
175  } else {
176  /* Decryption */
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
181  ks->k1.llrow ^= ALPHA;
182 #elif RC_ROW_SIZE == 32
183  ks->k1.lrow[0] ^= ALPHA_ROW0;
184  ks->k1.lrow[1] ^= ALPHA_ROW1;
185 #else
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;
190 #endif
191  }
192 
193  /* Set up the default tweak of zero */
194 #if SKINNY_64BIT
195  ks->tweak.llrow = 0;
196 #else
197  ks->tweak.lrow[0] = 0;
198  ks->tweak.lrow[1] = 0;
199 #endif
200 
201  /* Ready to go */
202  return 1;
203 }
204 
205 int mantis_set_tweak(MantisKey_t *ks, const void *tweak, unsigned size)
206 {
207  /* Validate the parameters */
208  if (!ks || size != MANTIS_TWEAK_SIZE)
209  return 0;
210 
211  /* Set up the new tweak */
212  if (tweak) {
213  mantis_unpack_block(&(ks->tweak), tweak, 0);
214  } else {
215 #if SKINNY_64BIT
216  ks->tweak.llrow = 0;
217 #else
218  ks->tweak.lrow[0] = 0;
219  ks->tweak.lrow[1] = 0;
220 #endif
221  }
222  return 1;
223 }
224 
226 {
227  /* Swap k0 with k0prime */
228  MantisCells_t tmp = ks->k0;
229  ks->k0 = ks->k0prime;
230  ks->k0prime = tmp;
231 
232  /* XOR k1 with the alpha constant */
233 #if RC_ROW_SIZE == 64
234  ks->k1.llrow ^= ALPHA;
235 #elif RC_ROW_SIZE == 32
236  ks->k1.lrow[0] ^= ALPHA_ROW0;
237  ks->k1.lrow[1] ^= ALPHA_ROW1;
238 #else
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;
243 #endif
244 }
245 
246 #if SKINNY_64BIT
247 
248 STATIC_INLINE uint64_t mantis_sbox(uint64_t d)
249 {
250  /*
251  * MIDORI Sb0 from section 4.2 of https://eprint.iacr.org/2015/1142.pdf
252  *
253  * {a, b, c, d} -> {aout, bout, cout, dout} where a/aout is the MSB.
254  *
255  * aout = NAND(NAND(~c, NAND(a, b)), (a | d))
256  * bout = NAND(NOR(NOR(a, d), (b & c)), NAND((a & c), d))
257  * cout = NAND(NAND(b, d), (NOR(b, d) | a))
258  * dout = NOR(NOR(a, (b | c)), NAND(NAND(a, b), (c | d)))
259  */
260  uint64_t a = (d >> 3);
261  uint64_t b = (d >> 2);
262  uint64_t c = (d >> 1);
263  uint64_t not_a = ~a;
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);
274 }
275 
276 #else
277 
278 STATIC_INLINE uint32_t mantis_sbox(uint32_t d)
279 {
280  /*
281  * MIDORI Sb0 from section 4.2 of https://eprint.iacr.org/2015/1142.pdf
282  *
283  * {a, b, c, d} -> {aout, bout, cout, dout} where a/aout is the MSB.
284  *
285  * aout = NAND(NAND(~c, NAND(a, b)), (a | d))
286  * bout = NAND(NOR(NOR(a, d), (b & c)), NAND((a & c), d))
287  * cout = NAND(NAND(b, d), (NOR(b, d) | a))
288  * dout = NOR(NOR(a, (b | c)), NAND(NAND(a, b), (c | d)))
289  */
290  uint32_t a = (d >> 3);
291  uint32_t b = (d >> 2);
292  uint32_t c = (d >> 1);
293  uint32_t not_a = ~a;
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);
302 }
303 
304 #endif
305 
306 STATIC_INLINE void mantis_update_tweak(MantisCells_t *tweak)
307 {
308  /* h = [6, 5, 14, 15, 0, 1, 2, 3, 7, 12, 13, 4, 8, 9, 10, 11] */
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) |
314  (row1 & 0x000FU) |
315  (row3 & 0xFF00U);
316  tweak->row[2] = ((row1 << 4) & 0x0F00U) |
317  ((row1 >> 4) & 0x00F0U) |
318  ((row3 >> 4) & 0x000FU) |
319  ((row3 << 12) & 0xF000U);
320 }
321 
322 STATIC_INLINE void mantis_update_tweak_inverse(MantisCells_t *tweak)
323 {
324  /* h' = [4, 5, 6, 7, 11, 1, 0, 8, 12, 13, 14, 15, 9, 10, 2, 3] */
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) |
331  (row0 & 0x000FU) |
332  ((row0 << 8) & 0xF000U);
333  tweak->row[3] = (row0 & 0xFF00U) |
334  ((row2 << 4) & 0x00F0U) |
335  ((row2 >> 12) & 0x000FU);
336 }
337 
338 STATIC_INLINE void mantis_shift_rows(MantisCells_t *state)
339 {
340  /* P = [0, 11, 6, 13, 10, 1, 12, 7, 5, 14, 3, 8, 15, 4, 9, 2] */
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) |
346  (row1 & 0xF000U) |
347  ((row2 >> 8) & 0x000FU) |
348  ((row3 << 8) & 0x0F00U);
349  state->row[1] = (row0 & 0x000FU) |
350  (row1 & 0x0F00U) |
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);
361 }
362 
363 STATIC_INLINE void mantis_shift_rows_inverse(MantisCells_t *state)
364 {
365  /* P' = [0, 5, 15, 10, 13, 8, 2, 7, 11, 14, 4, 1, 6, 3, 9, 12] */
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) |
371  (row1 & 0x000FU) |
372  ((row2 >> 4) & 0x0F00U) |
373  ((row3 << 4) & 0xF000U);
374  state->row[1] = (row0 & 0xF000U) |
375  (row1 & 0x0F00U) |
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);
386 }
387 
388 STATIC_INLINE void mantis_mix_columns(MantisCells_t *state)
389 {
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;
398 }
399 
400 void mantis_ecb_crypt(void *output, const void *input, const MantisKey_t *ks)
401 {
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];
406 #else
407  const uint16_t *r = rc[0];
408 #endif
409  MantisCells_t tweak = ks->tweak;
410  MantisCells_t k1 = ks->k1;
411  MantisCells_t state;
412  unsigned index;
413 
414  /* Read the input buffer and convert little-endian to host-endian */
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);
420 #else
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);
425 #endif
426 
427  /* XOR the initial whitening key k0 with the state,
428  together with k1 and the initial tweak value */
429 #if SKINNY_64BIT
430  state.llrow ^= ks->k0.llrow ^ k1.llrow ^ tweak.llrow;
431 #else
432  state.lrow[0] ^= ks->k0.lrow[0] ^ k1.lrow[0] ^ tweak.lrow[0];
433  state.lrow[1] ^= ks->k0.lrow[1] ^ k1.lrow[1] ^ tweak.lrow[1];
434 #endif
435 
436  /* Perform all forward rounds */
437  for (index = ks->rounds; index > 0; --index) {
438  /* Update the tweak with the forward h function */
439  mantis_update_tweak(&tweak);
440 
441  /* Apply the S-box */
442 #if SKINNY_64BIT
443  state.llrow = mantis_sbox(state.llrow);
444 #else
445  state.lrow[0] = mantis_sbox(state.lrow[0]);
446  state.lrow[1] = mantis_sbox(state.lrow[1]);
447 #endif
448 
449  /* Add the round constant */
450 #if RC_ROW_SIZE == 64
451  state.llrow ^= r[0];
452  ++r;
453 #elif RC_ROW_SIZE == 32
454  state.lrow[0] ^= r[0];
455  state.lrow[1] ^= r[1];
456  r += 2;
457 #else
458  state.row[0] ^= r[0];
459  state.row[1] ^= r[1];
460  state.row[2] ^= r[2];
461  state.row[3] ^= r[3];
462  r += 4;
463 #endif
464 
465  /* XOR with the key and tweak */
466 #if SKINNY_64BIT
467  state.llrow ^= k1.llrow ^ tweak.llrow;
468 #else
469  state.lrow[0] ^= k1.lrow[0] ^ tweak.lrow[0];
470  state.lrow[1] ^= k1.lrow[1] ^ tweak.lrow[1];
471 #endif
472 
473  /* Shift the rows */
474  mantis_shift_rows(&state);
475 
476  /* Mix the columns */
477  mantis_mix_columns(&state);
478  }
479 
480  /* Half-way there: sbox, mix, sbox */
481 #if SKINNY_64BIT
482  state.llrow = mantis_sbox(state.llrow);
483  mantis_mix_columns(&state);
484  state.llrow = mantis_sbox(state.llrow);
485 #else
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]);
491 #endif
492 
493  /* Convert k1 into k1 XOR alpha for the reverse rounds */
494 #if RC_ROW_SIZE == 64
495  k1.llrow ^= ALPHA;
496 #elif RC_ROW_SIZE == 32
497  k1.lrow[0] ^= ALPHA_ROW0;
498  k1.lrow[1] ^= ALPHA_ROW1;
499 #else
500  k1.row[0] ^= ALPHA_ROW0;
501  k1.row[1] ^= ALPHA_ROW1;
502  k1.row[2] ^= ALPHA_ROW2;
503  k1.row[3] ^= ALPHA_ROW3;
504 #endif
505 
506  /* Perform all reverse rounds */
507  for (index = ks->rounds; index > 0; --index) {
508  /* Inverse mix of the columns (same as the forward mix) */
509  mantis_mix_columns(&state);
510 
511  /* Inverse shift of the rows */
512  mantis_shift_rows_inverse(&state);
513 
514  /* XOR with the key and tweak */
515 #if SKINNY_64BIT
516  state.llrow ^= k1.llrow ^ tweak.llrow;
517 #else
518  state.lrow[0] ^= k1.lrow[0] ^ tweak.lrow[0];
519  state.lrow[1] ^= k1.lrow[1] ^ tweak.lrow[1];
520 #endif
521 
522  /* Add the round constant */
523 #if RC_ROW_SIZE == 64
524  --r;
525  state.llrow ^= r[0];
526 #elif RC_ROW_SIZE == 32
527  r -= 2;
528  state.lrow[0] ^= r[0];
529  state.lrow[1] ^= r[1];
530 #else
531  r -= 4;
532  state.row[0] ^= r[0];
533  state.row[1] ^= r[1];
534  state.row[2] ^= r[2];
535  state.row[3] ^= r[3];
536 #endif
537 
538  /* Apply the inverse S-box (which is the same as the forward S-box) */
539 #if SKINNY_64BIT
540  state.llrow = mantis_sbox(state.llrow);
541 #else
542  state.lrow[0] = mantis_sbox(state.lrow[0]);
543  state.lrow[1] = mantis_sbox(state.lrow[1]);
544 #endif
545 
546  /* Update the tweak with the reverse h function */
547  mantis_update_tweak_inverse(&tweak);
548  }
549 
550  /* XOR the final whitening key k0prime with the state,
551  together with k1alpha and the final tweak value */
552 #if SKINNY_64BIT
553  state.llrow ^= ks->k0prime.llrow ^ k1.llrow ^ tweak.llrow;
554 #else
555  state.lrow[0] ^= ks->k0prime.lrow[0] ^ k1.lrow[0] ^ tweak.lrow[0];
556  state.lrow[1] ^= ks->k0prime.lrow[1] ^ k1.lrow[1] ^ tweak.lrow[1];
557 #endif
558 
559  /* Convert host-endian back into little-endian in the output buffer */
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]);
565 #else
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]);
570 #endif
571 }
572 
574  (void *output, const void *input, const void *tweak, const MantisKey_t *ks)
575 {
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];
580 #else
581  const uint16_t *r = rc[0];
582 #endif
583  MantisCells_t tk;
584  MantisCells_t k1 = ks->k1;
585  MantisCells_t state;
586  unsigned index;
587 
588  /* Read the input and tweak and convert little-endian to host-endian */
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);
597 #else
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);
606 #endif
607 
608  /* XOR the initial whitening key k0 with the state,
609  together with k1 and the initial tweak value */
610 #if SKINNY_64BIT
611  state.llrow ^= ks->k0.llrow ^ k1.llrow ^ tk.llrow;
612 #else
613  state.lrow[0] ^= ks->k0.lrow[0] ^ k1.lrow[0] ^ tk.lrow[0];
614  state.lrow[1] ^= ks->k0.lrow[1] ^ k1.lrow[1] ^ tk.lrow[1];
615 #endif
616 
617  /* Perform all forward rounds */
618  for (index = ks->rounds; index > 0; --index) {
619  /* Update the tweak with the forward h function */
620  mantis_update_tweak(&tk);
621 
622  /* Apply the S-box */
623 #if SKINNY_64BIT
624  state.llrow = mantis_sbox(state.llrow);
625 #else
626  state.lrow[0] = mantis_sbox(state.lrow[0]);
627  state.lrow[1] = mantis_sbox(state.lrow[1]);
628 #endif
629 
630  /* Add the round constant */
631 #if RC_ROW_SIZE == 64
632  state.llrow ^= r[0];
633  ++r;
634 #elif RC_ROW_SIZE == 32
635  state.lrow[0] ^= r[0];
636  state.lrow[1] ^= r[1];
637  r += 2;
638 #else
639  state.row[0] ^= r[0];
640  state.row[1] ^= r[1];
641  state.row[2] ^= r[2];
642  state.row[3] ^= r[3];
643  r += 4;
644 #endif
645 
646  /* XOR with the key and tweak */
647 #if SKINNY_64BIT
648  state.llrow ^= k1.llrow ^ tk.llrow;
649 #else
650  state.lrow[0] ^= k1.lrow[0] ^ tk.lrow[0];
651  state.lrow[1] ^= k1.lrow[1] ^ tk.lrow[1];
652 #endif
653 
654  /* Shift the rows */
655  mantis_shift_rows(&state);
656 
657  /* Mix the columns */
658  mantis_mix_columns(&state);
659  }
660 
661  /* Half-way there: sbox, mix, sbox */
662 #if SKINNY_64BIT
663  state.llrow = mantis_sbox(state.llrow);
664  mantis_mix_columns(&state);
665  state.llrow = mantis_sbox(state.llrow);
666 #else
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]);
672 #endif
673 
674  /* Convert k1 into k1 XOR alpha for the reverse rounds */
675 #if RC_ROW_SIZE == 64
676  k1.llrow ^= ALPHA;
677 #elif RC_ROW_SIZE == 32
678  k1.lrow[0] ^= ALPHA_ROW0;
679  k1.lrow[1] ^= ALPHA_ROW1;
680 #else
681  k1.row[0] ^= ALPHA_ROW0;
682  k1.row[1] ^= ALPHA_ROW1;
683  k1.row[2] ^= ALPHA_ROW2;
684  k1.row[3] ^= ALPHA_ROW3;
685 #endif
686 
687  /* Perform all reverse rounds */
688  for (index = ks->rounds; index > 0; --index) {
689  /* Inverse mix of the columns (same as the forward mix) */
690  mantis_mix_columns(&state);
691 
692  /* Inverse shift of the rows */
693  mantis_shift_rows_inverse(&state);
694 
695  /* XOR with the key and tweak */
696 #if SKINNY_64BIT
697  state.llrow ^= k1.llrow ^ tk.llrow;
698 #else
699  state.lrow[0] ^= k1.lrow[0] ^ tk.lrow[0];
700  state.lrow[1] ^= k1.lrow[1] ^ tk.lrow[1];
701 #endif
702 
703  /* Add the round constant */
704 #if RC_ROW_SIZE == 64
705  --r;
706  state.llrow ^= r[0];
707 #elif RC_ROW_SIZE == 32
708  r -= 2;
709  state.lrow[0] ^= r[0];
710  state.lrow[1] ^= r[1];
711 #else
712  r -= 4;
713  state.row[0] ^= r[0];
714  state.row[1] ^= r[1];
715  state.row[2] ^= r[2];
716  state.row[3] ^= r[3];
717 #endif
718 
719  /* Apply the inverse S-box (which is the same as the forward S-box) */
720 #if SKINNY_64BIT
721  state.llrow = mantis_sbox(state.llrow);
722 #else
723  state.lrow[0] = mantis_sbox(state.lrow[0]);
724  state.lrow[1] = mantis_sbox(state.lrow[1]);
725 #endif
726 
727  /* Update the tweak with the reverse h function */
728  mantis_update_tweak_inverse(&tk);
729  }
730 
731  /* XOR the final whitening key k0prime with the state,
732  together with k1alpha and the final tweak value */
733 #if SKINNY_64BIT
734  state.llrow ^= ks->k0prime.llrow ^ k1.llrow ^ tk.llrow;
735 #else
736  state.lrow[0] ^= ks->k0prime.lrow[0] ^ k1.lrow[0] ^ tk.lrow[0];
737  state.lrow[1] ^= ks->k0prime.lrow[1] ^ k1.lrow[1] ^ tk.lrow[1];
738 #endif
739 
740  /* Convert host-endian back into little-endian in the output buffer */
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]);
746 #else
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]);
751 #endif
752 }
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.
Definition: mantis-cipher.h:87
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.
MantisCells_t tweak
int mantis_set_tweak(MantisKey_t *ks, const void *tweak, unsigned size)
Sets the tweak value for a previously-initialized key schedule.
MantisCells_t k1
#define MANTIS_MAX_ROUNDS
Maximum number of rounds for Mantis block ciphers.
Definition: mantis-cipher.h:82
#define MANTIS_BLOCK_SIZE
Size of a block for Mantis block ciphers.
Definition: mantis-cipher.h:59
uint32_t lrow[2]
unsigned rounds
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.
uint64_t llrow
MantisCells_t k0prime
Key schedule for Mantis block ciphers.
#define MANTIS_KEY_SIZE
Size of a Mantis block cipher key.
Definition: mantis-cipher.h:64
#define MANTIS_TWEAK_SIZE
Size of a Mantis block cipher tweak.
Definition: mantis-cipher.h:69
MantisCells_t k0
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.
Definition: mantis-cipher.h:77
Union that describes a 64-bit 4x4 array of cells.
Definition: mantis-cipher.h:97
uint16_t row[4]
Definition: mantis-cipher.h:99