aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common.h4
-rw-r--r--libhashsum.h11
-rw-r--r--libhashsum_init_hasher_from_string.c20
-rw-r--r--libhashsum_init_keccak__.c25
-rw-r--r--libhashsum_init_keccak_hasher.c20
-rw-r--r--libhashsum_init_rawshake_hasher.c2
-rw-r--r--libhashsum_init_sha3_hasher.c2
-rw-r--r--libhashsum_init_shake_hasher.c2
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);
}