#include "api.h" #include "endian.h" #include "permutations.h" #define PA_ROUNDS 12 #define PB_ROUNDS 6 #define IV \ ((uint64_t)(8 * (CRYPTO_KEYBYTES)) << 56 | \ (uint64_t)(8 * (ASCON_RATE)) << 48 | (uint64_t)(PA_ROUNDS) << 40 | \ (uint64_t)(PB_ROUNDS) << 32) int crypto_aead_decrypt(uint8_t* m, uint64_t* mlen, uint8_t* nsec, const uint8_t* c, uint64_t clen, const uint8_t* ad, uint64_t adlen, const uint8_t* npub, const uint8_t* k) { if (clen < CRYPTO_ABYTES) { *mlen = 0; return -1; } const uint64_t K0 = U64BIG(*(uint64_t*)k); const uint64_t K1 = U64BIG(*(uint64_t*)(k + 8)); const uint64_t N0 = U64BIG(*(uint64_t*)npub); const uint64_t N1 = U64BIG(*(uint64_t*)(npub + 8)); state_t s; uint32_t i; (void)nsec; /* set plaintext size */ *mlen = clen - CRYPTO_ABYTES; /* initialization */ s.x0 = IV; s.x1 = K0; s.x2 = K1; s.x3 = N0; s.x4 = N1; P12(); s.x3 ^= K0; s.x4 ^= K1; /* process associated data */ if (adlen) { AD(); for (i = 0; i < adlen; ++i, ++ad) s.x0 ^= SETBYTE(*ad, i); s.x0 ^= SETBYTE(0x80, adlen); P6(); } s.x4 ^= 1; /* process plaintext */ clen -= CRYPTO_ABYTES; CT(); for (i = 0; i < clen; ++i, ++m, ++c) { *m = GETBYTE(s.x0, i) ^ *c; s.x0 &= ~SETBYTE(0xff, i); s.x0 |= SETBYTE(*c, i); } s.x0 ^= SETBYTE(0x80, clen); /* finalization */ s.x1 ^= K0; s.x2 ^= K1; P12(); s.x3 ^= K0; s.x4 ^= K1; /* verify tag (should be constant time, check compiler output) */ if (((s.x3 ^ U64BIG(*(uint64_t*)c)) | (s.x4 ^ U64BIG(*(uint64_t*)(c + 8)))) != 0) { *mlen = 0; return -1; } return 0; }