diff --git a/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/api.h b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/api.h new file mode 100644 index 0000000..a4aa567 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/core.c b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/core.c new file mode 100644 index 0000000..1f75093 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/core.c @@ -0,0 +1,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 = U64BIG(*(u64*)in); + t0 = to_bit_interleaving(tmp0); + s->x0.e ^= t0.e; + s->x0.o ^= t0.o; + tmp1 = U64BIG(*(u64*)(in + 8)); + 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); + *(u64*)out = U64BIG(tmp0); + tmp1 = from_bit_interleaving(s->x1); + *(u64*)(out + 8) = U64BIG(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(U64BIG(*(u64*)k)); + K1 = to_bit_interleaving(U64BIG(*(u64*)(k + 8))); + N0 = to_bit_interleaving(U64BIG(*(u64*)npub)); + N1 = to_bit_interleaving(U64BIG(*(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; +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/core.h b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/core.h new file mode 100644 index 0000000..4a5330f --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/core.h @@ -0,0 +1,27 @@ +#ifndef CORE_H_ +#define CORE_H_ + +#include "api.h" +#include "endian.h" +#include "permutations.h" + +#define ASCON_AD 0 +#define ASCON_ENC 1 +#define ASCON_DEC 2 + +#define RATE (128 / 8) +#define PA_ROUNDS 12 +#define PB_ROUNDS 8 +#define IV \ + ((u64)(8 * (CRYPTO_KEYBYTES)) << 56 | (u64)(8 * (RATE)) << 48 | \ + (u64)(PA_ROUNDS) << 40 | (u64)(PB_ROUNDS) << 32) + +void process_data(state* s, unsigned char* out, const unsigned char* in, + unsigned long long len, u8 mode); + +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); + +#endif // CORE_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/decrypt.c b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/decrypt.c new file mode 100644 index 0000000..7e9dd1a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/decrypt.c @@ -0,0 +1,32 @@ +#include "core.h" + +int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen, + unsigned char* nsec, const unsigned char* c, + unsigned long long clen, const unsigned char* ad, + unsigned long long adlen, const unsigned char* npub, + const unsigned char* k) { + if (clen < CRYPTO_ABYTES) { + *mlen = 0; + return -1; + } + + state s; + u32_2 t0, t1; + (void)nsec; + + // set plaintext size + *mlen = clen - CRYPTO_ABYTES; + + ascon_core(&s, m, c, *mlen, ad, adlen, npub, k, ASCON_DEC); + + // verify tag (should be constant time, check compiler output) + t0 = to_bit_interleaving(U64BIG(*(u64*)(c + *mlen))); + t1 = to_bit_interleaving(U64BIG(*(u64*)(c + *mlen + 8))); + if (((s.x3.e ^ t0.e) | (s.x3.o ^ t0.o) | (s.x4.e ^ t1.e) | (s.x4.o ^ t1.o)) != + 0) { + *mlen = 0; + return -1; + } + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/encrypt.c b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/encrypt.c new file mode 100644 index 0000000..b5dc587 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/encrypt.c @@ -0,0 +1,24 @@ +#include "core.h" + +int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen, + const unsigned char* m, unsigned long long mlen, + const unsigned char* ad, unsigned long long adlen, + const unsigned char* nsec, const unsigned char* npub, + const unsigned char* k) { + state s; + u64 tmp0, tmp1; + (void)nsec; + + // set ciphertext size + *clen = mlen + CRYPTO_ABYTES; + + ascon_core(&s, c, m, mlen, ad, adlen, npub, k, ASCON_ENC); + + // set tag + tmp0 = from_bit_interleaving(s.x3); + *(u64*)(c + mlen) = U64BIG(tmp0); + tmp1 = from_bit_interleaving(s.x4); + *(u64*)(c + mlen + 8) = U64BIG(tmp1); + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/endian.h b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/endian.h new file mode 100644 index 0000000..b4d18f5 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/endian.h @@ -0,0 +1,29 @@ +#ifndef ENDIAN_H_ +#define ENDIAN_H_ + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +// macros for big endian machines +#define U64BIG(x) (x) +#define U32BIG(x) (x) +#define U16BIG(x) (x) + +#elif defined(_MSC_VER) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + +// macros for little endian machines +#define U64BIG(x) \ + ((((x)&0x00000000000000FFULL) << 56) | (((x)&0x000000000000FF00ULL) << 40) | \ + (((x)&0x0000000000FF0000ULL) << 24) | (((x)&0x00000000FF000000ULL) << 8) | \ + (((x)&0x000000FF00000000ULL) >> 8) | (((x)&0x0000FF0000000000ULL) >> 24) | \ + (((x)&0x00FF000000000000ULL) >> 40) | (((x)&0xFF00000000000000ULL) >> 56)) +#define U32BIG(x) \ + ((((x)&0x000000FF) << 24) | (((x)&0x0000FF00) << 8) | \ + (((x)&0x00FF0000) >> 8) | (((x)&0xFF000000) >> 24)) +#define U16BIG(x) ((((x)&0x00FF) << 8) | (((x)&0xFF00) >> 8)) + +#else +#error "ascon byte order macros not defined in endian.h" +#endif + +#endif // ENDIAN_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/implementors b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/implementors new file mode 100644 index 0000000..b110c1a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/implementors @@ -0,0 +1,2 @@ +Christoph Dobraunig +Martin Schläffer diff --git a/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/permutations.c b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/permutations.c new file mode 100644 index 0000000..bc47f5f --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/permutations.c @@ -0,0 +1,50 @@ +#include "permutations.h" + +static const u8 constants[][2] = { + {0xc, 0xc}, {0x9, 0xc}, {0xc, 0x9}, {0x9, 0x9}, {0x6, 0xc}, {0x3, 0xc}, + {0x6, 0x9}, {0x3, 0x9}, {0xc, 0x6}, {0x9, 0x6}, {0xc, 0x3}, {0x9, 0x3}}; + +// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +u32_2 to_bit_interleaving(u64 in) { + u32 hi = (in) >> 32; + u32 lo = (u32)(in); + u32 r0, r1; + u32_2 out; + r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1); + r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2); + r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4); + r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8); + r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1); + r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2); + r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4); + r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8); + out.e = (lo & 0x0000FFFF) | (hi << 16); + out.o = (lo >> 16) | (hi & 0xFFFF0000); + return out; +} + +// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +u64 from_bit_interleaving(u32_2 in) { + u32 lo = (in.e & 0x0000FFFF) | (in.o << 16); + u32 hi = (in.e >> 16) | (in.o & 0xFFFF0000); + u32 r0, r1; + u64 out; + r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8); + r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4); + r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2); + r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1); + r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8); + r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4); + r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2); + r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1); + out = (u64)hi << 32 | lo; + return out; +} + +void P(state *p, u8 rounds) { + state s = *p; + u32_2 t0, t1, t2, t3, t4; + u32 i, start = START_ROUND(rounds); + for (i = start; i < 12; i++) ROUND(constants[i][0], constants[i][1]); + *p = s; +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/permutations.h b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/permutations.h new file mode 100644 index 0000000..bc643ce --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/bi32_lowsize/permutations.h @@ -0,0 +1,71 @@ +#ifndef PERMUTATIONS_H_ +#define PERMUTATIONS_H_ + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned long long u64; + +typedef struct { + u32 e; + u32 o; +} u32_2; + +typedef struct { + u32_2 x0; + u32_2 x1; + u32_2 x2; + u32_2 x3; + u32_2 x4; +} state; + +#define EXT_BYTE64(x, n) ((u8)((u64)(x) >> (8 * (7 - (n))))) +#define INS_BYTE64(x, n) ((u64)(x) << (8 * (7 - (n)))) +#define ROTR32(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) +#define START_ROUND(x) (12 - (x)) + +// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +u32_2 to_bit_interleaving(u64 in); + +// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +u64 from_bit_interleaving(u32_2 in); + +/* clang-format off */ +#define ROUND(C_e, C_o) \ + do { \ + /* round constant */ \ + s.x2.e ^= C_e; s.x2.o ^= C_o; \ + /* s-box layer */ \ + s.x0.e ^= s.x4.e; s.x0.o ^= s.x4.o; \ + s.x4.e ^= s.x3.e; s.x4.o ^= s.x3.o; \ + s.x2.e ^= s.x1.e; s.x2.o ^= s.x1.o; \ + t0.e = s.x0.e; t0.o = s.x0.o; \ + t4.e = s.x4.e; t4.o = s.x4.o; \ + t3.e = s.x3.e; t3.o = s.x3.o; \ + t1.e = s.x1.e; t1.o = s.x1.o; \ + t2.e = s.x2.e; t2.o = s.x2.o; \ + s.x0.e = t0.e ^ (~t1.e & t2.e); s.x0.o = t0.o ^ (~t1.o & t2.o); \ + s.x2.e = t2.e ^ (~t3.e & t4.e); s.x2.o = t2.o ^ (~t3.o & t4.o); \ + s.x4.e = t4.e ^ (~t0.e & t1.e); s.x4.o = t4.o ^ (~t0.o & t1.o); \ + s.x1.e = t1.e ^ (~t2.e & t3.e); s.x1.o = t1.o ^ (~t2.o & t3.o); \ + s.x3.e = t3.e ^ (~t4.e & t0.e); s.x3.o = t3.o ^ (~t4.o & t0.o); \ + s.x1.e ^= s.x0.e; s.x1.o ^= s.x0.o; \ + s.x3.e ^= s.x2.e; s.x3.o ^= s.x2.o; \ + s.x0.e ^= s.x4.e; s.x0.o ^= s.x4.o; \ + /* linear layer */ \ + t0.e = s.x0.e ^ ROTR32(s.x0.o, 4); t0.o = s.x0.o ^ ROTR32(s.x0.e, 5); \ + t1.e = s.x1.e ^ ROTR32(s.x1.e, 11); t1.o = s.x1.o ^ ROTR32(s.x1.o, 11); \ + t2.e = s.x2.e ^ ROTR32(s.x2.o, 2); t2.o = s.x2.o ^ ROTR32(s.x2.e, 3); \ + t3.e = s.x3.e ^ ROTR32(s.x3.o, 3); t3.o = s.x3.o ^ ROTR32(s.x3.e, 4); \ + t4.e = s.x4.e ^ ROTR32(s.x4.e, 17); t4.o = s.x4.o ^ ROTR32(s.x4.o, 17); \ + s.x0.e ^= ROTR32(t0.o, 9); s.x0.o ^= ROTR32(t0.e, 10); \ + s.x1.e ^= ROTR32(t1.o, 19); s.x1.o ^= ROTR32(t1.e, 20); \ + s.x2.e ^= t2.o; s.x2.o ^= ROTR32(t2.e, 1); \ + s.x3.e ^= ROTR32(t3.e, 5); s.x3.o ^= ROTR32(t3.o, 5); \ + s.x4.e ^= ROTR32(t4.o, 3); s.x4.o ^= ROTR32(t4.e, 4); \ + s.x2.e = ~s.x2.e; s.x2.o = ~s.x2.o; \ + } while(0) +/* clang-format on */ + +void P(state *p, u8 rounds); + +#endif // PERMUTATIONS_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/api.h b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/api.h new file mode 100644 index 0000000..a4aa567 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/core.c b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/core.c new file mode 100644 index 0000000..676f436 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/core.c @@ -0,0 +1,78 @@ +#include "core.h" + +void process_data(state* s, unsigned char* out, const unsigned char* in, + unsigned long long len, u8 mode) { + u64* x; + u64 i; + + while (len >= RATE) { + s->x0 ^= U64BIG(*(u64*)in); + s->x1 ^= U64BIG(*(u64*)(in + 8)); + if (mode != ASCON_AD) { + *(u64*)out = U64BIG(s->x0); + *(u64*)(out + 8) = U64BIG(s->x1); + } + if (mode == ASCON_DEC) { + s->x0 = U64BIG(*((u64*)in)); + s->x1 = U64BIG(*((u64*)(in + 8))); + } + P(s, PB_ROUNDS); + in += RATE; + out += RATE; + len -= RATE; + } + + for (i = 0; i < len; ++i, ++out, ++in) { + if (i < 8) + x = &(s->x0); + else + x = &(s->x1); + *x ^= INS_BYTE64(*in, i % 8); + if (mode != ASCON_AD) *out = EXT_BYTE64(*x, i % 8); + if (mode == ASCON_DEC) { + *x &= ~INS_BYTE64(0xff, i % 8); + *x |= INS_BYTE64(*in, i % 8); + } + } + if (len < 8) + s->x0 ^= INS_BYTE64(0x80, len); + else + s->x1 ^= INS_BYTE64(0x80, len % 8); +} + +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); + const u64 K1 = U64BIG(*(u64*)(k + 8)); + const u64 N0 = U64BIG(*(u64*)npub); + const u64 N1 = U64BIG(*(u64*)(npub + 8)); + + // initialization + s->x0 = IV; + s->x1 = K0; + s->x2 = K1; + s->x3 = N0; + s->x4 = N1; + P(s, PA_ROUNDS); + s->x3 ^= K0; + s->x4 ^= K1; + + // 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->x2 ^= K0; + s->x3 ^= K1; + P(s, PA_ROUNDS); + s->x3 ^= K0; + s->x4 ^= K1; +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/core.h b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/core.h new file mode 100644 index 0000000..4a5330f --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/core.h @@ -0,0 +1,27 @@ +#ifndef CORE_H_ +#define CORE_H_ + +#include "api.h" +#include "endian.h" +#include "permutations.h" + +#define ASCON_AD 0 +#define ASCON_ENC 1 +#define ASCON_DEC 2 + +#define RATE (128 / 8) +#define PA_ROUNDS 12 +#define PB_ROUNDS 8 +#define IV \ + ((u64)(8 * (CRYPTO_KEYBYTES)) << 56 | (u64)(8 * (RATE)) << 48 | \ + (u64)(PA_ROUNDS) << 40 | (u64)(PB_ROUNDS) << 32) + +void process_data(state* s, unsigned char* out, const unsigned char* in, + unsigned long long len, u8 mode); + +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); + +#endif // CORE_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/decrypt.c b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/decrypt.c new file mode 100644 index 0000000..0cde81e --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/decrypt.c @@ -0,0 +1,29 @@ +#include "core.h" + +int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen, + unsigned char* nsec, const unsigned char* c, + unsigned long long clen, const unsigned char* ad, + unsigned long long adlen, const unsigned char* npub, + const unsigned char* k) { + if (clen < CRYPTO_ABYTES) { + *mlen = 0; + return -1; + } + + state s; + (void)nsec; + + // set plaintext size + *mlen = clen - CRYPTO_ABYTES; + + ascon_core(&s, m, c, *mlen, ad, adlen, npub, k, ASCON_DEC); + + // verify tag (should be constant time, check compiler output) + if (((s.x3 ^ U64BIG(*(u64*)(c + *mlen))) | + (s.x4 ^ U64BIG(*(u64*)(c + *mlen + 8)))) != 0) { + *mlen = 0; + return -1; + } + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/encrypt.c b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/encrypt.c new file mode 100644 index 0000000..5961c60 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/encrypt.c @@ -0,0 +1,21 @@ +#include "core.h" + +int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen, + const unsigned char* m, unsigned long long mlen, + const unsigned char* ad, unsigned long long adlen, + const unsigned char* nsec, const unsigned char* npub, + const unsigned char* k) { + state s; + (void)nsec; + + // set ciphertext size + *clen = mlen + CRYPTO_ABYTES; + + ascon_core(&s, c, m, mlen, ad, adlen, npub, k, ASCON_ENC); + + // set tag + *(u64*)(c + mlen) = U64BIG(s.x3); + *(u64*)(c + mlen + 8) = U64BIG(s.x4); + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/endian.h b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/endian.h new file mode 100644 index 0000000..b4d18f5 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/endian.h @@ -0,0 +1,29 @@ +#ifndef ENDIAN_H_ +#define ENDIAN_H_ + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +// macros for big endian machines +#define U64BIG(x) (x) +#define U32BIG(x) (x) +#define U16BIG(x) (x) + +#elif defined(_MSC_VER) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + +// macros for little endian machines +#define U64BIG(x) \ + ((((x)&0x00000000000000FFULL) << 56) | (((x)&0x000000000000FF00ULL) << 40) | \ + (((x)&0x0000000000FF0000ULL) << 24) | (((x)&0x00000000FF000000ULL) << 8) | \ + (((x)&0x000000FF00000000ULL) >> 8) | (((x)&0x0000FF0000000000ULL) >> 24) | \ + (((x)&0x00FF000000000000ULL) >> 40) | (((x)&0xFF00000000000000ULL) >> 56)) +#define U32BIG(x) \ + ((((x)&0x000000FF) << 24) | (((x)&0x0000FF00) << 8) | \ + (((x)&0x00FF0000) >> 8) | (((x)&0xFF000000) >> 24)) +#define U16BIG(x) ((((x)&0x00FF) << 8) | (((x)&0xFF00) >> 8)) + +#else +#error "ascon byte order macros not defined in endian.h" +#endif + +#endif // ENDIAN_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/implementors b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/implementors new file mode 100644 index 0000000..b110c1a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/implementors @@ -0,0 +1,2 @@ +Christoph Dobraunig +Martin Schläffer diff --git a/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/permutations.c b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/permutations.c new file mode 100644 index 0000000..9aaf9d1 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/permutations.c @@ -0,0 +1,8 @@ +#include "permutations.h" + +void P(state *p, u8 rounds) { + state s = *p; + u8 i, start = START_CONSTANT(rounds); + for (i = start; i > 0x4a; i -= 0x0f) ROUND(i); + *p = s; +} diff --git a/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/permutations.h b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/permutations.h new file mode 100644 index 0000000..7143e82 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128av12/opt64_lowsize/permutations.h @@ -0,0 +1,66 @@ +#ifndef PERMUTATIONS_H_ +#define PERMUTATIONS_H_ + +typedef unsigned char u8; +typedef unsigned long long u64; + +typedef struct { + u64 x0, x1, x2, x3, x4; +} state; + +#define EXT_BYTE64(x, n) ((u8)((u64)(x) >> (8 * (7 - (n))))) +#define INS_BYTE64(x, n) ((u64)(x) << (8 * (7 - (n)))) +#define ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) +#define START_CONSTANT(x) (((0xf - (12 - (x))) << 4) | (12 - (x))) + +#define ROUND(C) \ + do { \ + state t; \ + s.x2 ^= C; \ + s.x0 ^= s.x4; \ + s.x4 ^= s.x3; \ + s.x2 ^= s.x1; \ + t.x0 = s.x0; \ + t.x4 = s.x4; \ + t.x3 = s.x3; \ + t.x1 = s.x1; \ + t.x2 = s.x2; \ + s.x0 = t.x0 ^ ((~t.x1) & t.x2); \ + s.x2 = t.x2 ^ ((~t.x3) & t.x4); \ + s.x4 = t.x4 ^ ((~t.x0) & t.x1); \ + s.x1 = t.x1 ^ ((~t.x2) & t.x3); \ + s.x3 = t.x3 ^ ((~t.x4) & t.x0); \ + s.x1 ^= s.x0; \ + t.x1 = s.x1; \ + s.x1 = ROTR64(s.x1, 39); \ + s.x3 ^= s.x2; \ + t.x2 = s.x2; \ + s.x2 = ROTR64(s.x2, 1); \ + t.x4 = s.x4; \ + t.x2 ^= s.x2; \ + s.x2 = ROTR64(s.x2, 6 - 1); \ + t.x3 = s.x3; \ + t.x1 ^= s.x1; \ + s.x3 = ROTR64(s.x3, 10); \ + s.x0 ^= s.x4; \ + s.x4 = ROTR64(s.x4, 7); \ + t.x3 ^= s.x3; \ + s.x2 ^= t.x2; \ + s.x1 = ROTR64(s.x1, 61 - 39); \ + t.x0 = s.x0; \ + s.x2 = ~s.x2; \ + s.x3 = ROTR64(s.x3, 17 - 10); \ + t.x4 ^= s.x4; \ + s.x4 = ROTR64(s.x4, 41 - 7); \ + s.x3 ^= t.x3; \ + s.x1 ^= t.x1; \ + s.x0 = ROTR64(s.x0, 19); \ + s.x4 ^= t.x4; \ + t.x0 ^= s.x0; \ + s.x0 = ROTR64(s.x0, 28 - 19); \ + s.x0 ^= t.x0; \ + } while (0) + +void P(state *p, u8 rounds); + +#endif // PERMUTATIONS_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/api.h b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/api.h new file mode 100644 index 0000000..a4aa567 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/core.c b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/core.c new file mode 100644 index 0000000..79db104 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/core.c @@ -0,0 +1,93 @@ +#include "core.h" + +void process_data(state* s, unsigned char* out, const unsigned char* in, + unsigned long long len, u8 mode) { + u32_2 t0; + u64 tmp0; + u64 i; + + while (len >= RATE) { + tmp0 = U64BIG(*(u64*)in); + t0 = to_bit_interleaving(tmp0); + s->x0.e ^= t0.e; + s->x0.o ^= t0.o; + if (mode != ASCON_AD) { + tmp0 = from_bit_interleaving(s->x0); + *(u64*)out = U64BIG(tmp0); + } + if (mode == ASCON_DEC) s->x0 = t0; + P(s, PB_ROUNDS); + in += RATE; + out += RATE; + len -= RATE; + } + + tmp0 = 0; + for (i = 0; i < len; ++i, ++in) tmp0 |= INS_BYTE64(*in, i); + in -= len; + tmp0 |= INS_BYTE64(0x80, len); + t0 = to_bit_interleaving(tmp0); + s->x0.e ^= t0.e; + s->x0.o ^= t0.o; + if (mode != ASCON_AD) { + tmp0 = from_bit_interleaving(s->x0); + for (i = 0; i < len; ++i, ++out) *out = EXT_BYTE64(tmp0, i); + } + if (mode == ASCON_DEC) { + for (i = 0; i < len; ++i, ++in) { + tmp0 &= ~INS_BYTE64(0xff, i); + tmp0 |= INS_BYTE64(*in, i); + } + s->x0 = to_bit_interleaving(tmp0); + } +} + +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(U64BIG(*(u64*)k)); + K1 = to_bit_interleaving(U64BIG(*(u64*)(k + 8))); + N0 = to_bit_interleaving(U64BIG(*(u64*)npub)); + N1 = to_bit_interleaving(U64BIG(*(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->x1.e ^= K0.e; + s->x1.o ^= K0.o; + s->x2.e ^= K1.e; + s->x2.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; +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/core.h b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/core.h new file mode 100644 index 0000000..90076c1 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/core.h @@ -0,0 +1,27 @@ +#ifndef CORE_H_ +#define CORE_H_ + +#include "api.h" +#include "endian.h" +#include "permutations.h" + +#define ASCON_AD 0 +#define ASCON_ENC 1 +#define ASCON_DEC 2 + +#define RATE (64 / 8) +#define PA_ROUNDS 12 +#define PB_ROUNDS 6 +#define IV \ + ((u64)(8 * (CRYPTO_KEYBYTES)) << 56 | (u64)(8 * (RATE)) << 48 | \ + (u64)(PA_ROUNDS) << 40 | (u64)(PB_ROUNDS) << 32) + +void process_data(state* s, unsigned char* out, const unsigned char* in, + unsigned long long len, u8 mode); + +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); + +#endif // CORE_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/decrypt.c b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/decrypt.c new file mode 100644 index 0000000..7e9dd1a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/decrypt.c @@ -0,0 +1,32 @@ +#include "core.h" + +int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen, + unsigned char* nsec, const unsigned char* c, + unsigned long long clen, const unsigned char* ad, + unsigned long long adlen, const unsigned char* npub, + const unsigned char* k) { + if (clen < CRYPTO_ABYTES) { + *mlen = 0; + return -1; + } + + state s; + u32_2 t0, t1; + (void)nsec; + + // set plaintext size + *mlen = clen - CRYPTO_ABYTES; + + ascon_core(&s, m, c, *mlen, ad, adlen, npub, k, ASCON_DEC); + + // verify tag (should be constant time, check compiler output) + t0 = to_bit_interleaving(U64BIG(*(u64*)(c + *mlen))); + t1 = to_bit_interleaving(U64BIG(*(u64*)(c + *mlen + 8))); + if (((s.x3.e ^ t0.e) | (s.x3.o ^ t0.o) | (s.x4.e ^ t1.e) | (s.x4.o ^ t1.o)) != + 0) { + *mlen = 0; + return -1; + } + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/encrypt.c b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/encrypt.c new file mode 100644 index 0000000..b5dc587 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/encrypt.c @@ -0,0 +1,24 @@ +#include "core.h" + +int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen, + const unsigned char* m, unsigned long long mlen, + const unsigned char* ad, unsigned long long adlen, + const unsigned char* nsec, const unsigned char* npub, + const unsigned char* k) { + state s; + u64 tmp0, tmp1; + (void)nsec; + + // set ciphertext size + *clen = mlen + CRYPTO_ABYTES; + + ascon_core(&s, c, m, mlen, ad, adlen, npub, k, ASCON_ENC); + + // set tag + tmp0 = from_bit_interleaving(s.x3); + *(u64*)(c + mlen) = U64BIG(tmp0); + tmp1 = from_bit_interleaving(s.x4); + *(u64*)(c + mlen + 8) = U64BIG(tmp1); + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/endian.h b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/endian.h new file mode 100644 index 0000000..b4d18f5 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/endian.h @@ -0,0 +1,29 @@ +#ifndef ENDIAN_H_ +#define ENDIAN_H_ + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +// macros for big endian machines +#define U64BIG(x) (x) +#define U32BIG(x) (x) +#define U16BIG(x) (x) + +#elif defined(_MSC_VER) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + +// macros for little endian machines +#define U64BIG(x) \ + ((((x)&0x00000000000000FFULL) << 56) | (((x)&0x000000000000FF00ULL) << 40) | \ + (((x)&0x0000000000FF0000ULL) << 24) | (((x)&0x00000000FF000000ULL) << 8) | \ + (((x)&0x000000FF00000000ULL) >> 8) | (((x)&0x0000FF0000000000ULL) >> 24) | \ + (((x)&0x00FF000000000000ULL) >> 40) | (((x)&0xFF00000000000000ULL) >> 56)) +#define U32BIG(x) \ + ((((x)&0x000000FF) << 24) | (((x)&0x0000FF00) << 8) | \ + (((x)&0x00FF0000) >> 8) | (((x)&0xFF000000) >> 24)) +#define U16BIG(x) ((((x)&0x00FF) << 8) | (((x)&0xFF00) >> 8)) + +#else +#error "ascon byte order macros not defined in endian.h" +#endif + +#endif // ENDIAN_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/implementors b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/implementors new file mode 100644 index 0000000..b110c1a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/implementors @@ -0,0 +1,2 @@ +Christoph Dobraunig +Martin Schläffer diff --git a/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/permutations.c b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/permutations.c new file mode 100644 index 0000000..bc47f5f --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/permutations.c @@ -0,0 +1,50 @@ +#include "permutations.h" + +static const u8 constants[][2] = { + {0xc, 0xc}, {0x9, 0xc}, {0xc, 0x9}, {0x9, 0x9}, {0x6, 0xc}, {0x3, 0xc}, + {0x6, 0x9}, {0x3, 0x9}, {0xc, 0x6}, {0x9, 0x6}, {0xc, 0x3}, {0x9, 0x3}}; + +// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +u32_2 to_bit_interleaving(u64 in) { + u32 hi = (in) >> 32; + u32 lo = (u32)(in); + u32 r0, r1; + u32_2 out; + r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1); + r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2); + r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4); + r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8); + r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1); + r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2); + r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4); + r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8); + out.e = (lo & 0x0000FFFF) | (hi << 16); + out.o = (lo >> 16) | (hi & 0xFFFF0000); + return out; +} + +// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +u64 from_bit_interleaving(u32_2 in) { + u32 lo = (in.e & 0x0000FFFF) | (in.o << 16); + u32 hi = (in.e >> 16) | (in.o & 0xFFFF0000); + u32 r0, r1; + u64 out; + r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8); + r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4); + r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2); + r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1); + r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8); + r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4); + r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2); + r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1); + out = (u64)hi << 32 | lo; + return out; +} + +void P(state *p, u8 rounds) { + state s = *p; + u32_2 t0, t1, t2, t3, t4; + u32 i, start = START_ROUND(rounds); + for (i = start; i < 12; i++) ROUND(constants[i][0], constants[i][1]); + *p = s; +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/permutations.h b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/permutations.h new file mode 100644 index 0000000..bc643ce --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/bi32_lowsize/permutations.h @@ -0,0 +1,71 @@ +#ifndef PERMUTATIONS_H_ +#define PERMUTATIONS_H_ + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned long long u64; + +typedef struct { + u32 e; + u32 o; +} u32_2; + +typedef struct { + u32_2 x0; + u32_2 x1; + u32_2 x2; + u32_2 x3; + u32_2 x4; +} state; + +#define EXT_BYTE64(x, n) ((u8)((u64)(x) >> (8 * (7 - (n))))) +#define INS_BYTE64(x, n) ((u64)(x) << (8 * (7 - (n)))) +#define ROTR32(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) +#define START_ROUND(x) (12 - (x)) + +// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +u32_2 to_bit_interleaving(u64 in); + +// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +u64 from_bit_interleaving(u32_2 in); + +/* clang-format off */ +#define ROUND(C_e, C_o) \ + do { \ + /* round constant */ \ + s.x2.e ^= C_e; s.x2.o ^= C_o; \ + /* s-box layer */ \ + s.x0.e ^= s.x4.e; s.x0.o ^= s.x4.o; \ + s.x4.e ^= s.x3.e; s.x4.o ^= s.x3.o; \ + s.x2.e ^= s.x1.e; s.x2.o ^= s.x1.o; \ + t0.e = s.x0.e; t0.o = s.x0.o; \ + t4.e = s.x4.e; t4.o = s.x4.o; \ + t3.e = s.x3.e; t3.o = s.x3.o; \ + t1.e = s.x1.e; t1.o = s.x1.o; \ + t2.e = s.x2.e; t2.o = s.x2.o; \ + s.x0.e = t0.e ^ (~t1.e & t2.e); s.x0.o = t0.o ^ (~t1.o & t2.o); \ + s.x2.e = t2.e ^ (~t3.e & t4.e); s.x2.o = t2.o ^ (~t3.o & t4.o); \ + s.x4.e = t4.e ^ (~t0.e & t1.e); s.x4.o = t4.o ^ (~t0.o & t1.o); \ + s.x1.e = t1.e ^ (~t2.e & t3.e); s.x1.o = t1.o ^ (~t2.o & t3.o); \ + s.x3.e = t3.e ^ (~t4.e & t0.e); s.x3.o = t3.o ^ (~t4.o & t0.o); \ + s.x1.e ^= s.x0.e; s.x1.o ^= s.x0.o; \ + s.x3.e ^= s.x2.e; s.x3.o ^= s.x2.o; \ + s.x0.e ^= s.x4.e; s.x0.o ^= s.x4.o; \ + /* linear layer */ \ + t0.e = s.x0.e ^ ROTR32(s.x0.o, 4); t0.o = s.x0.o ^ ROTR32(s.x0.e, 5); \ + t1.e = s.x1.e ^ ROTR32(s.x1.e, 11); t1.o = s.x1.o ^ ROTR32(s.x1.o, 11); \ + t2.e = s.x2.e ^ ROTR32(s.x2.o, 2); t2.o = s.x2.o ^ ROTR32(s.x2.e, 3); \ + t3.e = s.x3.e ^ ROTR32(s.x3.o, 3); t3.o = s.x3.o ^ ROTR32(s.x3.e, 4); \ + t4.e = s.x4.e ^ ROTR32(s.x4.e, 17); t4.o = s.x4.o ^ ROTR32(s.x4.o, 17); \ + s.x0.e ^= ROTR32(t0.o, 9); s.x0.o ^= ROTR32(t0.e, 10); \ + s.x1.e ^= ROTR32(t1.o, 19); s.x1.o ^= ROTR32(t1.e, 20); \ + s.x2.e ^= t2.o; s.x2.o ^= ROTR32(t2.e, 1); \ + s.x3.e ^= ROTR32(t3.e, 5); s.x3.o ^= ROTR32(t3.o, 5); \ + s.x4.e ^= ROTR32(t4.o, 3); s.x4.o ^= ROTR32(t4.e, 4); \ + s.x2.e = ~s.x2.e; s.x2.o = ~s.x2.o; \ + } while(0) +/* clang-format on */ + +void P(state *p, u8 rounds); + +#endif // PERMUTATIONS_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/api.h b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/api.h new file mode 100644 index 0000000..a4aa567 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/core.c b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/core.c new file mode 100644 index 0000000..48cac3d --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/core.c @@ -0,0 +1,64 @@ +#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); + const u64 K1 = U64BIG(*(u64*)(k + 8)); + const u64 N0 = U64BIG(*(u64*)npub); + const u64 N1 = U64BIG(*(u64*)(npub + 8)); + + // initialization + s->x0 = IV; + s->x1 = K0; + s->x2 = K1; + s->x3 = N0; + s->x4 = N1; + P(s, PA_ROUNDS); + s->x3 ^= K0; + s->x4 ^= K1; + + // 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; + s->x2 ^= K1; + P(s, PA_ROUNDS); + s->x3 ^= K0; + s->x4 ^= K1; +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/core.h b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/core.h new file mode 100644 index 0000000..90076c1 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/core.h @@ -0,0 +1,27 @@ +#ifndef CORE_H_ +#define CORE_H_ + +#include "api.h" +#include "endian.h" +#include "permutations.h" + +#define ASCON_AD 0 +#define ASCON_ENC 1 +#define ASCON_DEC 2 + +#define RATE (64 / 8) +#define PA_ROUNDS 12 +#define PB_ROUNDS 6 +#define IV \ + ((u64)(8 * (CRYPTO_KEYBYTES)) << 56 | (u64)(8 * (RATE)) << 48 | \ + (u64)(PA_ROUNDS) << 40 | (u64)(PB_ROUNDS) << 32) + +void process_data(state* s, unsigned char* out, const unsigned char* in, + unsigned long long len, u8 mode); + +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); + +#endif // CORE_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/decrypt.c b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/decrypt.c new file mode 100644 index 0000000..0cde81e --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/decrypt.c @@ -0,0 +1,29 @@ +#include "core.h" + +int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen, + unsigned char* nsec, const unsigned char* c, + unsigned long long clen, const unsigned char* ad, + unsigned long long adlen, const unsigned char* npub, + const unsigned char* k) { + if (clen < CRYPTO_ABYTES) { + *mlen = 0; + return -1; + } + + state s; + (void)nsec; + + // set plaintext size + *mlen = clen - CRYPTO_ABYTES; + + ascon_core(&s, m, c, *mlen, ad, adlen, npub, k, ASCON_DEC); + + // verify tag (should be constant time, check compiler output) + if (((s.x3 ^ U64BIG(*(u64*)(c + *mlen))) | + (s.x4 ^ U64BIG(*(u64*)(c + *mlen + 8)))) != 0) { + *mlen = 0; + return -1; + } + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/encrypt.c b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/encrypt.c new file mode 100644 index 0000000..5961c60 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/encrypt.c @@ -0,0 +1,21 @@ +#include "core.h" + +int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen, + const unsigned char* m, unsigned long long mlen, + const unsigned char* ad, unsigned long long adlen, + const unsigned char* nsec, const unsigned char* npub, + const unsigned char* k) { + state s; + (void)nsec; + + // set ciphertext size + *clen = mlen + CRYPTO_ABYTES; + + ascon_core(&s, c, m, mlen, ad, adlen, npub, k, ASCON_ENC); + + // set tag + *(u64*)(c + mlen) = U64BIG(s.x3); + *(u64*)(c + mlen + 8) = U64BIG(s.x4); + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/endian.h b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/endian.h new file mode 100644 index 0000000..b4d18f5 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/endian.h @@ -0,0 +1,29 @@ +#ifndef ENDIAN_H_ +#define ENDIAN_H_ + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +// macros for big endian machines +#define U64BIG(x) (x) +#define U32BIG(x) (x) +#define U16BIG(x) (x) + +#elif defined(_MSC_VER) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + +// macros for little endian machines +#define U64BIG(x) \ + ((((x)&0x00000000000000FFULL) << 56) | (((x)&0x000000000000FF00ULL) << 40) | \ + (((x)&0x0000000000FF0000ULL) << 24) | (((x)&0x00000000FF000000ULL) << 8) | \ + (((x)&0x000000FF00000000ULL) >> 8) | (((x)&0x0000FF0000000000ULL) >> 24) | \ + (((x)&0x00FF000000000000ULL) >> 40) | (((x)&0xFF00000000000000ULL) >> 56)) +#define U32BIG(x) \ + ((((x)&0x000000FF) << 24) | (((x)&0x0000FF00) << 8) | \ + (((x)&0x00FF0000) >> 8) | (((x)&0xFF000000) >> 24)) +#define U16BIG(x) ((((x)&0x00FF) << 8) | (((x)&0xFF00) >> 8)) + +#else +#error "ascon byte order macros not defined in endian.h" +#endif + +#endif // ENDIAN_H_ diff --git a/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/implementors b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/implementors new file mode 100644 index 0000000..b110c1a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/implementors @@ -0,0 +1,2 @@ +Christoph Dobraunig +Martin Schläffer diff --git a/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/permutations.c b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/permutations.c new file mode 100644 index 0000000..9aaf9d1 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/permutations.c @@ -0,0 +1,8 @@ +#include "permutations.h" + +void P(state *p, u8 rounds) { + state s = *p; + u8 i, start = START_CONSTANT(rounds); + for (i = start; i > 0x4a; i -= 0x0f) ROUND(i); + *p = s; +} diff --git a/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/permutations.h b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/permutations.h new file mode 100644 index 0000000..7143e82 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon128v12/opt64_lowsize/permutations.h @@ -0,0 +1,66 @@ +#ifndef PERMUTATIONS_H_ +#define PERMUTATIONS_H_ + +typedef unsigned char u8; +typedef unsigned long long u64; + +typedef struct { + u64 x0, x1, x2, x3, x4; +} state; + +#define EXT_BYTE64(x, n) ((u8)((u64)(x) >> (8 * (7 - (n))))) +#define INS_BYTE64(x, n) ((u64)(x) << (8 * (7 - (n)))) +#define ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) +#define START_CONSTANT(x) (((0xf - (12 - (x))) << 4) | (12 - (x))) + +#define ROUND(C) \ + do { \ + state t; \ + s.x2 ^= C; \ + s.x0 ^= s.x4; \ + s.x4 ^= s.x3; \ + s.x2 ^= s.x1; \ + t.x0 = s.x0; \ + t.x4 = s.x4; \ + t.x3 = s.x3; \ + t.x1 = s.x1; \ + t.x2 = s.x2; \ + s.x0 = t.x0 ^ ((~t.x1) & t.x2); \ + s.x2 = t.x2 ^ ((~t.x3) & t.x4); \ + s.x4 = t.x4 ^ ((~t.x0) & t.x1); \ + s.x1 = t.x1 ^ ((~t.x2) & t.x3); \ + s.x3 = t.x3 ^ ((~t.x4) & t.x0); \ + s.x1 ^= s.x0; \ + t.x1 = s.x1; \ + s.x1 = ROTR64(s.x1, 39); \ + s.x3 ^= s.x2; \ + t.x2 = s.x2; \ + s.x2 = ROTR64(s.x2, 1); \ + t.x4 = s.x4; \ + t.x2 ^= s.x2; \ + s.x2 = ROTR64(s.x2, 6 - 1); \ + t.x3 = s.x3; \ + t.x1 ^= s.x1; \ + s.x3 = ROTR64(s.x3, 10); \ + s.x0 ^= s.x4; \ + s.x4 = ROTR64(s.x4, 7); \ + t.x3 ^= s.x3; \ + s.x2 ^= t.x2; \ + s.x1 = ROTR64(s.x1, 61 - 39); \ + t.x0 = s.x0; \ + s.x2 = ~s.x2; \ + s.x3 = ROTR64(s.x3, 17 - 10); \ + t.x4 ^= s.x4; \ + s.x4 = ROTR64(s.x4, 41 - 7); \ + s.x3 ^= t.x3; \ + s.x1 ^= t.x1; \ + s.x0 = ROTR64(s.x0, 19); \ + s.x4 ^= t.x4; \ + t.x0 ^= s.x0; \ + s.x0 = ROTR64(s.x0, 28 - 19); \ + s.x0 ^= t.x0; \ + } while (0) + +void P(state *p, u8 rounds); + +#endif // PERMUTATIONS_H_ diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/api.h b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/api.h new file mode 100644 index 0000000..4b53d6c --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 20 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/core.c b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/core.c new file mode 100644 index 0000000..88bcb45 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/core.c @@ -0,0 +1,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; +} diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/core.h b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/core.h new file mode 100644 index 0000000..90076c1 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/core.h @@ -0,0 +1,27 @@ +#ifndef CORE_H_ +#define CORE_H_ + +#include "api.h" +#include "endian.h" +#include "permutations.h" + +#define ASCON_AD 0 +#define ASCON_ENC 1 +#define ASCON_DEC 2 + +#define RATE (64 / 8) +#define PA_ROUNDS 12 +#define PB_ROUNDS 6 +#define IV \ + ((u64)(8 * (CRYPTO_KEYBYTES)) << 56 | (u64)(8 * (RATE)) << 48 | \ + (u64)(PA_ROUNDS) << 40 | (u64)(PB_ROUNDS) << 32) + +void process_data(state* s, unsigned char* out, const unsigned char* in, + unsigned long long len, u8 mode); + +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); + +#endif // CORE_H_ diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/decrypt.c b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/decrypt.c new file mode 100644 index 0000000..0cde81e --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/decrypt.c @@ -0,0 +1,29 @@ +#include "core.h" + +int crypto_aead_decrypt(unsigned char* m, unsigned long long* mlen, + unsigned char* nsec, const unsigned char* c, + unsigned long long clen, const unsigned char* ad, + unsigned long long adlen, const unsigned char* npub, + const unsigned char* k) { + if (clen < CRYPTO_ABYTES) { + *mlen = 0; + return -1; + } + + state s; + (void)nsec; + + // set plaintext size + *mlen = clen - CRYPTO_ABYTES; + + ascon_core(&s, m, c, *mlen, ad, adlen, npub, k, ASCON_DEC); + + // verify tag (should be constant time, check compiler output) + if (((s.x3 ^ U64BIG(*(u64*)(c + *mlen))) | + (s.x4 ^ U64BIG(*(u64*)(c + *mlen + 8)))) != 0) { + *mlen = 0; + return -1; + } + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/encrypt.c b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/encrypt.c new file mode 100644 index 0000000..5961c60 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/encrypt.c @@ -0,0 +1,21 @@ +#include "core.h" + +int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen, + const unsigned char* m, unsigned long long mlen, + const unsigned char* ad, unsigned long long adlen, + const unsigned char* nsec, const unsigned char* npub, + const unsigned char* k) { + state s; + (void)nsec; + + // set ciphertext size + *clen = mlen + CRYPTO_ABYTES; + + ascon_core(&s, c, m, mlen, ad, adlen, npub, k, ASCON_ENC); + + // set tag + *(u64*)(c + mlen) = U64BIG(s.x3); + *(u64*)(c + mlen + 8) = U64BIG(s.x4); + + return 0; +} diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/endian.h b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/endian.h new file mode 100644 index 0000000..b4d18f5 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/endian.h @@ -0,0 +1,29 @@ +#ifndef ENDIAN_H_ +#define ENDIAN_H_ + +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + +// macros for big endian machines +#define U64BIG(x) (x) +#define U32BIG(x) (x) +#define U16BIG(x) (x) + +#elif defined(_MSC_VER) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + +// macros for little endian machines +#define U64BIG(x) \ + ((((x)&0x00000000000000FFULL) << 56) | (((x)&0x000000000000FF00ULL) << 40) | \ + (((x)&0x0000000000FF0000ULL) << 24) | (((x)&0x00000000FF000000ULL) << 8) | \ + (((x)&0x000000FF00000000ULL) >> 8) | (((x)&0x0000FF0000000000ULL) >> 24) | \ + (((x)&0x00FF000000000000ULL) >> 40) | (((x)&0xFF00000000000000ULL) >> 56)) +#define U32BIG(x) \ + ((((x)&0x000000FF) << 24) | (((x)&0x0000FF00) << 8) | \ + (((x)&0x00FF0000) >> 8) | (((x)&0xFF000000) >> 24)) +#define U16BIG(x) ((((x)&0x00FF) << 8) | (((x)&0xFF00) >> 8)) + +#else +#error "ascon byte order macros not defined in endian.h" +#endif + +#endif // ENDIAN_H_ diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/implementors b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/implementors new file mode 100644 index 0000000..b110c1a --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/implementors @@ -0,0 +1,2 @@ +Christoph Dobraunig +Martin Schläffer diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/permutations.c b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/permutations.c new file mode 100644 index 0000000..9aaf9d1 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/permutations.c @@ -0,0 +1,8 @@ +#include "permutations.h" + +void P(state *p, u8 rounds) { + state s = *p; + u8 i, start = START_CONSTANT(rounds); + for (i = start; i > 0x4a; i -= 0x0f) ROUND(i); + *p = s; +} diff --git a/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/permutations.h b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/permutations.h new file mode 100644 index 0000000..7143e82 --- /dev/null +++ b/ascon/Implementations/crypto_aead/ascon80pqv12/opt64_lowsize/permutations.h @@ -0,0 +1,66 @@ +#ifndef PERMUTATIONS_H_ +#define PERMUTATIONS_H_ + +typedef unsigned char u8; +typedef unsigned long long u64; + +typedef struct { + u64 x0, x1, x2, x3, x4; +} state; + +#define EXT_BYTE64(x, n) ((u8)((u64)(x) >> (8 * (7 - (n))))) +#define INS_BYTE64(x, n) ((u64)(x) << (8 * (7 - (n)))) +#define ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) +#define START_CONSTANT(x) (((0xf - (12 - (x))) << 4) | (12 - (x))) + +#define ROUND(C) \ + do { \ + state t; \ + s.x2 ^= C; \ + s.x0 ^= s.x4; \ + s.x4 ^= s.x3; \ + s.x2 ^= s.x1; \ + t.x0 = s.x0; \ + t.x4 = s.x4; \ + t.x3 = s.x3; \ + t.x1 = s.x1; \ + t.x2 = s.x2; \ + s.x0 = t.x0 ^ ((~t.x1) & t.x2); \ + s.x2 = t.x2 ^ ((~t.x3) & t.x4); \ + s.x4 = t.x4 ^ ((~t.x0) & t.x1); \ + s.x1 = t.x1 ^ ((~t.x2) & t.x3); \ + s.x3 = t.x3 ^ ((~t.x4) & t.x0); \ + s.x1 ^= s.x0; \ + t.x1 = s.x1; \ + s.x1 = ROTR64(s.x1, 39); \ + s.x3 ^= s.x2; \ + t.x2 = s.x2; \ + s.x2 = ROTR64(s.x2, 1); \ + t.x4 = s.x4; \ + t.x2 ^= s.x2; \ + s.x2 = ROTR64(s.x2, 6 - 1); \ + t.x3 = s.x3; \ + t.x1 ^= s.x1; \ + s.x3 = ROTR64(s.x3, 10); \ + s.x0 ^= s.x4; \ + s.x4 = ROTR64(s.x4, 7); \ + t.x3 ^= s.x3; \ + s.x2 ^= t.x2; \ + s.x1 = ROTR64(s.x1, 61 - 39); \ + t.x0 = s.x0; \ + s.x2 = ~s.x2; \ + s.x3 = ROTR64(s.x3, 17 - 10); \ + t.x4 ^= s.x4; \ + s.x4 = ROTR64(s.x4, 41 - 7); \ + s.x3 ^= t.x3; \ + s.x1 ^= t.x1; \ + s.x0 = ROTR64(s.x0, 19); \ + s.x4 ^= t.x4; \ + t.x0 ^= s.x0; \ + s.x0 = ROTR64(s.x0, 28 - 19); \ + s.x0 ^= t.x0; \ + } while (0) + +void P(state *p, u8 rounds); + +#endif // PERMUTATIONS_H_