aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2023-09-04 23:27:29 -0400
committerPaul Duncan <pabs@pablotron.org>2023-09-04 23:27:29 -0400
commit6978574556c07410bed2f04fefce94018951d9f2 (patch)
tree5d80d37fdb55c08d9f2d8002770c28158540077d
parent058eba2d2171e38813d6ad722333ee58668d35b1 (diff)
downloadsha3-6978574556c07410bed2f04fefce94018951d9f2.tar.bz2
sha3-6978574556c07410bed2f04fefce94018951d9f2.zip
sha3.[hc]: add hmac_sha3_{224,256,384,512}(), hmac_sha3_{224,256,384,512}_{init,absorb,final}(), test_hmac_sha3_{224,256,384,512}(), test_hmac_sha3_{224,256,384,512}_ctx()
-rw-r--r--sha3.c970
-rw-r--r--sha3.h188
2 files changed, 1153 insertions, 5 deletions
diff --git a/sha3.c b/sha3.c
index 4a7f512..b03e0f3 100644
--- a/sha3.c
+++ b/sha3.c
@@ -219,13 +219,13 @@ static inline void sha3_init(sha3_t * const hash) {
}
// Absorb input data into iterative SHA-3 hash context.
-static inline bool sha3_absorb(sha3_t * const hash, const size_t rate, const uint8_t * const src, const size_t len) {
+static inline bool sha3_absorb(sha3_t * const hash, const size_t rate, const uint8_t *src, size_t len) {
if (hash->finalized) {
// hash already finalized, return false
return false;
}
- // absorb bytes (FIXME: should absorb larger chunks)
+ // absorb bytes (FIXME: absorb larger chunks)
for (size_t i = 0; i < len; i++) {
hash->a.u8[hash->num_bytes++] ^= src[i];
if (hash->num_bytes == rate) {
@@ -330,6 +330,242 @@ void sha3_512_final(sha3_t * const hash, uint8_t dst[SHA3_512_CAPACITY]) {
sha3_final(hash, SHA3_512_RATE, dst, SHA3_512_CAPACITY);
}
+void hmac_sha3_224_init(hmac_sha3_t *hmac, const uint8_t *k, const size_t k_len) {
+ // clear finalized flag
+ hmac->finalized = false;
+
+ // init key buffer
+ uint8_t k_buf[SHA3_224_RATE] = { 0 };
+ if (k_len <= sizeof(k_buf)) {
+ memcpy(k_buf, k, k_len);
+ } else {
+ sha3_224(k, k_len, k_buf);
+ }
+
+ // apply opad
+ for (size_t i = 0; i < SHA3_224_RATE; i++) {
+ k_buf[i] ^= 0x5c;
+ }
+
+ // init outer hash, absorb outer key
+ sha3_224_init(&(hmac->outer));
+ sha3_224_absorb(&(hmac->outer), k_buf, sizeof(k_buf));
+
+ // remove opad, apply ipad
+ for (size_t i = 0; i < SHA3_224_RATE; i++) {
+ k_buf[i] ^= (0x5c ^ 0x36);
+ }
+
+ // init outer hash, absorb inner key
+ sha3_224_init(&(hmac->inner));
+ sha3_224_absorb(&(hmac->inner), k_buf, sizeof(k_buf));
+}
+
+_Bool hmac_sha3_224_absorb(hmac_sha3_t *hmac, const uint8_t *src, const size_t len) {
+ return sha3_224_absorb(&(hmac->inner), src, len);
+}
+
+void hmac_sha3_224_final(hmac_sha3_t *hmac, uint8_t dst[28]) {
+ // finalize inner hash into buffer
+ uint8_t buf[28] = { 0 };
+ sha3_224_final(&(hmac->inner), buf);
+
+ // absorb into outer hash
+ sha3_224_absorb(&(hmac->outer), buf, sizeof(buf));
+
+ // finalize outer hash into destination
+ sha3_224_final(&(hmac->outer), dst);
+}
+
+void hmac_sha3_224(const uint8_t * const k, const size_t k_len, const uint8_t * const m, const size_t m_len, uint8_t dst[28]) {
+ // init
+ hmac_sha3_t hmac;
+ hmac_sha3_224_init(&hmac, k, k_len);
+
+ // absorb
+ hmac_sha3_224_absorb(&hmac, m, m_len);
+
+ // finalize
+ hmac_sha3_224_final(&hmac, dst);
+}
+
+void hmac_sha3_256_init(hmac_sha3_t *hmac, const uint8_t *k, const size_t k_len) {
+ // clear finalized flag
+ hmac->finalized = false;
+
+ // init key buffer
+ uint8_t k_buf[SHA3_256_RATE] = { 0 };
+ if (k_len <= sizeof(k_buf)) {
+ memcpy(k_buf, k, k_len);
+ } else {
+ sha3_256(k, k_len, k_buf);
+ }
+
+ // apply opad
+ for (size_t i = 0; i < SHA3_256_RATE; i++) {
+ k_buf[i] ^= 0x5c;
+ }
+
+ // init outer hash, absorb outer key
+ sha3_256_init(&(hmac->outer));
+ sha3_256_absorb(&(hmac->outer), k_buf, sizeof(k_buf));
+
+ // remove opad, apply ipad
+ for (size_t i = 0; i < SHA3_256_RATE; i++) {
+ k_buf[i] ^= (0x5c ^ 0x36);
+ }
+
+ // init outer hash, absorb inner key
+ sha3_256_init(&(hmac->inner));
+ sha3_256_absorb(&(hmac->inner), k_buf, sizeof(k_buf));
+}
+
+_Bool hmac_sha3_256_absorb(hmac_sha3_t *hmac, const uint8_t *src, const size_t len) {
+ return sha3_256_absorb(&(hmac->inner), src, len);
+}
+
+void hmac_sha3_256_final(hmac_sha3_t *hmac, uint8_t dst[32]) {
+ // finalize inner hash into buffer
+ uint8_t buf[32] = { 0 };
+ sha3_256_final(&(hmac->inner), buf);
+
+ // absorb into outer hash
+ sha3_256_absorb(&(hmac->outer), buf, sizeof(buf));
+
+ // finalize outer hash into destination
+ sha3_256_final(&(hmac->outer), dst);
+}
+
+void hmac_sha3_256(const uint8_t * const k, const size_t k_len, const uint8_t * const m, const size_t m_len, uint8_t dst[32]) {
+ // init
+ hmac_sha3_t hmac;
+ hmac_sha3_256_init(&hmac, k, k_len);
+
+ // absorb
+ hmac_sha3_256_absorb(&hmac, m, m_len);
+
+ // finalize
+ hmac_sha3_256_final(&hmac, dst);
+}
+
+void hmac_sha3_384_init(hmac_sha3_t *hmac, const uint8_t *k, const size_t k_len) {
+ // clear finalized flag
+ hmac->finalized = false;
+
+ // init key buffer
+ uint8_t k_buf[SHA3_384_RATE] = { 0 };
+ if (k_len <= sizeof(k_buf)) {
+ memcpy(k_buf, k, k_len);
+ } else {
+ sha3_384(k, k_len, k_buf);
+ }
+
+ // apply opad
+ for (size_t i = 0; i < SHA3_384_RATE; i++) {
+ k_buf[i] ^= 0x5c;
+ }
+
+ // init outer hash, absorb outer key
+ sha3_384_init(&(hmac->outer));
+ sha3_384_absorb(&(hmac->outer), k_buf, sizeof(k_buf));
+
+ // remove opad, apply ipad
+ for (size_t i = 0; i < SHA3_384_RATE; i++) {
+ k_buf[i] ^= (0x5c ^ 0x36);
+ }
+
+ // init outer hash, absorb inner key
+ sha3_384_init(&(hmac->inner));
+ sha3_384_absorb(&(hmac->inner), k_buf, sizeof(k_buf));
+}
+
+_Bool hmac_sha3_384_absorb(hmac_sha3_t *hmac, const uint8_t *src, const size_t len) {
+ return sha3_384_absorb(&(hmac->inner), src, len);
+}
+
+void hmac_sha3_384_final(hmac_sha3_t *hmac, uint8_t dst[48]) {
+ // finalize inner hash into buffer
+ uint8_t buf[48] = { 0 };
+ sha3_384_final(&(hmac->inner), buf);
+
+ // absorb into outer hash
+ sha3_384_absorb(&(hmac->outer), buf, sizeof(buf));
+
+ // finalize outer hash into destination
+ sha3_384_final(&(hmac->outer), dst);
+}
+
+void hmac_sha3_384(const uint8_t * const k, const size_t k_len, const uint8_t * const m, const size_t m_len, uint8_t dst[48]) {
+ // init
+ hmac_sha3_t hmac;
+ hmac_sha3_384_init(&hmac, k, k_len);
+
+ // absorb
+ hmac_sha3_384_absorb(&hmac, m, m_len);
+
+ // finalize
+ hmac_sha3_384_final(&hmac, dst);
+}
+
+void hmac_sha3_512_init(hmac_sha3_t *hmac, const uint8_t *k, const size_t k_len) {
+ // clear finalized flag
+ hmac->finalized = false;
+
+ // init key buffer
+ uint8_t k_buf[SHA3_512_RATE] = { 0 };
+ if (k_len <= sizeof(k_buf)) {
+ memcpy(k_buf, k, k_len);
+ } else {
+ sha3_512(k, k_len, k_buf);
+ }
+
+ // apply opad
+ for (size_t i = 0; i < SHA3_512_RATE; i++) {
+ k_buf[i] ^= 0x5c;
+ }
+
+ // init outer hash, absorb outer key
+ sha3_512_init(&(hmac->outer));
+ sha3_512_absorb(&(hmac->outer), k_buf, sizeof(k_buf));
+
+ // remove opad, apply ipad
+ for (size_t i = 0; i < SHA3_512_RATE; i++) {
+ k_buf[i] ^= (0x5c ^ 0x36);
+ }
+
+ // init outer hash, absorb inner key
+ sha3_512_init(&(hmac->inner));
+ sha3_512_absorb(&(hmac->inner), k_buf, sizeof(k_buf));
+}
+
+_Bool hmac_sha3_512_absorb(hmac_sha3_t *hmac, const uint8_t *src, const size_t len) {
+ return sha3_512_absorb(&(hmac->inner), src, len);
+}
+
+void hmac_sha3_512_final(hmac_sha3_t *hmac, uint8_t dst[64]) {
+ // finalize inner hash into buffer
+ uint8_t buf[64] = { 0 };
+ sha3_512_final(&(hmac->inner), buf);
+
+ // absorb into outer hash
+ sha3_512_absorb(&(hmac->outer), buf, sizeof(buf));
+
+ // finalize outer hash into destination
+ sha3_512_final(&(hmac->outer), dst);
+}
+
+void hmac_sha3_512(const uint8_t * const k, const size_t k_len, const uint8_t * const m, const size_t m_len, uint8_t dst[64]) {
+ // init
+ hmac_sha3_t hmac;
+ hmac_sha3_512_init(&hmac, k, k_len);
+
+ // absorb
+ hmac_sha3_512_absorb(&hmac, m, m_len);
+
+ // finalize
+ hmac_sha3_512_final(&hmac, dst);
+}
+
static inline void shake(const uint8_t *m, size_t m_len, uint8_t * const dst, const size_t dst_len) {
// in the sha3 xof functions, the capacity is always 2 times the
// destination length, and the rate is the total state size minus the
@@ -4885,6 +5121,728 @@ static void test_parallelhash256_xof(void) {
}
}
+static void test_hmac_sha3_224(void) {
+ static const struct {
+ const char *name; // test name
+ const uint8_t key[256]; // key
+ const size_t key_len; // key length, in bytes
+ const uint8_t msg[256]; // input data
+ const size_t msg_len; // message length, in bytes
+ const uint8_t exp[28]; // expected hash
+ } tests[] = {{
+ // src: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-224.pdf
+ .name = "HMAC-SHA3-224 Sample #1",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b,
+ },
+ .key_len = 28,
+ .msg = "Sample message for keylen<blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x33, 0x2c, 0xfd, 0x59, 0x34, 0x7f, 0xdb, 0x8e,
+ 0x57, 0x6e, 0x77, 0x26, 0x0b, 0xe4, 0xab, 0xa2,
+ 0xd6, 0xdc, 0x53, 0x11, 0x7b, 0x3b, 0xfb, 0x52,
+ 0xc6, 0xd1, 0x8c, 0x04,
+ },
+ }, {
+ .name = "HMAC-SHA3-224 Sample #2",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ },
+ .key_len = 144,
+ .msg = "Sample message for keylen=blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0xd8, 0xb7, 0x33, 0xbc, 0xf6, 0x6c, 0x64, 0x4a, 0x12, 0x32, 0x3d, 0x56, 0x4e, 0x24, 0xdc, 0xf3,
+ 0xfc, 0x75, 0xf2, 0x31, 0xf3, 0xb6, 0x79, 0x68, 0x35, 0x91, 0x00, 0xc7,
+ },
+ }, {
+ .name = "HMAC-SHA3-224 Sample #3",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ },
+ .key_len = 172,
+ .msg = "Sample message for keylen>blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x07, 0x86, 0x95, 0xee, 0xcc, 0x22, 0x7c, 0x63, 0x6a, 0xd3, 0x1d, 0x06, 0x3a, 0x15, 0xdd, 0x05,
+ 0xa7, 0xe8, 0x19, 0xa6, 0x6e, 0xc6, 0xd8, 0xde, 0x1e, 0x19, 0x3e, 0x59,
+ },
+ }};
+
+ for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ // run
+ uint8_t got[28];
+ hmac_sha3_224(tests[i].key, tests[i].key_len, tests[i].msg, tests[i].msg_len, got);
+
+ // check
+ if (memcmp(got, tests[i].exp, sizeof(got))) {
+ fprintf(stderr, "test_hmac_sha3_224(\"%s\") failed, got:\n", tests[i].name);
+ dump_hex(stderr, got, sizeof(got));
+
+ fprintf(stderr, "exp:\n");
+ dump_hex(stderr, tests[i].exp, sizeof(got));
+ }
+ }
+}
+
+static void test_hmac_sha3_256(void) {
+ static const struct {
+ const char *name; // test name
+ const uint8_t key[256]; // key
+ const size_t key_len; // key length, in bytes
+ const uint8_t msg[256]; // input data
+ const size_t msg_len; // message length, in bytes
+ const uint8_t exp[32]; // expected hash
+ } tests[] = {{
+ // src: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-256.pdf
+ .name = "HMAC-SHA3-256 Sample #1",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ },
+ .key_len = 32,
+ .msg = "Sample message for keylen<blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x4f, 0xe8, 0xe2, 0x02, 0xc4, 0xf0, 0x58, 0xe8, 0xdd, 0xdc, 0x23, 0xd8, 0xc3, 0x4e, 0x46, 0x73,
+ 0x43, 0xe2, 0x35, 0x55, 0xe2, 0x4f, 0xc2, 0xf0, 0x25, 0xd5, 0x98, 0xf5, 0x58, 0xf6, 0x72, 0x05,
+ },
+ }, {
+ .name = "HMAC-SHA3-256 Sample #2",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ },
+ .key_len = 136,
+ .msg = "Sample message for keylen=blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x68, 0xb9, 0x4e, 0x2e, 0x53, 0x8a, 0x9b, 0xe4, 0x10, 0x3b, 0xeb, 0xb5, 0xaa, 0x01, 0x6d, 0x47,
+ 0x96, 0x1d, 0x4d, 0x1a, 0xa9, 0x06, 0x06, 0x13, 0x13, 0xb5, 0x57, 0xf8, 0xaf, 0x2c, 0x3f, 0xaa,
+ },
+ }, {
+ .name = "HMAC-SHA3-256 Sample #3",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ },
+ .key_len = 168,
+ .msg = "Sample message for keylen>blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x9b, 0xcf, 0x2c, 0x23, 0x8e, 0x23, 0x5c, 0x3c, 0xe8, 0x84, 0x04, 0xe8, 0x13, 0xbd, 0x2f, 0x3a,
+ 0x97, 0x18, 0x5a, 0xc6, 0xf2, 0x38, 0xc6, 0x3d, 0x62, 0x29, 0xa0, 0x0b, 0x07, 0x97, 0x42, 0x58,
+ },
+ }};
+
+ for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ // run
+ uint8_t got[32];
+ hmac_sha3_256(tests[i].key, tests[i].key_len, tests[i].msg, tests[i].msg_len, got);
+
+ // check
+ if (memcmp(got, tests[i].exp, sizeof(got))) {
+ fprintf(stderr, "test_hmac_sha3_256(\"%s\") failed, got:\n", tests[i].name);
+ dump_hex(stderr, got, sizeof(got));
+
+ fprintf(stderr, "exp:\n");
+ dump_hex(stderr, tests[i].exp, sizeof(got));
+ }
+ }
+}
+
+static void test_hmac_sha3_384(void) {
+ static const struct {
+ const char *name; // test name
+ const uint8_t key[256]; // key
+ const size_t key_len; // key length, in bytes
+ const uint8_t msg[256]; // input data
+ const size_t msg_len; // message length, in bytes
+ const uint8_t exp[48]; // expected hash
+ } tests[] = {{
+ // src: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-384.pdf
+ .name = "HMAC-SHA3-384 Sample #1",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ },
+ .key_len = 48,
+ .msg = "Sample message for keylen<blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0xd5, 0x88, 0xa3, 0xc5, 0x1f, 0x3f, 0x2d, 0x90, 0x6e, 0x82, 0x98, 0xc1, 0x19, 0x9a, 0xa8, 0xff,
+ 0x62, 0x96, 0x21, 0x81, 0x27, 0xf6, 0xb3, 0x8a, 0x90, 0xb6, 0xaf, 0xe2, 0xc5, 0x61, 0x77, 0x25,
+ 0xbc, 0x99, 0x98, 0x7f, 0x79, 0xb2, 0x2a, 0x55, 0x7b, 0x65, 0x20, 0xdb, 0x71, 0x0b, 0x7f, 0x42,
+ },
+ }, {
+ .name = "HMAC-SHA3-384 Sample #2",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ },
+ .key_len = 104,
+ .msg = "Sample message for keylen=blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0xa2, 0x7d, 0x24, 0xb5, 0x92, 0xe8, 0xc8, 0xcb, 0xf6, 0xd4, 0xce, 0x6f, 0xc5, 0xbf, 0x62, 0xd8,
+ 0xfc, 0x98, 0xbf, 0x2d, 0x48, 0x66, 0x40, 0xd9, 0xeb, 0x80, 0x99, 0xe2, 0x40, 0x47, 0x83, 0x7f,
+ 0x5f, 0x3b, 0xff, 0xbe, 0x92, 0xdc, 0xce, 0x90, 0xb4, 0xed, 0x5b, 0x1e, 0x7e, 0x44, 0xfa, 0x90,
+ },
+ }, {
+ .name = "HMAC-SHA3-384 Sample #3",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ },
+ .key_len = 152,
+ .msg = "Sample message for keylen>blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0xe5, 0xae, 0x4c, 0x73, 0x9f, 0x45, 0x52, 0x79, 0x36, 0x8e, 0xbf, 0x36, 0xd4, 0xf5, 0x35, 0x4c,
+ 0x95, 0xaa, 0x18, 0x4c, 0x89, 0x9d, 0x38, 0x70, 0xe4, 0x60, 0xeb, 0xc2, 0x88, 0xef, 0x1f, 0x94,
+ 0x70, 0x05, 0x3f, 0x73, 0xf7, 0xc6, 0xda, 0x2a, 0x71, 0xbc, 0xae, 0xc3, 0x8c, 0xe7, 0xd6, 0xac,
+ },
+ }};
+
+ for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ // run
+ uint8_t got[48];
+ hmac_sha3_384(tests[i].key, tests[i].key_len, tests[i].msg, tests[i].msg_len, got);
+
+ // check
+ if (memcmp(got, tests[i].exp, sizeof(got))) {
+ fprintf(stderr, "test_hmac_sha3_384(\"%s\") failed, got:\n", tests[i].name);
+ dump_hex(stderr, got, sizeof(got));
+
+ fprintf(stderr, "exp:\n");
+ dump_hex(stderr, tests[i].exp, sizeof(got));
+ }
+ }
+}
+
+static void test_hmac_sha3_512(void) {
+ static const struct {
+ const char *name; // test name
+ const uint8_t key[256]; // key
+ const size_t key_len; // key length, in bytes
+ const uint8_t msg[256]; // input data
+ const size_t msg_len; // message length, in bytes
+ const uint8_t exp[64]; // expected hash
+ } tests[] = {{
+ // src: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-512.pdf
+ .name = "HMAC-SHA3-512 Sample #1",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ },
+ .key_len = 64,
+ .msg = "Sample message for keylen<blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x4e, 0xfd, 0x62, 0x9d, 0x6c, 0x71, 0xbf, 0x86, 0x16, 0x26, 0x58, 0xf2, 0x99, 0x43, 0xb1, 0xc3,
+ 0x08, 0xce, 0x27, 0xcd, 0xfa, 0x6d, 0xb0, 0xd9, 0xc3, 0xce, 0x81, 0x76, 0x3f, 0x9c, 0xbc, 0xe5,
+ 0xf7, 0xeb, 0xe9, 0x86, 0x80, 0x31, 0xdb, 0x1a, 0x8f, 0x8e, 0xb7, 0xb6, 0xb9, 0x5e, 0x5c, 0x5e,
+ 0x3f, 0x65, 0x7a, 0x89, 0x96, 0xc8, 0x6a, 0x2f, 0x65, 0x27, 0xe3, 0x07, 0xf0, 0x21, 0x31, 0x96,
+ },
+ }, {
+ .name = "HMAC-SHA3-512 Sample #2",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ },
+ .key_len = 72,
+ .msg = "Sample message for keylen=blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x54, 0x4e, 0x25, 0x7e, 0xa2, 0xa3, 0xe5, 0xea, 0x19, 0xa5, 0x90, 0xe6, 0xa2, 0x4b, 0x72, 0x4c,
+ 0xe6, 0x32, 0x77, 0x57, 0x72, 0x3f, 0xe2, 0x75, 0x1b, 0x75, 0xbf, 0x00, 0x7d, 0x80, 0xf6, 0xb3,
+ 0x60, 0x74, 0x4b, 0xf1, 0xb7, 0xa8, 0x8e, 0xa5, 0x85, 0xf9, 0x76, 0x5b, 0x47, 0x91, 0x19, 0x76,
+ 0xd3, 0x19, 0x1c, 0xf8, 0x3c, 0x03, 0x9f, 0x5f, 0xfa, 0xb0, 0xd2, 0x9c, 0xc9, 0xd9, 0xb6, 0xda,
+ },
+ }, {
+ .name = "HMAC-SHA3-512 Sample #3",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ },
+ .key_len = 136,
+ .msg = "Sample message for keylen>blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x5f, 0x46, 0x4f, 0x5e, 0x5b, 0x78, 0x48, 0xe3, 0x88, 0x5e, 0x49, 0xb2, 0xc3, 0x85, 0xf0, 0x69,
+ 0x49, 0x85, 0xd0, 0xe3, 0x89, 0x66, 0x24, 0x2d, 0xc4, 0xa5, 0xfe, 0x3f, 0xea, 0x4b, 0x37, 0xd4,
+ 0x6b, 0x65, 0xce, 0xce, 0xd5, 0xdc, 0xf5, 0x94, 0x38, 0xdd, 0x84, 0x0b, 0xab, 0x22, 0x26, 0x9f,
+ 0x0b, 0xa7, 0xfe, 0xbd, 0xb9, 0xfc, 0xf7, 0x46, 0x02, 0xa3, 0x56, 0x66, 0xb2, 0xa3, 0x29, 0x15,
+ },
+ }};
+
+ for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ // run
+ uint8_t got[64];
+ hmac_sha3_512(tests[i].key, tests[i].key_len, tests[i].msg, tests[i].msg_len, got);
+
+ // check
+ if (memcmp(got, tests[i].exp, sizeof(got))) {
+ fprintf(stderr, "test_hmac_sha3_512(\"%s\") failed, got:\n", tests[i].name);
+ dump_hex(stderr, got, sizeof(got));
+
+ fprintf(stderr, "exp:\n");
+ dump_hex(stderr, tests[i].exp, sizeof(got));
+ }
+ }
+}
+
+static void test_hmac_sha3_224_ctx(void) {
+ static const struct {
+ const char *name; // test name
+ const uint8_t key[256]; // key
+ const size_t key_len; // key length, in bytes
+ const uint8_t msg[256]; // input data
+ const size_t msg_len; // message length, in bytes
+ const uint8_t exp[28]; // expected hash
+ } tests[] = {{
+ // src: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-224.pdf
+ .name = "HMAC-SHA3-224 Sample #1",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b,
+ },
+ .key_len = 28,
+ .msg = "Sample message for keylen<blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x33, 0x2c, 0xfd, 0x59, 0x34, 0x7f, 0xdb, 0x8e,
+ 0x57, 0x6e, 0x77, 0x26, 0x0b, 0xe4, 0xab, 0xa2,
+ 0xd6, 0xdc, 0x53, 0x11, 0x7b, 0x3b, 0xfb, 0x52,
+ 0xc6, 0xd1, 0x8c, 0x04,
+ },
+ }, {
+ .name = "HMAC-SHA3-224 Sample #2",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ },
+ .key_len = 144,
+ .msg = "Sample message for keylen=blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0xd8, 0xb7, 0x33, 0xbc, 0xf6, 0x6c, 0x64, 0x4a, 0x12, 0x32, 0x3d, 0x56, 0x4e, 0x24, 0xdc, 0xf3,
+ 0xfc, 0x75, 0xf2, 0x31, 0xf3, 0xb6, 0x79, 0x68, 0x35, 0x91, 0x00, 0xc7,
+ },
+ }, {
+ .name = "HMAC-SHA3-224 Sample #3",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ },
+ .key_len = 172,
+ .msg = "Sample message for keylen>blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x07, 0x86, 0x95, 0xee, 0xcc, 0x22, 0x7c, 0x63, 0x6a, 0xd3, 0x1d, 0x06, 0x3a, 0x15, 0xdd, 0x05,
+ 0xa7, 0xe8, 0x19, 0xa6, 0x6e, 0xc6, 0xd8, 0xde, 0x1e, 0x19, 0x3e, 0x59,
+ },
+ }};
+
+ for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ for (size_t j = 1; j < tests[i].msg_len; j++) {
+ // init
+ hmac_sha3_t hmac;
+ hmac_sha3_224_init(&hmac, tests[i].key, tests[i].key_len);
+
+ // absorb
+ for (size_t k = 0; k < tests[i].msg_len; k += j) {
+ const size_t len = MIN(tests[i].msg_len - k, j);
+ hmac_sha3_224_absorb(&hmac, tests[i].msg + k, len);
+ }
+
+ // finalize
+ uint8_t got[28];
+ hmac_sha3_224_final(&hmac, got);
+
+ // check
+ if (memcmp(got, tests[i].exp, sizeof(got))) {
+ fprintf(stderr, "test_hmac_sha3_224_ctx(\"%s\") failed, got:\n", tests[i].name);
+ dump_hex(stderr, got, sizeof(got));
+
+ fprintf(stderr, "exp:\n");
+ dump_hex(stderr, tests[i].exp, sizeof(got));
+ }
+ }
+ }
+}
+
+static void test_hmac_sha3_256_ctx(void) {
+ static const struct {
+ const char *name; // test name
+ const uint8_t key[256]; // key
+ const size_t key_len; // key length, in bytes
+ const uint8_t msg[256]; // input data
+ const size_t msg_len; // message length, in bytes
+ const uint8_t exp[32]; // expected hash
+ } tests[] = {{
+ // src: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-256.pdf
+ .name = "HMAC-SHA3-256 Sample #1",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ },
+ .key_len = 32,
+ .msg = "Sample message for keylen<blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x4f, 0xe8, 0xe2, 0x02, 0xc4, 0xf0, 0x58, 0xe8, 0xdd, 0xdc, 0x23, 0xd8, 0xc3, 0x4e, 0x46, 0x73,
+ 0x43, 0xe2, 0x35, 0x55, 0xe2, 0x4f, 0xc2, 0xf0, 0x25, 0xd5, 0x98, 0xf5, 0x58, 0xf6, 0x72, 0x05,
+ },
+ }, {
+ .name = "HMAC-SHA3-256 Sample #2",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ },
+ .key_len = 136,
+ .msg = "Sample message for keylen=blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x68, 0xb9, 0x4e, 0x2e, 0x53, 0x8a, 0x9b, 0xe4, 0x10, 0x3b, 0xeb, 0xb5, 0xaa, 0x01, 0x6d, 0x47,
+ 0x96, 0x1d, 0x4d, 0x1a, 0xa9, 0x06, 0x06, 0x13, 0x13, 0xb5, 0x57, 0xf8, 0xaf, 0x2c, 0x3f, 0xaa,
+ },
+ }, {
+ .name = "HMAC-SHA3-256 Sample #3",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ },
+ .key_len = 168,
+ .msg = "Sample message for keylen>blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x9b, 0xcf, 0x2c, 0x23, 0x8e, 0x23, 0x5c, 0x3c, 0xe8, 0x84, 0x04, 0xe8, 0x13, 0xbd, 0x2f, 0x3a,
+ 0x97, 0x18, 0x5a, 0xc6, 0xf2, 0x38, 0xc6, 0x3d, 0x62, 0x29, 0xa0, 0x0b, 0x07, 0x97, 0x42, 0x58,
+ },
+ }};
+
+ for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ for (size_t j = 1; j < tests[i].msg_len; j++) {
+ // init
+ hmac_sha3_t hmac;
+ hmac_sha3_256_init(&hmac, tests[i].key, tests[i].key_len);
+
+ // absorb
+ for (size_t k = 0; k < tests[i].msg_len; k += j) {
+ const size_t len = MIN(tests[i].msg_len - k, j);
+ hmac_sha3_224_absorb(&hmac, tests[i].msg + k, len);
+ }
+
+ // finalize
+ uint8_t got[32];
+ hmac_sha3_256_final(&hmac, got);
+
+ // check
+ if (memcmp(got, tests[i].exp, sizeof(got))) {
+ fprintf(stderr, "test_hmac_sha3_256_ctx(\"%s\") failed, got:\n", tests[i].name);
+ dump_hex(stderr, got, sizeof(got));
+
+ fprintf(stderr, "exp:\n");
+ dump_hex(stderr, tests[i].exp, sizeof(got));
+ }
+ }
+ }
+}
+
+static void test_hmac_sha3_384_ctx(void) {
+ static const struct {
+ const char *name; // test name
+ const uint8_t key[256]; // key
+ const size_t key_len; // key length, in bytes
+ const uint8_t msg[256]; // input data
+ const size_t msg_len; // message length, in bytes
+ const uint8_t exp[48]; // expected hash
+ } tests[] = {{
+ // src: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-384.pdf
+ .name = "HMAC-SHA3-384 Sample #1",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ },
+ .key_len = 48,
+ .msg = "Sample message for keylen<blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0xd5, 0x88, 0xa3, 0xc5, 0x1f, 0x3f, 0x2d, 0x90, 0x6e, 0x82, 0x98, 0xc1, 0x19, 0x9a, 0xa8, 0xff,
+ 0x62, 0x96, 0x21, 0x81, 0x27, 0xf6, 0xb3, 0x8a, 0x90, 0xb6, 0xaf, 0xe2, 0xc5, 0x61, 0x77, 0x25,
+ 0xbc, 0x99, 0x98, 0x7f, 0x79, 0xb2, 0x2a, 0x55, 0x7b, 0x65, 0x20, 0xdb, 0x71, 0x0b, 0x7f, 0x42,
+ },
+ }, {
+ .name = "HMAC-SHA3-384 Sample #2",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ },
+ .key_len = 104,
+ .msg = "Sample message for keylen=blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0xa2, 0x7d, 0x24, 0xb5, 0x92, 0xe8, 0xc8, 0xcb, 0xf6, 0xd4, 0xce, 0x6f, 0xc5, 0xbf, 0x62, 0xd8,
+ 0xfc, 0x98, 0xbf, 0x2d, 0x48, 0x66, 0x40, 0xd9, 0xeb, 0x80, 0x99, 0xe2, 0x40, 0x47, 0x83, 0x7f,
+ 0x5f, 0x3b, 0xff, 0xbe, 0x92, 0xdc, 0xce, 0x90, 0xb4, 0xed, 0x5b, 0x1e, 0x7e, 0x44, 0xfa, 0x90,
+ },
+ }, {
+ .name = "HMAC-SHA3-384 Sample #3",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ },
+ .key_len = 152,
+ .msg = "Sample message for keylen>blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0xe5, 0xae, 0x4c, 0x73, 0x9f, 0x45, 0x52, 0x79, 0x36, 0x8e, 0xbf, 0x36, 0xd4, 0xf5, 0x35, 0x4c,
+ 0x95, 0xaa, 0x18, 0x4c, 0x89, 0x9d, 0x38, 0x70, 0xe4, 0x60, 0xeb, 0xc2, 0x88, 0xef, 0x1f, 0x94,
+ 0x70, 0x05, 0x3f, 0x73, 0xf7, 0xc6, 0xda, 0x2a, 0x71, 0xbc, 0xae, 0xc3, 0x8c, 0xe7, 0xd6, 0xac,
+ },
+ }};
+
+ for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ for (size_t j = 1; j < tests[i].msg_len; j++) {
+ // init
+ hmac_sha3_t hmac;
+ hmac_sha3_384_init(&hmac, tests[i].key, tests[i].key_len);
+
+ // absorb
+ for (size_t k = 0; k < tests[i].msg_len; k += j) {
+ const size_t len = MIN(tests[i].msg_len - k, j);
+ hmac_sha3_384_absorb(&hmac, tests[i].msg + k, len);
+ }
+
+ // finalize
+ uint8_t got[48];
+ hmac_sha3_384_final(&hmac, got);
+
+ // check
+ if (memcmp(got, tests[i].exp, sizeof(got))) {
+ fprintf(stderr, "test_hmac_sha3_384(\"%s\") failed, got:\n", tests[i].name);
+ dump_hex(stderr, got, sizeof(got));
+
+ fprintf(stderr, "exp:\n");
+ dump_hex(stderr, tests[i].exp, sizeof(got));
+ }
+ }
+ }
+}
+
+static void test_hmac_sha3_512_ctx(void) {
+ static const struct {
+ const char *name; // test name
+ const uint8_t key[256]; // key
+ const size_t key_len; // key length, in bytes
+ const uint8_t msg[256]; // input data
+ const size_t msg_len; // message length, in bytes
+ const uint8_t exp[64]; // expected hash
+ } tests[] = {{
+ // src: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-512.pdf
+ .name = "HMAC-SHA3-512 Sample #1",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ },
+ .key_len = 64,
+ .msg = "Sample message for keylen<blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x4e, 0xfd, 0x62, 0x9d, 0x6c, 0x71, 0xbf, 0x86, 0x16, 0x26, 0x58, 0xf2, 0x99, 0x43, 0xb1, 0xc3,
+ 0x08, 0xce, 0x27, 0xcd, 0xfa, 0x6d, 0xb0, 0xd9, 0xc3, 0xce, 0x81, 0x76, 0x3f, 0x9c, 0xbc, 0xe5,
+ 0xf7, 0xeb, 0xe9, 0x86, 0x80, 0x31, 0xdb, 0x1a, 0x8f, 0x8e, 0xb7, 0xb6, 0xb9, 0x5e, 0x5c, 0x5e,
+ 0x3f, 0x65, 0x7a, 0x89, 0x96, 0xc8, 0x6a, 0x2f, 0x65, 0x27, 0xe3, 0x07, 0xf0, 0x21, 0x31, 0x96,
+ },
+ }, {
+ .name = "HMAC-SHA3-512 Sample #2",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ },
+ .key_len = 72,
+ .msg = "Sample message for keylen=blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x54, 0x4e, 0x25, 0x7e, 0xa2, 0xa3, 0xe5, 0xea, 0x19, 0xa5, 0x90, 0xe6, 0xa2, 0x4b, 0x72, 0x4c,
+ 0xe6, 0x32, 0x77, 0x57, 0x72, 0x3f, 0xe2, 0x75, 0x1b, 0x75, 0xbf, 0x00, 0x7d, 0x80, 0xf6, 0xb3,
+ 0x60, 0x74, 0x4b, 0xf1, 0xb7, 0xa8, 0x8e, 0xa5, 0x85, 0xf9, 0x76, 0x5b, 0x47, 0x91, 0x19, 0x76,
+ 0xd3, 0x19, 0x1c, 0xf8, 0x3c, 0x03, 0x9f, 0x5f, 0xfa, 0xb0, 0xd2, 0x9c, 0xc9, 0xd9, 0xb6, 0xda,
+ },
+ }, {
+ .name = "HMAC-SHA3-512 Sample #3",
+ .key = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ },
+ .key_len = 136,
+ .msg = "Sample message for keylen>blocklen",
+ .msg_len = 34,
+ .exp = {
+ 0x5f, 0x46, 0x4f, 0x5e, 0x5b, 0x78, 0x48, 0xe3, 0x88, 0x5e, 0x49, 0xb2, 0xc3, 0x85, 0xf0, 0x69,
+ 0x49, 0x85, 0xd0, 0xe3, 0x89, 0x66, 0x24, 0x2d, 0xc4, 0xa5, 0xfe, 0x3f, 0xea, 0x4b, 0x37, 0xd4,
+ 0x6b, 0x65, 0xce, 0xce, 0xd5, 0xdc, 0xf5, 0x94, 0x38, 0xdd, 0x84, 0x0b, 0xab, 0x22, 0x26, 0x9f,
+ 0x0b, 0xa7, 0xfe, 0xbd, 0xb9, 0xfc, 0xf7, 0x46, 0x02, 0xa3, 0x56, 0x66, 0xb2, 0xa3, 0x29, 0x15,
+ },
+ }};
+
+ for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ for (size_t j = 1; j < tests[i].msg_len; j++) {
+ // init
+ hmac_sha3_t hmac;
+ hmac_sha3_512_init(&hmac, tests[i].key, tests[i].key_len);
+
+ // absorb
+ for (size_t k = 0; k < tests[i].msg_len; k += j) {
+ const size_t len = MIN(tests[i].msg_len - k, j);
+ hmac_sha3_512_absorb(&hmac, tests[i].msg + k, len);
+ }
+
+ // finalize
+ uint8_t got[64];
+ hmac_sha3_512_final(&hmac, got);
+
+ // check
+ if (memcmp(got, tests[i].exp, sizeof(got))) {
+ fprintf(stderr, "test_hmac_sha3_512(\"%s\") failed, got:\n", tests[i].name);
+ dump_hex(stderr, got, sizeof(got));
+
+ fprintf(stderr, "exp:\n");
+ dump_hex(stderr, tests[i].exp, sizeof(got));
+ }
+ }
+ }
+}
+
int main(void) {
test_theta();
test_rho();
@@ -4924,6 +5882,14 @@ int main(void) {
test_parallelhash128_xof();
test_parallelhash256();
test_parallelhash256_xof();
+ test_hmac_sha3_224();
+ test_hmac_sha3_256();
+ test_hmac_sha3_384();
+ test_hmac_sha3_512();
+ test_hmac_sha3_224_ctx();
+ test_hmac_sha3_256_ctx();
+ test_hmac_sha3_384_ctx();
+ test_hmac_sha3_512_ctx();
printf("ok\n");
}
diff --git a/sha3.h b/sha3.h
index 003d5b5..eb6ffd8 100644
--- a/sha3.h
+++ b/sha3.h
@@ -103,7 +103,7 @@ void sha3_256_init(sha3_t *hash);
_Bool sha3_256_absorb(sha3_t *hash, const uint8_t *src, const size_t len);
/**
- * Finalize SHA3-256 hash context and write 28 bytes of output to
+ * Finalize SHA3-256 hash context and write 32 bytes of output to
* destination buffer `dst`.
*
* @param[in/out] hash SHA3-256 hash context.
@@ -143,7 +143,7 @@ void sha3_384_init(sha3_t *hash);
_Bool sha3_384_absorb(sha3_t *hash, const uint8_t *src, const size_t len);
/**
- * Finalize SHA3-384 hash context and write 28 bytes of output to
+ * Finalize SHA3-384 hash context and write 48 bytes of output to
* destination buffer `dst`.
*
* @param[in/out] hash SHA3-384 hash context.
@@ -183,7 +183,7 @@ void sha3_512_init(sha3_t *hash);
_Bool sha3_512_absorb(sha3_t *hash, const uint8_t *src, const size_t len);
/**
- * Finalize SHA3-512 hash context and write 28 bytes of output to
+ * Finalize SHA3-512 hash context and write 64 bytes of output to
* destination buffer `dst`.
*
* @param[in/out] hash SHA3-512 hash context.
@@ -192,6 +192,188 @@ _Bool sha3_512_absorb(sha3_t *hash, const uint8_t *src, const size_t len);
void sha3_512_final(sha3_t *hash, uint8_t dst[64]);
/**
+ * Calculate HMAC-SHA3-224 (FIPS 202, Section 7) of key in buffer `k` of
+ * length `k_len` and input message in buffer `m` of length `m_len`
+ * bytes and write 28 bytes of output to destination buffer `dst`.
+ *
+ * @param[in] k Key.
+ * @param[in] k_len Key length, in bytes.
+ * @param[in] m Input message.
+ * @param[in] m_len Input message length, in bytes.
+ * @param[out] dst Destination array. Must be at least 28 bytes in length.
+ */
+void hmac_sha3_224(const uint8_t *k, const size_t k_len, const uint8_t *m, const size_t m_len, uint8_t dst[28]);
+
+/**
+ * Calculate HMAC-SHA3-256 (FIPS 202, Section 7) of key in buffer `k` of
+ * length `k_len` and input message in buffer `m` of length `m_len`
+ * bytes and write 32 bytes of output to destination buffer `dst`.
+ *
+ * @param[in] k Key.
+ * @param[in] k_len Key length, in bytes.
+ * @param[in] m Input message.
+ * @param[in] m_len Input message length, in bytes.
+ * @param[out] dst Destination array. Must be at least 32 bytes in length.
+ */
+void hmac_sha3_256(const uint8_t *k, const size_t k_len, const uint8_t *m, const size_t m_len, uint8_t dst[32]);
+
+/**
+ * Calculate HMAC-SHA3-384 (FIPS 202, Section 7) of key in buffer `k` of
+ * length `k_len` and input message in buffer `m` of length `m_len`
+ * bytes and write 48 bytes of output to destination buffer `dst`.
+ *
+ * @param[in] k Key.
+ * @param[in] k_len Key length, in bytes.
+ * @param[in] m Input message.
+ * @param[in] m_len Input message length, in bytes.
+ * @param[out] dst Destination array. Must be at least 48 bytes in length.
+ */
+void hmac_sha3_384(const uint8_t *k, const size_t k_len, const uint8_t *m, const size_t m_len, uint8_t dst[48]);
+
+/**
+ * Calculate HMAC-SHA3-512 (FIPS 202, Section 7) of key in buffer `k` of
+ * length `k_len` and input message in buffer `m` of length `m_len`
+ * bytes and write 64 bytes of output to destination buffer `dst`.
+ *
+ * @param[in] k Key.
+ * @param[in] k_len Key length, in bytes.
+ * @param[in] m Input message.
+ * @param[in] m_len Input message length, in bytes.
+ * @param[out] dst Destination array. Must be at least 64 bytes in length.
+ */
+void hmac_sha3_512(const uint8_t *k, const size_t k_len, const uint8_t *m, const size_t m_len, uint8_t dst[64]);
+
+// HMAC-SHA3 (Hash-based Message Authentication Code) context.
+typedef struct {
+ sha3_t inner, outer;
+ _Bool finalized;
+} hmac_sha3_t;
+
+/**
+ * Initialize HMAC-SHA3-224 (FIPS 202, Section 7) context.
+ *
+ * @param[out] hmac HMAC-SHA3-224 context.
+ * @param[in] k Key.
+ * @param[in] k_len Key length, in bytes.
+ */
+void hmac_sha3_224_init(hmac_sha3_t *hmac, const uint8_t *k, const size_t k_len);
+
+/**
+ * Absorb input data in `src` of length `len` bytes into HMAC-SHA3-224
+ * context `hmac`. Can be called iteratively to absorb input data in
+ * chunks.
+ *
+ * @param[in/out] hmac HMAC-SHA3-224 context.
+ * @param[in] src Input data.
+ * @param[in] len Input data length, in bytes.
+ *
+ * @return True if data was absorbed, and false otherwise (e.g., if context has already been finalized).
+ */
+_Bool hmac_sha3_224_absorb(hmac_sha3_t *hmac, const uint8_t *src, const size_t len);
+
+/**
+ * Finalize HMAC-SHA3-224 hash context and write 28 bytes of output to
+ * destination buffer `dst`.
+ *
+ * @param[in/out] hmac HMAC-SHA3-224 hash context.
+ * @param[out] dst Destination buffer. Must be at least 28 bytes in length.
+ */
+void hmac_sha3_224_final(hmac_sha3_t *hmac, uint8_t dst[28]);
+
+/**
+ * Initialize HMAC-SHA3-256 (FIPS 202, Section 7) context.
+ *
+ * @param[out] hmac HMAC-SHA3-256 context.
+ * @param[in] k Key.
+ * @param[in] k_len Key length, in bytes.
+ */
+void hmac_sha3_256_init(hmac_sha3_t *hmac, const uint8_t *k, const size_t k_len);
+
+/**
+ * Absorb input data in `src` of length `len` bytes into HMAC-SHA3-256
+ * context `hmac`. Can be called iteratively to absorb input data in
+ * chunks.
+ *
+ * @param[in/out] hmac HMAC-SHA3-256 context.
+ * @param[in] src Input data.
+ * @param[in] len Input data length, in bytes.
+ *
+ * @return True if data was absorbed, and false otherwise (e.g., if context has already been finalized).
+ */
+_Bool hmac_sha3_256_absorb(hmac_sha3_t *hmac, const uint8_t *src, const size_t len);
+
+/**
+ * Finalize HMAC-SHA3-256 hash context and write 32 bytes of output to
+ * destination buffer `dst`.
+ *
+ * @param[in/out] hmac HMAC-SHA3-256 hash context.
+ * @param[out] dst Destination buffer. Must be at least 32 bytes in length.
+ */
+void hmac_sha3_256_final(hmac_sha3_t *hmac, uint8_t dst[32]);
+
+/**
+ * Initialize HMAC-SHA3-384 (FIPS 202, Section 7) context.
+ *
+ * @param[out] hmac HMAC-SHA3-384 context.
+ * @param[in] k Key.
+ * @param[in] k_len Key length, in bytes.
+ */
+void hmac_sha3_384_init(hmac_sha3_t *hmac, const uint8_t *k, const size_t k_len);
+
+/**
+ * Absorb input data in `src` of length `len` bytes into HMAC-SHA3-384
+ * context `hmac`. Can be called iteratively to absorb input data in
+ * chunks.
+ *
+ * @param[in/out] hmac HMAC-SHA3-384 context.
+ * @param[in] src Input data.
+ * @param[in] len Input data length, in bytes.
+ *
+ * @return True if data was absorbed, and false otherwise (e.g., if context has already been finalized).
+ */
+_Bool hmac_sha3_384_absorb(hmac_sha3_t *hmac, const uint8_t *src, const size_t len);
+
+/**
+ * Finalize HMAC-SHA3-384 hash context and write 48 bytes of output to
+ * destination buffer `dst`.
+ *
+ * @param[in/out] hmac HMAC-SHA3-384 hash context.
+ * @param[out] dst Destination buffer. Must be at least 48 bytes in length.
+ */
+void hmac_sha3_384_final(hmac_sha3_t *hmac, uint8_t dst[48]);
+
+/**
+ * Initialize HMAC-SHA3-512 (FIPS 202, Section 7) context.
+ *
+ * @param[out] hmac HMAC-SHA3-512 context.
+ * @param[in] k Key.
+ * @param[in] k_len Key length, in bytes.
+ */
+void hmac_sha3_512_init(hmac_sha3_t *hmac, const uint8_t *k, const size_t k_len);
+
+/**
+ * Absorb input data in `src` of length `len` bytes into HMAC-SHA3-512
+ * context `hmac`. Can be called iteratively to absorb input data in
+ * chunks.
+ *
+ * @param[in/out] hmac HMAC-SHA3-512 context.
+ * @param[in] src Input data.
+ * @param[in] len Input data length, in bytes.
+ *
+ * @return True if data was absorbed, and false otherwise (e.g., if context has already been finalized).
+ */
+_Bool hmac_sha3_512_absorb(hmac_sha3_t *hmac, const uint8_t *src, const size_t len);
+
+/**
+ * Finalize HMAC-SHA3-512 hash context and write 64 bytes of output to
+ * destination buffer `dst`.
+ *
+ * @param[in/out] hmac HMAC-SHA3-512 hash context.
+ * @param[out] dst Destination buffer. Must be at least 64 bytes in length.
+ */
+void hmac_sha3_512_final(hmac_sha3_t *hmac, uint8_t dst[64]);
+
+/**
* Hash input message in buffer `m` of length `m_len` bytes with
* SHAKE128 (FIPS 202, section 6.2) and write 16 bytes of output to
* destination buffer `dst`.