aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-09-01 13:15:50 +0200
committerMattias Andrée <maandree@kth.se>2024-09-01 13:15:50 +0200
commitb9d4bfaea3209fdcebdba148cb99242c44371c4a (patch)
tree94c15e93ed1bf712064f225da3db7e33e550869c
parentAdd tests for SHAKE and RawSHAKE (diff)
downloadlibhashsum-b9d4bfaea3209fdcebdba148cb99242c44371c4a.tar.gz
libhashsum-b9d4bfaea3209fdcebdba148cb99242c44371c4a.tar.bz2
libhashsum-b9d4bfaea3209fdcebdba148cb99242c44371c4a.tar.xz
Add tests for Keccak and fix squeeze support in finalise_const for Keccak
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile1
-rw-r--r--keccak.c244
-rw-r--r--libhashsum_init_keccak__.c14
3 files changed, 258 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 7c01521..6a4b01c 100644
--- a/Makefile
+++ b/Makefile
@@ -102,6 +102,7 @@ TEST =\
keccak_256.t\
keccak_384.t\
keccak_512.t\
+ keccak.t\
sha3_224.t\
sha3_256.t\
sha3_384.t\
diff --git a/keccak.c b/keccak.c
new file mode 100644
index 0000000..9b20bbc
--- /dev/null
+++ b/keccak.c
@@ -0,0 +1,244 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef SUPPORT_KECCAK
+# include "common.h"
+
+int
+main(void)
+{
+ struct libhashsum_hasher hasher;
+ if (!libhashsum_init_keccak_hasher(&hasher, 0, 0, 0, 0)) {
+ fprintf(stderr, "expected libhashsum_init_keccak_hasher to fail, but it returned successfully\n");
+ return 2;
+ }
+ if (errno != ENOSYS) {
+ perror("expected libhashsum_init_keccak_hasher to set errno to ENOSYS, but got");
+ return 2;
+ }
+ return 0;
+}
+
+#else
+# include "common.h"
+
+
+# define ASSERT(ASSERTION)\
+ do {\
+ if ((ASSERTION))\
+ break;\
+ fprintf(stderr, "assertion `%s` at line %i failed\n", #ASSERTION, __LINE__);\
+ exit(2);\
+ } while (0)
+
+
+static const char *
+hex(const struct libhashsum_hasher *hasher)
+{
+ static char buffer[4096];
+ char *restrict out = buffer;
+ unsigned char *restrict in = hasher->hash_output;
+ size_t n = hasher->hash_size;
+ for (; n--; in++) {
+ *out++ = "0123456789abcdef"[(*in >> 4) & 15];
+ *out++ = "0123456789abcdef"[(*in >> 0) & 15];
+ }
+ *out = '\0';
+ return buffer;
+}
+
+
+int
+main(void)
+{
+ char buffer[4096];
+ struct libhashsum_hasher h1, h2;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if ((i&3) == 3)
+ continue;
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, (i&1)?0: 1600 - 2 * 224, (i&2)?0: 2 * 224, 224, 1));
+ ASSERT(!libhashsum_init_keccak_224_hasher(&h2));
+ ASSERT(!h1.finalise_const(&h1, (i&4) ? "testdata" : 0, (i&4) ? 8 : 0, 0));
+ ASSERT(!h2.finalise_const(&h2, (i&4) ? "testdata" : 0, (i&4) ? 8 : 0, 0));
+ ASSERT(h1.hash_size == h2.hash_size);
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h2.hash_size));
+ ASSERT(h1.algorithm == h2.algorithm);
+ ASSERT(!strcmp(h1.algorithm_string, h2.algorithm_string));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, (i&1)?0: 1600 - 2 * 256, (i&2)?0: 2 * 256, 256, 1));
+ ASSERT(!libhashsum_init_keccak_256_hasher(&h2));
+ ASSERT(!h1.finalise_const(&h1, (i&4) ? "testdata" : 0, (i&4) ? 8 : 0, 0));
+ ASSERT(!h2.finalise_const(&h2, (i&4) ? "testdata" : 0, (i&4) ? 8 : 0, 0));
+ ASSERT(h1.hash_size == h2.hash_size);
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h2.hash_size));
+ ASSERT(h1.algorithm == h2.algorithm);
+ ASSERT(!strcmp(h1.algorithm_string, h2.algorithm_string));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, (i&1)?0: 1600 - 2 * 384, (i&2)?0: 2 * 384, 384, 1));
+ ASSERT(!libhashsum_init_keccak_384_hasher(&h2));
+ ASSERT(!h1.finalise_const(&h1, (i&4) ? "testdata" : 0, (i&4) ? 8 : 0, 0));
+ ASSERT(!h2.finalise_const(&h2, (i&4) ? "testdata" : 0, (i&4) ? 8 : 0, 0));
+ ASSERT(h1.hash_size == h2.hash_size);
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h2.hash_size));
+ ASSERT(h1.algorithm == h2.algorithm);
+ ASSERT(!strcmp(h1.algorithm_string, h2.algorithm_string));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, (i&1)?0: 1600 - 2 * 512, (i&2)?0: 2 * 512, 512, 1));
+ ASSERT(!libhashsum_init_keccak_512_hasher(&h2));
+ ASSERT(!h1.finalise_const(&h1, (i&4) ? "testdata" : 0, (i&4) ? 8 : 0, 0));
+ ASSERT(!h2.finalise_const(&h2, (i&4) ? "testdata" : 0, (i&4) ? 8 : 0, 0));
+ ASSERT(h1.hash_size == h2.hash_size);
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h2.hash_size));
+ ASSERT(h1.algorithm == h2.algorithm);
+ ASSERT(!strcmp(h1.algorithm_string, h2.algorithm_string));
+ }
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 224, 1));
+ ASSERT(!libhashsum_init_keccak_224_hasher(&h2));
+ ASSERT(!h1.finalise_const(&h1, NULL, 0, 0));
+ ASSERT(!h2.finalise_const(&h2, NULL, 0, 0));
+ ASSERT(h1.hash_size == h2.hash_size);
+ ASSERT(memcmp(h1.hash_output, h2.hash_output, h2.hash_size));
+ ASSERT(h1.algorithm == LIBHASHSUM_KECCAK);
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=224]"));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 256, 1));
+ ASSERT(!libhashsum_init_keccak_256_hasher(&h2));
+ ASSERT(!h1.finalise_const(&h1, NULL, 0, 0));
+ ASSERT(!h2.finalise_const(&h2, NULL, 0, 0));
+ ASSERT(h1.hash_size == h2.hash_size);
+ ASSERT(memcmp(h1.hash_output, h2.hash_output, h2.hash_size));
+ ASSERT(h1.algorithm == LIBHASHSUM_KECCAK);
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=256]"));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 512, 0));
+ ASSERT(!h1.finalise_const(&h1, NULL, 0, 0));
+ ASSERT(h1.hash_size == 512U / 8U);
+ ASSERT(h1.algorithm == LIBHASHSUM_KECCAK);
+ ASSERT(strcmp(h1.algorithm_string, h2.algorithm_string));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(h1.hash_size == 512U / 8U);
+ ASSERT(h1.algorithm == LIBHASHSUM_KECCAK);
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 224, 1));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 512, 1));
+ ASSERT(!h1.finalise(&h1, buffer, 0, 0, sizeof(buffer)));
+ ASSERT(!h2.finalise(&h2, buffer, 0, 0, sizeof(buffer)));
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+
+#define Z1\
+ "6753e3380c09e385d0339eb6b050a68f66cfd60a73476e6fd6adeb72f5edd7c6"\
+ "f04a5d017a19cbe291935855b4860f69df04c98aa78b407a9ba9826f7266ef14"
+#define Z2\
+ "c3a2fa33f0bfb1cfef8da7875c4967f332c7fc93c050e81fb404f9a91503d601"\
+ "0ee16f50b4ed0bc563ba8431668b003d7e2e6f226cb7fa93bb2e132c861fdc21"
+#define Z200\
+ "f8354bead24cc78c835813c0eec02dcad2b8caf37d79566ea6dc2836f231070d"\
+ "cd786213580093a296578518ecc705c461264359e46c51b7c6beef3e3fb21a05"
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 0, 1));
+ ASSERT(!h1.finalise(&h1, buffer, 0, 0, sizeof(buffer)));
+ ASSERT(!h2.finalise(&h2, buffer, 0, 0, sizeof(buffer)));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!strcmp(h2.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+ ASSERT(!strcmp(hex(&h2), Z1));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 0, 200));
+ ASSERT(!h1.finalise(&h1, buffer, 0, 0, sizeof(buffer)));
+ ASSERT(!h2.finalise(&h2, buffer, 0, 0, sizeof(buffer)));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!strcmp(h2.algorithm_string, "Keccak[r=1024,c=576,n=512,z=200]"));
+ ASSERT(memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+ ASSERT(!strcmp(hex(&h2), Z200));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 0, 2));
+ ASSERT(!h1.finalise(&h1, buffer, 0, 0, sizeof(buffer)));
+ ASSERT(!h2.finalise(&h2, buffer, 0, 0, sizeof(buffer)));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!strcmp(h2.algorithm_string, "Keccak[r=1024,c=576,n=512,z=2]"));
+ ASSERT(memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+ ASSERT(!strcmp(hex(&h2), Z2));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 224, 1));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 512, 1));
+ ASSERT(!h1.finalise(&h1, buffer, 0, 0, 0));
+ ASSERT(!h2.finalise(&h2, buffer, 0, 0, 0));
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 0, 1));
+ ASSERT(!h1.finalise(&h1, buffer, 0, 0, 0));
+ ASSERT(!h2.finalise(&h2, buffer, 0, 0, 0));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!strcmp(h2.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+ ASSERT(!strcmp(hex(&h2), Z1));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 0, 200));
+ ASSERT(!h1.finalise(&h1, buffer, 0, 0, 0));
+ ASSERT(!h2.finalise(&h2, buffer, 0, 0, 0));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!strcmp(h2.algorithm_string, "Keccak[r=1024,c=576,n=512,z=200]"));
+ ASSERT(memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+ ASSERT(!strcmp(hex(&h2), Z200));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 0, 2));
+ ASSERT(!h1.finalise(&h1, buffer, 0, 0, 0));
+ ASSERT(!h2.finalise(&h2, buffer, 0, 0, 0));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!strcmp(h2.algorithm_string, "Keccak[r=1024,c=576,n=512,z=2]"));
+ ASSERT(memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+ ASSERT(!strcmp(hex(&h2), Z2));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 224, 1));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 512, 1));
+ ASSERT(!h1.finalise_const(&h1, NULL, 0, 0));
+ ASSERT(!h2.finalise_const(&h2, NULL, 0, 0));
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 0, 1));
+ ASSERT(!h1.finalise_const(&h1, NULL, 0, 0));
+ ASSERT(!h2.finalise_const(&h2, NULL, 0, 0));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!strcmp(h2.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+ ASSERT(!strcmp(hex(&h2), Z1));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 0, 200));
+ ASSERT(!h1.finalise_const(&h1, NULL, 0, 0));
+ ASSERT(!h2.finalise_const(&h2, NULL, 0, 0));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!strcmp(h2.algorithm_string, "Keccak[r=1024,c=576,n=512,z=200]"));
+ ASSERT(memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+ ASSERT(!strcmp(hex(&h2), Z200));
+
+ ASSERT(!libhashsum_init_keccak_hasher(&h1, 0, 0, 0, 0));
+ ASSERT(!libhashsum_init_keccak_hasher(&h2, 0, 0, 0, 2));
+ ASSERT(!h1.finalise_const(&h1, NULL, 0, 0));
+ ASSERT(!h2.finalise_const(&h2, NULL, 0, 0));
+ ASSERT(!strcmp(h1.algorithm_string, "Keccak[r=1024,c=576,n=512]"));
+ ASSERT(!strcmp(h2.algorithm_string, "Keccak[r=1024,c=576,n=512,z=2]"));
+ ASSERT(memcmp(h1.hash_output, h2.hash_output, h1.hash_size));
+ ASSERT(!strcmp(hex(&h2), Z2));
+
+#undef Z1
+#undef Z2
+#undef Z200
+
+ return 0;
+}
+
+
+#endif
diff --git a/libhashsum_init_keccak__.c b/libhashsum_init_keccak__.c
index ee146bc..9a9fa06 100644
--- a/libhashsum_init_keccak__.c
+++ b/libhashsum_init_keccak__.c
@@ -55,7 +55,19 @@ finalise_const(struct libhashsum_hasher *this, const void *data, size_t bytes, u
else
this->hash_output = this->state.keccak.sum.buf;
}
- libkeccak_digest(&this->state.keccak.s, m, bytes, extra_bits, this->state.keccak.suffix, this->hash_output);
+ libkeccak_digest(&this->state.keccak.s, m, bytes, extra_bits, this->state.keccak.suffix,
+ this->state.keccak.squeezes > 1U ? NULL : this->hash_output);
+ if (this->state.keccak.squeezes > 2U) {
+ size_t squeezes = this->state.keccak.squeezes - 2U;
+ while (squeezes > (size_t)LONG_MAX) {
+ libkeccak_fast_squeeze(&this->state.keccak.s, LONG_MAX);
+ squeezes -= (size_t)LONG_MAX;
+ }
+ libkeccak_fast_squeeze(&this->state.keccak.s, (long int)squeezes);
+ }
+ if (this->state.keccak.squeezes > 1U)
+ libkeccak_squeeze(&this->state.keccak.s, this->hash_output);
+
libkeccak_state_wipe_message(&this->state.keccak.s);
this->stretch = &stretch;
return 0;