From 9a0a1b696a47041985ce4d3969ba5d1261105ff0 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Wed, 28 Aug 2024 16:41:28 +0200 Subject: m + add support for z parameter for keccak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- common.h | 4 ++-- libhashsum.h | 11 +++++++---- libhashsum_init_hasher_from_string.c | 20 +++++++++++--------- libhashsum_init_keccak__.c | 25 +++++++++++++++++++------ libhashsum_init_keccak_hasher.c | 20 +++++++++++++++----- libhashsum_init_rawshake_hasher.c | 2 +- libhashsum_init_sha3_hasher.c | 2 +- libhashsum_init_shake_hasher.c | 2 +- 8 files changed, 57 insertions(+), 29 deletions(-) diff --git a/common.h b/common.h index 7ff0f9c..642f6bc 100644 --- a/common.h +++ b/common.h @@ -44,10 +44,10 @@ __attribute__((__const__)) uint8_t libhashsum_reverse_byte__(uint8_t); #ifdef LIBHASHSUM_INCLUDE_LIBKECCAK_STATE -int libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void *spec, const char *suffix); +int libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void *spec, size_t squeezes, const char *suffix); #endif -#define KECCAKN(N) 1600 - 2 * (N), 2 * (N), (N) +#define KECCAKN(N) 1600 - 2 * (N), 2 * (N), (N), 1 #ifdef TEST diff --git a/libhashsum.h b/libhashsum.h index 29a8f6f..65c3a66 100644 --- a/libhashsum.h +++ b/libhashsum.h @@ -37,8 +37,8 @@ */ enum libhashsum_algorithm { /* since 1.0 */ - LIBHASHSUM_MD2, /**< MD2 */ - LIBHASHSUM_MD4, /**< MD4 */ + LIBHASHSUM_MD2, /**< MD2; this algorithm has been theoretically compromised */ + LIBHASHSUM_MD4, /**< MD4; this algorithm has been compromised */ LIBHASHSUM_MD5, /**< MD5; this algorithm has been compromised */ LIBHASHSUM_RIPEMD_128, /**< RIPEMD-128 */ LIBHASHSUM_RIPEMD_160, /**< RIPEMD-160 */ @@ -422,8 +422,9 @@ union libhashsum_state { uint8_t *dyn; } sum; const char *suffix; + size_t squeezes; char algostr[256]; - } keccak; /* size = [1020, 1065] */ + } keccak; /* size = [1024, 1072] */ #endif #ifdef LIBHASHSUM_INCLUDE_LIBBLAKE_STATE @@ -974,6 +975,7 @@ int libhashsum_init_keccak_512_hasher(struct libhashsum_hasher *this); * @param ratebits Bitrate (in bits), 0 for automatic * @param capbits Capacity in bits, 0 for automatic * @param hashbits Hash output size in bits, 0 for automatic + * @param squeezes The number of squeezes to performed, 0 for automatic (which is 1) * @return 0 on success, -1 on failure * * @throws EINVAL (`ratebits`, `capbits`, `hashbits`) is invalid @@ -983,7 +985,8 @@ int libhashsum_init_keccak_512_hasher(struct libhashsum_hasher *this); * @since 1.0 */ LIBHASHSUM_1_NONNULL_ -int libhashsum_init_keccak_hasher(struct libhashsum_hasher *this, size_t ratebits, size_t capbits, size_t hashbits); +int libhashsum_init_keccak_hasher(struct libhashsum_hasher *this, size_t ratebits, + size_t capbits, size_t hashbits, size_t squeezes); /** * Create an initialised state for SHA3-224 diff --git a/libhashsum_init_hasher_from_string.c b/libhashsum_init_hasher_from_string.c index 55fe882..0eaa12e 100644 --- a/libhashsum_init_hasher_from_string.c +++ b/libhashsum_init_hasher_from_string.c @@ -41,7 +41,6 @@ parse_value(size_t *valp, const char *p, const char **end_out) size_t digit; if (*valp) return -1; - p++; if (*p++ != '=' || !('1' <= *p && *p <= '9')) return -1; while (isdigit(*p)) { @@ -56,25 +55,28 @@ parse_value(size_t *valp, const char *p, const char **end_out) static int -with_rcn(int (*initfunc)(struct libhashsum_hasher *, size_t, size_t, size_t), +with_rcnz(int (*initfunc)(struct libhashsum_hasher *, size_t, size_t, size_t, size_t), struct libhashsum_hasher *this, const char *algorithm) { const char *p; - size_t r = 0, c = 0, n = 0; + size_t r = 0, c = 0, n = 0, z = 0; p = strchr(algorithm, '['); if (!p || *++p == ']') - return initfunc(this, 0, 0, 0); + return initfunc(this, 0, 0, 0, 0); for (;;) { if (*p == 'r' || *p == 'R') { - if (parse_value(&r, p, &p)) + if (parse_value(&r, &p[1], &p)) goto einval; } else if (*p == 'c' || *p == 'C') { - if (parse_value(&c, p, &p)) + if (parse_value(&c, &p[1], &p)) goto einval; } else if (*p == 'n' || *p == 'N') { - if (parse_value(&n, p, &p)) + if (parse_value(&n, &p[1], &p)) + goto einval; + } else if (*p == 'z' || *p == 'Z') { + if (parse_value(&z, &p[1], &p)) goto einval; } else if (*p == ']') { break; @@ -89,7 +91,7 @@ with_rcn(int (*initfunc)(struct libhashsum_hasher *, size_t, size_t, size_t), if (p[1]) goto einval; - return initfunc(this, r, c, n); + return initfunc(this, r, c, n, z); einval: errno = EINVAL; @@ -190,7 +192,7 @@ libhashsum_init_hasher_from_string(struct libhashsum_hasher *this, const char *a case LIBHASHSUM_RAWSHAKE128: return with_n(&libhashsum_init_rawshake128_hasher, this, algorithm); case LIBHASHSUM_RAWSHAKE256: return with_n(&libhashsum_init_rawshake256_hasher, this, algorithm); case LIBHASHSUM_RAWSHAKE512: return with_n(&libhashsum_init_rawshake512_hasher, this, algorithm); - case LIBHASHSUM_KECCAK: return with_rcn(&libhashsum_init_keccak_hasher, this, algorithm); + case LIBHASHSUM_KECCAK: return with_rcnz(&libhashsum_init_keccak_hasher, this, algorithm); case LIBHASHSUM_BLAKE224: return with_salt(&libhashsum_init_blake224_hasher, this, algorithm, 16U); case LIBHASHSUM_BLAKE256: return with_salt(&libhashsum_init_blake256_hasher, this, algorithm, 16U); case LIBHASHSUM_BLAKE384: return with_salt(&libhashsum_init_blake384_hasher, this, algorithm, 32U); diff --git a/libhashsum_init_keccak__.c b/libhashsum_init_keccak__.c index b0023a5..03dd466 100644 --- a/libhashsum_init_keccak__.c +++ b/libhashsum_init_keccak__.c @@ -73,11 +73,22 @@ finalise(struct libhashsum_hasher *this, void *data, size_t bytes, unsigned extr 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); + libkeccak_digest(&this->state.keccak.s, m, bytes, extra_bits, this->state.keccak.suffix, + this->state.keccak.squeezes > 1U ? NULL : this->hash_output); else - libkeccak_zerocopy_digest(&this->state.keccak.s, m, bytes, extra_bits, - this->state.keccak.suffix, this->hash_output); + libkeccak_zerocopy_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); libkeccak_state_fast_destroy(&this->state.keccak.s); memset(&this->state.keccak.s, 0, sizeof(this->state.keccak.s)); @@ -102,7 +113,7 @@ destroy(struct libhashsum_hasher *this) int -libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void *spec_, const char *suffix) +libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void *spec_, size_t squeezes, const char *suffix) { struct libkeccak_spec *spec = spec_; @@ -110,6 +121,7 @@ libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void * this->hash_size += (size_t)!!(hashbits & 7U); this->hash_output = NULL; this->supports_non_whole_bytes = 1; + this->state.keccak.squeezes = squeezes; this->state.keccak.suffix = suffix; if (this->hash_size > sizeof(this->state.keccak.sum.buf)) { @@ -137,10 +149,11 @@ libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void * #else int -libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void *spec, const char *suffix); +libhashsum_init_keccak__(struct libhashsum_hasher *this, size_t hashbits, void *spec, size_t squeezes, const char *suffix); { (void) this; (void) spec; + (void) squeezes; (void) suffix; errno = ENOSYS; return -1; diff --git a/libhashsum_init_keccak_hasher.c b/libhashsum_init_keccak_hasher.c index 93622f6..45e8627 100644 --- a/libhashsum_init_keccak_hasher.c +++ b/libhashsum_init_keccak_hasher.c @@ -4,11 +4,14 @@ int -libhashsum_init_keccak_hasher(struct libhashsum_hasher *this, size_t ratebits, size_t capbits, size_t hashbits) +libhashsum_init_keccak_hasher(struct libhashsum_hasher *this, size_t ratebits, size_t capbits, size_t hashbits, size_t squeezes) { struct libkeccak_generalised_spec gspec; struct libkeccak_spec spec; + if (!squeezes) + squeezes = 1U; + if ((ratebits | capbits | hashbits) > (size_t)LONG_MAX) { errno = EINVAL; return -1; @@ -38,7 +41,7 @@ libhashsum_init_keccak_hasher(struct libhashsum_hasher *this, size_t ratebits, s } this->algorithm = LIBHASHSUM_KECCAK; - if ((capbits >> 1) == hashbits && !(capbits & 1U) && + if ((capbits >> 1) == hashbits && !(capbits & 1U) && squeezes == 1U && 1600U >= capbits && ratebits == 1600U - capbits) { if (hashbits == 224U) { this->algorithm = LIBHASHSUM_KECCAK_224; @@ -55,19 +58,26 @@ libhashsum_init_keccak_hasher(struct libhashsum_hasher *this, size_t ratebits, s } } if (this->algorithm == LIBHASHSUM_KECCAK) { - sprintf(this->state.keccak.algostr, "Keccak[r=%zu,c=%zu,n=%zu]", ratebits, capbits, hashbits); + if (squeezes > 1U) { + sprintf(this->state.keccak.algostr, "Keccak[r=%zu,c=%zu,n=%zu,z=%zu]", + ratebits, capbits, hashbits, squeezes); + } else { + sprintf(this->state.keccak.algostr, "Keccak[r=%zu,c=%zu,n=%zu]", ratebits, capbits, hashbits); + } this->algorithm_string = this->state.keccak.algostr; } - return libhashsum_init_keccak__(this, hashbits, &spec, ""); + return libhashsum_init_keccak__(this, hashbits, &spec, squeezes, ""); } #else int -libhashsum_init_keccak_hasher(struct libhashsum_hasher *this, size_t hashbits) +libhashsum_init_keccak_hasher(struct libhashsum_hasher *this, size_t ratebits, size_t capbits, size_t hashbits, size_t squeezes) { (void) this; + (void) ratebits; + (void) capbits; (void) hashbits; errno = ENOSYS; return -1; diff --git a/libhashsum_init_rawshake_hasher.c b/libhashsum_init_rawshake_hasher.c index f90e3b7..f6cba3b 100644 --- a/libhashsum_init_rawshake_hasher.c +++ b/libhashsum_init_rawshake_hasher.c @@ -35,7 +35,7 @@ libhashsum_init_rawshake_hasher(struct libhashsum_hasher *this, size_t hcapbits, } libkeccak_spec_rawshake(&spec, (long int)hcapbits, (long int)hashbits); - return libhashsum_init_keccak__(this, hashbits, &spec, LIBKECCAK_RAWSHAKE_SUFFIX); + return libhashsum_init_keccak__(this, hashbits, &spec, 1U, LIBKECCAK_RAWSHAKE_SUFFIX); } diff --git a/libhashsum_init_sha3_hasher.c b/libhashsum_init_sha3_hasher.c index c9d6ac7..fc03114 100644 --- a/libhashsum_init_sha3_hasher.c +++ b/libhashsum_init_sha3_hasher.c @@ -26,7 +26,7 @@ libhashsum_init_sha3_hasher(struct libhashsum_hasher *this, size_t hashbits) } libkeccak_spec_sha3(&spec, (long int)hashbits); - return libhashsum_init_keccak__(this, hashbits, &spec, LIBKECCAK_SHA3_SUFFIX); + return libhashsum_init_keccak__(this, hashbits, &spec, 1U, LIBKECCAK_SHA3_SUFFIX); } diff --git a/libhashsum_init_shake_hasher.c b/libhashsum_init_shake_hasher.c index a5f5746..460e4c0 100644 --- a/libhashsum_init_shake_hasher.c +++ b/libhashsum_init_shake_hasher.c @@ -35,7 +35,7 @@ libhashsum_init_shake_hasher(struct libhashsum_hasher *this, size_t hcapbits, si } libkeccak_spec_shake(&spec, (long int)hcapbits, (long int)hashbits); - return libhashsum_init_keccak__(this, hashbits, &spec, LIBKECCAK_SHAKE_SUFFIX); + return libhashsum_init_keccak__(this, hashbits, &spec, 1U, LIBKECCAK_SHAKE_SUFFIX); } -- cgit v1.2.3-70-g09d2