diff options
Diffstat (limited to '')
-rw-r--r-- | libhashsum_init_keccak__.c | 148 |
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 |