core.c 2.9 KB
Newer Older
Ferdinand Bachmann committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
#include "core.h"

void process_data(state* s, unsigned char* out, const unsigned char* in,
                  unsigned long long len, u8 mode) {
  u32_2 t0, t1;
  u64 tmp0, tmp1;
  u64 i;

  while (len >= RATE) {
    tmp0 = (*(u64*)in);
    t0 = to_bit_interleaving_big(tmp0);
    s->x0.e ^= t0.e;
    s->x0.o ^= t0.o;
    tmp1 = (*(u64*)(in + 8));
    t1 = to_bit_interleaving_big(tmp1);
    s->x1.e ^= t1.e;
    s->x1.o ^= t1.o;
    if (mode != ASCON_AD) {
      tmp0 = from_bit_interleaving_big(s->x0);
      *(u64*)out = (tmp0);
      tmp1 = from_bit_interleaving_big(s->x1);
      *(u64*)(out + 8) = (tmp1);
    }
    if (mode == ASCON_DEC) {
      s->x0 = t0;
      s->x1 = t1;
    }
    P(s, PB_ROUNDS);
    in += RATE;
    out += RATE;
    len -= RATE;
  }

  tmp0 = 0;
  tmp1 = 0;
  for (i = 0; i < len; ++i, ++in)
    if (i < 8)
      tmp0 ^= INS_BYTE64(*in, i);
    else
      tmp1 ^= INS_BYTE64(*in, i % 8);
  in -= len;
  if (len < 8)
    tmp0 ^= INS_BYTE64(0x80, len);
  else
    tmp1 ^= INS_BYTE64(0x80, len % 8);
  t0 = to_bit_interleaving(tmp0);
  s->x0.e ^= t0.e;
  s->x0.o ^= t0.o;
  t1 = to_bit_interleaving(tmp1);
  s->x1.e ^= t1.e;
  s->x1.o ^= t1.o;
  if (mode != ASCON_AD) {
    tmp0 = from_bit_interleaving(s->x0);
    tmp1 = from_bit_interleaving(s->x1);
    for (i = 0; i < len; ++i, ++out)
      if (i < 8)
        *out = EXT_BYTE64(tmp0, i);
      else
        *out = EXT_BYTE64(tmp1, i % 8);
  }
  if (mode == ASCON_DEC) {
    for (i = 0; i < len; ++i, ++in)
      if (i < 8) {
        tmp0 &= ~INS_BYTE64(0xff, i);
        tmp0 |= INS_BYTE64(*in, i);
      } else {
        tmp1 &= ~INS_BYTE64(0xff, i % 8);
        tmp1 |= INS_BYTE64(*in, i % 8);
      }
    s->x0 = to_bit_interleaving(tmp0);
    s->x1 = to_bit_interleaving(tmp1);
  }
}

void ascon_core(state* s, unsigned char* out, const unsigned char* in,
                unsigned long long tlen, const unsigned char* ad,
                unsigned long long adlen, const unsigned char* npub,
                const unsigned char* k, u8 mode) {
  u32_2 K0, K1, N0, N1;

  // load key and nonce
  K0 = to_bit_interleaving_big((*(u64*)k));
  K1 = to_bit_interleaving_big((*(u64*)(k + 8)));
  N0 = to_bit_interleaving_big((*(u64*)npub));
  N1 = to_bit_interleaving_big((*(u64*)(npub + 8)));

  // initialization
  s->x0 = to_bit_interleaving(IV);
  s->x1.o = K0.o;
  s->x1.e = K0.e;
  s->x2.e = K1.e;
  s->x2.o = K1.o;
  s->x3.e = N0.e;
  s->x3.o = N0.o;
  s->x4.e = N1.e;
  s->x4.o = N1.o;
  P(s, PA_ROUNDS);
  s->x3.e ^= K0.e;
  s->x3.o ^= K0.o;
  s->x4.e ^= K1.e;
  s->x4.o ^= K1.o;

  // process associated data
  if (adlen) {
    process_data(s, (void*)0, ad, adlen, ASCON_AD);
    P(s, PB_ROUNDS);
  }
  s->x4.e ^= 1;

  // process plaintext/ciphertext
  process_data(s, out, in, tlen, mode);

  // finalization
  s->x2.e ^= K0.e;
  s->x2.o ^= K0.o;
  s->x3.e ^= K1.e;
  s->x3.o ^= K1.o;
  P(s, PA_ROUNDS);
  s->x3.e ^= K0.e;
  s->x3.o ^= K0.o;
  s->x4.e ^= K1.e;
  s->x4.o ^= K1.o;
}