core.c 1.63 KB
Newer Older
Christoph Dobraunig 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
#include "core.h"

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

  while (len >= RATE) {
    s->x0 ^= U64BIG(*(u64*)in);
    if (mode != ASCON_AD) *(u64*)out = U64BIG(s->x0);
    if (mode == ASCON_DEC) s->x0 = U64BIG(*((u64*)in));
    P(s, PB_ROUNDS);
    in += RATE;
    out += RATE;
    len -= RATE;
  }

  for (i = 0; i < len; ++i, ++out, ++in) {
    s->x0 ^= INS_BYTE64(*in, i);

    if (mode != ASCON_AD) *out = EXT_BYTE64(s->x0, i);
    if (mode == ASCON_DEC) {
      s->x0 &= ~INS_BYTE64(0xff, i);
      s->x0 |= INS_BYTE64(*in, i);
    }
  }
  s->x0 ^= INS_BYTE64(0x80, len);
}

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) {
  const u64 K0 = U64BIG(*(u64*)(k + 0)) >> 32;
  const u64 K1 = U64BIG(*(u64*)(k + 4));
  const u64 K2 = U64BIG(*(u64*)(k + 12));
  const u64 N0 = U64BIG(*(u64*)npub);
  const u64 N1 = U64BIG(*(u64*)(npub + 8));

  // initialization
  s->x0 = IV | K0;
  s->x1 = K1;
  s->x2 = K2;
  s->x3 = N0;
  s->x4 = N1;
  P(s, PA_ROUNDS);
  s->x2 ^= K0;
  s->x3 ^= K1;
  s->x4 ^= K2;

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

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

  // finalization
  s->x1 ^= K0 << 32 | K1 >> 32;
  s->x2 ^= K1 << 32 | K2 >> 32;
  s->x3 ^= K2 << 32;
  P(s, PA_ROUNDS);
  s->x3 ^= K1;
  s->x4 ^= K2;
}