diff --git a/README.md b/README.md index 66b90bb..58c1d52 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Portable C implementations of the [AEGIS](https://datatracker.ietf.org/doc/draft - AEGIS-256 with 16 and 32 bytes tags (software, AES-NI, ARM Crypto) - AEGIS-256X2 with 16 and 32 bytes tags (software, VAES + AVX2, AES-NI, ARM Crypto) - AEGIS-256X4 with 16 and 32 bytes tags (software, AVX512, VAES + AVX2, AES-NI, ARM Crypto) +- All variants of AEGIS-MAC, supporting incremental updates. - Encryption and decryption with attached and detached tags - Incremental encryption and decryption. - Unauthenticated encryption and decryption (not recommended - only implemented for specific protocols) diff --git a/src/aegis128l/aegis128l_common.h b/src/aegis128l/aegis128l_common.h index b7146ab..3d5d7a9 100644 --- a/src/aegis128l/aegis128l_common.h +++ b/src/aegis128l/aegis128l_common.h @@ -324,53 +324,6 @@ state_init(aegis128l_state *st_, const uint8_t *ad, size_t adlen, const uint8_t st->adlen = adlen; } -static int -state_mac_update(aegis128l_state *st_, const uint8_t *ad, size_t adlen) -{ - _aegis128l_state *const st = - (_aegis128l_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); - size_t i; - size_t left; - - left = st->adlen % RATE; - st->adlen += adlen; - if (left != 0) { - if (left + adlen < RATE) { - memcpy(st->buf + left, ad, adlen); - return 0; - } - memcpy(st->buf + left, ad, RATE - left); - aegis128l_absorb(st->buf, st->state); - ad += RATE - left; - adlen -= RATE - left; - } - for (i = 0; i + RATE <= adlen; i += RATE) { - aegis128l_absorb(ad + i, st->state); - } - if (i < adlen) { - memset(st->buf, 0, RATE); - memcpy(st->buf, ad + i, adlen - i); - } - return 0; -} - -static int -state_mac_final(aegis128l_state *st_, uint8_t *mac, size_t maclen) -{ - _aegis128l_state *const st = - (_aegis128l_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); - size_t left; - - left = st->adlen % RATE; - if (left != 0) { - memset(st->buf + left, 0, RATE - left); - aegis128l_absorb(st->buf, st->state); - } - aegis128l_mac(mac, maclen, st->adlen, 0, st->state); - - return 0; -} - static int state_encrypt_update(aegis128l_state *st_, uint8_t *c, size_t clen_max, size_t *written, const uint8_t *m, size_t mlen) @@ -574,3 +527,50 @@ state_decrypt_detached_final(aegis128l_state *st_, uint8_t *m, size_t mlen_max, } return ret; } + +static int +state_mac_update(aegis128l_state *st_, const uint8_t *ad, size_t adlen) +{ + _aegis128l_state *const st = + (_aegis128l_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t i; + size_t left; + + left = st->adlen % RATE; + st->adlen += adlen; + if (left != 0) { + if (left + adlen < RATE) { + memcpy(st->buf + left, ad, adlen); + return 0; + } + memcpy(st->buf + left, ad, RATE - left); + aegis128l_absorb(st->buf, st->state); + ad += RATE - left; + adlen -= RATE - left; + } + for (i = 0; i + RATE <= adlen; i += RATE) { + aegis128l_absorb(ad + i, st->state); + } + if (i < adlen) { + memset(st->buf, 0, RATE); + memcpy(st->buf, ad + i, adlen - i); + } + return 0; +} + +static int +state_mac_final(aegis128l_state *st_, uint8_t *mac, size_t maclen) +{ + _aegis128l_state *const st = + (_aegis128l_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t left; + + left = st->adlen % RATE; + if (left != 0) { + memset(st->buf + left, 0, RATE - left); + aegis128l_absorb(st->buf, st->state); + } + aegis128l_mac(mac, maclen, st->adlen, 0, st->state); + + return 0; +} \ No newline at end of file diff --git a/src/aegis128x2/aegis128x2.c b/src/aegis128x2/aegis128x2.c index bd436f5..45ba837 100644 --- a/src/aegis128x2/aegis128x2.c +++ b/src/aegis128x2/aegis128x2.c @@ -172,6 +172,49 @@ aegis128x2_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, co implementation->decrypt_unauthenticated(m, c, clen, npub, k); } +void +aegis128x2_mac_init(aegis128x2_state *st_, const uint8_t *k) +{ + const uint8_t npub[aegis128x2_NPUBBYTES] = { 0 }; + + memset(st_, 0, sizeof *st_); + implementation->state_init(st_, NULL, 0, npub, k); +} + +int +aegis128x2_mac_update(aegis128x2_state *st_, const uint8_t *m, size_t mlen) +{ + return implementation->state_mac_update(st_, m, mlen); +} + +int +aegis128x2_mac_final(aegis128x2_state *st_, uint8_t *mac, size_t maclen) +{ + if (maclen != 16 && maclen != 32) { + errno = EINVAL; + return -1; + } + return implementation->state_mac_final(st_, mac, maclen); +} + +int +aegis128x2_mac_verify(aegis128x2_state *st_, const uint8_t *mac, size_t maclen) +{ + uint8_t expected_mac[32]; + + switch (maclen) { + case 16: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_16(expected_mac, mac); + case 32: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_32(expected_mac, mac); + default: + errno = EINVAL; + return -1; + } +} + int aegis128x2_pick_best_implementation(void) { diff --git a/src/aegis128x2/aegis128x2_aesni.c b/src/aegis128x2/aegis128x2_aesni.c index dc4340f..5a91bab 100644 --- a/src/aegis128x2/aegis128x2_aesni.c +++ b/src/aegis128x2/aegis128x2_aesni.c @@ -98,6 +98,8 @@ struct aegis128x2_implementation aegis128x2_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis128x2/aegis128x2_armcrypto.c b/src/aegis128x2/aegis128x2_armcrypto.c index 7224071..42ff965 100644 --- a/src/aegis128x2/aegis128x2_armcrypto.c +++ b/src/aegis128x2/aegis128x2_armcrypto.c @@ -101,6 +101,8 @@ struct aegis128x2_implementation aegis128x2_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis128x2/aegis128x2_avx2.c b/src/aegis128x2/aegis128x2_avx2.c index 7fd1df8..a435395 100644 --- a/src/aegis128x2/aegis128x2_avx2.c +++ b/src/aegis128x2/aegis128x2_avx2.c @@ -66,6 +66,8 @@ struct aegis128x2_implementation aegis128x2_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis128x2/aegis128x2_common.h b/src/aegis128x2/aegis128x2_common.h index a857643..76c00b7 100644 --- a/src/aegis128x2/aegis128x2_common.h +++ b/src/aegis128x2/aegis128x2_common.h @@ -561,3 +561,50 @@ state_decrypt_detached_final(aegis128x2_state *st_, uint8_t *m, size_t mlen_max, } return ret; } + +static int +state_mac_update(aegis128x2_state *st_, const uint8_t *ad, size_t adlen) +{ + _aegis128x2_state *const st = + (_aegis128x2_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t i; + size_t left; + + left = st->adlen % RATE; + st->adlen += adlen; + if (left != 0) { + if (left + adlen < RATE) { + memcpy(st->buf + left, ad, adlen); + return 0; + } + memcpy(st->buf + left, ad, RATE - left); + aegis128x2_absorb(st->buf, st->state); + ad += RATE - left; + adlen -= RATE - left; + } + for (i = 0; i + RATE <= adlen; i += RATE) { + aegis128x2_absorb(ad + i, st->state); + } + if (i < adlen) { + memset(st->buf, 0, RATE); + memcpy(st->buf, ad + i, adlen - i); + } + return 0; +} + +static int +state_mac_final(aegis128x2_state *st_, uint8_t *mac, size_t maclen) +{ + _aegis128x2_state *const st = + (_aegis128x2_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t left; + + left = st->adlen % RATE; + if (left != 0) { + memset(st->buf + left, 0, RATE - left); + aegis128x2_absorb(st->buf, st->state); + } + aegis128x2_mac(mac, maclen, st->adlen, 0, st->state); + + return 0; +} \ No newline at end of file diff --git a/src/aegis128x2/aegis128x2_soft.c b/src/aegis128x2/aegis128x2_soft.c index a9b80b1..9dc33c5 100644 --- a/src/aegis128x2/aegis128x2_soft.c +++ b/src/aegis128x2/aegis128x2_soft.c @@ -90,6 +90,8 @@ struct aegis128x2_implementation aegis128x2_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; #endif \ No newline at end of file diff --git a/src/aegis128x2/implementations.h b/src/aegis128x2/implementations.h index da43aed..20cc0df 100644 --- a/src/aegis128x2/implementations.h +++ b/src/aegis128x2/implementations.h @@ -29,6 +29,9 @@ typedef struct aegis128x2_implementation { size_t *written, const uint8_t *c, size_t clen); int (*state_decrypt_detached_final)(aegis128x2_state *st_, uint8_t *m, size_t mlen_max, size_t *written, const uint8_t *mac, size_t maclen); + int (*state_mac_update)(aegis128x2_state *st_, const uint8_t *ad, size_t adlen); + int (*state_mac_final)(aegis128x2_state *st_, uint8_t *mac, size_t maclen); + } aegis128x2_implementation; #endif diff --git a/src/aegis128x4/aegis128x4.c b/src/aegis128x4/aegis128x4.c index da30d14..540a880 100644 --- a/src/aegis128x4/aegis128x4.c +++ b/src/aegis128x4/aegis128x4.c @@ -173,6 +173,49 @@ aegis128x4_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, co implementation->decrypt_unauthenticated(m, c, clen, npub, k); } +void +aegis128x4_mac_init(aegis128x4_state *st_, const uint8_t *k) +{ + const uint8_t npub[aegis128x4_NPUBBYTES] = { 0 }; + + memset(st_, 0, sizeof *st_); + implementation->state_init(st_, NULL, 0, npub, k); +} + +int +aegis128x4_mac_update(aegis128x4_state *st_, const uint8_t *m, size_t mlen) +{ + return implementation->state_mac_update(st_, m, mlen); +} + +int +aegis128x4_mac_final(aegis128x4_state *st_, uint8_t *mac, size_t maclen) +{ + if (maclen != 16 && maclen != 32) { + errno = EINVAL; + return -1; + } + return implementation->state_mac_final(st_, mac, maclen); +} + +int +aegis128x4_mac_verify(aegis128x4_state *st_, const uint8_t *mac, size_t maclen) +{ + uint8_t expected_mac[32]; + + switch (maclen) { + case 16: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_16(expected_mac, mac); + case 32: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_32(expected_mac, mac); + default: + errno = EINVAL; + return -1; + } +} + int aegis128x4_pick_best_implementation(void) { diff --git a/src/aegis128x4/aegis128x4_aesni.c b/src/aegis128x4/aegis128x4_aesni.c index 6917f4b..7425efa 100644 --- a/src/aegis128x4/aegis128x4_aesni.c +++ b/src/aegis128x4/aegis128x4_aesni.c @@ -107,6 +107,8 @@ struct aegis128x4_implementation aegis128x4_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis128x4/aegis128x4_armcrypto.c b/src/aegis128x4/aegis128x4_armcrypto.c index b45ad84..876eed7 100644 --- a/src/aegis128x4/aegis128x4_armcrypto.c +++ b/src/aegis128x4/aegis128x4_armcrypto.c @@ -109,6 +109,8 @@ struct aegis128x4_implementation aegis128x4_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis128x4/aegis128x4_avx2.c b/src/aegis128x4/aegis128x4_avx2.c index aa54fba..d8ccbac 100644 --- a/src/aegis128x4/aegis128x4_avx2.c +++ b/src/aegis128x4/aegis128x4_avx2.c @@ -99,6 +99,8 @@ struct aegis128x4_implementation aegis128x4_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis128x4/aegis128x4_avx512.c b/src/aegis128x4/aegis128x4_avx512.c index 610aa0f..8c96f90 100644 --- a/src/aegis128x4/aegis128x4_avx512.c +++ b/src/aegis128x4/aegis128x4_avx512.c @@ -72,6 +72,8 @@ struct aegis128x4_implementation aegis128x4_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis128x4/aegis128x4_common.h b/src/aegis128x4/aegis128x4_common.h index cba5525..dd8e962 100644 --- a/src/aegis128x4/aegis128x4_common.h +++ b/src/aegis128x4/aegis128x4_common.h @@ -576,3 +576,50 @@ state_decrypt_detached_final(aegis128x4_state *st_, uint8_t *m, size_t mlen_max, } return ret; } + +static int +state_mac_update(aegis128x4_state *st_, const uint8_t *ad, size_t adlen) +{ + _aegis128x4_state *const st = + (_aegis128x4_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t i; + size_t left; + + left = st->adlen % RATE; + st->adlen += adlen; + if (left != 0) { + if (left + adlen < RATE) { + memcpy(st->buf + left, ad, adlen); + return 0; + } + memcpy(st->buf + left, ad, RATE - left); + aegis128x4_absorb(st->buf, st->state); + ad += RATE - left; + adlen -= RATE - left; + } + for (i = 0; i + RATE <= adlen; i += RATE) { + aegis128x4_absorb(ad + i, st->state); + } + if (i < adlen) { + memset(st->buf, 0, RATE); + memcpy(st->buf, ad + i, adlen - i); + } + return 0; +} + +static int +state_mac_final(aegis128x4_state *st_, uint8_t *mac, size_t maclen) +{ + _aegis128x4_state *const st = + (_aegis128x4_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t left; + + left = st->adlen % RATE; + if (left != 0) { + memset(st->buf + left, 0, RATE - left); + aegis128x4_absorb(st->buf, st->state); + } + aegis128x4_mac(mac, maclen, st->adlen, 0, st->state); + + return 0; +} \ No newline at end of file diff --git a/src/aegis128x4/aegis128x4_soft.c b/src/aegis128x4/aegis128x4_soft.c index 8b111fb..9c2ad31 100644 --- a/src/aegis128x4/aegis128x4_soft.c +++ b/src/aegis128x4/aegis128x4_soft.c @@ -98,6 +98,8 @@ struct aegis128x4_implementation aegis128x4_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; #endif \ No newline at end of file diff --git a/src/aegis128x4/implementations.h b/src/aegis128x4/implementations.h index 34ab769..0d0e0a2 100644 --- a/src/aegis128x4/implementations.h +++ b/src/aegis128x4/implementations.h @@ -29,6 +29,8 @@ typedef struct aegis128x4_implementation { size_t *written, const uint8_t *c, size_t clen); int (*state_decrypt_detached_final)(aegis128x4_state *st_, uint8_t *m, size_t mlen_max, size_t *written, const uint8_t *mac, size_t maclen); + int (*state_mac_update)(aegis128x4_state *st_, const uint8_t *ad, size_t adlen); + int (*state_mac_final)(aegis128x4_state *st_, uint8_t *mac, size_t maclen); } aegis128x4_implementation; #endif diff --git a/src/aegis256/aegis256.c b/src/aegis256/aegis256.c index 3699d60..db0a551 100644 --- a/src/aegis256/aegis256.c +++ b/src/aegis256/aegis256.c @@ -171,6 +171,49 @@ aegis256_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, cons implementation->decrypt_unauthenticated(m, c, clen, npub, k); } +void +aegis256_mac_init(aegis256_state *st_, const uint8_t *k) +{ + const uint8_t npub[aegis256_NPUBBYTES] = { 0 }; + + memset(st_, 0, sizeof *st_); + implementation->state_init(st_, NULL, 0, npub, k); +} + +int +aegis256_mac_update(aegis256_state *st_, const uint8_t *m, size_t mlen) +{ + return implementation->state_mac_update(st_, m, mlen); +} + +int +aegis256_mac_final(aegis256_state *st_, uint8_t *mac, size_t maclen) +{ + if (maclen != 16 && maclen != 32) { + errno = EINVAL; + return -1; + } + return implementation->state_mac_final(st_, mac, maclen); +} + +int +aegis256_mac_verify(aegis256_state *st_, const uint8_t *mac, size_t maclen) +{ + uint8_t expected_mac[32]; + + switch (maclen) { + case 16: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_16(expected_mac, mac); + case 32: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_32(expected_mac, mac); + default: + errno = EINVAL; + return -1; + } +} + int aegis256_pick_best_implementation(void) { diff --git a/src/aegis256/aegis256_aesni.c b/src/aegis256/aegis256_aesni.c index 1f02c22..570364a 100644 --- a/src/aegis256/aegis256_aesni.c +++ b/src/aegis256/aegis256_aesni.c @@ -58,6 +58,8 @@ struct aegis256_implementation aegis256_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis256/aegis256_armcrypto.c b/src/aegis256/aegis256_armcrypto.c index 52ed1a9..669514a 100644 --- a/src/aegis256/aegis256_armcrypto.c +++ b/src/aegis256/aegis256_armcrypto.c @@ -65,6 +65,8 @@ struct aegis256_implementation aegis256_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis256/aegis256_common.h b/src/aegis256/aegis256_common.h index 6e898a9..60b60fb 100644 --- a/src/aegis256/aegis256_common.h +++ b/src/aegis256/aegis256_common.h @@ -513,3 +513,50 @@ state_decrypt_detached_final(aegis256_state *st_, uint8_t *m, size_t mlen_max, s } return ret; } + +static int +state_mac_update(aegis256_state *st_, const uint8_t *ad, size_t adlen) +{ + _aegis256_state *const st = + (_aegis256_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t i; + size_t left; + + left = st->adlen % RATE; + st->adlen += adlen; + if (left != 0) { + if (left + adlen < RATE) { + memcpy(st->buf + left, ad, adlen); + return 0; + } + memcpy(st->buf + left, ad, RATE - left); + aegis256_absorb(st->buf, st->state); + ad += RATE - left; + adlen -= RATE - left; + } + for (i = 0; i + RATE <= adlen; i += RATE) { + aegis256_absorb(ad + i, st->state); + } + if (i < adlen) { + memset(st->buf, 0, RATE); + memcpy(st->buf, ad + i, adlen - i); + } + return 0; +} + +static int +state_mac_final(aegis256_state *st_, uint8_t *mac, size_t maclen) +{ + _aegis256_state *const st = + (_aegis256_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t left; + + left = st->adlen % RATE; + if (left != 0) { + memset(st->buf + left, 0, RATE - left); + aegis256_absorb(st->buf, st->state); + } + aegis256_mac(mac, maclen, st->adlen, 0, st->state); + + return 0; +} \ No newline at end of file diff --git a/src/aegis256/aegis256_soft.c b/src/aegis256/aegis256_soft.c index 4e8a10f..9115471 100644 --- a/src/aegis256/aegis256_soft.c +++ b/src/aegis256/aegis256_soft.c @@ -52,6 +52,8 @@ struct aegis256_implementation aegis256_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_update = state_mac_update, + .state_mac_final = state_mac_final, }; #endif diff --git a/src/aegis256/implementations.h b/src/aegis256/implementations.h index e28ea71..ffaf37d 100644 --- a/src/aegis256/implementations.h +++ b/src/aegis256/implementations.h @@ -29,6 +29,8 @@ typedef struct aegis256_implementation { size_t *written, const uint8_t *c, size_t clen); int (*state_decrypt_detached_final)(aegis256_state *st_, uint8_t *m, size_t mlen_max, size_t *written, const uint8_t *mac, size_t maclen); + int (*state_mac_update)(aegis256_state *st_, const uint8_t *ad, size_t adlen); + int (*state_mac_final)(aegis256_state *st_, uint8_t *mac, size_t maclen); } aegis256_implementation; #endif diff --git a/src/aegis256x2/aegis256x2.c b/src/aegis256x2/aegis256x2.c index 98b6960..deafe09 100644 --- a/src/aegis256x2/aegis256x2.c +++ b/src/aegis256x2/aegis256x2.c @@ -172,6 +172,49 @@ aegis256x2_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, co implementation->decrypt_unauthenticated(m, c, clen, npub, k); } +void +aegis256x2_mac_init(aegis256x2_state *st_, const uint8_t *k) +{ + const uint8_t npub[aegis256x2_NPUBBYTES] = { 0 }; + + memset(st_, 0, sizeof *st_); + implementation->state_init(st_, NULL, 0, npub, k); +} + +int +aegis256x2_mac_update(aegis256x2_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) +{ + if (maclen != 16 && maclen != 32) { + errno = EINVAL; + return -1; + } + return implementation->state_mac_final(st_, mac, maclen); +} + +int +aegis256x2_mac_verify(aegis256x2_state *st_, const uint8_t *mac, size_t maclen) +{ + uint8_t expected_mac[32]; + + switch (maclen) { + case 16: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_16(expected_mac, mac); + case 32: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_32(expected_mac, mac); + default: + errno = EINVAL; + return -1; + } +} + int aegis256x2_pick_best_implementation(void) { diff --git a/src/aegis256x2/aegis256x2_aesni.c b/src/aegis256x2/aegis256x2_aesni.c index cd96d15..b6e03aa 100644 --- a/src/aegis256x2/aegis256x2_aesni.c +++ b/src/aegis256x2/aegis256x2_aesni.c @@ -93,6 +93,8 @@ 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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis256x2/aegis256x2_armcrypto.c b/src/aegis256x2/aegis256x2_armcrypto.c index bf91920..3a70504 100644 --- a/src/aegis256x2/aegis256x2_armcrypto.c +++ b/src/aegis256x2/aegis256x2_armcrypto.c @@ -99,6 +99,8 @@ 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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis256x2/aegis256x2_avx2.c b/src/aegis256x2/aegis256x2_avx2.c index c17ce5c..f458dc9 100644 --- a/src/aegis256x2/aegis256x2_avx2.c +++ b/src/aegis256x2/aegis256x2_avx2.c @@ -61,6 +61,8 @@ 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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis256x2/aegis256x2_common.h b/src/aegis256x2/aegis256x2_common.h index fe7a6c4..121ff6c 100644 --- a/src/aegis256x2/aegis256x2_common.h +++ b/src/aegis256x2/aegis256x2_common.h @@ -562,3 +562,50 @@ state_decrypt_detached_final(aegis256x2_state *st_, uint8_t *m, size_t mlen_max, } return ret; } + +static int +state_mac_update(aegis256x2_state *st_, const uint8_t *ad, size_t adlen) +{ + _aegis256x2_state *const st = + (_aegis256x2_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t i; + size_t left; + + left = st->adlen % RATE; + st->adlen += adlen; + if (left != 0) { + if (left + adlen < RATE) { + memcpy(st->buf + left, ad, adlen); + return 0; + } + memcpy(st->buf + left, ad, RATE - left); + aegis256x2_absorb(st->buf, st->state); + ad += RATE - left; + adlen -= RATE - left; + } + for (i = 0; i + RATE <= adlen; i += RATE) { + aegis256x2_absorb(ad + i, st->state); + } + if (i < adlen) { + memset(st->buf, 0, RATE); + memcpy(st->buf, ad + i, adlen - i); + } + return 0; +} + +static int +state_mac_final(aegis256x2_state *st_, uint8_t *mac, size_t maclen) +{ + _aegis256x2_state *const st = + (_aegis256x2_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t left; + + left = st->adlen % RATE; + if (left != 0) { + memset(st->buf + left, 0, RATE - left); + aegis256x2_absorb(st->buf, st->state); + } + aegis256x2_mac(mac, maclen, st->adlen, 0, st->state); + + return 0; +} \ No newline at end of file diff --git a/src/aegis256x2/aegis256x2_soft.c b/src/aegis256x2/aegis256x2_soft.c index eb65c10..2110b96 100644 --- a/src/aegis256x2/aegis256x2_soft.c +++ b/src/aegis256x2/aegis256x2_soft.c @@ -85,6 +85,8 @@ 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_update = state_mac_update, + .state_mac_final = state_mac_final, }; #endif \ No newline at end of file diff --git a/src/aegis256x2/implementations.h b/src/aegis256x2/implementations.h index 7201279..040cdda 100644 --- a/src/aegis256x2/implementations.h +++ b/src/aegis256x2/implementations.h @@ -29,6 +29,8 @@ 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); } aegis256x2_implementation; #endif diff --git a/src/aegis256x4/aegis256x4.c b/src/aegis256x4/aegis256x4.c index 2c8dea7..73bb647 100644 --- a/src/aegis256x4/aegis256x4.c +++ b/src/aegis256x4/aegis256x4.c @@ -173,6 +173,49 @@ aegis256x4_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, co implementation->decrypt_unauthenticated(m, c, clen, npub, k); } +void +aegis256x4_mac_init(aegis256x4_state *st_, const uint8_t *k) +{ + const uint8_t npub[aegis256x4_NPUBBYTES] = { 0 }; + + memset(st_, 0, sizeof *st_); + implementation->state_init(st_, NULL, 0, npub, k); +} + +int +aegis256x4_mac_update(aegis256x4_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) +{ + if (maclen != 16 && maclen != 32) { + errno = EINVAL; + return -1; + } + return implementation->state_mac_final(st_, mac, maclen); +} + +int +aegis256x4_mac_verify(aegis256x4_state *st_, const uint8_t *mac, size_t maclen) +{ + uint8_t expected_mac[32]; + + switch (maclen) { + case 16: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_16(expected_mac, mac); + case 32: + implementation->state_mac_final(st_, expected_mac, maclen); + return aegis_verify_32(expected_mac, mac); + default: + errno = EINVAL; + return -1; + } +} + int aegis256x4_pick_best_implementation(void) { diff --git a/src/aegis256x4/aegis256x4_aesni.c b/src/aegis256x4/aegis256x4_aesni.c index 4cdd774..743a99d 100644 --- a/src/aegis256x4/aegis256x4_aesni.c +++ b/src/aegis256x4/aegis256x4_aesni.c @@ -102,6 +102,8 @@ 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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis256x4/aegis256x4_armcrypto.c b/src/aegis256x4/aegis256x4_armcrypto.c index c8d5345..5194ac2 100644 --- a/src/aegis256x4/aegis256x4_armcrypto.c +++ b/src/aegis256x4/aegis256x4_armcrypto.c @@ -107,6 +107,8 @@ 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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis256x4/aegis256x4_avx2.c b/src/aegis256x4/aegis256x4_avx2.c index a1bd5ba..493b340 100644 --- a/src/aegis256x4/aegis256x4_avx2.c +++ b/src/aegis256x4/aegis256x4_avx2.c @@ -94,6 +94,8 @@ 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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis256x4/aegis256x4_avx512.c b/src/aegis256x4/aegis256x4_avx512.c index 20ff319..cdaf9bc 100644 --- a/src/aegis256x4/aegis256x4_avx512.c +++ b/src/aegis256x4/aegis256x4_avx512.c @@ -67,6 +67,8 @@ 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_update = state_mac_update, + .state_mac_final = state_mac_final, }; # ifdef __clang__ diff --git a/src/aegis256x4/aegis256x4_common.h b/src/aegis256x4/aegis256x4_common.h index b5748a4..260019b 100644 --- a/src/aegis256x4/aegis256x4_common.h +++ b/src/aegis256x4/aegis256x4_common.h @@ -581,3 +581,50 @@ state_decrypt_detached_final(aegis256x4_state *st_, uint8_t *m, size_t mlen_max, } return ret; } + +static int +state_mac_update(aegis256x4_state *st_, const uint8_t *ad, size_t adlen) +{ + _aegis256x4_state *const st = + (_aegis256x4_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t i; + size_t left; + + left = st->adlen % RATE; + st->adlen += adlen; + if (left != 0) { + if (left + adlen < RATE) { + memcpy(st->buf + left, ad, adlen); + return 0; + } + memcpy(st->buf + left, ad, RATE - left); + aegis256x4_absorb(st->buf, st->state); + ad += RATE - left; + adlen -= RATE - left; + } + for (i = 0; i + RATE <= adlen; i += RATE) { + aegis256x4_absorb(ad + i, st->state); + } + if (i < adlen) { + memset(st->buf, 0, RATE); + memcpy(st->buf, ad + i, adlen - i); + } + return 0; +} + +static int +state_mac_final(aegis256x4_state *st_, uint8_t *mac, size_t maclen) +{ + _aegis256x4_state *const st = + (_aegis256x4_state *) ((((uintptr_t) &st_->opaque) + (RATE - 1)) & ~(uintptr_t) (RATE - 1)); + size_t left; + + left = st->adlen % RATE; + if (left != 0) { + memset(st->buf + left, 0, RATE - left); + aegis256x4_absorb(st->buf, st->state); + } + aegis256x4_mac(mac, maclen, st->adlen, 0, st->state); + + return 0; +} \ No newline at end of file diff --git a/src/aegis256x4/aegis256x4_soft.c b/src/aegis256x4/aegis256x4_soft.c index a619fad..f7a7446 100644 --- a/src/aegis256x4/aegis256x4_soft.c +++ b/src/aegis256x4/aegis256x4_soft.c @@ -93,6 +93,8 @@ 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_update = state_mac_update, + .state_mac_final = state_mac_final, }; #endif \ No newline at end of file diff --git a/src/aegis256x4/implementations.h b/src/aegis256x4/implementations.h index 2a56d10..fa0ede2 100644 --- a/src/aegis256x4/implementations.h +++ b/src/aegis256x4/implementations.h @@ -29,6 +29,8 @@ 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); } aegis256x4_implementation; #endif diff --git a/src/include/aegis128x2.h b/src/include/aegis128x2.h index 8e3fea9..4d40e38 100644 --- a/src/include/aegis128x2.h +++ b/src/include/aegis128x2.h @@ -251,6 +251,54 @@ void aegis128x2_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mle void aegis128x2_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *npub, const uint8_t *k); +/* + * Initialize a state for generating a MAC. + * + * st_: state to initialize + * k: key input buffer (16 bytes) + * + * - The same key MUST NOT be used both for MAC and encryption. + * - The nonce is not used in the MAC mode (fixed to zero). + * - 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. + */ +void aegis128x2_mac_init(aegis128x2_state *st_, const uint8_t *k); + +/* + * Update the MAC state with input data. + * + * st_: state to update + * m: input data + * mlen: length of the input data + * + * This function can be called multiple times. + * + * Once the full input has been absorb, call either `_mac_final` or `_mac_verify`. + */ +int aegis128x2_mac_update(aegis128x2_state *st_, const uint8_t *m, size_t mlen); + +/* + * Finalize the MAC and generate the authentication tag. + * + * st_: state to finalize + * mac: authentication tag output buffer + * maclen: length of the authentication tag to generate (16 or 32. 32 is recommended). + */ +int aegis128x2_mac_final(aegis128x2_state *st_, uint8_t *mac, size_t maclen); + +/* + * Verify a MAC in constant time. + * + * st_: state to verify + * mac: authentication tag to verify + * maclen: length of the authentication tag (16 or 32) + * + * Returns 0 if the tag is authentic, -1 otherwise. + */ +int aegis128x2_mac_verify(aegis128x2_state *st_, const uint8_t *mac, size_t maclen); + #ifdef __cplusplus } #endif diff --git a/src/include/aegis128x4.h b/src/include/aegis128x4.h index f7bf8ac..f3321dd 100644 --- a/src/include/aegis128x4.h +++ b/src/include/aegis128x4.h @@ -251,6 +251,54 @@ void aegis128x4_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mle void aegis128x4_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *npub, const uint8_t *k); +/* + * Initialize a state for generating a MAC. + * + * st_: state to initialize + * k: key input buffer (16 bytes) + * + * - The same key MUST NOT be used both for MAC and encryption. + * - The nonce is not used in the MAC mode (fixed to zero). + * - 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. + */ +void aegis128x4_mac_init(aegis128x4_state *st_, const uint8_t *k); + +/* + * Update the MAC state with input data. + * + * st_: state to update + * m: input data + * mlen: length of the input data + * + * This function can be called multiple times. + * + * Once the full input has been absorb, call either `_mac_final` or `_mac_verify`. + */ +int aegis128x4_mac_update(aegis128x4_state *st_, const uint8_t *m, size_t mlen); + +/* + * Finalize the MAC and generate the authentication tag. + * + * st_: state to finalize + * mac: authentication tag output buffer + * maclen: length of the authentication tag to generate (16 or 32. 32 is recommended). + */ +int aegis128x4_mac_final(aegis128x4_state *st_, uint8_t *mac, size_t maclen); + +/* + * Verify a MAC in constant time. + * + * st_: state to verify + * mac: authentication tag to verify + * maclen: length of the authentication tag (16 or 32) + * + * Returns 0 if the tag is authentic, -1 otherwise. + */ +int aegis128x4_mac_verify(aegis128x4_state *st_, const uint8_t *mac, size_t maclen); + #ifdef __cplusplus } #endif diff --git a/src/include/aegis256.h b/src/include/aegis256.h index c080534..2e562b0 100644 --- a/src/include/aegis256.h +++ b/src/include/aegis256.h @@ -251,6 +251,54 @@ void aegis256_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mlen, void aegis256_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *npub, const uint8_t *k); +/* + * Initialize a state for generating a MAC. + * + * st_: state to initialize + * k: key input buffer (32 bytes) + * + * - The same key MUST NOT be used both for MAC and encryption. + * - The nonce is not used in the MAC mode (fixed to zero). + * - 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. + */ +void aegis256_mac_init(aegis256_state *st_, const uint8_t *k); + +/* + * Update the MAC state with input data. + * + * st_: state to update + * m: input data + * mlen: length of the input data + * + * This function can be called multiple times. + * + * Once the full input has been absorb, call either `_mac_final` or `_mac_verify`. + */ +int aegis256_mac_update(aegis256_state *st_, const uint8_t *m, size_t mlen); + +/* + * Finalize the MAC and generate the authentication tag. + * + * st_: state to finalize + * mac: authentication tag output buffer + * maclen: length of the authentication tag to generate (16 or 32. 32 is recommended). + */ +int aegis256_mac_final(aegis256_state *st_, uint8_t *mac, size_t maclen); + +/* + * Verify a MAC in constant time. + * + * st_: state to verify + * mac: authentication tag to verify + * maclen: length of the authentication tag (16 or 32) + * + * Returns 0 if the tag is authentic, -1 otherwise. + */ +int aegis256_mac_verify(aegis256_state *st_, const uint8_t *mac, size_t maclen); + #ifdef __cplusplus } #endif diff --git a/src/include/aegis256x2.h b/src/include/aegis256x2.h index 968a8f3..ab78390 100644 --- a/src/include/aegis256x2.h +++ b/src/include/aegis256x2.h @@ -251,6 +251,54 @@ void aegis256x2_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mle void aegis256x2_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *npub, const uint8_t *k); +/* + * Initialize a state for generating a MAC. + * + * st_: state to initialize + * k: key input buffer (32 bytes) + * + * - The same key MUST NOT be used both for MAC and encryption. + * - The nonce is not used in the MAC mode (fixed to zero). + * - 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. + */ +void aegis256x2_mac_init(aegis256x2_state *st_, const uint8_t *k); + +/* + * Update the MAC state with input data. + * + * st_: state to update + * m: input data + * mlen: length of the input data + * + * This function can be called multiple times. + * + * 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); + +/* + * Finalize the MAC and generate the authentication tag. + * + * st_: state to finalize + * 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); + +/* + * Verify a MAC in constant time. + * + * st_: state to verify + * mac: authentication tag to verify + * maclen: length of the authentication tag (16 or 32) + * + * Returns 0 if the tag is authentic, -1 otherwise. + */ +int aegis256x2_mac_verify(aegis256x2_state *st_, const uint8_t *mac, size_t maclen); + #ifdef __cplusplus } #endif diff --git a/src/include/aegis256x4.h b/src/include/aegis256x4.h index 478ba7b..4b833cb 100644 --- a/src/include/aegis256x4.h +++ b/src/include/aegis256x4.h @@ -251,6 +251,54 @@ void aegis256x4_encrypt_unauthenticated(uint8_t *c, const uint8_t *m, size_t mle void aegis256x4_decrypt_unauthenticated(uint8_t *m, const uint8_t *c, size_t clen, const uint8_t *npub, const uint8_t *k); +/* + * Initialize a state for generating a MAC. + * + * st_: state to initialize + * k: key input buffer (32 bytes) + * + * - The same key MUST NOT be used both for MAC and encryption. + * - The nonce is not used in the MAC mode (fixed to zero). + * - 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. + */ +void aegis256x4_mac_init(aegis256x4_state *st_, const uint8_t *k); + +/* + * Update the MAC state with input data. + * + * st_: state to update + * m: input data + * mlen: length of the input data + * + * This function can be called multiple times. + * + * 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); + +/* + * Finalize the MAC and generate the authentication tag. + * + * st_: state to finalize + * 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); + +/* + * Verify a MAC in constant time. + * + * st_: state to verify + * mac: authentication tag to verify + * maclen: length of the authentication tag (16 or 32) + * + * Returns 0 if the tag is authentic, -1 otherwise. + */ +int aegis256x4_mac_verify(aegis256x4_state *st_, const uint8_t *mac, size_t maclen); + #ifdef __cplusplus } #endif diff --git a/src/test/benchmark.zig b/src/test/benchmark.zig index a7fb53a..97e124c 100644 --- a/src/test/benchmark.zig +++ b/src/test/benchmark.zig @@ -214,7 +214,7 @@ fn bench_aegis128l_mac() !void { for (0..iterations) |_| { var st = st0; _ = aegis.aegis128l_mac_update(&st, &buf, msg_len); - _ = aegis.aegis128l_mac_final(&st, &buf, aegis.aegis128l_ABYTES_MIN); + _ = aegis.aegis128l_mac_final(&st, &buf, aegis.aegis128l_ABYTES_MAX); } const end = timer.read(); mem.doNotOptimizeAway(buf[0]); @@ -227,27 +227,19 @@ fn bench_aegis128l_mac() !void { fn bench_aegis128x2_mac() !void { var key: [aegis.aegis128x2_KEYBYTES]u8 = undefined; - var nonce: [aegis.aegis128x2_NPUBBYTES]u8 = undefined; var buf: [msg_len]u8 = undefined; + var st0: aegis.aegis128x2_state = undefined; random.bytes(&key); - random.bytes(&nonce); random.bytes(&buf); + aegis.aegis128x2_mac_init(&st0, &key); var timer = try Timer.start(); const start = timer.lap(); for (0..iterations) |_| { - _ = aegis.aegis128x2_encrypt_detached( - null, - &buf, - aegis.aegis128x2_ABYTES_MAX, - null, - 0, - &buf, - msg_len, - &nonce, - &key, - ); + var st = st0; + _ = aegis.aegis128x2_mac_update(&st, &buf, msg_len); + _ = aegis.aegis128x2_mac_final(&st, &buf, aegis.aegis128x2_ABYTES_MAX); } const end = timer.read(); mem.doNotOptimizeAway(buf[0]); @@ -258,29 +250,22 @@ fn bench_aegis128x2_mac() !void { try stdout.print("AEGIS-128X2 MAC\t{d:10.2} Mb/s\n", .{throughput}); } + 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; random.bytes(&key); - random.bytes(&nonce); random.bytes(&buf); + aegis.aegis128x4_mac_init(&st0, &key); var timer = try Timer.start(); const start = timer.lap(); for (0..iterations) |_| { - _ = aegis.aegis128x4_encrypt_detached( - null, - &buf, - aegis.aegis128x4_ABYTES_MAX, - null, - 0, - &buf, - msg_len, - &nonce, - &key, - ); + var st = st0; + _ = aegis.aegis128x4_mac_update(&st, &buf, msg_len); + _ = aegis.aegis128x4_mac_final(&st, &buf, aegis.aegis128x4_ABYTES_MAX); } const end = timer.read(); mem.doNotOptimizeAway(buf[0]); @@ -291,6 +276,8 @@ fn bench_aegis128x4_mac() !void { try stdout.print("AEGIS-128X4 MAC\t{d:10.2} Mb/s\n", .{throughput}); } + + pub fn main() !void { try bench_aegis256(); try bench_aegis256x2(); diff --git a/src/test/main.zig b/src/test/main.zig index c26715b..6e9a80d 100644 --- a/src/test/main.zig +++ b/src/test/main.zig @@ -600,8 +600,8 @@ test "aegis-256x4 - test vector" { } test "aegis128l - Unauthenticated encryption" { - const key = [32]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; - const nonce = [32]u8{ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 }; + const key = [16]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + const nonce = [16]u8{ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; var msg: [100]u8 = undefined; var msg2: [100]u8 = undefined; @@ -613,8 +613,8 @@ test "aegis128l - Unauthenticated encryption" { } test "aegis128l - Random stream" { - const key = [32]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; - var nonce = [32]u8{ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 }; + const key = [16]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + var nonce = [16]u8{ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; var msg: [100]u8 = undefined; var msg2: [100]u8 = undefined; aegis.aegis128l_stream(&msg, msg.len, &nonce, &key); @@ -626,7 +626,7 @@ test "aegis128l - Random stream" { } test "aegis128l - MAC" { - const key = [32]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; + const key = [16]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; const msg = [_]u8{ 1, 2, 3 } ** 30; const msg2 = [_]u8{ 4, 5, 6, 7, 8 } ** 30; var st0: aegis.aegis128l_state = undefined; @@ -656,3 +656,35 @@ test "aegis128l - MAC" { ret = aegis.aegis128l_mac_verify(&st, &mac, mac.len); try testing.expectEqual(ret, 0); } + +test "aegis256 - MAC" { + const key = [32]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; + const msg = [_]u8{ 1, 2, 3 } ** 30; + const msg2 = [_]u8{ 4, 5, 6, 7, 8 } ** 30; + var st0: aegis.aegis256_state = undefined; + aegis.aegis256_mac_init(&st0, &key); + + var st = st0; + var ret = aegis.aegis256_mac_update(&st, &msg, msg.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256_mac_update(&st, &msg2, msg2.len); + try testing.expectEqual(ret, 0); + var mac: [32]u8 = undefined; + ret = aegis.aegis256_mac_final(&st, &mac, mac.len); + try testing.expectEqual(ret, 0); + + st = st0; + ret = aegis.aegis256_mac_update(&st, &msg, msg.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256_mac_update(&st, &msg2, msg2.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256_mac_verify(&st, &mac, mac.len); + try testing.expectEqual(ret, 0); + + st = st0; + const msg3 = msg ++ msg2; + ret = aegis.aegis256_mac_update(&st, &msg3, msg3.len); + try testing.expectEqual(ret, 0); + ret = aegis.aegis256_mac_verify(&st, &mac, mac.len); + try testing.expectEqual(ret, 0); +}