From: Niels Möller Date: Sun, 16 Nov 2025 15:14:37 +0000 (+0100) Subject: Add blake2b_set_key and blake2s_set_key, and more tests. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fblake2;p=thirdparty%2Fnettle.git Add blake2b_set_key and blake2s_set_key, and more tests. --- diff --git a/blake2.h b/blake2.h index 8741f5a4..0719a3db 100644 --- a/blake2.h +++ b/blake2.h @@ -42,16 +42,19 @@ extern "C" { /* Name mangling */ #define blake2b_init nettle_blake2b_init +#define blake2b_set_key nettle_blake2b_set_key #define blake2b_update nettle_blake2b_update #define blake2b_digest nettle_blake2b_digest #define blake2b_512_init nettle_blake2b_512_init #define blake2s_init nettle_blake2s_init +#define blake2s_set_key nettle_blake2s_set_key #define blake2s_update nettle_blake2s_update #define blake2s_digest nettle_blake2s_digest #define blake2s_256_init nettle_blake2s_256_init #define BLAKE2B_DIGEST_SIZE 64 #define BLAKE2B_BLOCK_SIZE 128 +#define BLAKE2B_KEY_SIZE 64 struct blake2b_ctx { @@ -63,7 +66,12 @@ struct blake2b_ctx }; void -blake2b_init (struct blake2b_ctx *ctx, unsigned digest_size); +blake2b_init (struct blake2b_ctx *ctx, size_t digest_size); + +/* Alternative initialization function with key. */ +void +blake2b_set_key(struct blake2b_ctx *ctx, size_t key_size, const uint8_t *key, + size_t digest_size); void blake2b_update (struct blake2b_ctx *ctx, @@ -77,6 +85,7 @@ blake2b_512_init (struct blake2b_ctx *ctx); #define BLAKE2S_DIGEST_SIZE 32 #define BLAKE2S_BLOCK_SIZE 64 +#define BLAKE2S_KEY_SIZE 32 struct blake2s_ctx { @@ -88,7 +97,12 @@ struct blake2s_ctx }; void -blake2s_init (struct blake2s_ctx *ctx, unsigned digest_size); +blake2s_init (struct blake2s_ctx *ctx, size_t digest_size); + +/* Alternative initialization function with key. */ +void +blake2s_set_key(struct blake2s_ctx *ctx, size_t key_size, const uint8_t *key, + size_t digest_size); void blake2s_update (struct blake2s_ctx *ctx, diff --git a/blake2b.c b/blake2b.c index 153acd33..d8fe07bb 100644 --- a/blake2b.c +++ b/blake2b.c @@ -110,16 +110,37 @@ blake2b_compress (uint64_t *h, const uint8_t *input, h[i] ^= v[i] ^ v[8+i]; } -void -blake2b_init (struct blake2b_ctx *ctx, unsigned digest_size) +/* Initializes everything but ctx->index. */ +static void +blake2b_init_internal (struct blake2b_ctx *ctx, size_t key_size,size_t digest_size) { assert (digest_size > 0 && digest_size <= BLAKE2B_DIGEST_SIZE); memcpy (ctx->state, iv, sizeof (ctx->state)); - ctx->state[0] ^= 0x01010000 ^ digest_size; - ctx->count_low = ctx->count_high = ctx->index = 0; + ctx->state[0] ^= 0x01010000 ^ ((key_size << 8) | digest_size); + ctx->count_high = ctx->count_low = 0; ctx->digest_size = digest_size; } +void +blake2b_init (struct blake2b_ctx *ctx, size_t digest_size) +{ + ctx->index = 0; + blake2b_init_internal (ctx, 0, digest_size); +} + +void +blake2b_set_key(struct blake2b_ctx *ctx, size_t key_size, const uint8_t *key, + size_t digest_size) +{ + assert (key_size > 0 && key_size <= BLAKE2B_KEY_SIZE); + + memcpy (ctx->block, key, key_size); + memset (ctx->block + key_size, 0, sizeof(ctx->block) - key_size); + ctx->index = sizeof(ctx->block); + + blake2b_init_internal (ctx, key_size, digest_size); +} + void blake2b_update (struct blake2b_ctx *ctx, size_t length, const uint8_t *data) diff --git a/blake2s.c b/blake2s.c index 0e585b07..b7effbbd 100644 --- a/blake2s.c +++ b/blake2s.c @@ -105,16 +105,37 @@ blake2s_compress (uint32_t *h, const uint8_t *input, h[i] ^= v[i] ^ v[8+i]; } -void -blake2s_init (struct blake2s_ctx *ctx, unsigned digest_size) +/* Initializes everything but ctx->index. */ +static void +blake2s_init_internal (struct blake2s_ctx *ctx, size_t key_size, size_t digest_size) { assert (digest_size > 0 && digest_size <= BLAKE2S_DIGEST_SIZE); memcpy (ctx->state, iv, sizeof (ctx->state)); - ctx->state[0] ^= 0x01010000 ^ digest_size; - ctx->count = ctx->index = 0; + ctx->state[0] ^= 0x01010000 ^ ((key_size << 8) | digest_size); + ctx->count = 0; ctx->digest_size = digest_size; } +void +blake2s_init (struct blake2s_ctx *ctx, size_t digest_size) +{ + ctx->index = 0; + blake2s_init_internal (ctx, 0, digest_size); +} + +void +blake2s_set_key(struct blake2s_ctx *ctx, size_t key_size, const uint8_t *key, + size_t digest_size) +{ + assert (key_size > 0 && key_size <= BLAKE2S_KEY_SIZE); + + memcpy (ctx->block, key, key_size); + memset (ctx->block + key_size, 0, sizeof(ctx->block) - key_size); + ctx->index = sizeof(ctx->block); + + blake2s_init_internal (ctx, key_size, digest_size); +} + void blake2s_update (struct blake2s_ctx *ctx, size_t length, const uint8_t *data) diff --git a/testsuite/blake2b-test.c b/testsuite/blake2b-test.c index 1843cc96..110a79ad 100644 --- a/testsuite/blake2b-test.c +++ b/testsuite/blake2b-test.c @@ -1,13 +1,168 @@ #include "testutils.h" +#include "blake2.h" #include "non-nettle.h" +static void +blake2b (size_t digest_size, uint8_t *digest, + size_t size, const uint8_t *data) +{ + struct blake2b_ctx ctx; + blake2b_init (&ctx, digest_size); + blake2b_update (&ctx, size, data); + blake2b_digest (&ctx, digest); +} + +static void +blake2b_key (size_t digest_size, uint8_t *digest, + size_t key_size, const uint8_t *key, + size_t size, const uint8_t *data) +{ + struct blake2b_ctx ctx; + blake2b_set_key (&ctx, key_size, key, digest_size); + blake2b_update (&ctx, size, data); + blake2b_digest (&ctx, digest); +} + +static void +test_blake2b (const struct tstring *key, const struct tstring *data, + const struct tstring *digest) +{ + uint8_t buf [BLAKE2B_DIGEST_SIZE]; + ASSERT (digest->length <= BLAKE2B_DIGEST_SIZE); + if (key) + blake2b_key (digest->length, buf, key->length, key->data, data->length, data->data); + else + blake2b (digest->length, buf, data->length, data->data); + if (!MEMEQ(digest->length, buf, digest->data)) + { + fprintf (stderr, "blake2b failed:\n"); + if (key) + { + fprintf (stderr, "key:"); + tstring_print_hex (key); + } + fprintf (stderr, "data:"); + tstring_print_hex (data); + fprintf (stderr, "digest:"); + print_hex (digest->length, buf); + fprintf (stderr, "expect:"); + tstring_print_hex (digest); + FAIL (); + } +} + +/* Self test from RFC7693 */ + +// Deterministic sequences (Fibonacci generator). +static void +selftest_seq(uint8_t *out, size_t len, uint32_t seed) +{ + size_t i; + uint32_t t, a , b; + + a = 0xDEAD4BAD * seed; // prime + b = 1; + + for (i = 0; i < len; i++) { // fill the buf + t = a + b; + a = b; + b = t; + out[i] = (t >> 24) & 0xFF; + } +} + +static void +blake2b_selftest (void) +{ + // grand hash of hash results + static const uint8_t blake2b_res[32] = { + 0xC2, 0x3A, 0x78, 0x00, 0xD9, 0x81, 0x23, 0xBD, + 0x10, 0xF5, 0x06, 0xC6, 0x1E, 0x29, 0xDA, 0x56, + 0x03, 0xD7, 0x63, 0xB8, 0xBB, 0xAD, 0x2E, 0x73, + 0x7F, 0x5E, 0x76, 0x5A, 0x7B, 0xCC, 0xD4, 0x75 + }; + // parameter sets + static const size_t b2b_md_len[4] = { 20, 32, 48, 64 }; + static const size_t b2b_in_len[6] = { 0, 3, 128, 129, 255, 1024 }; + + size_t i, j, outlen, inlen; + uint8_t in[1024], md[64], key[64]; + struct blake2b_ctx ctx; + + // 256-bit hash for testing + blake2b_init(&ctx, 32); + + for (i = 0; i < 4; i++) { + outlen = b2b_md_len[i]; + for (j = 0; j < 6; j++) { + inlen = b2b_in_len[j]; + + selftest_seq (in, inlen, inlen); // unkeyed hash + blake2b (outlen, md, inlen, in); + blake2b_update (&ctx, outlen, md); // hash the hash + + selftest_seq (key, outlen, outlen); // keyed hash + blake2b_key (outlen, md, outlen, key, inlen, in); + blake2b_update (&ctx, outlen, md); // hash the hash + } + } + + // compute and compare the hash of hashes + blake2b_digest (&ctx, md); + ASSERT (MEMEQ (sizeof(blake2b_res), blake2b_res, md)); +} + void test_main(void) { - test_hash(&nettle_blake2b_512, SDATA("abc"), - SHEX("BA 80 A5 3F 98 1C 4D 0D 6A 27 97 B6 9F 12 F6 E9" - "4C 21 2F 14 68 5A C4 B7 4B 12 BB 6F DB FF A2 D1" - "7D 87 C5 39 2A AB 79 2D C2 52 D5 DE 45 33 CC 95" - "18 D3 8A A8 DB F1 92 5A B9 23 86 ED D4 00 99 23")); + /* RFC 7693 */ + test_hash (&nettle_blake2b_512, SDATA("abc"), + SHEX("BA 80 A5 3F 98 1C 4D 0D 6A 27 97 B6 9F 12 F6 E9" + "4C 21 2F 14 68 5A C4 B7 4B 12 BB 6F DB FF A2 D1" + "7D 87 C5 39 2A AB 79 2D C2 52 D5 DE 45 33 CC 95" + "18 D3 8A A8 DB F1 92 5A B9 23 86 ED D4 00 99 23")); + /* Selected from + https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt */ + test_blake2b (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + SHEX(""), + SHEX("10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786" + "b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568")); + test_blake2b (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + SHEX("00"), + SHEX("961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4" + "187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd")); + test_blake2b (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + SHEX("0001"), + SHEX("da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b" + "983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965")); + test_blake2b (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + SHEX("65676d800617972fbd87e4b9514e1c67402b7a331096d3bfac22f1abb95374ab" + "c942f16e9ab0ead33b87c91968a6e509e119ff07787b3ef483e1dcdccf6e3022")); + test_blake2b (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "40"), + SHEX("939fa189699c5d2c81ddd1ffc1fa207c970b6a3685bb29ce1d3e99d42f2f7442" + "da53e95a72907314f4588399a3ff5b0a92beb3f6be2694f9f86ecf2952d5b41c")); + test_blake2b (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe"), + SHEX("142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e9248" + "4be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461")); + blake2b_selftest (); } diff --git a/testsuite/blake2s-test.c b/testsuite/blake2s-test.c index 2a447284..bfdb72b7 100644 --- a/testsuite/blake2s-test.c +++ b/testsuite/blake2s-test.c @@ -1,11 +1,151 @@ #include "testutils.h" +#include "blake2.h" #include "non-nettle.h" +// Convenience function for all-in-one computation. +static void +blake2s (size_t digest_size, uint8_t *digest, + size_t size, const uint8_t *data) +{ + struct blake2s_ctx ctx; + blake2s_init (&ctx, digest_size); + blake2s_update (&ctx, size, data); + blake2s_digest (&ctx, digest); +} + +static void +blake2s_key (size_t digest_size, uint8_t *digest, + size_t key_size, const uint8_t *key, + size_t size, const uint8_t *data) +{ + struct blake2s_ctx ctx; + blake2s_set_key (&ctx, key_size, key, digest_size); + blake2s_update (&ctx, size, data); + blake2s_digest (&ctx, digest); +} + +static void +test_blake2s (const struct tstring *key, const struct tstring *data, + const struct tstring *digest) +{ + uint8_t buf [BLAKE2S_DIGEST_SIZE]; + ASSERT (digest->length <= BLAKE2S_DIGEST_SIZE); + if (key) + blake2s_key (digest->length, buf, key->length, key->data, data->length, data->data); + else + blake2s (digest->length, buf, data->length, data->data); + if (!MEMEQ(digest->length, buf, digest->data)) + { + fprintf (stderr, "blake2s failed:\n"); + if (key) + { + fprintf (stderr, "key:"); + tstring_print_hex (key); + } + fprintf (stderr, "data:"); + tstring_print_hex (data); + fprintf (stderr, "digest:"); + print_hex (digest->length, buf); + fprintf (stderr, "expect:"); + tstring_print_hex (digest); + FAIL (); + } +} + +/* Self test from RFC7693 */ + +// Deterministic sequences (Fibonacci generator). +static void +selftest_seq(uint8_t *out, size_t len, uint32_t seed) +{ + size_t i; + uint32_t t, a , b; + + a = 0xDEAD4BAD * seed; // prime + b = 1; + + for (i = 0; i < len; i++) { // fill the buf + t = a + b; + a = b; + b = t; + out[i] = (t >> 24) & 0xFF; + } +} + +static void +blake2s_selftest (void) +{ + // Grand hash of hash results. + static const uint8_t blake2s_res[32] = { + 0x6A, 0x41, 0x1F, 0x08, 0xCE, 0x25, 0xAD, 0xCD, + 0xFB, 0x02, 0xAB, 0xA6, 0x41, 0x45, 0x1C, 0xEC, + 0x53, 0xC5, 0x98, 0xB2, 0x4F, 0x4F, 0xC7, 0x87, + 0xFB, 0xDC, 0x88, 0x79, 0x7F, 0x4C, 0x1D, 0xFE + }; + // Parameter sets. + static const size_t b2s_md_len[4] = { 16, 20, 28, 32 }; + static const size_t b2s_in_len[6] = { 0, 3, 64, 65, 255, 1024 }; + + size_t i, j, outlen, inlen; + uint8_t in[1024], md[32], key[32]; + struct blake2s_ctx ctx; + + // 256-bit hash for testing. + blake2s_init(&ctx, 32); + + for (i = 0; i < 4; i++) { + outlen = b2s_md_len[i]; + for (j = 0; j < 6; j++) { + inlen = b2s_in_len[j]; + + selftest_seq (in, inlen, inlen); // unkeyed hash + blake2s (outlen, md, inlen, in); + blake2s_update (&ctx, outlen, md); // hash the hash + + selftest_seq (key, outlen, outlen); // keyed hash + blake2s_key (outlen, md, outlen, key, inlen, in); + blake2s_update (&ctx, outlen, md); // hash the hash + } + } + + // Compute and compare the hash of hashes. + blake2s_digest (&ctx, md); + ASSERT (MEMEQ (sizeof(blake2s_res), blake2s_res, md)); +} + void test_main(void) { test_hash(&nettle_blake2s_256, SDATA("abc"), SHEX("50 8C 5E 8C 32 7C 14 E2 E1 A7 2B A3 4E EB 45 2F" "37 45 8B 20 9E D6 3A 29 4D 99 9B 4C 86 67 59 82")); + /* Selected from + https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2s-kat.txt */ + test_blake2s (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + SHEX(""), + SHEX("48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49")); + test_blake2s (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + SHEX("00"), + SHEX("40d15fee7c328830166ac3f918650f807e7e01e177258cdc0a39b11f598066f1")); + test_blake2s (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + SHEX("0001"), + SHEX("6bb71300644cd3991b26ccd4d274acd1adeab8b1d7914546c1198bbe9fc9d803")); + test_blake2s (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + SHEX("c03bc642b20959cbe133a0303e0c1abff3e31ec8e1a328ec8565c36decff5265")); + test_blake2s (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), + SHEX("2c3e08176f760c6264c3a2cd66fec6c3d78de43fc192457b2a4a660a1e0eb22b")); + test_blake2s (SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe"), + SHEX("3fb735061abc519dfe979e54c1ee5bfad0a9d858b3315bad34bde999efd724dd")); + blake2s_selftest (); }