aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libkeccak/spec.h21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/libkeccak/spec.h b/src/libkeccak/spec.h
index c72c04d..bc5f6c3 100644
--- a/src/libkeccak/spec.h
+++ b/src/libkeccak/spec.h
@@ -20,6 +20,9 @@
#define LIBKECCAK_SPEC_H 1
+#include <limits.h>
+
+
/**
* Message suffix for SHA3 hashing
*/
@@ -62,7 +65,7 @@
#define LIBKECCAK_SPEC_ERROR_OUTPUT_NONPOSITIVE 5
/**
- * Invalid `libkeccak_spec_t` values: `.bitrate + `.capacity`
+ * Invalid `libkeccak_spec_t` values: `.bitrate + `.capacity`
* is greater 1600 which is the largest supported state size
*/
#define LIBKECCAK_SPEC_ERROR_STATE_TOO_LARGE 6
@@ -73,6 +76,12 @@
*/
#define LIBKECCAK_SPEC_ERROR_STATE_MOD_25 7
+/**
+ * Invalid `libkeccak_spec_t` values: `.bitrate + `.capacity`
+ * is a not a 2-potent multiple of 25
+ */
+#define LIBKECCAK_SPEC_ERROR_WORD_NON_2_POTENT 8
+
/**
@@ -150,7 +159,7 @@ void libkeccak_spec_rawshake(libkeccak_spec_t* restrict spec, long x, long d)
static inline __attribute__((nonnull, nothrow, unused, warn_unused_result, pure))
int libkeccak_spec_check(const libkeccak_spec_t* restrict spec)
{
- long state_size = spec->capacity + spec->bitrate;
+ long state_size = spec->capacity + spec->bitrate, n_state_size;
if (spec->bitrate <= 0) return LIBKECCAK_SPEC_ERROR_BITRATE_NONPOSITIVE;
if (spec->bitrate % 8) return LIBKECCAK_SPEC_ERROR_BITRATE_MOD_8;
if (spec->capacity <= 0) return LIBKECCAK_SPEC_ERROR_CAPACITY_NONPOSITIVE;
@@ -158,6 +167,14 @@ int libkeccak_spec_check(const libkeccak_spec_t* restrict spec)
if (spec->output <= 0) return LIBKECCAK_SPEC_ERROR_OUTPUT_NONPOSITIVE;
if (state_size > 1600) return LIBKECCAK_SPEC_ERROR_STATE_TOO_LARGE;
if (state_size % 25) return LIBKECCAK_SPEC_ERROR_STATE_MOD_25;
+ state_size /= 25;
+
+ /* This is a portable implementation of `(x & -x) != x` which assumes
+ * two's complement, which of course is always satisfied by GCC, but anyway... */
+ n_state_size = ((~state_size) ^ (LONG_MIN & ~LONG_MAX)) + 1;
+ if ((state_size & n_state_size) != state_size)
+ return LIBKECCAK_SPEC_ERROR_WORD_NON_2_POTENT;
+
return 0;
}