diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libkeccak/spec.h | 21 |
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; } |