#include "api.h" #include "ascon.h" #include "permutations.h" #include "printstate.h" void ascon_initaead(state_t* s, const mask_npub_uint32_t* n, const mask_key_uint32_t* k) { word_t N0, N1; word_t K1, K2; /* randomize the initial state */ s->x[5] = MZERO(NUM_SHARES_KEY); s->x[0] = MZERO(NUM_SHARES_KEY); /* set the initial value */ s->x[0].s[0].w[0] ^= 0x08220000; s->x[0].s[0].w[1] ^= 0x80210000; /* set the nonce */ s->x[3] = N0 = MLOAD((uint32_t*)n, NUM_SHARES_NPUB); s->x[4] = N1 = MLOAD((uint32_t*)(n + 2), NUM_SHARES_NPUB); /* first key xor */ s->x[1] = K1 = MLOAD((uint32_t*)k, NUM_SHARES_KEY); s->x[2] = K2 = MLOAD((uint32_t*)(k + 2), NUM_SHARES_KEY); printstate("init 1st key xor", s, NUM_SHARES_KEY); /* compute the permutation */ P(s, ASCON_PA_ROUNDS, NUM_SHARES_KEY); /* second key xor */ s->x[3] = MXOR(s->x[3], K1, NUM_SHARES_KEY); s->x[4] = MXOR(s->x[4], K2, NUM_SHARES_KEY); printstate("init 2nd key xor", s, NUM_SHARES_KEY); } void ascon_adata(state_t* s, const mask_ad_uint32_t* ad, uint64_t adlen) { const int nr = ASCON_PB_ROUNDS; if (adlen) { /* full associated data blocks */ while (adlen >= ASCON_AEAD_RATE) { word_t as = MLOAD((uint32_t*)ad, NUM_SHARES_AD); s->x[0] = MXOR(s->x[0], as, NUM_SHARES_AD); printstate("absorb adata", s, NUM_SHARES_AD); P(s, nr, NUM_SHARES_AD); adlen -= ASCON_AEAD_RATE; ad += 2; } /* final associated data block */ s->x[0].s[0].w[1] ^= 0x80000000 >> (adlen * 4); if (adlen) { word_t as = MLOAD((uint32_t*)ad, NUM_SHARES_AD); s->x[0] = MXOR(s->x[0], as, NUM_SHARES_AD); } printstate("pad adata", s, NUM_SHARES_AD); P(s, nr, NUM_SHARES_AD); } /* domain separation */ s->x[4].s[0].w[0] ^= 1; printstate("domain separation", s, NUM_SHARES_AD); } void ascon_encrypt(state_t* s, mask_c_uint32_t* c, const mask_m_uint32_t* m, uint64_t mlen) { const int nr = ASCON_PB_ROUNDS; /* full plaintext blocks */ while (mlen >= ASCON_AEAD_RATE) { word_t ms = MLOAD((uint32_t*)m, NUM_SHARES_M); s->x[0] = MXOR(s->x[0], ms, NUM_SHARES_M); MSTORE((uint32_t*)c, s->x[0], NUM_SHARES_C); printstate("absorb plaintext", s, NUM_SHARES_M); P(s, nr, NUM_SHARES_M); mlen -= ASCON_AEAD_RATE; m += 2; c += 2; } /* final plaintext block */ s->x[0].s[0].w[1] ^= 0x80000000 >> (mlen * 4); if (mlen) { word_t ms = MLOAD((uint32_t*)m, NUM_SHARES_M); s->x[0] = MXOR(s->x[0], ms, NUM_SHARES_M); MSTORE((uint32_t*)c, s->x[0], NUM_SHARES_C); } printstate("pad plaintext", s, NUM_SHARES_M); } void ascon_decrypt(state_t* s, mask_m_uint32_t* m, const mask_c_uint32_t* c, uint64_t clen) { const int nr = ASCON_PB_ROUNDS; /* full ciphertext blocks */ while (clen >= ASCON_AEAD_RATE) { word_t cx = MLOAD((uint32_t*)c, NUM_SHARES_C); s->x[0] = MXOR(s->x[0], cx, NUM_SHARES_C); MSTORE((uint32_t*)m, s->x[0], NUM_SHARES_M); s->x[0] = cx; printstate("insert ciphertext", s, NUM_SHARES_M); P(s, nr, NUM_SHARES_M); clen -= ASCON_AEAD_RATE; c += 2; m += 2; } /* final ciphertext block */ s->x[0].s[0].w[1] ^= 0x80000000 >> (clen * 4); if (clen) { word_t cx = MLOAD((uint32_t*)c, NUM_SHARES_C); s->x[0] = MXOR(s->x[0], cx, NUM_SHARES_C); MSTORE((uint32_t*)m, s->x[0], NUM_SHARES_M); word_t mask = MMASK(clen, NUM_SHARES_C); s->x[0] = MXORAND(cx, s->x[0], mask, NUM_SHARES_C); } printstate("pad ciphertext", s, NUM_SHARES_M); } void ascon_final(state_t* s, const mask_key_uint32_t* k) { word_t K1, K2; K1 = MLOAD((uint32_t*)k, NUM_SHARES_KEY); K2 = MLOAD((uint32_t*)(k + 2), NUM_SHARES_KEY); /* first key xor (first 64-bit word) */ s->x[1] = MXOR(s->x[1], K1, NUM_SHARES_KEY); /* first key xor (second 64-bit word) */ s->x[2] = MXOR(s->x[2], K2, NUM_SHARES_KEY); printstate("final 1st key xor", s, NUM_SHARES_KEY); /* compute the permutation */ P(s, ASCON_PA_ROUNDS, NUM_SHARES_KEY); /* second key xor (first 64-bit word) */ s->x[3] = MXOR(s->x[3], K1, NUM_SHARES_KEY); /* second key xor (second 64-bit word) */ s->x[4] = MXOR(s->x[4], K2, NUM_SHARES_KEY); printstate("final 2nd key xor", s, NUM_SHARES_KEY); } void ascon_settag(state_t* s, mask_c_uint32_t* t) { MSTORE((uint32_t*)t, s->x[3], NUM_SHARES_C); MSTORE((uint32_t*)(t + 2), s->x[4], NUM_SHARES_C); } /* expected value of x3,x4 for P(0) */ #if ASCON_PB_ROUNDS == 1 static const uint32_t c[4] = {0x4b000009, 0x1c800003, 0x00000000, 0x00000000}; #elif ASCON_PB_ROUNDS == 2 static const uint32_t c[4] = {0x5d2d1034, 0x76fa81d1, 0x0cc1c9ef, 0xdb30a503}; #elif ASCON_PB_ROUNDS == 3 static const uint32_t c[4] = {0xbcaa1d46, 0xf1d0bde9, 0x32c4e651, 0x7b797cd9}; #elif ASCON_PB_ROUNDS == 4 static const uint32_t c[4] = {0xf7820616, 0xeffead2d, 0x94846901, 0xd4895cf5}; #elif ASCON_PB_ROUNDS == 5 static const uint32_t c[4] = {0x9e5ce5e3, 0xd40e9b87, 0x0bfc74af, 0xf8e408a9}; #else /* ASCON_PB_ROUNDS == 6 */ static const uint32_t c[4] = {0x11874f08, 0x7520afef, 0xa4dd41b4, 0x4bd6f9a4}; #endif void ascon_xortag(state_t* s, const mask_c_uint32_t* t) { /* set x0, x1, x2 to zero */ s->x[0] = MREUSE(s->x[0], 0, NUM_SHARES_KEY); s->x[1] = MREUSE(s->x[1], 0, NUM_SHARES_KEY); s->x[2] = MREUSE(s->x[2], 0, NUM_SHARES_KEY); /* xor tag to x3, x4 */ word_t t0 = MLOAD((uint32_t*)t, NUM_SHARES_C); s->x[3] = MXOR(s->x[3], t0, NUM_SHARES_C); word_t t1 = MLOAD((uint32_t*)(t + 2), NUM_SHARES_C); s->x[4] = MXOR(s->x[4], t1, NUM_SHARES_C); /* compute P(0) if tags are equal */ P(s, ASCON_PB_ROUNDS, NUM_SHARES_KEY); /* xor expected result to x3, x4 */ s->x[3].s[0].w[0] ^= c[0]; s->x[3].s[0].w[1] ^= c[1]; s->x[4].s[0].w[0] ^= c[2]; s->x[4].s[0].w[1] ^= c[3]; } int ascon_iszero(state_t* s) { #if NUM_SHARES_KEY >= 2 s->x[3].s[0].w[0] ^= ROR32(s->x[3].s[1].w[0], ROT(1)); s->x[3].s[0].w[1] ^= ROR32(s->x[3].s[1].w[1], ROT(1)); s->x[4].s[0].w[0] ^= ROR32(s->x[4].s[1].w[0], ROT(1)); s->x[4].s[0].w[1] ^= ROR32(s->x[4].s[1].w[1], ROT(1)); #endif #if NUM_SHARES_KEY >= 3 s->x[3].s[0].w[0] ^= ROR32(s->x[3].s[2].w[0], ROT(2)); s->x[3].s[0].w[1] ^= ROR32(s->x[3].s[2].w[1], ROT(2)); s->x[4].s[0].w[0] ^= ROR32(s->x[4].s[2].w[0], ROT(2)); s->x[4].s[0].w[1] ^= ROR32(s->x[4].s[2].w[1], ROT(2)); #endif #if NUM_SHARES_KEY >= 4 s->x[3].s[0].w[0] ^= ROR32(s->x[3].s[3].w[0], ROT(3)); s->x[3].s[0].w[1] ^= ROR32(s->x[3].s[3].w[1], ROT(3)); s->x[4].s[0].w[0] ^= ROR32(s->x[4].s[3].w[0], ROT(3)); s->x[4].s[0].w[1] ^= ROR32(s->x[4].s[3].w[1], ROT(3)); #endif uint32_t result; result = s->x[3].s[0].w[0] ^ s->x[3].s[0].w[1]; result ^= s->x[4].s[0].w[0] ^ s->x[4].s[0].w[1]; result |= result >> 16; result |= result >> 8; return ((((int)(result & 0xff) - 1) >> 8) & 1) - 1; } int ascon_verify(state_t* s, const mask_c_uint32_t* t) { ascon_xortag(s, t); return ascon_iszero(s); }