aboutsummaryrefslogtreecommitdiffstats
path: root/libhashsum_init_keccak__.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-08-24 18:02:00 +0200
committerMattias Andrée <maandree@kth.se>2024-08-24 18:02:00 +0200
commit72111e7a53eaad7bea841ab8b09e70642bde00ae (patch)
tree016e0326b794f8a5b9cc03139b8a5ab094ed7411 /libhashsum_init_keccak__.c
parentMake it possible for libhashsum_state to grow in future versions (diff)
downloadlibhashsum-72111e7a53eaad7bea841ab8b09e70642bde00ae.tar.gz
libhashsum-72111e7a53eaad7bea841ab8b09e70642bde00ae.tar.bz2
libhashsum-72111e7a53eaad7bea841ab8b09e70642bde00ae.tar.xz
Add support for Keccak, SHA3, SHAKE, and RawSHAKE via libkeccak>=1.3 (this version introduced zerocopy)
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'libhashsum_init_keccak__.c')
-rw-r--r--libhashsum_init_keccak__.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/libhashsum_init_keccak__.c b/libhashsum_init_keccak__.c
new file mode 100644
index 0000000..b0023a5
--- /dev/null
+++ b/libhashsum_init_keccak__.c
@@ -0,0 +1,148 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifdef LIBHASHSUM_INCLUDE_LIBKECCAK_STATE
+
+
+LIBHASHSUM_1_NONNULL_
+static size_t
+process(struct libhashsum_hasher *this, const void *data, size_t bytes)
+{
+ bytes -= bytes % this->input_block_size;
+ libkeccak_zerocopy_update(&this->state.keccak.s, data, bytes);
+ return bytes;
+}
+
+
+LIBHASHSUM_1_NONNULL_
+static int
+finalise_const(struct libhashsum_hasher *this, const void *data, size_t bytes, unsigned extra_bits)
+{
+ const uint8_t *m = data;
+ size_t r;
+
+ if (extra_bits > 7U) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ r = process(this, m, bytes);
+ m = &m[r];
+ bytes -= r;
+
+ if (this->hash_size > sizeof(this->state.keccak.sum.buf))
+ this->hash_output = this->state.keccak.sum.dyn;
+ 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_state_wipe_message(&this->state.keccak.s);
+ libkeccak_state_fast_destroy(&this->state.keccak.s);
+ memset(&this->state.keccak.s, 0, sizeof(this->state.keccak.s));
+ this->state.keccak.s.M = NULL;
+ return 0;
+}
+
+
+LIBHASHSUM_1_NONNULL_
+static int
+finalise(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extra_bits, size_t size)
+{
+ uint8_t *m = data;
+ size_t r;
+ size_t need;
+
+ if (extra_bits > 7U) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ r = process(this, m, bytes);
+ m = &m[r];
+ bytes -= r;
+ size -= r;
+
+ need = strlen(this->state.keccak.suffix) + 2U + extra_bits;
+ need = (need + 7U) >> 3;
+ need += bytes;
+ if (need & (this->input_block_size - 1U)) {
+ need &= ~(this->input_block_size - 1U);
+ need += this->input_block_size;
+ }
+
+ if (this->hash_size > sizeof(this->state.keccak.sum.buf))
+ this->hash_output = this->state.keccak.sum.dyn;
+ else
+ this->hash_output = this->state.keccak.sum.buf;
+ if (size < need)
+ libkeccak_digest(&this->state.keccak.s, m, bytes, extra_bits,
+ this->state.keccak.suffix, this->hash_output);
+ else
+ libkeccak_zerocopy_digest(&this->state.keccak.s, m, bytes, extra_bits,
+ this->state.keccak.suffix, this->hash_output);
+ libkeccak_state_wipe_message(&this->state.keccak.s);
+ libkeccak_state_fast_destroy(&this->state.keccak.s);
+ memset(&this->state.keccak.s, 0, sizeof(this->state.keccak.s));
+ this->state.keccak.s.M = NULL;
+ return 0;
+}
+
+
+LIBHASHSUM_1_NONNULL_
+static void
+destroy(struct libhashsum_hasher *this)
+{
+ libkeccak_state_wipe_message(&this->state.keccak.s);
+ libkeccak_state_fast_destroy(&this->state.keccak.s);
+ memset(&this->state.keccak.s, 0, sizeof(this->state.keccak.s));
+ this->state.keccak.s.M = NULL;
+ if (this->hash_size > sizeof(this->state.keccak.sum.buf)) {
+ free(this->state.keccak.sum.dyn);
+ this->state.keccak.sum.dyn = NULL;
+ }
+}
+
+
+int
+libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void *spec_, const char *suffix)
+{
+ struct libkeccak_spec *spec = spec_;
+
+ this->hash_size = hashbits >> 3;
+ this->hash_size += (size_t)!!(hashbits & 7U);
+ this->hash_output = NULL;
+ this->supports_non_whole_bytes = 1;
+ this->state.keccak.suffix = suffix;
+
+ if (this->hash_size > sizeof(this->state.keccak.sum.buf)) {
+ this->state.keccak.sum.dyn = malloc(this->hash_size);
+ if (!this->state.keccak.sum.dyn)
+ return -1;
+ }
+
+ if (libkeccak_state_initialise(&this->state.keccak.s, spec)) {
+ if (this->hash_size > sizeof(this->state.keccak.sum.buf)) {
+ free(this->state.keccak.sum.dyn);
+ this->state.keccak.sum.dyn = NULL;
+ }
+ return -1;
+ }
+
+ this->input_block_size = libkeccak_zerocopy_chunksize(&this->state.keccak.s);
+ this->process = &process;
+ this->finalise_const = &finalise_const;
+ this->finalise = &finalise;
+ this->destroy = &destroy;
+ return 0;
+}
+
+
+#else
+int
+libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void *spec, const char *suffix);
+{
+ (void) this;
+ (void) spec;
+ (void) suffix;
+ errno = ENOSYS;
+ return -1;
+}
+#endif