23 #include "mantis-cipher.h"
24 #include "mantis-ctr-internal.h"
25 #include "skinny-internal.h"
28 #if SKINNY_VEC128_MATH
31 #define MANTIS_CTR_BLOCK_SIZE (MANTIS_BLOCK_SIZE * 8)
40 SkinnyVector8x16_t counter[4];
43 unsigned char ecounter[MANTIS_CTR_BLOCK_SIZE];
51 } MantisCTRVec128Ctx_t;
55 MantisCTRVec128Ctx_t *ctx;
57 if ((ctx = skinny_calloc(
sizeof(MantisCTRVec128Ctx_t), &base_ptr)) == NULL)
59 ctx->base_ptr = base_ptr;
60 ctx->offset = MANTIS_CTR_BLOCK_SIZE;
65 static void mantis_ctr_vec128_cleanup(
MantisCTR_t *ctr)
68 MantisCTRVec128Ctx_t *ctx = ctr->
ctx;
69 void *base_ptr = ctx->base_ptr;
70 skinny_cleanse(ctx,
sizeof(MantisCTRVec128Ctx_t));
76 static int mantis_ctr_vec128_set_key
77 (
MantisCTR_t *ctr,
const void *key,
unsigned size,
unsigned rounds)
79 MantisCTRVec128Ctx_t *ctx;
93 ctx->offset = MANTIS_CTR_BLOCK_SIZE;
97 static int mantis_ctr_vec128_set_tweak
98 (
MantisCTR_t *ctr,
const void *tweak,
unsigned tweak_size)
100 MantisCTRVec128Ctx_t *ctx;
112 ctx->offset = MANTIS_CTR_BLOCK_SIZE;
117 STATIC_INLINE
void mantis_ctr_increment
118 (SkinnyVector8x16_t *counter,
unsigned column,
unsigned inc)
120 uint8_t *ctr = ((uint8_t *)counter) + column * 2;
123 for (index = 8; index > 0; ) {
125 ptr = ctr + (index & 0x06) * 8;
126 #if SKINNY_LITTLE_ENDIAN
129 ptr += 1 - (index & 0x01);
132 ptr[0] = (uint8_t)inc;
137 static int mantis_ctr_vec128_set_counter
138 (
MantisCTR_t *ctr,
const void *counter,
unsigned size)
140 MantisCTRVec128Ctx_t *ctx;
157 ctx->offset = MANTIS_CTR_BLOCK_SIZE;
160 ctx->counter[0] = skinny_to_vec8x16(READ_WORD16(block, 0));
161 ctx->counter[1] = skinny_to_vec8x16(READ_WORD16(block, 2));
162 ctx->counter[2] = skinny_to_vec8x16(READ_WORD16(block, 4));
163 ctx->counter[3] = skinny_to_vec8x16(READ_WORD16(block, 6));
166 mantis_ctr_increment(ctx->counter, 1, 1);
167 mantis_ctr_increment(ctx->counter, 2, 2);
168 mantis_ctr_increment(ctx->counter, 3, 3);
169 mantis_ctr_increment(ctx->counter, 4, 4);
170 mantis_ctr_increment(ctx->counter, 5, 5);
171 mantis_ctr_increment(ctx->counter, 6, 6);
172 mantis_ctr_increment(ctx->counter, 7, 7);
175 skinny_cleanse(block,
sizeof(block));
184 SkinnyVector8x16_t row[4];
186 } MantisVectorCells_t;
188 STATIC_INLINE SkinnyVector8x16_t mantis_sbox(SkinnyVector8x16_t d)
200 SkinnyVector8x16_t a = (d >> 3);
201 SkinnyVector8x16_t b = (d >> 2);
202 SkinnyVector8x16_t c = (d >> 1);
203 SkinnyVector8x16_t not_a = ~a;
204 SkinnyVector8x16_t ab = not_a | (~b);
205 SkinnyVector8x16_t ad = not_a & (~d);
206 SkinnyVector8x16_t aout = (((~c) & ab) | ad);
207 SkinnyVector8x16_t bout = ad | (b & c) | (a & c & d);
208 SkinnyVector8x16_t cout = (b & d) | ((b | d) & not_a);
209 SkinnyVector8x16_t dout = (a | b | c) & ab & (c | d);
210 return ((aout & 0x1111U) << 3) | ((bout & 0x1111U) << 2) |
211 ((cout & 0x1111U) << 1) | (dout & 0x1111U);
217 uint16_t row1 = tweak->
row[1];
218 uint16_t row3 = tweak->
row[3];
219 tweak->
row[1] = tweak->
row[0];
220 tweak->
row[3] = tweak->
row[2];
221 tweak->
row[0] = ((row1 >> 8) & 0x00F0U) |
224 tweak->
row[2] = ((row1 << 4) & 0x0F00U) |
225 ((row1 >> 4) & 0x00F0U) |
226 ((row3 >> 4) & 0x000FU) |
227 ((row3 << 12) & 0xF000U);
230 STATIC_INLINE
void mantis_update_tweak_inverse(
MantisCells_t *tweak)
233 uint16_t row0 = tweak->
row[0];
234 uint16_t row2 = tweak->
row[2];
235 tweak->
row[0] = tweak->
row[1];
236 tweak->
row[2] = tweak->
row[3];
237 tweak->
row[1] = ((row2 >> 4) & 0x00F0U) |
238 ((row2 << 4) & 0x0F00U) |
240 ((row0 << 8) & 0xF000U);
241 tweak->
row[3] = (row0 & 0xFF00U) |
242 ((row2 << 4) & 0x00F0U) |
243 ((row2 >> 12) & 0x000FU);
246 STATIC_INLINE
void mantis_shift_rows(MantisVectorCells_t *state)
249 SkinnyVector8x16_t row0 = state->row[0];
250 SkinnyVector8x16_t row1 = state->row[1];
251 SkinnyVector8x16_t row2 = state->row[2];
252 SkinnyVector8x16_t row3 = state->row[3];
253 state->row[0] = (row0 & 0x00F0U) |
255 ((row2 >> 8) & 0x000FU) |
256 ((row3 << 8) & 0x0F00U);
257 state->row[1] = (row0 & 0x000FU) |
259 ((row2 >> 8) & 0x00F0U) |
260 ((row3 << 8) & 0xF000U);
261 state->row[2] = ((row0 << 4) & 0xF000U) |
262 ((row1 << 4) & 0x00F0U) |
263 ((row2 << 4) & 0x0F00U) |
264 ((row3 >> 12) & 0x000FU);
265 state->row[3] = ((row0 >> 4) & 0x0F00U) |
266 ((row1 >> 4) & 0x000FU) |
267 ((row2 << 12) & 0xF000U) |
268 ((row3 >> 4) & 0x00F0U);
271 STATIC_INLINE
void mantis_shift_rows_inverse(MantisVectorCells_t *state)
274 SkinnyVector8x16_t row0 = state->row[0];
275 SkinnyVector8x16_t row1 = state->row[1];
276 SkinnyVector8x16_t row2 = state->row[2];
277 SkinnyVector8x16_t row3 = state->row[3];
278 state->row[0] = (row0 & 0x00F0U) |
280 ((row2 >> 4) & 0x0F00U) |
281 ((row3 << 4) & 0xF000U);
282 state->row[1] = (row0 & 0xF000U) |
284 ((row2 >> 4) & 0x000FU) |
285 ((row3 << 4) & 0x00F0U);
286 state->row[2] = ((row0 << 8) & 0x0F00U) |
287 ((row1 << 8) & 0xF000U) |
288 ((row2 >> 4) & 0x00F0U) |
289 ((row3 >> 12) & 0x000FU);
290 state->row[3] = ((row0 >> 8) & 0x000FU) |
291 ((row1 >> 8) & 0x00F0U) |
292 ((row2 << 12) & 0xF000U) |
293 ((row3 << 4) & 0x0F00U);
296 STATIC_INLINE
void mantis_mix_columns(MantisVectorCells_t *state)
298 SkinnyVector8x16_t t0 = state->row[0];
299 SkinnyVector8x16_t t1 = state->row[1];
300 SkinnyVector8x16_t t2 = state->row[2];
301 SkinnyVector8x16_t t3 = state->row[3];
302 state->row[0] = t1 ^ t2 ^ t3;
303 state->row[1] = t0 ^ t2 ^ t3;
304 state->row[2] = t0 ^ t1 ^ t3;
305 state->row[3] = t0 ^ t1 ^ t2;
309 #define RC_EXTRACT_ROW(x,shift) \
310 (((((uint16_t)((x) >> ((shift) + 8))) & 0xFF)) | \
311 ((((uint16_t)((x) >> ((shift)))) & 0xFF) << 8))
315 {RC_EXTRACT_ROW((x), 48), RC_EXTRACT_ROW((x), 32), \
316 RC_EXTRACT_ROW((x), 16), RC_EXTRACT_ROW((x), 0)}
319 #define ALPHA 0x243F6A8885A308D3ULL
320 #define ALPHA_ROW0 (RC_EXTRACT_ROW(ALPHA, 48))
321 #define ALPHA_ROW1 (RC_EXTRACT_ROW(ALPHA, 32))
322 #define ALPHA_ROW2 (RC_EXTRACT_ROW(ALPHA, 16))
323 #define ALPHA_ROW3 (RC_EXTRACT_ROW(ALPHA, 0))
327 RC(0x13198A2E03707344ULL),
328 RC(0xA4093822299F31D0ULL),
329 RC(0x082EFA98EC4E6C89ULL),
330 RC(0x452821E638D01377ULL),
331 RC(0xBE5466CF34E90C6CULL),
332 RC(0xC0AC29B7C97C50DDULL),
333 RC(0x3F84D5B5B5470917ULL),
334 RC(0x9216D5D98979FB1BULL)
337 static void mantis_ecb_encrypt_eight
338 (
void *output,
const SkinnyVector8x16_t *input,
const MantisKey_t *ks)
340 const uint16_t *r = rc[0];
343 MantisVectorCells_t state;
347 state.
row[0] = input[0];
348 state.row[1] = input[1];
349 state.row[2] = input[2];
350 state.row[3] = input[3];
354 state.row[0] ^= ks->
k0.
row[0] ^ k1.
row[0] ^ tweak.
row[0];
355 state.row[1] ^= ks->
k0.
row[1] ^ k1.
row[1] ^ tweak.
row[1];
356 state.row[2] ^= ks->
k0.
row[2] ^ k1.
row[2] ^ tweak.
row[2];
357 state.row[3] ^= ks->
k0.
row[3] ^ k1.
row[3] ^ tweak.
row[3];
360 for (index = ks->
rounds; index > 0; --index) {
362 mantis_update_tweak(&tweak);
365 state.row[0] = mantis_sbox(state.row[0]);
366 state.row[1] = mantis_sbox(state.row[1]);
367 state.row[2] = mantis_sbox(state.row[2]);
368 state.row[3] = mantis_sbox(state.row[3]);
371 state.row[0] ^= r[0];
372 state.row[1] ^= r[1];
373 state.row[2] ^= r[2];
374 state.row[3] ^= r[3];
378 state.row[0] ^= k1.
row[0] ^ tweak.
row[0];
379 state.row[1] ^= k1.
row[1] ^ tweak.
row[1];
380 state.row[2] ^= k1.
row[2] ^ tweak.
row[2];
381 state.row[3] ^= k1.
row[3] ^ tweak.
row[3];
384 mantis_shift_rows(&state);
387 mantis_mix_columns(&state);
391 state.row[0] = mantis_sbox(state.row[0]);
392 state.row[1] = mantis_sbox(state.row[1]);
393 state.row[2] = mantis_sbox(state.row[2]);
394 state.row[3] = mantis_sbox(state.row[3]);
395 mantis_mix_columns(&state);
396 state.row[0] = mantis_sbox(state.row[0]);
397 state.row[1] = mantis_sbox(state.row[1]);
398 state.row[2] = mantis_sbox(state.row[2]);
399 state.row[3] = mantis_sbox(state.row[3]);
402 k1.
row[0] ^= ALPHA_ROW0;
403 k1.
row[1] ^= ALPHA_ROW1;
404 k1.
row[2] ^= ALPHA_ROW2;
405 k1.
row[3] ^= ALPHA_ROW3;
408 for (index = ks->
rounds; index > 0; --index) {
410 mantis_mix_columns(&state);
413 mantis_shift_rows_inverse(&state);
416 state.row[0] ^= k1.
row[0] ^ tweak.
row[0];
417 state.row[1] ^= k1.
row[1] ^ tweak.
row[1];
418 state.row[2] ^= k1.
row[2] ^ tweak.
row[2];
419 state.row[3] ^= k1.
row[3] ^ tweak.
row[3];
423 state.row[0] ^= r[0];
424 state.row[1] ^= r[1];
425 state.row[2] ^= r[2];
426 state.row[3] ^= r[3];
429 state.row[0] = mantis_sbox(state.row[0]);
430 state.row[1] = mantis_sbox(state.row[1]);
431 state.row[2] = mantis_sbox(state.row[2]);
432 state.row[3] = mantis_sbox(state.row[3]);
435 mantis_update_tweak_inverse(&tweak);
450 *((SkinnyVector8x16U_t *)output) =
451 (SkinnyVector8x16_t){state.row[0][0], state.row[1][0],
452 state.row[2][0], state.row[3][0],
453 state.row[0][1], state.row[1][1],
454 state.row[2][1], state.row[3][1]};
455 *((SkinnyVector8x16U_t *)(output + 16)) =
456 (SkinnyVector8x16_t){state.row[0][2], state.row[1][2],
457 state.row[2][2], state.row[3][2],
458 state.row[0][3], state.row[1][3],
459 state.row[2][3], state.row[3][3]};
460 *((SkinnyVector8x16U_t *)(output + 32)) =
461 (SkinnyVector8x16_t){state.row[0][4], state.row[1][4],
462 state.row[2][4], state.row[3][4],
463 state.row[0][5], state.row[1][5],
464 state.row[2][5], state.row[3][5]};
465 *((SkinnyVector8x16U_t *)(output + 48)) =
466 (SkinnyVector8x16_t){state.row[0][6], state.row[1][6],
467 state.row[2][6], state.row[3][6],
468 state.row[0][7], state.row[1][7],
469 state.row[2][7], state.row[3][7]};
471 WRITE_WORD16(output, 0, state.row[0][0]);
472 WRITE_WORD16(output, 2, state.row[1][0]);
473 WRITE_WORD16(output, 4, state.row[2][0]);
474 WRITE_WORD16(output, 6, state.row[3][0]);
475 WRITE_WORD16(output, 8, state.row[0][1]);
476 WRITE_WORD16(output, 10, state.row[1][1]);
477 WRITE_WORD16(output, 12, state.row[2][1]);
478 WRITE_WORD16(output, 14, state.row[3][1]);
479 WRITE_WORD16(output, 16, state.row[0][2]);
480 WRITE_WORD16(output, 18, state.row[1][2]);
481 WRITE_WORD16(output, 20, state.row[2][2]);
482 WRITE_WORD16(output, 22, state.row[3][2]);
483 WRITE_WORD16(output, 24, state.row[0][3]);
484 WRITE_WORD16(output, 26, state.row[1][3]);
485 WRITE_WORD16(output, 28, state.row[2][3]);
486 WRITE_WORD16(output, 30, state.row[3][3]);
487 WRITE_WORD16(output, 32, state.row[0][4]);
488 WRITE_WORD16(output, 34, state.row[1][4]);
489 WRITE_WORD16(output, 36, state.row[2][4]);
490 WRITE_WORD16(output, 38, state.row[3][4]);
491 WRITE_WORD16(output, 40, state.row[0][5]);
492 WRITE_WORD16(output, 42, state.row[1][5]);
493 WRITE_WORD16(output, 44, state.row[2][5]);
494 WRITE_WORD16(output, 46, state.row[3][5]);
495 WRITE_WORD16(output, 48, state.row[0][6]);
496 WRITE_WORD16(output, 50, state.row[1][6]);
497 WRITE_WORD16(output, 52, state.row[2][6]);
498 WRITE_WORD16(output, 54, state.row[3][6]);
499 WRITE_WORD16(output, 56, state.row[0][7]);
500 WRITE_WORD16(output, 58, state.row[1][7]);
501 WRITE_WORD16(output, 60, state.row[2][7]);
502 WRITE_WORD16(output, 62, state.row[3][7]);
506 static int mantis_ctr_vec128_encrypt
507 (
void *output,
const void *input,
size_t size,
MantisCTR_t *ctr)
509 MantisCTRVec128Ctx_t *ctx;
510 uint8_t *out = (uint8_t *)output;
511 const uint8_t *in = (
const uint8_t *)input;
514 if (!output || !input)
522 if (ctx->offset >= MANTIS_CTR_BLOCK_SIZE) {
524 mantis_ecb_encrypt_eight(ctx->ecounter, ctx->counter, &(ctx->ks));
525 mantis_ctr_increment(ctx->counter, 0, 8);
526 mantis_ctr_increment(ctx->counter, 1, 8);
527 mantis_ctr_increment(ctx->counter, 2, 8);
528 mantis_ctr_increment(ctx->counter, 3, 8);
529 mantis_ctr_increment(ctx->counter, 4, 8);
530 mantis_ctr_increment(ctx->counter, 5, 8);
531 mantis_ctr_increment(ctx->counter, 6, 8);
532 mantis_ctr_increment(ctx->counter, 7, 8);
535 if (size >= MANTIS_CTR_BLOCK_SIZE) {
536 skinny64_xor(out, in, ctx->ecounter);
558 out += MANTIS_CTR_BLOCK_SIZE;
559 in += MANTIS_CTR_BLOCK_SIZE;
560 size -= MANTIS_CTR_BLOCK_SIZE;
563 skinny_xor(out, in, ctx->ecounter, size);
569 size_t temp = MANTIS_CTR_BLOCK_SIZE - ctx->offset;
572 skinny_xor(out, in, ctx->ecounter + ctx->offset, temp);
583 MantisCTRVtable_t
const _mantis_ctr_vec128 = {
584 mantis_ctr_vec128_init,
585 mantis_ctr_vec128_cleanup,
586 mantis_ctr_vec128_set_key,
587 mantis_ctr_vec128_set_tweak,
588 mantis_ctr_vec128_set_counter,
589 mantis_ctr_vec128_encrypt
595 MantisCTRVtable_t
const _mantis_ctr_vec128;
#define MANTIS_ENCRYPT
Mode that selects Mantis encryption when the key schedule is setup.
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.
State information for Mantis in CTR mode.
Key schedule for Mantis block ciphers.
Union that describes a 64-bit 4x4 array of cells.