diff --git a/src/aegis128x2/aegis128x2_common.h b/src/aegis128x2/aegis128x2_common.h index 01aa97d..e604ff5 100644 --- a/src/aegis128x2/aegis128x2_common.h +++ b/src/aegis128x2/aegis128x2_common.h @@ -407,8 +407,8 @@ typedef struct _aegis128x2_state { } _aegis128x2_state; typedef struct _aegis128x2_mac_state { - aegis_blocks blocks0; aegis_blocks blocks; + aegis_blocks blocks0; uint8_t buf[RATE]; uint64_t adlen; size_t pos; diff --git a/src/aegis128x4/aegis128x4_common.h b/src/aegis128x4/aegis128x4_common.h index 19384ef..9dd1c3e 100644 --- a/src/aegis128x4/aegis128x4_common.h +++ b/src/aegis128x4/aegis128x4_common.h @@ -422,8 +422,8 @@ typedef struct _aegis128x4_state { } _aegis128x4_state; typedef struct _aegis128x4_mac_state { - aegis_blocks blocks0; aegis_blocks blocks; + aegis_blocks blocks0; uint8_t buf[RATE]; uint64_t adlen; size_t pos; diff --git a/src/aegis256/aegis256_common.h b/src/aegis256/aegis256_common.h index acf66e0..3ab1a47 100644 --- a/src/aegis256/aegis256_common.h +++ b/src/aegis256/aegis256_common.h @@ -289,8 +289,8 @@ typedef struct _aegis256_state { } _aegis256_state; typedef struct _aegis256_mac_state { - aegis_blocks blocks0; aegis_blocks blocks; + aegis_blocks blocks0; uint8_t buf[RATE]; uint64_t adlen; size_t pos; diff --git a/src/aegis256x2/aegis256x2.c b/src/aegis256x2/aegis256x2.c index 0777d7f..cb12585 100644 --- a/src/aegis256x2/aegis256x2.c +++ b/src/aegis256x2/aegis256x2.c @@ -176,19 +176,19 @@ aegis256x2_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, co } void -aegis256x2_mac_init(aegis256x2_state *st_, const uint8_t *k, const uint8_t *npub) +aegis256x2_mac_init(aegis256x2_mac_state *st_, const uint8_t *k, const uint8_t *npub) { - implementation->state_init(st_, NULL, 0, npub, k); + implementation->state_mac_init(st_, npub, k); } int -aegis256x2_mac_update(aegis256x2_state *st_, const uint8_t *m, size_t mlen) +aegis256x2_mac_update(aegis256x2_mac_state *st_, const uint8_t *m, size_t mlen) { return implementation->state_mac_update(st_, m, mlen); } int -aegis256x2_mac_final(aegis256x2_state *st_, uint8_t *mac, size_t maclen) +aegis256x2_mac_final(aegis256x2_mac_state *st_, uint8_t *mac, size_t maclen) { if (maclen != 16 && maclen != 32) { errno = EINVAL; @@ -198,7 +198,7 @@ aegis256x2_mac_final(aegis256x2_state *st_, uint8_t *mac, size_t maclen) } int -aegis256x2_mac_verify(aegis256x2_state *st_, const uint8_t *mac, size_t maclen) +aegis256x2_mac_verify(aegis256x2_mac_state *st_, const uint8_t *mac, size_t maclen) { uint8_t expected_mac[32]; @@ -216,9 +216,15 @@ aegis256x2_mac_verify(aegis256x2_state *st_, const uint8_t *mac, size_t maclen) } void -aegis256x2_mac_state_clone(aegis256x2_state *dst, const aegis256x2_state *src) +aegis256x2_mac_reset(aegis256x2_mac_state *st_) { - implementation->state_clone(dst, src); + implementation->state_mac_reset(st_); +} + +void +aegis256x2_mac_state_clone(aegis256x2_mac_state *dst, const aegis256x2_mac_state *src) +{ + implementation->state_mac_clone(dst, src); } int diff --git a/src/aegis256x2/aegis256x2_aesni.c b/src/aegis256x2/aegis256x2_aesni.c index 98020cf..7064c96 100644 --- a/src/aegis256x2/aegis256x2_aesni.c +++ b/src/aegis256x2/aegis256x2_aesni.c @@ -93,9 +93,11 @@ struct aegis256x2_implementation aegis256x2_aesni_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; # ifdef __clang__ diff --git a/src/aegis256x2/aegis256x2_altivec.c b/src/aegis256x2/aegis256x2_altivec.c index 52d7e0e..d34901d 100644 --- a/src/aegis256x2/aegis256x2_altivec.c +++ b/src/aegis256x2/aegis256x2_altivec.c @@ -91,9 +91,11 @@ struct aegis256x2_implementation aegis256x2_altivec_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; # ifdef __clang__ diff --git a/src/aegis256x2/aegis256x2_armcrypto.c b/src/aegis256x2/aegis256x2_armcrypto.c index 6ffbab8..8ecdf73 100644 --- a/src/aegis256x2/aegis256x2_armcrypto.c +++ b/src/aegis256x2/aegis256x2_armcrypto.c @@ -99,9 +99,11 @@ struct aegis256x2_implementation aegis256x2_armcrypto_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; # ifdef __clang__ diff --git a/src/aegis256x2/aegis256x2_avx2.c b/src/aegis256x2/aegis256x2_avx2.c index d5d7e57..01d4505 100644 --- a/src/aegis256x2/aegis256x2_avx2.c +++ b/src/aegis256x2/aegis256x2_avx2.c @@ -61,9 +61,11 @@ struct aegis256x2_implementation aegis256x2_avx2_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; # ifdef __clang__ diff --git a/src/aegis256x2/aegis256x2_common.h b/src/aegis256x2/aegis256x2_common.h index 94157dd..80f904e 100644 --- a/src/aegis256x2/aegis256x2_common.h +++ b/src/aegis256x2/aegis256x2_common.h @@ -178,6 +178,74 @@ aegis256x2_declast(uint8_t *const dst, const uint8_t *const src, size_t len, aegis256x2_update(state, msg); } +static void +aegis256x2_mac_nr(uint8_t *mac, size_t maclen, uint64_t adlen, aes_block_t *state) +{ + uint8_t t[2 * AES_BLOCK_LENGTH]; + uint8_t r[RATE]; + aes_block_t tmp; + int i; + const int d = AES_BLOCK_LENGTH / 16; + + tmp = AES_BLOCK_LOAD_64x2(0, adlen << 3); + tmp = AES_BLOCK_XOR(tmp, state[3]); + + for (i = 0; i < 7; i++) { + aegis256x2_update(state, tmp); + } + + memset(r, 0, sizeof r); + if (maclen == 16) { +#if AES_BLOCK_LENGTH > 16 + tmp = AES_BLOCK_XOR(state[5], state[4]); + tmp = AES_BLOCK_XOR(tmp, AES_BLOCK_XOR(state[3], state[2])); + tmp = AES_BLOCK_XOR(tmp, AES_BLOCK_XOR(state[1], state[0])); + AES_BLOCK_STORE(t, tmp); + + for (i = 1; i < d; i++) { + memcpy(r, t + i * 16, 16); + aegis256x2_absorb(r, state); + } + tmp = AES_BLOCK_LOAD_64x2(d, maclen); + tmp = AES_BLOCK_XOR(tmp, state[3]); + for (i = 0; i < 7; i++) { + aegis256x2_update(state, tmp); + } +#endif + tmp = AES_BLOCK_XOR(state[5], state[4]); + tmp = AES_BLOCK_XOR(tmp, AES_BLOCK_XOR(state[3], state[2])); + tmp = AES_BLOCK_XOR(tmp, AES_BLOCK_XOR(state[1], state[0])); + AES_BLOCK_STORE(t, tmp); + memcpy(mac, t, 16); + } else if (maclen == 32) { +#if AES_BLOCK_LENGTH > 16 + tmp = AES_BLOCK_XOR(state[2], AES_BLOCK_XOR(state[1], state[0])); + AES_BLOCK_STORE(t, tmp); + tmp = AES_BLOCK_XOR(state[5], AES_BLOCK_XOR(state[4], state[3])); + AES_BLOCK_STORE(t + AES_BLOCK_LENGTH, tmp); + for (i = 1; i < d; i++) { + memcpy(r, t + i * 16, 16); + aegis256x2_absorb(r, state); + memcpy(r, t + AES_BLOCK_LENGTH + i * 16, 16); + aegis256x2_absorb(r, state); + } + tmp = AES_BLOCK_LOAD_64x2(d, maclen); + tmp = AES_BLOCK_XOR(tmp, state[3]); + for (i = 0; i < 7; i++) { + aegis256x2_update(state, tmp); + } +#endif + tmp = AES_BLOCK_XOR(state[2], AES_BLOCK_XOR(state[1], state[0])); + AES_BLOCK_STORE(t, tmp); + memcpy(mac, t, 16); + tmp = AES_BLOCK_XOR(state[5], AES_BLOCK_XOR(state[4], state[3])); + AES_BLOCK_STORE(t, tmp); + memcpy(mac + 16, t, 16); + } else { + memset(mac, 0, maclen); + } +} + static int encrypt_detached(uint8_t *c, uint8_t *mac, size_t maclen, const uint8_t *m, size_t mlen, const uint8_t *ad, size_t adlen, const uint8_t *npub, const uint8_t *k) @@ -337,6 +405,14 @@ typedef struct _aegis256x2_state { size_t pos; } _aegis256x2_state; +typedef struct _aegis256x2_mac_state { + aegis_blocks blocks; + aegis_blocks blocks0; + uint8_t buf[RATE]; + uint64_t adlen; + size_t pos; +} _aegis256x2_mac_state; + static void state_init(aegis256x2_state *st_, const uint8_t *ad, size_t adlen, const uint8_t *npub, const uint8_t *k) @@ -605,13 +681,33 @@ state_decrypt_detached_final(aegis256x2_state *st_, uint8_t *m, size_t mlen_max, return ret; } +static void +state_mac_init(aegis256x2_mac_state *st_, const uint8_t *npub, const uint8_t *k) +{ + aegis_blocks blocks; + _aegis256x2_mac_state *const st = + (_aegis256x2_mac_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); + + COMPILER_ASSERT((sizeof *st) + ALIGNMENT <= sizeof *st_); + st->pos = 0; + + memcpy(blocks, st->blocks, sizeof blocks); + + aegis256x2_init(k, npub, blocks); + + memcpy(st->blocks0, blocks, sizeof blocks); + memcpy(st->blocks, blocks, sizeof blocks); + st->adlen = 0; +} + static int -state_mac_update(aegis256x2_state *st_, const uint8_t *ad, size_t adlen) +state_mac_update(aegis256x2_mac_state *st_, const uint8_t *ad, size_t adlen) { - aegis_blocks blocks; - _aegis256x2_state *const st = - (_aegis256x2_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & - ~(uintptr_t) (ALIGNMENT - 1)); + aegis_blocks blocks; + _aegis256x2_mac_state *const st = + (_aegis256x2_mac_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); size_t i; size_t left; @@ -653,12 +749,12 @@ state_mac_update(aegis256x2_state *st_, const uint8_t *ad, size_t adlen) } static int -state_mac_final(aegis256x2_state *st_, uint8_t *mac, size_t maclen) +state_mac_final(aegis256x2_mac_state *st_, uint8_t *mac, size_t maclen) { - aegis_blocks blocks; - _aegis256x2_state *const st = - (_aegis256x2_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & - ~(uintptr_t) (ALIGNMENT - 1)); + aegis_blocks blocks; + _aegis256x2_mac_state *const st = + (_aegis256x2_mac_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); size_t left; memcpy(blocks, st->blocks, sizeof blocks); @@ -668,7 +764,7 @@ state_mac_final(aegis256x2_state *st_, uint8_t *mac, size_t maclen) memset(st->buf + left, 0, RATE - left); aegis256x2_absorb(st->buf, blocks); } - aegis256x2_mac(mac, maclen, st->adlen, 0, blocks); + aegis256x2_mac_nr(mac, maclen, st->adlen, blocks); memcpy(st->blocks, blocks, sizeof blocks); @@ -676,13 +772,24 @@ state_mac_final(aegis256x2_state *st_, uint8_t *mac, size_t maclen) } static void -state_clone(aegis256x2_state *dst, const aegis256x2_state *src) +state_mac_reset(aegis256x2_mac_state *st_) { - _aegis256x2_state *const dst_ = - (_aegis256x2_state *) ((((uintptr_t) &dst->opaque) + (ALIGNMENT - 1)) & - ~(uintptr_t) (ALIGNMENT - 1)); - const _aegis256x2_state *const src_ = - (const _aegis256x2_state *) ((((uintptr_t) &src->opaque) + (ALIGNMENT - 1)) & - ~(uintptr_t) (ALIGNMENT - 1)); + _aegis256x2_mac_state *const st = + (_aegis256x2_mac_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); + st->adlen = 0; + st->pos = 0; + memcpy(st->blocks, st->blocks0, sizeof(aegis_blocks)); +} + +static void +state_mac_clone(aegis256x2_mac_state *dst, const aegis256x2_mac_state *src) +{ + _aegis256x2_mac_state *const dst_ = + (_aegis256x2_mac_state *) ((((uintptr_t) &dst->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); + const _aegis256x2_mac_state *const src_ = + (const _aegis256x2_mac_state *) ((((uintptr_t) &src->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); *dst_ = *src_; } \ No newline at end of file diff --git a/src/aegis256x2/aegis256x2_soft.c b/src/aegis256x2/aegis256x2_soft.c index c45cf8e..3e478be 100644 --- a/src/aegis256x2/aegis256x2_soft.c +++ b/src/aegis256x2/aegis256x2_soft.c @@ -85,9 +85,11 @@ struct aegis256x2_implementation aegis256x2_soft_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; #endif \ No newline at end of file diff --git a/src/aegis256x2/implementations.h b/src/aegis256x2/implementations.h index ebf66c3..2698e38 100644 --- a/src/aegis256x2/implementations.h +++ b/src/aegis256x2/implementations.h @@ -29,9 +29,12 @@ typedef struct aegis256x2_implementation { size_t *written, const uint8_t *c, size_t clen); int (*state_decrypt_detached_final)(aegis256x2_state *st_, uint8_t *m, size_t mlen_max, size_t *written, const uint8_t *mac, size_t maclen); - int (*state_mac_update)(aegis256x2_state *st_, const uint8_t *ad, size_t adlen); - int (*state_mac_final)(aegis256x2_state *st_, uint8_t *mac, size_t maclen); - void (*state_clone)(aegis256x2_state *dst, const aegis256x2_state *src); + void (*state_mac_init)(aegis256x2_mac_state *st_, const uint8_t *npub, const uint8_t *k); + int (*state_mac_update)(aegis256x2_mac_state *st_, const uint8_t *ad, size_t adlen); + int (*state_mac_final)(aegis256x2_mac_state *st_, uint8_t *mac, size_t maclen); + void (*state_mac_reset)(aegis256x2_mac_state *st); + void (*state_mac_clone)(aegis256x2_mac_state *dst, const aegis256x2_mac_state *src); + } aegis256x2_implementation; #endif diff --git a/src/aegis256x4/aegis256x4.c b/src/aegis256x4/aegis256x4.c index 6d430f8..e94dc89 100644 --- a/src/aegis256x4/aegis256x4.c +++ b/src/aegis256x4/aegis256x4.c @@ -177,19 +177,19 @@ aegis256x4_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, co } void -aegis256x4_mac_init(aegis256x4_state *st_, const uint8_t *k, const uint8_t *npub) +aegis256x4_mac_init(aegis256x4_mac_state *st_, const uint8_t *k, const uint8_t *npub) { - implementation->state_init(st_, NULL, 0, npub, k); + implementation->state_mac_init(st_, npub, k); } int -aegis256x4_mac_update(aegis256x4_state *st_, const uint8_t *m, size_t mlen) +aegis256x4_mac_update(aegis256x4_mac_state *st_, const uint8_t *m, size_t mlen) { return implementation->state_mac_update(st_, m, mlen); } int -aegis256x4_mac_final(aegis256x4_state *st_, uint8_t *mac, size_t maclen) +aegis256x4_mac_final(aegis256x4_mac_state *st_, uint8_t *mac, size_t maclen) { if (maclen != 16 && maclen != 32) { errno = EINVAL; @@ -199,7 +199,7 @@ aegis256x4_mac_final(aegis256x4_state *st_, uint8_t *mac, size_t maclen) } int -aegis256x4_mac_verify(aegis256x4_state *st_, const uint8_t *mac, size_t maclen) +aegis256x4_mac_verify(aegis256x4_mac_state *st_, const uint8_t *mac, size_t maclen) { uint8_t expected_mac[32]; @@ -217,9 +217,15 @@ aegis256x4_mac_verify(aegis256x4_state *st_, const uint8_t *mac, size_t maclen) } void -aegis256x4_mac_state_clone(aegis256x4_state *dst, const aegis256x4_state *src) +aegis256x4_mac_reset(aegis256x4_mac_state *st_) { - implementation->state_clone(dst, src); + implementation->state_mac_reset(st_); +} + +void +aegis256x4_mac_state_clone(aegis256x4_mac_state *dst, const aegis256x4_mac_state *src) +{ + implementation->state_mac_clone(dst, src); } int diff --git a/src/aegis256x4/aegis256x4_aesni.c b/src/aegis256x4/aegis256x4_aesni.c index b9bbebb..54f6aef 100644 --- a/src/aegis256x4/aegis256x4_aesni.c +++ b/src/aegis256x4/aegis256x4_aesni.c @@ -102,9 +102,11 @@ struct aegis256x4_implementation aegis256x4_aesni_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; # ifdef __clang__ diff --git a/src/aegis256x4/aegis256x4_altivec.c b/src/aegis256x4/aegis256x4_altivec.c index c061cb2..84d2db2 100644 --- a/src/aegis256x4/aegis256x4_altivec.c +++ b/src/aegis256x4/aegis256x4_altivec.c @@ -99,9 +99,11 @@ struct aegis256x4_implementation aegis256x4_altivec_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; # ifdef __clang__ diff --git a/src/aegis256x4/aegis256x4_armcrypto.c b/src/aegis256x4/aegis256x4_armcrypto.c index 42aa0d4..e30d55f 100644 --- a/src/aegis256x4/aegis256x4_armcrypto.c +++ b/src/aegis256x4/aegis256x4_armcrypto.c @@ -107,9 +107,11 @@ struct aegis256x4_implementation aegis256x4_armcrypto_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; # ifdef __clang__ diff --git a/src/aegis256x4/aegis256x4_avx2.c b/src/aegis256x4/aegis256x4_avx2.c index cbd2c30..aeb6369 100644 --- a/src/aegis256x4/aegis256x4_avx2.c +++ b/src/aegis256x4/aegis256x4_avx2.c @@ -94,9 +94,11 @@ struct aegis256x4_implementation aegis256x4_avx2_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; # ifdef __clang__ diff --git a/src/aegis256x4/aegis256x4_avx512.c b/src/aegis256x4/aegis256x4_avx512.c index 22d3b69..3c3cd64 100644 --- a/src/aegis256x4/aegis256x4_avx512.c +++ b/src/aegis256x4/aegis256x4_avx512.c @@ -67,9 +67,11 @@ struct aegis256x4_implementation aegis256x4_avx512_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; # ifdef __clang__ diff --git a/src/aegis256x4/aegis256x4_common.h b/src/aegis256x4/aegis256x4_common.h index b28a3d5..47ce415 100644 --- a/src/aegis256x4/aegis256x4_common.h +++ b/src/aegis256x4/aegis256x4_common.h @@ -197,6 +197,74 @@ aegis256x4_declast(uint8_t *const dst, const uint8_t *const src, size_t len, aegis256x4_update(state, msg); } +static void +aegis256x4_mac_nr(uint8_t *mac, size_t maclen, uint64_t adlen, aes_block_t *state) +{ + uint8_t t[2 * AES_BLOCK_LENGTH]; + uint8_t r[RATE]; + aes_block_t tmp; + int i; + const int d = AES_BLOCK_LENGTH / 16; + + tmp = AES_BLOCK_LOAD_64x2(0, adlen << 3); + tmp = AES_BLOCK_XOR(tmp, state[3]); + + for (i = 0; i < 7; i++) { + aegis256x4_update(state, tmp); + } + + memset(r, 0, sizeof r); + if (maclen == 16) { +#if AES_BLOCK_LENGTH > 16 + tmp = AES_BLOCK_XOR(state[5], state[4]); + tmp = AES_BLOCK_XOR(tmp, AES_BLOCK_XOR(state[3], state[2])); + tmp = AES_BLOCK_XOR(tmp, AES_BLOCK_XOR(state[1], state[0])); + AES_BLOCK_STORE(t, tmp); + + for (i = 1; i < d; i++) { + memcpy(r, t + i * 16, 16); + aegis256x4_absorb(r, state); + } + tmp = AES_BLOCK_LOAD_64x2(d, maclen); + tmp = AES_BLOCK_XOR(tmp, state[3]); + for (i = 0; i < 7; i++) { + aegis256x4_update(state, tmp); + } +#endif + tmp = AES_BLOCK_XOR(state[5], state[4]); + tmp = AES_BLOCK_XOR(tmp, AES_BLOCK_XOR(state[3], state[2])); + tmp = AES_BLOCK_XOR(tmp, AES_BLOCK_XOR(state[1], state[0])); + AES_BLOCK_STORE(t, tmp); + memcpy(mac, t, 16); + } else if (maclen == 32) { +#if AES_BLOCK_LENGTH > 16 + tmp = AES_BLOCK_XOR(state[2], AES_BLOCK_XOR(state[1], state[0])); + AES_BLOCK_STORE(t, tmp); + tmp = AES_BLOCK_XOR(state[5], AES_BLOCK_XOR(state[4], state[3])); + AES_BLOCK_STORE(t + AES_BLOCK_LENGTH, tmp); + for (i = 1; i < d; i++) { + memcpy(r, t + i * 16, 16); + aegis256x4_absorb(r, state); + memcpy(r, t + AES_BLOCK_LENGTH + i * 16, 16); + aegis256x4_absorb(r, state); + } + tmp = AES_BLOCK_LOAD_64x2(d, maclen); + tmp = AES_BLOCK_XOR(tmp, state[3]); + for (i = 0; i < 7; i++) { + aegis256x4_update(state, tmp); + } +#endif + tmp = AES_BLOCK_XOR(state[2], AES_BLOCK_XOR(state[1], state[0])); + AES_BLOCK_STORE(t, tmp); + memcpy(mac, t, 16); + tmp = AES_BLOCK_XOR(state[5], AES_BLOCK_XOR(state[4], state[3])); + AES_BLOCK_STORE(t, tmp); + memcpy(mac + 16, t, 16); + } else { + memset(mac, 0, maclen); + } +} + static int encrypt_detached(uint8_t *c, uint8_t *mac, size_t maclen, const uint8_t *m, size_t mlen, const uint8_t *ad, size_t adlen, const uint8_t *npub, const uint8_t *k) @@ -356,6 +424,14 @@ typedef struct _aegis256x4_state { size_t pos; } _aegis256x4_state; +typedef struct _aegis256x4_mac_state { + aegis_blocks blocks; + aegis_blocks blocks0; + uint8_t buf[RATE]; + uint64_t adlen; + size_t pos; +} _aegis256x4_mac_state; + static void state_init(aegis256x4_state *st_, const uint8_t *ad, size_t adlen, const uint8_t *npub, const uint8_t *k) @@ -624,13 +700,33 @@ state_decrypt_detached_final(aegis256x4_state *st_, uint8_t *m, size_t mlen_max, return ret; } +static void +state_mac_init(aegis256x4_mac_state *st_, const uint8_t *npub, const uint8_t *k) +{ + aegis_blocks blocks; + _aegis256x4_mac_state *const st = + (_aegis256x4_mac_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); + + COMPILER_ASSERT((sizeof *st) + ALIGNMENT <= sizeof *st_); + st->pos = 0; + + memcpy(blocks, st->blocks, sizeof blocks); + + aegis256x4_init(k, npub, blocks); + + memcpy(st->blocks0, blocks, sizeof blocks); + memcpy(st->blocks, blocks, sizeof blocks); + st->adlen = 0; +} + static int -state_mac_update(aegis256x4_state *st_, const uint8_t *ad, size_t adlen) +state_mac_update(aegis256x4_mac_state *st_, const uint8_t *ad, size_t adlen) { - aegis_blocks blocks; - _aegis256x4_state *const st = - (_aegis256x4_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & - ~(uintptr_t) (ALIGNMENT - 1)); + aegis_blocks blocks; + _aegis256x4_mac_state *const st = + (_aegis256x4_mac_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); size_t i; size_t left; @@ -672,12 +768,12 @@ state_mac_update(aegis256x4_state *st_, const uint8_t *ad, size_t adlen) } static int -state_mac_final(aegis256x4_state *st_, uint8_t *mac, size_t maclen) +state_mac_final(aegis256x4_mac_state *st_, uint8_t *mac, size_t maclen) { - aegis_blocks blocks; - _aegis256x4_state *const st = - (_aegis256x4_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & - ~(uintptr_t) (ALIGNMENT - 1)); + aegis_blocks blocks; + _aegis256x4_mac_state *const st = + (_aegis256x4_mac_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); size_t left; memcpy(blocks, st->blocks, sizeof blocks); @@ -687,7 +783,7 @@ state_mac_final(aegis256x4_state *st_, uint8_t *mac, size_t maclen) memset(st->buf + left, 0, RATE - left); aegis256x4_absorb(st->buf, blocks); } - aegis256x4_mac(mac, maclen, st->adlen, 0, blocks); + aegis256x4_mac_nr(mac, maclen, st->adlen, blocks); memcpy(st->blocks, blocks, sizeof blocks); @@ -695,13 +791,24 @@ state_mac_final(aegis256x4_state *st_, uint8_t *mac, size_t maclen) } static void -state_clone(aegis256x4_state *dst, const aegis256x4_state *src) +state_mac_reset(aegis256x4_mac_state *st_) { - _aegis256x4_state *const dst_ = - (_aegis256x4_state *) ((((uintptr_t) &dst->opaque) + (ALIGNMENT - 1)) & - ~(uintptr_t) (ALIGNMENT - 1)); - const _aegis256x4_state *const src_ = - (const _aegis256x4_state *) ((((uintptr_t) &src->opaque) + (ALIGNMENT - 1)) & - ~(uintptr_t) (ALIGNMENT - 1)); + _aegis256x4_mac_state *const st = + (_aegis256x4_mac_state *) ((((uintptr_t) &st_->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); + st->adlen = 0; + st->pos = 0; + memcpy(st->blocks, st->blocks0, sizeof(aegis_blocks)); +} + +static void +state_mac_clone(aegis256x4_mac_state *dst, const aegis256x4_mac_state *src) +{ + _aegis256x4_mac_state *const dst_ = + (_aegis256x4_mac_state *) ((((uintptr_t) &dst->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); + const _aegis256x4_mac_state *const src_ = + (const _aegis256x4_mac_state *) ((((uintptr_t) &src->opaque) + (ALIGNMENT - 1)) & + ~(uintptr_t) (ALIGNMENT - 1)); *dst_ = *src_; } \ No newline at end of file diff --git a/src/aegis256x4/aegis256x4_soft.c b/src/aegis256x4/aegis256x4_soft.c index 4b2c227..f98bb35 100644 --- a/src/aegis256x4/aegis256x4_soft.c +++ b/src/aegis256x4/aegis256x4_soft.c @@ -93,9 +93,11 @@ struct aegis256x4_implementation aegis256x4_soft_implementation = { .state_encrypt_final = state_encrypt_final, .state_decrypt_detached_update = state_decrypt_detached_update, .state_decrypt_detached_final = state_decrypt_detached_final, + .state_mac_init = state_mac_init, .state_mac_update = state_mac_update, .state_mac_final = state_mac_final, - .state_clone = state_clone, + .state_mac_reset = state_mac_reset, + .state_mac_clone = state_mac_clone, }; #endif \ No newline at end of file diff --git a/src/aegis256x4/implementations.h b/src/aegis256x4/implementations.h index ecdf2cb..4ca8120 100644 --- a/src/aegis256x4/implementations.h +++ b/src/aegis256x4/implementations.h @@ -29,9 +29,12 @@ typedef struct aegis256x4_implementation { size_t *written, const uint8_t *c, size_t clen); int (*state_decrypt_detached_final)(aegis256x4_state *st_, uint8_t *m, size_t mlen_max, size_t *written, const uint8_t *mac, size_t maclen); - int (*state_mac_update)(aegis256x4_state *st_, const uint8_t *ad, size_t adlen); - int (*state_mac_final)(aegis256x4_state *st_, uint8_t *mac, size_t maclen); - void (*state_clone)(aegis256x4_state *dst, const aegis256x4_state *src); + void (*state_mac_init)(aegis256x4_mac_state *st_, const uint8_t *npub, const uint8_t *k); + int (*state_mac_update)(aegis256x4_mac_state *st_, const uint8_t *ad, size_t adlen); + int (*state_mac_final)(aegis256x4_mac_state *st_, uint8_t *mac, size_t maclen); + void (*state_mac_reset)(aegis256x4_mac_state *st); + void (*state_mac_clone)(aegis256x4_mac_state *dst, const aegis256x4_mac_state *src); + } aegis256x4_implementation; #endif diff --git a/src/include/aegis128l.h b/src/include/aegis128l.h index ab44596..1ff762b 100644 --- a/src/include/aegis128l.h +++ b/src/include/aegis128l.h @@ -33,7 +33,7 @@ typedef struct aegis128l_state { /* An AEGIS state, only for MAC updates */ typedef struct aegis128l_mac_state { - CRYPTO_ALIGN(32) uint8_t opaque[512]; + CRYPTO_ALIGN(32) uint8_t opaque[384]; } aegis128l_mac_state; /* The length of an AEGIS key, in bytes */ diff --git a/src/include/aegis128x2.h b/src/include/aegis128x2.h index 84cf3d0..6692186 100644 --- a/src/include/aegis128x2.h +++ b/src/include/aegis128x2.h @@ -33,7 +33,7 @@ typedef struct aegis128x2_state { /* An AEGIS state, only for MAC updates */ typedef struct aegis128x2_mac_state { - CRYPTO_ALIGN(64) uint8_t opaque[896]; + CRYPTO_ALIGN(64) uint8_t opaque[704]; } aegis128x2_mac_state; /* The length of an AEGIS key, in bytes */ diff --git a/src/include/aegis128x4.h b/src/include/aegis128x4.h index 2de55e4..75b00e7 100644 --- a/src/include/aegis128x4.h +++ b/src/include/aegis128x4.h @@ -33,7 +33,7 @@ typedef struct aegis128x4_state { /* An AEGIS state, only for MAC updates */ typedef struct aegis128x4_mac_state { - CRYPTO_ALIGN(32) uint8_t opaque[1664]; + CRYPTO_ALIGN(64) uint8_t opaque[1344]; } aegis128x4_mac_state; /* The length of an AEGIS key, in bytes */ @@ -267,6 +267,10 @@ void aegis128x4_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t cle * - However, if the key is known, arbitrary inputs matching a tag can be efficiently computed. * * The recommended way to use the MAC mode is to generate a random key and keep it secret. + * + * After initialization, the state can be reused to generate multiple MACs by cloning it + * with `aegis128x4_mac_state_clone()`. It is only safe to copy a state directly without using + * the clone function if the state is guaranteed to be properly aligned. */ void aegis128x4_mac_init(aegis128x4_mac_state *st_, const uint8_t *k, const uint8_t *npub); diff --git a/src/include/aegis256.h b/src/include/aegis256.h index f88d662..378da3a 100644 --- a/src/include/aegis256.h +++ b/src/include/aegis256.h @@ -33,7 +33,7 @@ typedef struct aegis256_state { /* An AEGIS state, only for MAC updates */ typedef struct aegis256_mac_state { - CRYPTO_ALIGN(16) uint8_t opaque[384]; + CRYPTO_ALIGN(16) uint8_t opaque[288]; } aegis256_mac_state; /* The length of an AEGIS key, in bytes */ diff --git a/src/include/aegis256x2.h b/src/include/aegis256x2.h index 00ac5a4..fc67439 100644 --- a/src/include/aegis256x2.h +++ b/src/include/aegis256x2.h @@ -31,6 +31,11 @@ typedef struct aegis256x2_state { CRYPTO_ALIGN(32) uint8_t opaque[320]; } aegis256x2_state; +/* An AEGIS state, only for MAC updates */ +typedef struct aegis256x2_mac_state { + CRYPTO_ALIGN(32) uint8_t opaque[512]; +} aegis256x2_mac_state; + /* The length of an AEGIS key, in bytes */ size_t aegis256x2_keybytes(void); @@ -258,13 +263,16 @@ void aegis256x2_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t cle * k: key input buffer (32 bytes) * * - The same key MUST NOT be used both for MAC and encryption. - * - The nonce MUST NOT be reused with the same key. * - If the key is secret, the MAC is secure against forgery. * - However, if the key is known, arbitrary inputs matching a tag can be efficiently computed. * * The recommended way to use the MAC mode is to generate a random key and keep it secret. + * + * After initialization, the state can be reused to generate multiple MACs by cloning it + * with `aegis256x2_mac_state_clone()`. It is only safe to copy a state directly without using + * the clone function if the state is guaranteed to be properly aligned. */ -void aegis256x2_mac_init(aegis256x2_state *st_, const uint8_t *k, const uint8_t *npub); +void aegis256x2_mac_init(aegis256x2_mac_state *st_, const uint8_t *k, const uint8_t *npub); /* * Update the MAC state with input data. @@ -277,7 +285,7 @@ void aegis256x2_mac_init(aegis256x2_state *st_, const uint8_t *k, const uint8_t * * Once the full input has been absorb, call either `_mac_final` or `_mac_verify`. */ -int aegis256x2_mac_update(aegis256x2_state *st_, const uint8_t *m, size_t mlen); +int aegis256x2_mac_update(aegis256x2_mac_state *st_, const uint8_t *m, size_t mlen); /* * Finalize the MAC and generate the authentication tag. @@ -286,7 +294,7 @@ int aegis256x2_mac_update(aegis256x2_state *st_, const uint8_t *m, size_t mlen); * mac: authentication tag output buffer * maclen: length of the authentication tag to generate (16 or 32. 32 is recommended). */ -int aegis256x2_mac_final(aegis256x2_state *st_, uint8_t *mac, size_t maclen); +int aegis256x2_mac_final(aegis256x2_mac_state *st_, uint8_t *mac, size_t maclen); /* * Verify a MAC in constant time. @@ -297,7 +305,12 @@ int aegis256x2_mac_final(aegis256x2_state *st_, uint8_t *mac, size_t maclen); * * Returns 0 if the tag is authentic, -1 otherwise. */ -int aegis256x2_mac_verify(aegis256x2_state *st_, const uint8_t *mac, size_t maclen); +int aegis256x2_mac_verify(aegis256x2_mac_state *st_, const uint8_t *mac, size_t maclen); + +/* + * Reset an AEGIS_MAC state. + */ +void aegis256x2_mac_reset(aegis256x2_mac_state *st_); /* * Clone an AEGIS-MAC state. @@ -307,7 +320,7 @@ int aegis256x2_mac_verify(aegis256x2_state *st_, const uint8_t *mac, size_t macl * * This function MUST be used in order to clone states. */ -void aegis256x2_mac_state_clone(aegis256x2_state *dst, const aegis256x2_state *src); +void aegis256x2_mac_state_clone(aegis256x2_mac_state *dst, const aegis256x2_mac_state *src); #ifdef __cplusplus } diff --git a/src/include/aegis256x4.h b/src/include/aegis256x4.h index 01d0ad7..e9d2482 100644 --- a/src/include/aegis256x4.h +++ b/src/include/aegis256x4.h @@ -31,6 +31,11 @@ typedef struct aegis256x4_state { CRYPTO_ALIGN(64) uint8_t opaque[576]; } aegis256x4_state; +/* An AEGIS state, only for MAC updates */ +typedef struct aegis256x4_mac_state { + CRYPTO_ALIGN(64) uint8_t opaque[960]; +} aegis256x4_mac_state; + /* The length of an AEGIS key, in bytes */ size_t aegis256x4_keybytes(void); @@ -258,13 +263,16 @@ void aegis256x4_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t cle * k: key input buffer (32 bytes) * * - The same key MUST NOT be used both for MAC and encryption. - * - The nonce MUST NOT be reused with the same key. * - If the key is secret, the MAC is secure against forgery. * - However, if the key is known, arbitrary inputs matching a tag can be efficiently computed. * * The recommended way to use the MAC mode is to generate a random key and keep it secret. + * + * After initialization, the state can be reused to generate multiple MACs by cloning it + * with `aegis256x4_mac_state_clone()`. It is only safe to copy a state directly without using + * the clone function if the state is guaranteed to be properly aligned. */ -void aegis256x4_mac_init(aegis256x4_state *st_, const uint8_t *k, const uint8_t *npub); +void aegis256x4_mac_init(aegis256x4_mac_state *st_, const uint8_t *k, const uint8_t *npub); /* * Update the MAC state with input data. @@ -277,7 +285,7 @@ void aegis256x4_mac_init(aegis256x4_state *st_, const uint8_t *k, const uint8_t * * Once the full input has been absorb, call either `_mac_final` or `_mac_verify`. */ -int aegis256x4_mac_update(aegis256x4_state *st_, const uint8_t *m, size_t mlen); +int aegis256x4_mac_update(aegis256x4_mac_state *st_, const uint8_t *m, size_t mlen); /* * Finalize the MAC and generate the authentication tag. @@ -286,7 +294,7 @@ int aegis256x4_mac_update(aegis256x4_state *st_, const uint8_t *m, size_t mlen); * mac: authentication tag output buffer * maclen: length of the authentication tag to generate (16 or 32. 32 is recommended). */ -int aegis256x4_mac_final(aegis256x4_state *st_, uint8_t *mac, size_t maclen); +int aegis256x4_mac_final(aegis256x4_mac_state *st_, uint8_t *mac, size_t maclen); /* * Verify a MAC in constant time. @@ -297,7 +305,12 @@ int aegis256x4_mac_final(aegis256x4_state *st_, uint8_t *mac, size_t maclen); * * Returns 0 if the tag is authentic, -1 otherwise. */ -int aegis256x4_mac_verify(aegis256x4_state *st_, const uint8_t *mac, size_t maclen); +int aegis256x4_mac_verify(aegis256x4_mac_state *st_, const uint8_t *mac, size_t maclen); + +/* + * Reset an AEGIS_MAC state. + */ +void aegis256x4_mac_reset(aegis256x4_mac_state *st_); /* * Clone an AEGIS-MAC state. @@ -307,7 +320,7 @@ int aegis256x4_mac_verify(aegis256x4_state *st_, const uint8_t *mac, size_t macl * * This function MUST be used in order to clone states. */ -void aegis256x4_mac_state_clone(aegis256x4_state *dst, const aegis256x4_state *src); +void aegis256x4_mac_state_clone(aegis256x4_mac_state *dst, const aegis256x4_mac_state *src); #ifdef __cplusplus } diff --git a/src/test/benchmark.zig b/src/test/benchmark.zig index 0c2417b..89e687b 100644 --- a/src/test/benchmark.zig +++ b/src/test/benchmark.zig @@ -258,7 +258,7 @@ fn bench_aegis128x4_mac() !void { var key: [aegis.aegis128x4_KEYBYTES]u8 = undefined; var nonce: [aegis.aegis128x4_NPUBBYTES]u8 = undefined; var buf: [msg_len]u8 = undefined; - var st0: aegis.aegis128x4_state = undefined; + var st0: aegis.aegis128x4_mac_state = undefined; random.bytes(&key); random.bytes(&nonce); @@ -268,7 +268,7 @@ fn bench_aegis128x4_mac() !void { var timer = try Timer.start(); const start = timer.lap(); for (0..iterations) |_| { - var st: aegis.aegis128x4_state = undefined; + var st: aegis.aegis128x4_mac_state = undefined; aegis.aegis128x4_mac_state_clone(&st, &st0); _ = aegis.aegis128x4_mac_update(&st, &buf, msg_len); _ = aegis.aegis128x4_mac_final(&st, &buf, aegis.aegis128x4_ABYTES_MAX); @@ -313,7 +313,7 @@ fn bench_aegis256x2_mac() !void { var key: [aegis.aegis256x2_KEYBYTES]u8 = undefined; var nonce: [aegis.aegis256x2_NPUBBYTES]u8 = undefined; var buf: [msg_len]u8 = undefined; - var st0: aegis.aegis256x2_state = undefined; + var st0: aegis.aegis256x2_mac_state = undefined; random.bytes(&key); random.bytes(&nonce); @@ -323,7 +323,7 @@ fn bench_aegis256x2_mac() !void { var timer = try Timer.start(); const start = timer.lap(); for (0..iterations) |_| { - var st: aegis.aegis256x2_state = undefined; + var st: aegis.aegis256x2_mac_state = undefined; aegis.aegis256x2_mac_state_clone(&st, &st0); _ = aegis.aegis256x2_mac_update(&st, &buf, msg_len); _ = aegis.aegis256x2_mac_final(&st, &buf, aegis.aegis256x2_ABYTES_MAX); @@ -341,7 +341,7 @@ fn bench_aegis256x4_mac() !void { var key: [aegis.aegis256x4_KEYBYTES]u8 = undefined; var nonce: [aegis.aegis256x2_NPUBBYTES]u8 = undefined; var buf: [msg_len]u8 = undefined; - var st0: aegis.aegis256x4_state = undefined; + var st0: aegis.aegis256x4_mac_state = undefined; random.bytes(&key); random.bytes(&nonce); @@ -351,7 +351,7 @@ fn bench_aegis256x4_mac() !void { var timer = try Timer.start(); const start = timer.lap(); for (0..iterations) |_| { - var st: aegis.aegis256x4_state = undefined; + var st: aegis.aegis256x4_mac_state = undefined; aegis.aegis256x4_mac_state_clone(&st, &st0); _ = aegis.aegis256x4_mac_update(&st, &buf, msg_len); _ = aegis.aegis256x4_mac_final(&st, &buf, aegis.aegis256x4_ABYTES_MAX); diff --git a/src/test/main.zig b/src/test/main.zig index 07a214a..e3e7490 100644 --- a/src/test/main.zig +++ b/src/test/main.zig @@ -829,6 +829,93 @@ test "aegis128x4 - MAC test vector" { try std.testing.expectEqualSlices(u8, &expected256, &mac256); } +test "aegis256 - MAC test vector" { + const key = [_]u8{ 0x10, 0x01 } ++ [_]u8{0x00} ** (32 - 2); + const nonce = [_]u8{ 0x10, 0x00, 0x02 } ++ [_]u8{0x00} ** (32 - 3); + var msg: [35]u8 = undefined; + for (&msg, 0..) |*byte, i| byte.* = @truncate(i); + var mac128: [16]u8 = undefined; + var mac256: [32]u8 = undefined; + var st: aegis.aegis256_mac_state = undefined; + var ret: c_int = undefined; + aegis.aegis256_mac_init(&st, &key, &nonce); + ret = aegis.aegis256_mac_update(&st, &msg, msg.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256_mac_final(&st, &mac128, mac128.len); + try testing.expectEqual(ret, 0); + aegis.aegis256_mac_reset(&st); + ret = aegis.aegis256_mac_update(&st, &msg, msg.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256_mac_final(&st, &mac256, mac256.len); + try testing.expectEqual(ret, 0); + const expected128_hex = "49f70470ccf49529674babd6db6670c9"; + const expected256_hex = "f5945eccdb14c836d8470b8abcf87e26bc635abc17e05d1fbf0ca05c679e0eef"; + var expected128: [16]u8 = undefined; + var expected256: [32]u8 = undefined; + _ = try std.fmt.hexToBytes(&expected128, expected128_hex); + _ = try std.fmt.hexToBytes(&expected256, expected256_hex); + try std.testing.expectEqualSlices(u8, &expected128, &mac128); + try std.testing.expectEqualSlices(u8, &expected256, &mac256); +} + +test "aegis256x2 - MAC test vector" { + const key = [_]u8{ 0x10, 0x01 } ++ [_]u8{0x00} ** (32 - 2); + const nonce = [_]u8{ 0x10, 0x00, 0x02 } ++ [_]u8{0x00} ** (32 - 3); + var msg: [35]u8 = undefined; + for (&msg, 0..) |*byte, i| byte.* = @truncate(i); + var mac128: [16]u8 = undefined; + var mac256: [32]u8 = undefined; + var st: aegis.aegis256x2_mac_state = undefined; + var ret: c_int = undefined; + aegis.aegis256x2_mac_init(&st, &key, &nonce); + ret = aegis.aegis256x2_mac_update(&st, &msg, msg.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256x2_mac_final(&st, &mac128, mac128.len); + try testing.expectEqual(ret, 0); + aegis.aegis256x2_mac_reset(&st); + ret = aegis.aegis256x2_mac_update(&st, &msg, msg.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256x2_mac_final(&st, &mac256, mac256.len); + try testing.expectEqual(ret, 0); + const expected128_hex = "1468bcd6376f12ef29b2ba281f491dd8"; + const expected256_hex = "e854c36a63b86dc22130c7025b9ba84e0e597871b075b563845171b856871bbf"; + var expected128: [16]u8 = undefined; + var expected256: [32]u8 = undefined; + _ = try std.fmt.hexToBytes(&expected128, expected128_hex); + _ = try std.fmt.hexToBytes(&expected256, expected256_hex); + try std.testing.expectEqualSlices(u8, &expected128, &mac128); + try std.testing.expectEqualSlices(u8, &expected256, &mac256); +} + +test "aegis256x4 - MAC test vector" { + const key = [_]u8{ 0x10, 0x01 } ++ [_]u8{0x00} ** (32 - 2); + const nonce = [_]u8{ 0x10, 0x00, 0x02 } ++ [_]u8{0x00} ** (32 - 3); + var msg: [35]u8 = undefined; + for (&msg, 0..) |*byte, i| byte.* = @truncate(i); + var mac128: [16]u8 = undefined; + var mac256: [32]u8 = undefined; + var st: aegis.aegis256x4_mac_state = undefined; + var ret: c_int = undefined; + aegis.aegis256x4_mac_init(&st, &key, &nonce); + ret = aegis.aegis256x4_mac_update(&st, &msg, msg.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256x4_mac_final(&st, &mac128, mac128.len); + try testing.expectEqual(ret, 0); + aegis.aegis256x4_mac_reset(&st); + ret = aegis.aegis256x4_mac_update(&st, &msg, msg.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256x4_mac_final(&st, &mac256, mac256.len); + try testing.expectEqual(ret, 0); + const expected128_hex = "8ac8b254b708d1dd673535bd5dc77775"; + const expected256_hex = "962abc85dcc6522311ae2fbfc6d0f66ee263fd18be4d9135f36d14bf05fa460b"; + var expected128: [16]u8 = undefined; + var expected256: [32]u8 = undefined; + _ = try std.fmt.hexToBytes(&expected128, expected128_hex); + _ = try std.fmt.hexToBytes(&expected256, expected256_hex); + try std.testing.expectEqualSlices(u8, &expected128, &mac128); + try std.testing.expectEqualSlices(u8, &expected256, &mac256); +} + // Wycheproof tests const JsonTest = struct {