From d4ce8327ff902b5ecd42d057063c03793e6d91c2 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sun, 15 Sep 2024 02:15:08 +0200 Subject: Organise files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- Makefile | 89 ++++++------- common.h | 38 ++++++ digest.c | 51 +++----- extra/libkeccak_state_copy.c | 25 ++++ extra/libkeccak_state_create.c | 20 +++ extra/libkeccak_state_duplicate.c | 20 +++ extra/libkeccak_state_fast_free.c | 5 + extra/libkeccak_state_free.c | 5 + extra/libkeccak_state_marshal.c | 55 ++++++++ extra/libkeccak_state_reset.c | 5 + extra/libkeccak_state_unmarshal.c | 66 ++++++++++ extra/libkeccak_state_wipe.c | 15 +++ extra/libkeccak_state_wipe_message.c | 18 +++ extra/libkeccak_state_wipe_sponge.c | 18 +++ hmac/libkeccak_hmac_copy.c | 38 ++++++ hmac/libkeccak_hmac_create.c | 5 + hmac/libkeccak_hmac_destroy.c | 5 + hmac/libkeccak_hmac_digest.c | 81 ++++++++++++ hmac/libkeccak_hmac_duplicate.c | 5 + hmac/libkeccak_hmac_fast_destroy.c | 5 + hmac/libkeccak_hmac_fast_digest.c | 78 +++++++++++ hmac/libkeccak_hmac_fast_free.c | 5 + hmac/libkeccak_hmac_fast_update.c | 52 ++++++++ hmac/libkeccak_hmac_free.c | 5 + hmac/libkeccak_hmac_initialise.c | 6 + hmac/libkeccak_hmac_marshal.c | 5 + hmac/libkeccak_hmac_reset.c | 5 + hmac/libkeccak_hmac_set_key.c | 47 +++++++ hmac/libkeccak_hmac_unmarshal.c | 59 +++++++++ hmac/libkeccak_hmac_update.c | 53 ++++++++ hmac/libkeccak_hmac_wipe.c | 24 ++++ libkeccak.h | 188 ++++++--------------------- libkeccak/extra.h | 140 ++++++++++++++++++++ libkeccak_behex_lower.c | 22 ---- libkeccak_behex_upper.c | 22 ---- libkeccak_cshake_suffix.c | 5 - libkeccak_degeneralise_spec.c | 120 ----------------- libkeccak_generalised_spec_initialise.c | 5 - libkeccak_generalised_sum_fd.c | 112 ---------------- libkeccak_hmac_copy.c | 38 ------ libkeccak_hmac_create.c | 5 - libkeccak_hmac_destroy.c | 5 - libkeccak_hmac_digest.c | 81 ------------ libkeccak_hmac_duplicate.c | 5 - libkeccak_hmac_fast_destroy.c | 5 - libkeccak_hmac_fast_digest.c | 78 ----------- libkeccak_hmac_fast_free.c | 5 - libkeccak_hmac_fast_update.c | 52 -------- libkeccak_hmac_free.c | 5 - libkeccak_hmac_initialise.c | 6 - libkeccak_hmac_marshal.c | 5 - libkeccak_hmac_reset.c | 5 - libkeccak_hmac_set_key.c | 47 ------- libkeccak_hmac_unmarshal.c | 59 --------- libkeccak_hmac_update.c | 53 -------- libkeccak_hmac_wipe.c | 24 ---- libkeccak_keccaksum_fd.c | 5 - libkeccak_rawshakesum_fd.c | 5 - libkeccak_sha3sum_fd.c | 5 - libkeccak_shakesum_fd.c | 5 - libkeccak_spec_check.c | 5 - libkeccak_spec_rawshake.c | 5 - libkeccak_spec_sha3.c | 5 - libkeccak_state_copy.c | 25 ---- libkeccak_state_create.c | 20 --- libkeccak_state_duplicate.c | 20 --- libkeccak_state_fast_free.c | 5 - libkeccak_state_free.c | 5 - libkeccak_state_marshal.c | 55 -------- libkeccak_state_reset.c | 5 - libkeccak_state_unmarshal.c | 66 ---------- libkeccak_state_wipe.c | 15 --- libkeccak_state_wipe_message.c | 18 --- libkeccak_state_wipe_sponge.c | 18 --- libkeccak_unhex.c | 30 ----- spec/libkeccak_cshake_suffix.c | 5 + spec/libkeccak_degeneralise_spec.c | 120 +++++++++++++++++ spec/libkeccak_generalised_spec_initialise.c | 5 + spec/libkeccak_spec_check.c | 5 + spec/libkeccak_spec_rawshake.c | 5 + spec/libkeccak_spec_sha3.c | 5 + util/libkeccak_behex_lower.c | 22 ++++ util/libkeccak_behex_upper.c | 22 ++++ util/libkeccak_generalised_sum_fd.c | 112 ++++++++++++++++ util/libkeccak_keccaksum_fd.c | 5 + util/libkeccak_rawshakesum_fd.c | 5 + util/libkeccak_sha3sum_fd.c | 5 + util/libkeccak_shakesum_fd.c | 5 + util/libkeccak_unhex.c | 30 +++++ 89 files changed, 1357 insertions(+), 1311 deletions(-) create mode 100644 extra/libkeccak_state_copy.c create mode 100644 extra/libkeccak_state_create.c create mode 100644 extra/libkeccak_state_duplicate.c create mode 100644 extra/libkeccak_state_fast_free.c create mode 100644 extra/libkeccak_state_free.c create mode 100644 extra/libkeccak_state_marshal.c create mode 100644 extra/libkeccak_state_reset.c create mode 100644 extra/libkeccak_state_unmarshal.c create mode 100644 extra/libkeccak_state_wipe.c create mode 100644 extra/libkeccak_state_wipe_message.c create mode 100644 extra/libkeccak_state_wipe_sponge.c create mode 100644 hmac/libkeccak_hmac_copy.c create mode 100644 hmac/libkeccak_hmac_create.c create mode 100644 hmac/libkeccak_hmac_destroy.c create mode 100644 hmac/libkeccak_hmac_digest.c create mode 100644 hmac/libkeccak_hmac_duplicate.c create mode 100644 hmac/libkeccak_hmac_fast_destroy.c create mode 100644 hmac/libkeccak_hmac_fast_digest.c create mode 100644 hmac/libkeccak_hmac_fast_free.c create mode 100644 hmac/libkeccak_hmac_fast_update.c create mode 100644 hmac/libkeccak_hmac_free.c create mode 100644 hmac/libkeccak_hmac_initialise.c create mode 100644 hmac/libkeccak_hmac_marshal.c create mode 100644 hmac/libkeccak_hmac_reset.c create mode 100644 hmac/libkeccak_hmac_set_key.c create mode 100644 hmac/libkeccak_hmac_unmarshal.c create mode 100644 hmac/libkeccak_hmac_update.c create mode 100644 hmac/libkeccak_hmac_wipe.c create mode 100644 libkeccak/extra.h delete mode 100644 libkeccak_behex_lower.c delete mode 100644 libkeccak_behex_upper.c delete mode 100644 libkeccak_cshake_suffix.c delete mode 100644 libkeccak_degeneralise_spec.c delete mode 100644 libkeccak_generalised_spec_initialise.c delete mode 100644 libkeccak_generalised_sum_fd.c delete mode 100644 libkeccak_hmac_copy.c delete mode 100644 libkeccak_hmac_create.c delete mode 100644 libkeccak_hmac_destroy.c delete mode 100644 libkeccak_hmac_digest.c delete mode 100644 libkeccak_hmac_duplicate.c delete mode 100644 libkeccak_hmac_fast_destroy.c delete mode 100644 libkeccak_hmac_fast_digest.c delete mode 100644 libkeccak_hmac_fast_free.c delete mode 100644 libkeccak_hmac_fast_update.c delete mode 100644 libkeccak_hmac_free.c delete mode 100644 libkeccak_hmac_initialise.c delete mode 100644 libkeccak_hmac_marshal.c delete mode 100644 libkeccak_hmac_reset.c delete mode 100644 libkeccak_hmac_set_key.c delete mode 100644 libkeccak_hmac_unmarshal.c delete mode 100644 libkeccak_hmac_update.c delete mode 100644 libkeccak_hmac_wipe.c delete mode 100644 libkeccak_keccaksum_fd.c delete mode 100644 libkeccak_rawshakesum_fd.c delete mode 100644 libkeccak_sha3sum_fd.c delete mode 100644 libkeccak_shakesum_fd.c delete mode 100644 libkeccak_spec_check.c delete mode 100644 libkeccak_spec_rawshake.c delete mode 100644 libkeccak_spec_sha3.c delete mode 100644 libkeccak_state_copy.c delete mode 100644 libkeccak_state_create.c delete mode 100644 libkeccak_state_duplicate.c delete mode 100644 libkeccak_state_fast_free.c delete mode 100644 libkeccak_state_free.c delete mode 100644 libkeccak_state_marshal.c delete mode 100644 libkeccak_state_reset.c delete mode 100644 libkeccak_state_unmarshal.c delete mode 100644 libkeccak_state_wipe.c delete mode 100644 libkeccak_state_wipe_message.c delete mode 100644 libkeccak_state_wipe_sponge.c delete mode 100644 libkeccak_unhex.c create mode 100644 spec/libkeccak_cshake_suffix.c create mode 100644 spec/libkeccak_degeneralise_spec.c create mode 100644 spec/libkeccak_generalised_spec_initialise.c create mode 100644 spec/libkeccak_spec_check.c create mode 100644 spec/libkeccak_spec_rawshake.c create mode 100644 spec/libkeccak_spec_sha3.c create mode 100644 util/libkeccak_behex_lower.c create mode 100644 util/libkeccak_behex_upper.c create mode 100644 util/libkeccak_generalised_sum_fd.c create mode 100644 util/libkeccak_keccaksum_fd.c create mode 100644 util/libkeccak_rawshakesum_fd.c create mode 100644 util/libkeccak_sha3sum_fd.c create mode 100644 util/libkeccak_shakesum_fd.c create mode 100644 util/libkeccak_unhex.c diff --git a/Makefile b/Makefile index 6db74cf..1897ce4 100644 --- a/Makefile +++ b/Makefile @@ -19,53 +19,53 @@ LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR) OBJ =\ digest.o\ - libkeccak_behex_lower.o\ - libkeccak_behex_upper.o\ libkeccak_cshake_initialise.o\ - libkeccak_cshake_suffix.o\ - libkeccak_degeneralise_spec.o\ - libkeccak_generalised_spec_initialise.o\ - libkeccak_generalised_sum_fd.o\ - libkeccak_hmac_copy.o\ - libkeccak_hmac_create.o\ - libkeccak_hmac_destroy.o\ - libkeccak_hmac_digest.o\ - libkeccak_hmac_duplicate.o\ - libkeccak_hmac_fast_destroy.o\ - libkeccak_hmac_fast_digest.o\ - libkeccak_hmac_fast_free.o\ - libkeccak_hmac_fast_update.o\ - libkeccak_hmac_free.o\ - libkeccak_hmac_initialise.o\ - libkeccak_hmac_marshal.o\ - libkeccak_hmac_reset.o\ - libkeccak_hmac_set_key.o\ - libkeccak_hmac_unmarshal.o\ - libkeccak_hmac_update.o\ - libkeccak_hmac_wipe.o\ - libkeccak_keccaksum_fd.o\ - libkeccak_rawshakesum_fd.o\ - libkeccak_sha3sum_fd.o\ - libkeccak_shakesum_fd.o\ - libkeccak_spec_check.o\ - libkeccak_spec_rawshake.o\ - libkeccak_spec_sha3.o\ - libkeccak_state_copy.o\ - libkeccak_state_create.o\ libkeccak_state_destroy.o\ - libkeccak_state_duplicate.o\ libkeccak_state_fast_destroy.o\ - libkeccak_state_fast_free.o\ - libkeccak_state_free.o\ libkeccak_state_initialise.o\ - libkeccak_state_marshal.o\ - libkeccak_state_reset.o\ - libkeccak_state_unmarshal.o\ - libkeccak_state_wipe.o\ - libkeccak_state_wipe_message.o\ - libkeccak_state_wipe_sponge.o\ - libkeccak_unhex.o\ - libkeccak_zerocopy_chunksize.o + libkeccak_zerocopy_chunksize.o\ + extra/libkeccak_state_copy.o\ + extra/libkeccak_state_create.o\ + extra/libkeccak_state_duplicate.o\ + extra/libkeccak_state_fast_free.o\ + extra/libkeccak_state_free.o\ + extra/libkeccak_state_marshal.o\ + extra/libkeccak_state_reset.o\ + extra/libkeccak_state_unmarshal.o\ + extra/libkeccak_state_wipe.o\ + extra/libkeccak_state_wipe_message.o\ + extra/libkeccak_state_wipe_sponge.o\ + hmac/libkeccak_hmac_copy.o\ + hmac/libkeccak_hmac_create.o\ + hmac/libkeccak_hmac_destroy.o\ + hmac/libkeccak_hmac_digest.o\ + hmac/libkeccak_hmac_duplicate.o\ + hmac/libkeccak_hmac_fast_destroy.o\ + hmac/libkeccak_hmac_fast_digest.o\ + hmac/libkeccak_hmac_fast_free.o\ + hmac/libkeccak_hmac_fast_update.o\ + hmac/libkeccak_hmac_free.o\ + hmac/libkeccak_hmac_initialise.o\ + hmac/libkeccak_hmac_marshal.o\ + hmac/libkeccak_hmac_reset.o\ + hmac/libkeccak_hmac_set_key.o\ + hmac/libkeccak_hmac_unmarshal.o\ + hmac/libkeccak_hmac_update.o\ + hmac/libkeccak_hmac_wipe.o\ + spec/libkeccak_cshake_suffix.o\ + spec/libkeccak_degeneralise_spec.o\ + spec/libkeccak_generalised_spec_initialise.o\ + spec/libkeccak_spec_check.o\ + spec/libkeccak_spec_rawshake.o\ + spec/libkeccak_spec_sha3.o\ + util/libkeccak_behex_lower.o\ + util/libkeccak_behex_upper.o\ + util/libkeccak_generalised_sum_fd.o\ + util/libkeccak_keccaksum_fd.o\ + util/libkeccak_rawshakesum_fd.o\ + util/libkeccak_sha3sum_fd.o\ + util/libkeccak_shakesum_fd.o\ + util/libkeccak_unhex.o HDR =\ libkeccak.h\ @@ -78,6 +78,7 @@ SUBHDR =\ libkeccak/rawshake.h\ libkeccak/shake.h\ libkeccak/cshake.h\ + libkeccak/extra.h\ libkeccak/hmac.h\ libkeccak/legacy.h\ libkeccak/util.h @@ -214,7 +215,7 @@ uninstall: -rm -rf -- "$(DESTDIR)$(PREFIX)/share/licenses/libkeccak" clean: - -rm -f -- *.o *.su test benchmark benchfile + -rm -f -- *.o *.su */*.o */*.su test benchmark benchfile -rm -f -- *.a libkeccak.$(LIBEXT) libkeccak.$(LIBEXT).* libkeccak.*.$(LIBEXT) .SUFFIXES: diff --git a/common.h b/common.h index 4b95a06..96df9e7 100644 --- a/common.h +++ b/common.h @@ -32,6 +32,44 @@ #endif +/** + * Literal comma that can be passed as a macro argument + */ +#define COMMA , + +/** + * X-macro-enabled listing of all intergers in [0, 4] + * + * @param X(int) The macro to expand 5 times + * @param D Code to insert between each expansion of `X` + */ +#define LIST_5(X, D)\ + X(0) D X(1) D X(2) D X(3) D X(4) + +/** + * X-macro-enabled listing of all intergers in [0, 7] + * + * @param X(int) The macro to expand 8 times + * @param D Code to insert between each expansion of `X` + */ +#define LIST_8(X, D)\ + X(0) D X(1) D X(2) D X(3) D X(4) D\ + X(5) D X(6) D X(7) + +/** + * X-macro-enabled listing of all intergers in [0, 24] + * + * @param X(int) The macro to expand 25 times + * @param D Code to insert between each expansion of `X` + */ +#define LIST_25(X, D)\ + X( 0) D X( 1) D X( 2) D X( 3) D X( 4) D\ + X( 5) D X( 6) D X( 7) D X( 8) D X( 9) D\ + X(10) D X(11) D X(12) D X(13) D X(14) D\ + X(15) D X(16) D X(17) D X(18) D X(19) D\ + X(20) D X(21) D X(22) D X(23) D X(24) + + /** * The outer pad pattern for HMAC */ diff --git a/digest.c b/digest.c index 6a81f80..7ee744a 100644 --- a/digest.c +++ b/digest.c @@ -2,34 +2,15 @@ #include "common.h" -/** - * X-macro-enabled listing of all intergers in [0, 4] - */ -#define LIST_5 X(0) X(1) X(2) X(3) X(4) - -/** - * X-macro-enabled listing of all intergers in [0, 7] - */ -#define LIST_8 LIST_5 X(5) X(6) X(7) - -/** - * X-macro-enabled listing of all intergers in [0, 24] - */ -#define LIST_25 LIST_8 X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15)\ - X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) X(24) - - - -#define X(N) (N % 5) * 5 + N / 5, +#define X(N) (N % 5) * 5 + N / 5 /** * The order the lanes should be read when absorbing or squeezing, * it transposes the lanes in the sponge */ -static const long int LANE_TRANSPOSE_MAP[] = { LIST_25 }; +static const long int LANE_TRANSPOSE_MAP[] = { LIST_25(X, COMMA) }; #undef X - /** * Keccak-f round constants */ @@ -83,8 +64,8 @@ libkeccak_f_round(register struct libkeccak_state *state, register int_fast64_t long int w = state->w; /* θ step (step 1 of 3). */ -#define X(N) C[N] = A[N * 5] ^ A[N * 5 + 1] ^ A[N * 5 + 2] ^ A[N * 5 + 3] ^ A[N * 5 + 4]; - LIST_5 +#define X(N) C[N] = A[N * 5] ^ A[N * 5 + 1] ^ A[N * 5 + 2] ^ A[N * 5 + 3] ^ A[N * 5 + 4] + LIST_5(X, ;); #undef X /* θ step (step 2 of 3). */ @@ -104,8 +85,8 @@ libkeccak_f_round(register struct libkeccak_state *state, register int_fast64_t #undef X /* ξ step. */ -#define X(N) A[N] = B[N] ^ ((~(B[(N + 5) % 25])) & B[(N + 10) % 25]); - LIST_25 +#define X(N) A[N] = B[N] ^ ((~(B[(N + 5) % 25])) & B[(N + 10) % 25]) + LIST_25(X, ;); #undef X /* ι step. */ @@ -129,8 +110,8 @@ libkeccak_f_round64(register struct libkeccak_state *state, register int_fast64_ int_fast64_t da, db, dc, dd, de; /* θ step (step 1 of 3). */ -#define X(N) C[N] = A[N * 5] ^ A[N * 5 + 1] ^ A[N * 5 + 2] ^ A[N * 5 + 3] ^ A[N * 5 + 4]; - LIST_5 +#define X(N) C[N] = A[N * 5] ^ A[N * 5 + 1] ^ A[N * 5 + 2] ^ A[N * 5 + 3] ^ A[N * 5 + 4] + LIST_5(X, ;); #undef X /* θ step (step 2 of 3). */ @@ -150,8 +131,8 @@ libkeccak_f_round64(register struct libkeccak_state *state, register int_fast64_ #undef X /* ξ step. */ -#define X(N) A[N] = B[N] ^ ((~(B[(N + 5) % 25])) & B[(N + 10) % 25]); - LIST_25 +#define X(N) A[N] = B[N] ^ ((~(B[(N + 5) % 25])) & B[(N + 10) % 25]) + LIST_25(X, ;); #undef X /* ι step. */ @@ -224,8 +205,8 @@ libkeccak_to_lane64(register const unsigned char *message, register size_t msgle int_fast64_t rc = 0; message += off; #define X(N) if (__builtin_expect(N < n, 1)) rc |= (int_fast64_t)(unsigned char)(message[N]) << (N * 8);\ - else return rc; - LIST_8 + else return rc + LIST_8(X, ;); #undef X return rc; } @@ -284,8 +265,8 @@ libkeccak_absorption_phase(register struct libkeccak_state *restrict state, register long int n = (long)len / rr; if (__builtin_expect(ww >= 8, 1)) { /* ww > 8 is impossible, it is just for optimisation possibilities. */ while (n--) { -#define X(N) state->S[N] ^= libkeccak_to_lane64(message, len, rr, (size_t)(LANE_TRANSPOSE_MAP[N] * 8)); - LIST_25 +#define X(N) state->S[N] ^= libkeccak_to_lane64(message, len, rr, (size_t)(LANE_TRANSPOSE_MAP[N] * 8)) + LIST_25(X, ;); #undef X libkeccak_f(state); message += (size_t)rr; @@ -293,8 +274,8 @@ libkeccak_absorption_phase(register struct libkeccak_state *restrict state, } } else { while (n--) { -#define X(N) state->S[N] ^= libkeccak_to_lane(message, len, rr, ww, (size_t)(LANE_TRANSPOSE_MAP[N] * ww)); - LIST_25 +#define X(N) state->S[N] ^= libkeccak_to_lane(message, len, rr, ww, (size_t)(LANE_TRANSPOSE_MAP[N] * ww)) + LIST_25(X, ;); #undef X libkeccak_f(state); message += (size_t)rr; diff --git a/extra/libkeccak_state_copy.c b/extra/libkeccak_state_copy.c new file mode 100644 index 0000000..950fc91 --- /dev/null +++ b/extra/libkeccak_state_copy.c @@ -0,0 +1,25 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Make a copy of a state + * + * @param dest The slot for the duplicate, must not be initialised (memory leak otherwise) + * @param src The state to duplicate + * @return Zero on success, -1 on error + */ +int +libkeccak_state_copy(struct libkeccak_state *restrict dest, const struct libkeccak_state *restrict src) +{ + *dest = *src; + if (src->mlen) { + dest->M = malloc(src->mlen * sizeof(char)); + if (!dest->M) + return -1; + memcpy(dest->M, src->M, src->mptr * sizeof(char)); + } else { + dest->M = NULL; + } + return 0; +} diff --git a/extra/libkeccak_state_create.c b/extra/libkeccak_state_create.c new file mode 100644 index 0000000..eda9011 --- /dev/null +++ b/extra/libkeccak_state_create.c @@ -0,0 +1,20 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Wrapper for `libkeccak_state_initialise` that also allocates the states + * + * @param spec The specifications for the state + * @return The state, `NULL` on error + */ +struct libkeccak_state * +libkeccak_state_create(const struct libkeccak_spec *spec) +{ + struct libkeccak_state *state = malloc(sizeof(struct libkeccak_state)); + if (!state || libkeccak_state_initialise(state, spec)) { + free(state); + return NULL; + } + return state; +} diff --git a/extra/libkeccak_state_duplicate.c b/extra/libkeccak_state_duplicate.c new file mode 100644 index 0000000..3d90d02 --- /dev/null +++ b/extra/libkeccak_state_duplicate.c @@ -0,0 +1,20 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * A wrapper for `libkeccak_state_copy` that also allocates the duplicate + * + * @param src The state to duplicate + * @return The duplicate, `NULL` on error + */ +struct libkeccak_state * +libkeccak_state_duplicate(const struct libkeccak_state *src) +{ + struct libkeccak_state *dest = malloc(sizeof(struct libkeccak_state)); + if (!dest || libkeccak_state_copy(dest, src)) { + libkeccak_state_free(dest); + return NULL; + } + return dest; +} diff --git a/extra/libkeccak_state_fast_free.c b/extra/libkeccak_state_fast_free.c new file mode 100644 index 0000000..af75e39 --- /dev/null +++ b/extra/libkeccak_state_fast_free.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_state_fast_free(struct libkeccak_state *); diff --git a/extra/libkeccak_state_free.c b/extra/libkeccak_state_free.c new file mode 100644 index 0000000..6a879b3 --- /dev/null +++ b/extra/libkeccak_state_free.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_state_free(volatile struct libkeccak_state *); diff --git a/extra/libkeccak_state_marshal.c b/extra/libkeccak_state_marshal.c new file mode 100644 index 0000000..7541164 --- /dev/null +++ b/extra/libkeccak_state_marshal.c @@ -0,0 +1,55 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wcast-align" +#endif + + +/** + * Marshal a `struct libkeccak_state` into a buffer + * + * @param state The state to marshal + * @param data_ The output buffer, can be `NULL` + * @return The number of bytes stored to `data` + */ +size_t +libkeccak_state_marshal(const struct libkeccak_state *restrict state, void *restrict data_) +{ +#define set(VAR)\ + do {\ + __builtin_memcpy(data, &state->VAR, sizeof(state->VAR));\ + data += sizeof(state->VAR);\ + } while (0) + + unsigned char *restrict start = data_; + unsigned char *restrict data = start; + + if (!data) { + return 7 * sizeof(long int) + + 1 * sizeof(int64_t) + + sizeof(state->S) + + 2 * sizeof(size_t) + + state->mptr; + } + + set(r); + set(c); + set(n); + set(b); + set(w); + set(wmod); + set(l); + set(nr); + __builtin_memcpy(data, state->S, sizeof(state->S)); + data += sizeof(state->S); + set(mptr); + set(mlen); + memcpy(data, state->M, state->mptr * sizeof(char)); + data += state->mptr; + + return (size_t)(data - start); + +#undef set +} diff --git a/extra/libkeccak_state_reset.c b/extra/libkeccak_state_reset.c new file mode 100644 index 0000000..44eb5a4 --- /dev/null +++ b/extra/libkeccak_state_reset.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_state_reset(struct libkeccak_state *); diff --git a/extra/libkeccak_state_unmarshal.c b/extra/libkeccak_state_unmarshal.c new file mode 100644 index 0000000..4714566 --- /dev/null +++ b/extra/libkeccak_state_unmarshal.c @@ -0,0 +1,66 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wcast-align" +#endif + + +/** + * Unmarshal a `struct libkeccak_state` from a buffer + * + * @param state The slot for the unmarshalled state, must not be + * initialised (memory leak otherwise), can be `NULL` + * @param data_ The input buffer + * @return The number of bytes read from `data`, 0 on error + */ +size_t +libkeccak_state_unmarshal(struct libkeccak_state *restrict state, const void *restrict data_) +{ +#define get(VAR) \ + do {\ + __builtin_memcpy(&state->VAR, data, sizeof(state->VAR));\ + data += sizeof(state->VAR);\ + } while (0) + + const unsigned char *restrict start = data_; + const unsigned char *restrict data = start; + size_t mptr; + + if (!state) { + data += 7U * sizeof(long int); + data += 1U * sizeof(int64_t); + data += sizeof(state->S); + mptr = *(const size_t *)data; + data += 2U * sizeof(size_t); + data += mptr; + return (size_t)(data - start); + } + + get(r); + get(c); + get(n); + get(b); + get(w); + get(wmod); + get(l); + get(nr); + memcpy(state->S, data, sizeof(state->S)); + data += sizeof(state->S); + get(mptr); + get(mlen); + if (state->mptr) { + state->M = malloc(state->mptr * sizeof(char)); + if (!state->M) + return 0; + memcpy(state->M, data, state->mptr * sizeof(char)); + data += state->mptr; + } else { + state->M = NULL; + } + + return (size_t)(data - start); + +#undef get +} diff --git a/extra/libkeccak_state_wipe.c b/extra/libkeccak_state_wipe.c new file mode 100644 index 0000000..728f72f --- /dev/null +++ b/extra/libkeccak_state_wipe.c @@ -0,0 +1,15 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Wipe sensitive data without freeing any data + * + * @param state The state that should be wipe + */ +void +libkeccak_state_wipe(volatile struct libkeccak_state *state) +{ + libkeccak_state_wipe_message(state); + libkeccak_state_wipe_sponge(state); +} diff --git a/extra/libkeccak_state_wipe_message.c b/extra/libkeccak_state_wipe_message.c new file mode 100644 index 0000000..364eb8e --- /dev/null +++ b/extra/libkeccak_state_wipe_message.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Wipe data in the state's message without freeing any data + * + * @param state The state that should be wipe + */ +void +libkeccak_state_wipe_message(volatile struct libkeccak_state *state) +{ + volatile unsigned char *restrict M = state->M; + size_t i; + + for (i = 0; i < state->mptr; i++) + M[i] = 0; +} diff --git a/extra/libkeccak_state_wipe_sponge.c b/extra/libkeccak_state_wipe_sponge.c new file mode 100644 index 0000000..91e845a --- /dev/null +++ b/extra/libkeccak_state_wipe_sponge.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Wipe data in the state's sponge without freeing any data + * + * @param state The state that should be wipe + */ +void +libkeccak_state_wipe_sponge(volatile struct libkeccak_state *state) +{ + volatile int64_t *restrict S = state->S; + size_t i; + + for (i = 0; i < 25; i++) + S[i] = 0; +} diff --git a/hmac/libkeccak_hmac_copy.c b/hmac/libkeccak_hmac_copy.c new file mode 100644 index 0000000..8a4077b --- /dev/null +++ b/hmac/libkeccak_hmac_copy.c @@ -0,0 +1,38 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Make a copy of an HMAC hashing-state + * + * @param dest The slot for the duplicate, must not be initialised (memory leak otherwise) + * @param src The state to duplicate + * @return Zero on success, -1 on error + */ +int +libkeccak_hmac_copy(struct libkeccak_hmac_state *restrict dest, const struct libkeccak_hmac_state *restrict src) +{ + size_t size; + + dest->key_opad = NULL; + dest->key_ipad = NULL; + + if (libkeccak_state_copy(&dest->sponge, &src->sponge) < 0) + return -1; + + dest->key_length = src->key_length; + dest->leftover = src->leftover; + + size = (src->key_length + 7) >> 3; + dest->key_opad = malloc(2 * size); + if (!dest->key_opad) { + libkeccak_state_destroy(&dest->sponge); + return -1; + } + dest->key_ipad = dest->key_opad + size; + + memcpy(dest->key_opad, src->key_opad, size); + memcpy(dest->key_ipad, src->key_ipad, size); + + return 0; +} diff --git a/hmac/libkeccak_hmac_create.c b/hmac/libkeccak_hmac_create.c new file mode 100644 index 0000000..ef6f025 --- /dev/null +++ b/hmac/libkeccak_hmac_create.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline struct libkeccak_hmac_state *libkeccak_hmac_create(const struct libkeccak_spec *restrict, const void *restrict, size_t); diff --git a/hmac/libkeccak_hmac_destroy.c b/hmac/libkeccak_hmac_destroy.c new file mode 100644 index 0000000..f2d7419 --- /dev/null +++ b/hmac/libkeccak_hmac_destroy.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_hmac_destroy(volatile struct libkeccak_hmac_state *); diff --git a/hmac/libkeccak_hmac_digest.c b/hmac/libkeccak_hmac_digest.c new file mode 100644 index 0000000..a9e3609 --- /dev/null +++ b/hmac/libkeccak_hmac_digest.c @@ -0,0 +1,81 @@ +/* See LICENSE file for copyright and license details. */ +#define NEED_EXPLICIT_BZERO 1 +#include "../common.h" + + +/** + * Absorb the last part of the message and fetch the hash + * and wipe sensitive data when possible + * + * You may use `&state->sponge` for continued squeezing + * + * @param state The hashing state + * @param msg_ The rest of the message, may be `NULL`, may be modified + * @param msglen The length of the partial message + * @param bits The number of bits at the end of the message not covered by `msglen` + * @param suffix The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination + * @param hashsum Output parameter for the hashsum, may be `NULL` + * @return Zero on success, -1 on error + */ +int +libkeccak_hmac_digest(struct libkeccak_hmac_state *restrict state, const void *restrict msg_, size_t msglen, + size_t bits, const char *restrict suffix, void *restrict hashsum) +{ + const unsigned char *restrict msg = msg_; + size_t hashsize = (size_t)(state->sponge.n >> 3); + char *tmp = malloc((size_t)((state->sponge.n + 7) >> 3) * sizeof(char)); + unsigned char leftover[2]; + size_t newlen; + + if (!tmp) + return -1; + + if (!(state->key_length & 7)) { + if (libkeccak_digest(&state->sponge, msg, msglen, bits, suffix, tmp) < 0) + goto fail; + goto stage_2; + } + + if (libkeccak_hmac_update(state, msg, msglen) < 0) + goto fail; + leftover[0] = state->leftover; + if (bits) { + leftover[0] |= (unsigned char)(msg[msglen] >> (state->key_length & 7)); + leftover[1] = (unsigned char)(msg[msglen] << (8 - (state->key_length & 7))); + } + newlen = (state->key_length & 7) + bits; + if (libkeccak_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) + goto fail; + +stage_2: + bits = state->sponge.n & 7; + state->key_ipad = state->key_opad; + if (libkeccak_hmac_update(state, NULL, 0) < 0) + goto fail; + + if (!(state->key_length & 7)) { + if (libkeccak_digest(&state->sponge, tmp, hashsize, bits, suffix, hashsum) < 0) + goto fail; + goto stage_3; + } + + if (libkeccak_hmac_update(state, tmp, hashsize) < 0) + goto fail; + leftover[0] = state->leftover; + if (bits) { + leftover[0] |= (unsigned char)(tmp[hashsize] >> (state->key_length & 7)); + leftover[1] = (unsigned char)(tmp[hashsize] << (8 - (state->key_length & 7))); + } + newlen = (state->key_length & 7) + bits; + if (libkeccak_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) + goto fail; + +stage_3: + my_explicit_bzero(tmp, (size_t)((state->sponge.n + 7) >> 3) * sizeof(char)); + free(tmp); + return 0; +fail: + my_explicit_bzero(tmp, (size_t)((state->sponge.n + 7) >> 3) * sizeof(char)); + free(tmp); + return -1; +} diff --git a/hmac/libkeccak_hmac_duplicate.c b/hmac/libkeccak_hmac_duplicate.c new file mode 100644 index 0000000..959eae9 --- /dev/null +++ b/hmac/libkeccak_hmac_duplicate.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline struct libkeccak_hmac_state *libkeccak_hmac_duplicate(const struct libkeccak_hmac_state *); diff --git a/hmac/libkeccak_hmac_fast_destroy.c b/hmac/libkeccak_hmac_fast_destroy.c new file mode 100644 index 0000000..7d9feab --- /dev/null +++ b/hmac/libkeccak_hmac_fast_destroy.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_hmac_fast_destroy(struct libkeccak_hmac_state *); diff --git a/hmac/libkeccak_hmac_fast_digest.c b/hmac/libkeccak_hmac_fast_digest.c new file mode 100644 index 0000000..dc98136 --- /dev/null +++ b/hmac/libkeccak_hmac_fast_digest.c @@ -0,0 +1,78 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Absorb the last part of the message and fetch the hash + * without wiping sensitive data when possible + * + * You may use `&state->sponge` for continued squeezing + * + * @param state The hashing state + * @param msg_ The rest of the message, may be `NULL`, may be modified + * @param msglen The length of the partial message + * @param bits The number of bits at the end of the message not covered by `msglen` + * @param suffix The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination + * @param hashsum Output parameter for the hashsum, may be `NULL` + * @return Zero on success, -1 on error + */ +int +libkeccak_hmac_fast_digest(struct libkeccak_hmac_state *restrict state, const void *restrict msg_, size_t msglen, + size_t bits, const char *restrict suffix, void *restrict hashsum) +{ + const unsigned char *restrict msg = msg_; + size_t hashsize = (size_t)state->sponge.n >> 3; + unsigned char *tmp = malloc((size_t)((state->sponge.n + 7) >> 3) * sizeof(char)); + unsigned char leftover[2]; + size_t newlen; + + if (!tmp) + return -1; + + if (!(state->key_length & 7)) { + if (libkeccak_fast_digest(&state->sponge, msg, msglen, bits, suffix, tmp) < 0) + goto fail; + goto stage_2; + } + + if (libkeccak_hmac_fast_update(state, msg, msglen) < 0) + goto fail; + leftover[0] = state->leftover; + if (bits) { + leftover[0] |= (unsigned char)(msg[msglen] >> (state->key_length & 7)); + leftover[1] = (unsigned char)(msg[msglen] << (8 - (state->key_length & 7))); + } + newlen = (state->key_length & 7) + bits; + if (libkeccak_fast_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) + goto fail; + +stage_2: + bits = state->sponge.n & 7; + state->key_ipad = state->key_opad; + if (libkeccak_hmac_fast_update(state, NULL, 0) < 0) + goto fail; + + if (!(state->key_length & 7)) { + if (libkeccak_fast_digest(&state->sponge, tmp, hashsize, bits, suffix, hashsum) < 0) + goto fail; + goto stage_3; + } + + if (libkeccak_hmac_fast_update(state, tmp, hashsize) < 0) + goto fail; + leftover[0] = state->leftover; + if (bits) { + leftover[0] |= (unsigned char)(tmp[hashsize] >> (state->key_length & 7)); + leftover[1] = (unsigned char)(tmp[hashsize] << (8 - (state->key_length & 7))); + } + newlen = (state->key_length & 7) + bits; + if (libkeccak_fast_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) + goto fail; + +stage_3: + free(tmp); + return 0; +fail: + free(tmp); + return -1; +} diff --git a/hmac/libkeccak_hmac_fast_free.c b/hmac/libkeccak_hmac_fast_free.c new file mode 100644 index 0000000..5a38207 --- /dev/null +++ b/hmac/libkeccak_hmac_fast_free.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_hmac_fast_free(struct libkeccak_hmac_state *); diff --git a/hmac/libkeccak_hmac_fast_update.c b/hmac/libkeccak_hmac_fast_update.c new file mode 100644 index 0000000..fe163b7 --- /dev/null +++ b/hmac/libkeccak_hmac_fast_update.c @@ -0,0 +1,52 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Absorb more, or the first part, of the message + * without wiping sensitive data when possible + * + * @param state The hashing state + * @param msg_ The partial message + * @param msglen The length of the partial message, in bytes + * @return Zero on success, -1 on error + */ +int +libkeccak_hmac_fast_update(struct libkeccak_hmac_state *restrict state, const void *restrict msg_, size_t msglen) +{ + const unsigned char *restrict msg = msg_; + void *new; + size_t i; + int n, cn; + + if (state->key_ipad) { + if (libkeccak_fast_update(&state->sponge, state->key_ipad, state->key_length >> 3) < 0) + return -1; + if (state->key_length & 7) + state->leftover = state->key_ipad[state->key_length >> 3]; + state->key_ipad = NULL; + } + + if (!msg || !msglen) + return 0; + + if (!(state->key_length & 7)) + return libkeccak_fast_update(&state->sponge, msg, msglen); + + if (msglen != state->buffer_size) { + new = realloc(state->buffer, msglen); + if (!new) + return -1; + state->buffer = new; + state->buffer_size = msglen; + } + + n = (int)(state->key_length & 7); + cn = 8 - n; + for (i = 1; i < msglen; i++) + state->buffer[i] = (unsigned char)((msg[i - 1] >> cn) | (msg[i] << n)); + state->buffer[0] = (unsigned char)((state->leftover & ((1 << n) - 1)) | (msg[0] << n)); + state->leftover = (unsigned char)(msg[msglen - 1] >> cn); + + return libkeccak_fast_update(&state->sponge, state->buffer, msglen); +} diff --git a/hmac/libkeccak_hmac_free.c b/hmac/libkeccak_hmac_free.c new file mode 100644 index 0000000..d31e3a8 --- /dev/null +++ b/hmac/libkeccak_hmac_free.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_hmac_free(volatile struct libkeccak_hmac_state *); diff --git a/hmac/libkeccak_hmac_initialise.c b/hmac/libkeccak_hmac_initialise.c new file mode 100644 index 0000000..ca71860 --- /dev/null +++ b/hmac/libkeccak_hmac_initialise.c @@ -0,0 +1,6 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline int +libkeccak_hmac_initialise(struct libkeccak_hmac_state *restrict, const struct libkeccak_spec *restrict, const void *restrict, size_t); diff --git a/hmac/libkeccak_hmac_marshal.c b/hmac/libkeccak_hmac_marshal.c new file mode 100644 index 0000000..acd8f63 --- /dev/null +++ b/hmac/libkeccak_hmac_marshal.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline size_t libkeccak_hmac_marshal(const struct libkeccak_hmac_state *restrict, void *restrict); diff --git a/hmac/libkeccak_hmac_reset.c b/hmac/libkeccak_hmac_reset.c new file mode 100644 index 0000000..b6eccf5 --- /dev/null +++ b/hmac/libkeccak_hmac_reset.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline int libkeccak_hmac_reset(struct libkeccak_hmac_state *restrict, const void *restrict, size_t); diff --git a/hmac/libkeccak_hmac_set_key.c b/hmac/libkeccak_hmac_set_key.c new file mode 100644 index 0000000..e329f5b --- /dev/null +++ b/hmac/libkeccak_hmac_set_key.c @@ -0,0 +1,47 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Change the HMAC-hashing key on the state + * + * @param state The state that should be reset + * @param key The new key + * @param key_length The length of key, in bits + * @return Zero on success, -1 on error + */ +int +libkeccak_hmac_set_key(struct libkeccak_hmac_state *restrict state, const void *restrict key, size_t key_length) +{ + size_t i, size, new_key_length, key_bytes; + void *new; + + size = (size_t)(state->sponge.r) > key_length ? (size_t)(state->sponge.r) : key_length; + new_key_length = size; + size = (size + 7) >> 3; + key_bytes = (key_length + 7) >> 3; + + if (size != key_bytes) { + new = realloc(state->key_opad, 2 * size); + if (!new) + return -1; + state->key_opad = new; + state->key_ipad = state->key_opad + size; + } + + memcpy(state->key_opad, key, key_bytes); + if (key_length & 7) + state->key_opad[(key_bytes >> 3) - 1] &= (unsigned char)((1 << (key_length & 7)) - 1); + + if ((size_t)(state->sponge.r) > key_length) + __builtin_memset(state->key_opad + key_bytes, 0, size - key_bytes); + + for (i = 0; i < size; i++) { + state->key_ipad[i] = state->key_opad[i] ^ HMAC_INNER_PAD; + state->key_opad[i] ^= HMAC_OUTER_PAD; + } + + state->key_length = new_key_length; + + return 0; +} diff --git a/hmac/libkeccak_hmac_unmarshal.c b/hmac/libkeccak_hmac_unmarshal.c new file mode 100644 index 0000000..ddada17 --- /dev/null +++ b/hmac/libkeccak_hmac_unmarshal.c @@ -0,0 +1,59 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wcast-align" +#endif + + +/** + * Unmarshal a `struct libkeccak_hmac_state` from a buffer + * + * @param state The slot for the unmarshalled state, must not be + * initialised (memory leak otherwise), can be `NULL` + * @param data_ The input buffer + * @return The number of bytes read from `data`, 0 on error + */ +size_t +libkeccak_hmac_unmarshal(struct libkeccak_hmac_state *restrict state, const void *restrict data_) +{ + const unsigned char *restrict data = data_; + size_t parsed, size, i; + + state->key_opad = NULL; + state->key_ipad = NULL; + + parsed = libkeccak_state_unmarshal(state ? &state->sponge : NULL, data); + if (!parsed) + return 0; + data += parsed; + + __builtin_memcpy(&size, data, sizeof(size)); + data += sizeof(size_t); + if (state) + size = state->key_length; + size = (state->key_length + 7) >> 3; + + if (state) { + state->key_opad = malloc(2 * size); + if (!state->key_opad) { + libkeccak_state_destroy(&state->sponge); + return 0; + } + memcpy(state->key_opad, data, size); + data += size; + + if (data[0]) { + state->key_ipad = &state->key_opad[size]; + memcpy(state->key_ipad, state->key_opad, size); + for (i = 0; i < size; i++) + state->key_ipad[i] ^= (char)(HMAC_OUTER_PAD ^ HMAC_INNER_PAD); + } + + state->leftover = data[1]; + state->buffer = NULL; + state->buffer_size = 0; + } + + return parsed + sizeof(size_t) + size + 2 * sizeof(char); +} diff --git a/hmac/libkeccak_hmac_update.c b/hmac/libkeccak_hmac_update.c new file mode 100644 index 0000000..1717390 --- /dev/null +++ b/hmac/libkeccak_hmac_update.c @@ -0,0 +1,53 @@ +/* See LICENSE file for copyright and license details. */ +#define NEED_EXPLICIT_BZERO 1 +#include "../common.h" + + +/** + * Absorb more, or the first part, of the message + * and wipe sensitive data when possible + * + * @param state The hashing state + * @param msg_ The partial message + * @param msglen The length of the partial message, in bytes + * @return Zero on success, -1 on error + */ +int +libkeccak_hmac_update(struct libkeccak_hmac_state *restrict state, const void *restrict msg_, size_t msglen) +{ + const unsigned char *restrict msg = msg_; + size_t i; + int n, cn, r; + + if (state->key_ipad) { + if (libkeccak_update(&state->sponge, state->key_ipad, state->key_length >> 3) < 0) + return -1; + if (state->key_length & 7) + state->leftover = state->key_ipad[state->key_length >> 3]; + state->key_ipad = NULL; + } + + if (!msg || !msglen) + return 0; + + if (!(state->key_length & 7)) + return libkeccak_update(&state->sponge, msg, msglen); + + if (msglen != state->buffer_size) { + free(state->buffer); + state->buffer = malloc(state->buffer_size = msglen); + if (!state->buffer) + return -1; + } + + n = (int)(state->key_length & 7); + cn = 8 - n; + for (i = 1; i < msglen; i++) + state->buffer[i] = (unsigned char)((msg[i - 1] >> cn) | (msg[i] << n)); + state->buffer[0] = (unsigned char)((state->leftover & ((1 << n) - 1)) | (msg[0] << n)); + state->leftover = (unsigned char)(msg[msglen - 1] >> cn); + + r = libkeccak_update(&state->sponge, state->buffer, msglen); + my_explicit_bzero(state->buffer, msglen); + return r; +} diff --git a/hmac/libkeccak_hmac_wipe.c b/hmac/libkeccak_hmac_wipe.c new file mode 100644 index 0000000..ec0be2d --- /dev/null +++ b/hmac/libkeccak_hmac_wipe.c @@ -0,0 +1,24 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Wipe sensitive data wihout freeing any data + * + * @param state The state that should be wipe + */ +void +libkeccak_hmac_wipe(volatile struct libkeccak_hmac_state *state) +{ + volatile unsigned char *restrict key_pads; + size_t i, size; + + key_pads = state->key_opad; + size = 2 * ((state->key_length + 7) >> 3); + + libkeccak_state_wipe(&state->sponge); + for (i = 0; i < size; i++) + key_pads[i] = 0; + state->leftover = 0; + __builtin_memset(state->buffer, 0, state->buffer_size); +} diff --git a/libkeccak.h b/libkeccak.h index 081e9e2..670c69e 100644 --- a/libkeccak.h +++ b/libkeccak.h @@ -16,7 +16,6 @@ #endif - /** * Only include some C code if compiling with GCC. * @@ -50,6 +49,7 @@ struct libkeccak_spec { long int output; }; + /** * Data structure that describes the state of a hashing process * @@ -117,6 +117,7 @@ struct libkeccak_state { unsigned char *M; }; + /** * Initialise a state according to hashing specifications * @@ -127,154 +128,6 @@ struct libkeccak_state { LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__))) int libkeccak_state_initialise(struct libkeccak_state *, const struct libkeccak_spec *); -/** - * Reset a state according to hashing specifications - * - * @param state The state that should be reset - */ -LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__))) -inline void -libkeccak_state_reset(struct libkeccak_state *state) -{ - state->mptr = 0; - memset(state->S, 0, sizeof(state->S)); -} - -/** - * Release resources allocation for a state without wiping sensitive data - * - * @param state The state that should be destroyed - */ -inline void -libkeccak_state_fast_destroy(struct libkeccak_state *state) -{ - if (state) { - free(state->M); - state->M = NULL; - } -} - -/** - * Wipe data in the state's message wihout freeing any data - * - * @param state The state that should be wipe - */ -LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__, __nothrow__, __optimize__("-O0")))) -void libkeccak_state_wipe_message(volatile struct libkeccak_state *); - -/** - * Wipe data in the state's sponge wihout freeing any data - * - * @param state The state that should be wipe - */ -LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__, __nothrow__, __optimize__("-O0")))) -void libkeccak_state_wipe_sponge(volatile struct libkeccak_state *); - -/** - * Wipe sensitive data wihout freeing any data - * - * @param state The state that should be wipe - */ -LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__, __optimize__("-O0")))) -void libkeccak_state_wipe(volatile struct libkeccak_state *); - -/** - * Release resources allocation for a state and wipe sensitive data - * - * @param state The state that should be destroyed - */ -LIBKECCAK_GCC_ONLY(__attribute__((__optimize__("-O0")))) -inline void -libkeccak_state_destroy(volatile struct libkeccak_state *state) -{ - if (state) { - libkeccak_state_wipe(state); - free(state->M); - state->M = NULL; - } -} - -/** - * Wrapper for `libkeccak_state_initialise` that also allocates the states - * - * @param spec The specifications for the state - * @return The state, `NULL` on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __malloc__))) -struct libkeccak_state *libkeccak_state_create(const struct libkeccak_spec *); - -/** - * Wrapper for `libkeccak_state_fast_destroy` that also frees the allocation of the state - * - * @param state The state that should be freed - */ -inline void -libkeccak_state_fast_free(struct libkeccak_state *state) -{ - libkeccak_state_fast_destroy(state); - free(state); -} - -/** - * Wrapper for `libkeccak_state_destroy` that also frees the allocation of the state - * - * @param state The state that should be freed - */ -LIBKECCAK_GCC_ONLY(__attribute__((__optimize__("-O0")))) -inline void -libkeccak_state_free(volatile struct libkeccak_state *state) -{ -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wcast-qual" -#endif - libkeccak_state_destroy(state); - free((struct libkeccak_state *)state); -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif -} - -/** - * Make a copy of a state - * - * @param dest The slot for the duplicate, must not be initialised (memory leak otherwise) - * @param src The state to duplicate - * @return Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__))) -int libkeccak_state_copy(struct libkeccak_state *restrict, const struct libkeccak_state *restrict); - -/** - * A wrapper for `libkeccak_state_copy` that also allocates the duplicate - * - * @param src The state to duplicate - * @return The duplicate, `NULL` on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __malloc__))) -struct libkeccak_state *libkeccak_state_duplicate(const struct libkeccak_state *); - -/** - * Marshal a `struct libkeccak_state` into a buffer - * - * @param state The state to marshal - * @param data The output buffer, can be `NULL` - * @return The number of bytes stored to `data` - */ -LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__(1), __nothrow__))) -size_t libkeccak_state_marshal(const struct libkeccak_state *restrict, void *restrict); - -/** - * Unmarshal a `struct libkeccak_state` from a buffer - * - * @param state The slot for the unmarshalled state, must not be - * initialised (memory leak otherwise), can be `NULL` - * @param data The input buffer - * @return The number of bytes read from `data`, 0 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__(2)))) -size_t libkeccak_state_unmarshal(struct libkeccak_state *restrict, const void *restrict); - /** * Get the number of bytes that are absorbed during * one pass of the absorption phase @@ -413,10 +266,40 @@ void libkeccak_fast_squeeze(register struct libkeccak_state *, register long int LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__))) void libkeccak_squeeze(register struct libkeccak_state *restrict, register void *restrict); +#include "libkeccak/extra.h" + +/** + * Release resources allocation for a state without wiping sensitive data + * + * @param state The state that should be destroyed + */ +inline void +libkeccak_state_fast_destroy(struct libkeccak_state *state) +{ + if (state) { + free(state->M); + state->M = NULL; + } +} + +/** + * Release resources allocation for a state and wipe sensitive data + * + * @param state The state that should be destroyed + */ +LIBKECCAK_GCC_ONLY(__attribute__((__optimize__("-O0")))) +inline void +libkeccak_state_destroy(volatile struct libkeccak_state *state) +{ + if (state) { + libkeccak_state_wipe(state); + free(state->M); + state->M = NULL; + } +} -#include "libkeccak/hmac.h" -#include "libkeccak/legacy.h" #include "libkeccak/util.h" +#include "libkeccak/hmac.h" #include "libkeccak/keccak.h" #include "libkeccak/sha3.h" @@ -424,6 +307,9 @@ void libkeccak_squeeze(register struct libkeccak_state *restrict, register void #include "libkeccak/shake.h" #include "libkeccak/cshake.h" +#include "libkeccak/legacy.h" + + #if defined(__clang__) # pragma clang diagnostic pop diff --git a/libkeccak/extra.h b/libkeccak/extra.h new file mode 100644 index 0000000..60a2601 --- /dev/null +++ b/libkeccak/extra.h @@ -0,0 +1,140 @@ +/* See LICENSE file for copyright and license details. */ + + +/** + * Reset a state according to hashing specifications + * + * @param state The state that should be reset + */ +LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__))) +inline void +libkeccak_state_reset(struct libkeccak_state *state) +{ + state->mptr = 0; + memset(state->S, 0, sizeof(state->S)); +} + + +/** + * Wipe data in the state's message without freeing any data + * + * @param state The state that should be wipe + */ +LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__, __nothrow__, __optimize__("-O0")))) +void libkeccak_state_wipe_message(volatile struct libkeccak_state *); + + +/** + * Wipe data in the state's sponge without freeing any data + * + * @param state The state that should be wipe + */ +LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__, __nothrow__, __optimize__("-O0")))) +void libkeccak_state_wipe_sponge(volatile struct libkeccak_state *); + + +/** + * Wipe sensitive data without freeing any data + * + * @param state The state that should be wipe + */ +LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__, __optimize__("-O0")))) +void libkeccak_state_wipe(volatile struct libkeccak_state *); + + +/** + * Wrapper for `libkeccak_state_initialise` that also allocates the states + * + * @param spec The specifications for the state + * @return The state, `NULL` on error + */ +LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __malloc__))) +struct libkeccak_state *libkeccak_state_create(const struct libkeccak_spec *); + + +/** + * Release resources allocation for a state, + * without wiping sensitive data, and deallocate + * the state object itself + * + * @param state The state that should be freed + */ +inline void +libkeccak_state_fast_free(struct libkeccak_state *state) +{ + if (state) { + free(state->M); + state->M = NULL; + free(state); + } +} + + +/** + * Release resources allocation for a state, and wipe + * sensitive data, and deallocate the state object itself + * + * @param state The state that should be freed + */ +LIBKECCAK_GCC_ONLY(__attribute__((__optimize__("-O0")))) +inline void +libkeccak_state_free(volatile struct libkeccak_state *state) +{ +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wcast-qual" +#endif + if (state) { + libkeccak_state_wipe(state); + free(state->M); + state->M = NULL; + free((struct libkeccak_state *)state); + } +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif +} + + +/** + * Make a copy of a state + * + * @param dest The slot for the duplicate, must not be initialised (memory leak otherwise) + * @param src The state to duplicate + * @return Zero on success, -1 on error + */ +LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__))) +int libkeccak_state_copy(struct libkeccak_state *restrict, const struct libkeccak_state *restrict); + + +/** + * A wrapper for `libkeccak_state_copy` that also allocates the duplicate + * + * @param src The state to duplicate + * @return The duplicate, `NULL` on error + */ +LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__, __malloc__))) +struct libkeccak_state *libkeccak_state_duplicate(const struct libkeccak_state *); + + +/** + * Marshal a `struct libkeccak_state` into a buffer + * + * @param state The state to marshal + * @param data The output buffer, can be `NULL` + * @return The number of bytes stored to `data` + */ +LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__(1), __nothrow__))) +size_t libkeccak_state_marshal(const struct libkeccak_state *restrict, void *restrict); + + +/** + * Unmarshal a `struct libkeccak_state` from a buffer + * + * @param state The slot for the unmarshalled state, must not be + * initialised (memory leak otherwise), can be `NULL` + * @param data The input buffer + * @return The number of bytes read from `data`, 0 on error + */ +LIBKECCAK_GCC_ONLY(__attribute__((__leaf__, __nonnull__(2)))) +size_t libkeccak_state_unmarshal(struct libkeccak_state *restrict, const void *restrict); diff --git a/libkeccak_behex_lower.c b/libkeccak_behex_lower.c deleted file mode 100644 index fe71e19..0000000 --- a/libkeccak_behex_lower.c +++ /dev/null @@ -1,22 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Convert a binary hashsum to lower case hexadecimal representation - * - * @param output Output array, should have an allocation size of at least `2 * n + 1` - * @param hashsum_ The hashsum to convert - * @param n The size of `hashsum` - */ -void -libkeccak_behex_lower(char *restrict output, const void *restrict hashsum_, size_t n) -{ - const unsigned char *restrict hashsum = hashsum_; - - output[2 * n] = '\0'; - while (n--) { - output[2 * n + 0] = "0123456789abcdef"[(hashsum[n] >> 4) & 15]; - output[2 * n + 1] = "0123456789abcdef"[(hashsum[n] >> 0) & 15]; - } -} diff --git a/libkeccak_behex_upper.c b/libkeccak_behex_upper.c deleted file mode 100644 index e3bae6a..0000000 --- a/libkeccak_behex_upper.c +++ /dev/null @@ -1,22 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Convert a binary hashsum to upper case hexadecimal representation - * - * @param output Output array, should have an allocation size of at least `2 * n + 1` - * @param hashsum_ The hashsum to convert - * @param n The size of `hashsum` - */ -void -libkeccak_behex_upper(char *restrict output, const void *restrict hashsum_, size_t n) -{ - const unsigned char *restrict hashsum = hashsum_; - - output[2 * n] = '\0'; - while (n--) { - output[2 * n + 0] = "0123456789ABCDEF"[(hashsum[n] >> 4) & 15]; - output[2 * n + 1] = "0123456789ABCDEF"[(hashsum[n] >> 0) & 15]; - } -} diff --git a/libkeccak_cshake_suffix.c b/libkeccak_cshake_suffix.c deleted file mode 100644 index f4068dd..0000000 --- a/libkeccak_cshake_suffix.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline const char *libkeccak_cshake_suffix(size_t, size_t); diff --git a/libkeccak_degeneralise_spec.c b/libkeccak_degeneralise_spec.c deleted file mode 100644 index efe5127..0000000 --- a/libkeccak_degeneralise_spec.c +++ /dev/null @@ -1,120 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wconditional-uninitialized" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif - -#define deft(v, dv) (have_##v ? v : (dv)) - - -/** - * Convert a `struct libkeccak_generalised_spec` to a `struct libkeccak_spec` - * - * If you are interrested in finding errors, you should call - * `libkeccak_spec_check(output)` if this function returns zero - * - * @param spec The generalised input specifications, will be update with resolved automatic values - * @param output_spec The specification datastructure to fill in - * @return Zero if `spec` is valid, a `LIBKECCAK_GENERALISED_SPEC_ERROR_*` if an error was found - */ -int -libkeccak_degeneralise_spec(struct libkeccak_generalised_spec *restrict spec, struct libkeccak_spec *restrict output_spec) -{ - long int state_size, word_size, capacity, bitrate, output; - int have_state_size = spec->state_size != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; - int have_word_size = spec->word_size != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; - int have_capacity = spec->capacity != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; - int have_bitrate = spec->bitrate != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; - int have_output = spec->output != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; - - - if (have_state_size) { - state_size = spec->state_size; - if (state_size <= 0) - return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_NONPOSITIVE; - if (state_size > 1600) - return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_TOO_LARGE; - if (state_size % 25) - return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_MOD_25; - } - - if (have_word_size) { - word_size = spec->word_size; - if (word_size <= 0) - return LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_NONPOSITIVE; - if (word_size > 64) - return LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_TOO_LARGE; - if (have_state_size && state_size != word_size * 25) - return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_WORD_INCOHERENCY; - else if (!have_state_size) { - have_state_size = 1; - state_size = word_size * 25; - } - } - - if (have_capacity) { - capacity = spec->capacity; - if (capacity <= 0) - return LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_NONPOSITIVE; - if (capacity & 7) - return LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_MOD_8; - } - - if (have_bitrate) { - bitrate = spec->bitrate; - if (bitrate <= 0) - return LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_NONPOSITIVE; - if (bitrate & 7) - return LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_MOD_8; - } - - if (have_output) { - output = spec->output; - if (output <= 0) - return LIBKECCAK_GENERALISED_SPEC_ERROR_OUTPUT_NONPOSITIVE; - } - - - if (have_bitrate + have_capacity == 2) { - if (!have_state_size) { - state_size = bitrate + capacity; - output = deft(output, capacity * 2L <= 8 ? 8 : capacity * 2L); - } else if (state_size != bitrate + capacity) { - return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_BITRATE_CAPACITY_INCONSISTENCY; - } - } else if (have_bitrate + have_capacity == 1) { - state_size = deft(state_size, 1600L); - capacity = deft(capacity, state_size - bitrate); - bitrate = deft(bitrate, state_size - capacity); - output = deft(output, capacity * 2L <= 8 ? 8 : capacity * 2L); - } else { - state_size = deft(state_size, 1600L); - capacity = state_size * 9 / 25; - bitrate = state_size - capacity; - output = deft(output, bitrate / 2L <= 8 ? 8 : bitrate / 2L); - } - - - spec->capacity = output_spec->capacity = capacity; - spec->bitrate = output_spec->bitrate = bitrate; - spec->output = output_spec->output = output; - spec->state_size = state_size; - spec->word_size = state_size / 25; - - return 0; -} - - -#undef deft - -#if defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif diff --git a/libkeccak_generalised_spec_initialise.c b/libkeccak_generalised_spec_initialise.c deleted file mode 100644 index 736618c..0000000 --- a/libkeccak_generalised_spec_initialise.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_generalised_spec_initialise(struct libkeccak_generalised_spec *); diff --git a/libkeccak_generalised_sum_fd.c b/libkeccak_generalised_sum_fd.c deleted file mode 100644 index 11431f0..0000000 --- a/libkeccak_generalised_sum_fd.c +++ /dev/null @@ -1,112 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" -#include - - -/** - * Calculate a Keccak-family hashsum of a file, - * the content of the file is assumed non-sensitive - * - * @param fd The file descriptor of the file to hash - * @param state The hashing state, should not be initialised unless - * `spec` is `NULL` (memory leak otherwise) - * @param spec Specifications for the hashing algorithm; or `NULL` - * if `spec` is already initialised - * @param suffix The data suffix, see `libkeccak_digest` - * @param hashsum Output array for the hashsum, have an allocation size of - * at least `((spec->output + 7) / 8) * sizeof(char)`, may be `NULL` - * @return Zero on success, -1 on error - */ -int -libkeccak_generalised_sum_fd(int fd, struct libkeccak_state *restrict state, const struct libkeccak_spec *restrict spec, - const char *restrict suffix, void *restrict hashsum) -{ - ssize_t got; - size_t offset; -#ifndef _WIN32 - struct stat attr; -#endif - size_t blksize = 4096; - unsigned char *restrict chunk; - size_t chunksize, extrasize, extrachunks; - size_t chunks, chunkmod; - - if (spec && libkeccak_state_initialise(state, spec) < 0) - return -1; - - chunksize = libkeccak_zerocopy_chunksize(state); - extrasize = ((suffix ? strlen(suffix) : 0) + 2 + 7) >> 3; - extrachunks = (extrasize + (chunksize - 1)) / chunksize; - -#ifndef _WIN32 - if (fstat(fd, &attr) == 0) - if (attr.st_blksize > 0) - blksize = (size_t)attr.st_blksize; -#endif - - chunks = blksize / chunksize; - chunkmod = blksize % chunksize; - if (chunkmod) { - blksize -= chunkmod; - blksize += chunksize; - chunks += 1; - } - if (chunks < extrachunks + 1) - blksize = (extrachunks + 1) * chunksize; - -#if ALLOCA_LIMIT > 0 - if (blksize > (size_t)ALLOCA_LIMIT) { - blksize = (size_t)ALLOCA_LIMIT; - blksize -= blksize % chunksize; - if (!blksize) - blksize = chunksize; - } -# if defined(__clang__) - /* We are using a limit so it's just like declaring an array - * in a function, except we might use less of the stack. */ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Walloca" -# endif - chunk = alloca(blksize); -# if defined(__clang__) -# pragma clang diagnostic pop -# endif -#else - chunk = malloc(blksize); - if (!chunk) - return -1; -#endif - - offset = 0; - for (;;) { - got = read(fd, &chunk[offset], blksize - offset); - if (got <= 0) { - if (!got) - break; - if (errno == EINTR) - continue; - goto fail; - } - offset += (size_t)got; - if (offset == blksize) { - libkeccak_zerocopy_update(state, chunk, blksize); - offset = 0; - } - } - - if (extrasize > blksize - offset) { - chunkmod = offset % chunksize; - libkeccak_zerocopy_update(state, chunk, offset - chunkmod); - __builtin_memcpy(chunk, &chunk[offset - chunkmod], chunkmod * sizeof(char)); - offset = chunkmod; - } - - libkeccak_zerocopy_digest(state, chunk, offset, 0, suffix, hashsum); - return 0; - -fail: -#if ALLOCA_LIMIT <= 0 - free(chunk); -#endif - return -1; -} diff --git a/libkeccak_hmac_copy.c b/libkeccak_hmac_copy.c deleted file mode 100644 index 6c61553..0000000 --- a/libkeccak_hmac_copy.c +++ /dev/null @@ -1,38 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Make a copy of an HMAC hashing-state - * - * @param dest The slot for the duplicate, must not be initialised (memory leak otherwise) - * @param src The state to duplicate - * @return Zero on success, -1 on error - */ -int -libkeccak_hmac_copy(struct libkeccak_hmac_state *restrict dest, const struct libkeccak_hmac_state *restrict src) -{ - size_t size; - - dest->key_opad = NULL; - dest->key_ipad = NULL; - - if (libkeccak_state_copy(&dest->sponge, &src->sponge) < 0) - return -1; - - dest->key_length = src->key_length; - dest->leftover = src->leftover; - - size = (src->key_length + 7) >> 3; - dest->key_opad = malloc(2 * size); - if (!dest->key_opad) { - libkeccak_state_destroy(&dest->sponge); - return -1; - } - dest->key_ipad = dest->key_opad + size; - - memcpy(dest->key_opad, src->key_opad, size); - memcpy(dest->key_ipad, src->key_ipad, size); - - return 0; -} diff --git a/libkeccak_hmac_create.c b/libkeccak_hmac_create.c deleted file mode 100644 index 15286b6..0000000 --- a/libkeccak_hmac_create.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline struct libkeccak_hmac_state *libkeccak_hmac_create(const struct libkeccak_spec *restrict, const void *restrict, size_t); diff --git a/libkeccak_hmac_destroy.c b/libkeccak_hmac_destroy.c deleted file mode 100644 index 9444c0d..0000000 --- a/libkeccak_hmac_destroy.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_hmac_destroy(volatile struct libkeccak_hmac_state *); diff --git a/libkeccak_hmac_digest.c b/libkeccak_hmac_digest.c deleted file mode 100644 index 2e1732f..0000000 --- a/libkeccak_hmac_digest.c +++ /dev/null @@ -1,81 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#define NEED_EXPLICIT_BZERO 1 -#include "common.h" - - -/** - * Absorb the last part of the message and fetch the hash - * and wipe sensitive data when possible - * - * You may use `&state->sponge` for continued squeezing - * - * @param state The hashing state - * @param msg_ The rest of the message, may be `NULL`, may be modified - * @param msglen The length of the partial message - * @param bits The number of bits at the end of the message not covered by `msglen` - * @param suffix The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param hashsum Output parameter for the hashsum, may be `NULL` - * @return Zero on success, -1 on error - */ -int -libkeccak_hmac_digest(struct libkeccak_hmac_state *restrict state, const void *restrict msg_, size_t msglen, - size_t bits, const char *restrict suffix, void *restrict hashsum) -{ - const unsigned char *restrict msg = msg_; - size_t hashsize = (size_t)(state->sponge.n >> 3); - char *tmp = malloc((size_t)((state->sponge.n + 7) >> 3) * sizeof(char)); - unsigned char leftover[2]; - size_t newlen; - - if (!tmp) - return -1; - - if (!(state->key_length & 7)) { - if (libkeccak_digest(&state->sponge, msg, msglen, bits, suffix, tmp) < 0) - goto fail; - goto stage_2; - } - - if (libkeccak_hmac_update(state, msg, msglen) < 0) - goto fail; - leftover[0] = state->leftover; - if (bits) { - leftover[0] |= (unsigned char)(msg[msglen] >> (state->key_length & 7)); - leftover[1] = (unsigned char)(msg[msglen] << (8 - (state->key_length & 7))); - } - newlen = (state->key_length & 7) + bits; - if (libkeccak_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) - goto fail; - -stage_2: - bits = state->sponge.n & 7; - state->key_ipad = state->key_opad; - if (libkeccak_hmac_update(state, NULL, 0) < 0) - goto fail; - - if (!(state->key_length & 7)) { - if (libkeccak_digest(&state->sponge, tmp, hashsize, bits, suffix, hashsum) < 0) - goto fail; - goto stage_3; - } - - if (libkeccak_hmac_update(state, tmp, hashsize) < 0) - goto fail; - leftover[0] = state->leftover; - if (bits) { - leftover[0] |= (unsigned char)(tmp[hashsize] >> (state->key_length & 7)); - leftover[1] = (unsigned char)(tmp[hashsize] << (8 - (state->key_length & 7))); - } - newlen = (state->key_length & 7) + bits; - if (libkeccak_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) - goto fail; - -stage_3: - my_explicit_bzero(tmp, (size_t)((state->sponge.n + 7) >> 3) * sizeof(char)); - free(tmp); - return 0; -fail: - my_explicit_bzero(tmp, (size_t)((state->sponge.n + 7) >> 3) * sizeof(char)); - free(tmp); - return -1; -} diff --git a/libkeccak_hmac_duplicate.c b/libkeccak_hmac_duplicate.c deleted file mode 100644 index 6c07854..0000000 --- a/libkeccak_hmac_duplicate.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline struct libkeccak_hmac_state *libkeccak_hmac_duplicate(const struct libkeccak_hmac_state *); diff --git a/libkeccak_hmac_fast_destroy.c b/libkeccak_hmac_fast_destroy.c deleted file mode 100644 index 529175e..0000000 --- a/libkeccak_hmac_fast_destroy.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_hmac_fast_destroy(struct libkeccak_hmac_state *); diff --git a/libkeccak_hmac_fast_digest.c b/libkeccak_hmac_fast_digest.c deleted file mode 100644 index db242a5..0000000 --- a/libkeccak_hmac_fast_digest.c +++ /dev/null @@ -1,78 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Absorb the last part of the message and fetch the hash - * without wiping sensitive data when possible - * - * You may use `&state->sponge` for continued squeezing - * - * @param state The hashing state - * @param msg_ The rest of the message, may be `NULL`, may be modified - * @param msglen The length of the partial message - * @param bits The number of bits at the end of the message not covered by `msglen` - * @param suffix The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param hashsum Output parameter for the hashsum, may be `NULL` - * @return Zero on success, -1 on error - */ -int -libkeccak_hmac_fast_digest(struct libkeccak_hmac_state *restrict state, const void *restrict msg_, size_t msglen, - size_t bits, const char *restrict suffix, void *restrict hashsum) -{ - const unsigned char *restrict msg = msg_; - size_t hashsize = (size_t)state->sponge.n >> 3; - unsigned char *tmp = malloc((size_t)((state->sponge.n + 7) >> 3) * sizeof(char)); - unsigned char leftover[2]; - size_t newlen; - - if (!tmp) - return -1; - - if (!(state->key_length & 7)) { - if (libkeccak_fast_digest(&state->sponge, msg, msglen, bits, suffix, tmp) < 0) - goto fail; - goto stage_2; - } - - if (libkeccak_hmac_fast_update(state, msg, msglen) < 0) - goto fail; - leftover[0] = state->leftover; - if (bits) { - leftover[0] |= (unsigned char)(msg[msglen] >> (state->key_length & 7)); - leftover[1] = (unsigned char)(msg[msglen] << (8 - (state->key_length & 7))); - } - newlen = (state->key_length & 7) + bits; - if (libkeccak_fast_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) - goto fail; - -stage_2: - bits = state->sponge.n & 7; - state->key_ipad = state->key_opad; - if (libkeccak_hmac_fast_update(state, NULL, 0) < 0) - goto fail; - - if (!(state->key_length & 7)) { - if (libkeccak_fast_digest(&state->sponge, tmp, hashsize, bits, suffix, hashsum) < 0) - goto fail; - goto stage_3; - } - - if (libkeccak_hmac_fast_update(state, tmp, hashsize) < 0) - goto fail; - leftover[0] = state->leftover; - if (bits) { - leftover[0] |= (unsigned char)(tmp[hashsize] >> (state->key_length & 7)); - leftover[1] = (unsigned char)(tmp[hashsize] << (8 - (state->key_length & 7))); - } - newlen = (state->key_length & 7) + bits; - if (libkeccak_fast_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) - goto fail; - -stage_3: - free(tmp); - return 0; -fail: - free(tmp); - return -1; -} diff --git a/libkeccak_hmac_fast_free.c b/libkeccak_hmac_fast_free.c deleted file mode 100644 index 897f6e1..0000000 --- a/libkeccak_hmac_fast_free.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_hmac_fast_free(struct libkeccak_hmac_state *); diff --git a/libkeccak_hmac_fast_update.c b/libkeccak_hmac_fast_update.c deleted file mode 100644 index 50c34dd..0000000 --- a/libkeccak_hmac_fast_update.c +++ /dev/null @@ -1,52 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Absorb more, or the first part, of the message - * without wiping sensitive data when possible - * - * @param state The hashing state - * @param msg_ The partial message - * @param msglen The length of the partial message, in bytes - * @return Zero on success, -1 on error - */ -int -libkeccak_hmac_fast_update(struct libkeccak_hmac_state *restrict state, const void *restrict msg_, size_t msglen) -{ - const unsigned char *restrict msg = msg_; - void *new; - size_t i; - int n, cn; - - if (state->key_ipad) { - if (libkeccak_fast_update(&state->sponge, state->key_ipad, state->key_length >> 3) < 0) - return -1; - if (state->key_length & 7) - state->leftover = state->key_ipad[state->key_length >> 3]; - state->key_ipad = NULL; - } - - if (!msg || !msglen) - return 0; - - if (!(state->key_length & 7)) - return libkeccak_fast_update(&state->sponge, msg, msglen); - - if (msglen != state->buffer_size) { - new = realloc(state->buffer, msglen); - if (!new) - return -1; - state->buffer = new; - state->buffer_size = msglen; - } - - n = (int)(state->key_length & 7); - cn = 8 - n; - for (i = 1; i < msglen; i++) - state->buffer[i] = (unsigned char)((msg[i - 1] >> cn) | (msg[i] << n)); - state->buffer[0] = (unsigned char)((state->leftover & ((1 << n) - 1)) | (msg[0] << n)); - state->leftover = (unsigned char)(msg[msglen - 1] >> cn); - - return libkeccak_fast_update(&state->sponge, state->buffer, msglen); -} diff --git a/libkeccak_hmac_free.c b/libkeccak_hmac_free.c deleted file mode 100644 index 2e8e3fb..0000000 --- a/libkeccak_hmac_free.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_hmac_free(volatile struct libkeccak_hmac_state *); diff --git a/libkeccak_hmac_initialise.c b/libkeccak_hmac_initialise.c deleted file mode 100644 index b2f2552..0000000 --- a/libkeccak_hmac_initialise.c +++ /dev/null @@ -1,6 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline int -libkeccak_hmac_initialise(struct libkeccak_hmac_state *restrict, const struct libkeccak_spec *restrict, const void *restrict, size_t); diff --git a/libkeccak_hmac_marshal.c b/libkeccak_hmac_marshal.c deleted file mode 100644 index 604bde2..0000000 --- a/libkeccak_hmac_marshal.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline size_t libkeccak_hmac_marshal(const struct libkeccak_hmac_state *restrict, void *restrict); diff --git a/libkeccak_hmac_reset.c b/libkeccak_hmac_reset.c deleted file mode 100644 index 13d7c0e..0000000 --- a/libkeccak_hmac_reset.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline int libkeccak_hmac_reset(struct libkeccak_hmac_state *restrict, const void *restrict, size_t); diff --git a/libkeccak_hmac_set_key.c b/libkeccak_hmac_set_key.c deleted file mode 100644 index 2795e4f..0000000 --- a/libkeccak_hmac_set_key.c +++ /dev/null @@ -1,47 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Change the HMAC-hashing key on the state - * - * @param state The state that should be reset - * @param key The new key - * @param key_length The length of key, in bits - * @return Zero on success, -1 on error - */ -int -libkeccak_hmac_set_key(struct libkeccak_hmac_state *restrict state, const void *restrict key, size_t key_length) -{ - size_t i, size, new_key_length, key_bytes; - void *new; - - size = (size_t)(state->sponge.r) > key_length ? (size_t)(state->sponge.r) : key_length; - new_key_length = size; - size = (size + 7) >> 3; - key_bytes = (key_length + 7) >> 3; - - if (size != key_bytes) { - new = realloc(state->key_opad, 2 * size); - if (!new) - return -1; - state->key_opad = new; - state->key_ipad = state->key_opad + size; - } - - memcpy(state->key_opad, key, key_bytes); - if (key_length & 7) - state->key_opad[(key_bytes >> 3) - 1] &= (unsigned char)((1 << (key_length & 7)) - 1); - - if ((size_t)(state->sponge.r) > key_length) - __builtin_memset(state->key_opad + key_bytes, 0, size - key_bytes); - - for (i = 0; i < size; i++) { - state->key_ipad[i] = state->key_opad[i] ^ HMAC_INNER_PAD; - state->key_opad[i] ^= HMAC_OUTER_PAD; - } - - state->key_length = new_key_length; - - return 0; -} diff --git a/libkeccak_hmac_unmarshal.c b/libkeccak_hmac_unmarshal.c deleted file mode 100644 index 070c7b5..0000000 --- a/libkeccak_hmac_unmarshal.c +++ /dev/null @@ -1,59 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wcast-align" -#endif - - -/** - * Unmarshal a `struct libkeccak_hmac_state` from a buffer - * - * @param state The slot for the unmarshalled state, must not be - * initialised (memory leak otherwise), can be `NULL` - * @param data_ The input buffer - * @return The number of bytes read from `data`, 0 on error - */ -size_t -libkeccak_hmac_unmarshal(struct libkeccak_hmac_state *restrict state, const void *restrict data_) -{ - const unsigned char *restrict data = data_; - size_t parsed, size, i; - - state->key_opad = NULL; - state->key_ipad = NULL; - - parsed = libkeccak_state_unmarshal(state ? &state->sponge : NULL, data); - if (!parsed) - return 0; - data += parsed; - - __builtin_memcpy(&size, data, sizeof(size)); - data += sizeof(size_t); - if (state) - size = state->key_length; - size = (state->key_length + 7) >> 3; - - if (state) { - state->key_opad = malloc(2 * size); - if (!state->key_opad) { - libkeccak_state_destroy(&state->sponge); - return 0; - } - memcpy(state->key_opad, data, size); - data += size; - - if (data[0]) { - state->key_ipad = &state->key_opad[size]; - memcpy(state->key_ipad, state->key_opad, size); - for (i = 0; i < size; i++) - state->key_ipad[i] ^= (char)(HMAC_OUTER_PAD ^ HMAC_INNER_PAD); - } - - state->leftover = data[1]; - state->buffer = NULL; - state->buffer_size = 0; - } - - return parsed + sizeof(size_t) + size + 2 * sizeof(char); -} diff --git a/libkeccak_hmac_update.c b/libkeccak_hmac_update.c deleted file mode 100644 index 6f38348..0000000 --- a/libkeccak_hmac_update.c +++ /dev/null @@ -1,53 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#define NEED_EXPLICIT_BZERO 1 -#include "common.h" - - -/** - * Absorb more, or the first part, of the message - * and wipe sensitive data when possible - * - * @param state The hashing state - * @param msg_ The partial message - * @param msglen The length of the partial message, in bytes - * @return Zero on success, -1 on error - */ -int -libkeccak_hmac_update(struct libkeccak_hmac_state *restrict state, const void *restrict msg_, size_t msglen) -{ - const unsigned char *restrict msg = msg_; - size_t i; - int n, cn, r; - - if (state->key_ipad) { - if (libkeccak_update(&state->sponge, state->key_ipad, state->key_length >> 3) < 0) - return -1; - if (state->key_length & 7) - state->leftover = state->key_ipad[state->key_length >> 3]; - state->key_ipad = NULL; - } - - if (!msg || !msglen) - return 0; - - if (!(state->key_length & 7)) - return libkeccak_update(&state->sponge, msg, msglen); - - if (msglen != state->buffer_size) { - free(state->buffer); - state->buffer = malloc(state->buffer_size = msglen); - if (!state->buffer) - return -1; - } - - n = (int)(state->key_length & 7); - cn = 8 - n; - for (i = 1; i < msglen; i++) - state->buffer[i] = (unsigned char)((msg[i - 1] >> cn) | (msg[i] << n)); - state->buffer[0] = (unsigned char)((state->leftover & ((1 << n) - 1)) | (msg[0] << n)); - state->leftover = (unsigned char)(msg[msglen - 1] >> cn); - - r = libkeccak_update(&state->sponge, state->buffer, msglen); - my_explicit_bzero(state->buffer, msglen); - return r; -} diff --git a/libkeccak_hmac_wipe.c b/libkeccak_hmac_wipe.c deleted file mode 100644 index 11d268a..0000000 --- a/libkeccak_hmac_wipe.c +++ /dev/null @@ -1,24 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Wipe sensitive data wihout freeing any data - * - * @param state The state that should be wipe - */ -void -libkeccak_hmac_wipe(volatile struct libkeccak_hmac_state *state) -{ - volatile unsigned char *restrict key_pads; - size_t i, size; - - key_pads = state->key_opad; - size = 2 * ((state->key_length + 7) >> 3); - - libkeccak_state_wipe(&state->sponge); - for (i = 0; i < size; i++) - key_pads[i] = 0; - state->leftover = 0; - __builtin_memset(state->buffer, 0, state->buffer_size); -} diff --git a/libkeccak_keccaksum_fd.c b/libkeccak_keccaksum_fd.c deleted file mode 100644 index f738115..0000000 --- a/libkeccak_keccaksum_fd.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline int libkeccak_keccaksum_fd(int, struct libkeccak_state *restrict, const struct libkeccak_spec *restrict, void *restrict); diff --git a/libkeccak_rawshakesum_fd.c b/libkeccak_rawshakesum_fd.c deleted file mode 100644 index a988cf2..0000000 --- a/libkeccak_rawshakesum_fd.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline int libkeccak_rawshakesum_fd(int, struct libkeccak_state *restrict, long, long, void *restrict); diff --git a/libkeccak_sha3sum_fd.c b/libkeccak_sha3sum_fd.c deleted file mode 100644 index 6662ad4..0000000 --- a/libkeccak_sha3sum_fd.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline int libkeccak_sha3sum_fd(int, struct libkeccak_state *restrict, long, void *restrict); diff --git a/libkeccak_shakesum_fd.c b/libkeccak_shakesum_fd.c deleted file mode 100644 index 45289f7..0000000 --- a/libkeccak_shakesum_fd.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline int libkeccak_shakesum_fd(int, struct libkeccak_state *restrict, long, long, void *restrict); diff --git a/libkeccak_spec_check.c b/libkeccak_spec_check.c deleted file mode 100644 index 0649e5a..0000000 --- a/libkeccak_spec_check.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline int libkeccak_spec_check(const struct libkeccak_spec *); diff --git a/libkeccak_spec_rawshake.c b/libkeccak_spec_rawshake.c deleted file mode 100644 index 99b704c..0000000 --- a/libkeccak_spec_rawshake.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_spec_rawshake(struct libkeccak_spec *, long int, long int); diff --git a/libkeccak_spec_sha3.c b/libkeccak_spec_sha3.c deleted file mode 100644 index 1ac387e..0000000 --- a/libkeccak_spec_sha3.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_spec_sha3(struct libkeccak_spec *, long int); diff --git a/libkeccak_state_copy.c b/libkeccak_state_copy.c deleted file mode 100644 index abec573..0000000 --- a/libkeccak_state_copy.c +++ /dev/null @@ -1,25 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Make a copy of a state - * - * @param dest The slot for the duplicate, must not be initialised (memory leak otherwise) - * @param src The state to duplicate - * @return Zero on success, -1 on error - */ -int -libkeccak_state_copy(struct libkeccak_state *restrict dest, const struct libkeccak_state *restrict src) -{ - *dest = *src; - if (src->mlen) { - dest->M = malloc(src->mlen * sizeof(char)); - if (!dest->M) - return -1; - memcpy(dest->M, src->M, src->mptr * sizeof(char)); - } else { - dest->M = NULL; - } - return 0; -} diff --git a/libkeccak_state_create.c b/libkeccak_state_create.c deleted file mode 100644 index b5a6990..0000000 --- a/libkeccak_state_create.c +++ /dev/null @@ -1,20 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Wrapper for `libkeccak_state_initialise` that also allocates the states - * - * @param spec The specifications for the state - * @return The state, `NULL` on error - */ -struct libkeccak_state * -libkeccak_state_create(const struct libkeccak_spec *spec) -{ - struct libkeccak_state *state = malloc(sizeof(struct libkeccak_state)); - if (!state || libkeccak_state_initialise(state, spec)) { - free(state); - return NULL; - } - return state; -} diff --git a/libkeccak_state_duplicate.c b/libkeccak_state_duplicate.c deleted file mode 100644 index 75f85da..0000000 --- a/libkeccak_state_duplicate.c +++ /dev/null @@ -1,20 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * A wrapper for `libkeccak_state_copy` that also allocates the duplicate - * - * @param src The state to duplicate - * @return The duplicate, `NULL` on error - */ -struct libkeccak_state * -libkeccak_state_duplicate(const struct libkeccak_state *src) -{ - struct libkeccak_state *dest = malloc(sizeof(struct libkeccak_state)); - if (!dest || libkeccak_state_copy(dest, src)) { - libkeccak_state_free(dest); - return NULL; - } - return dest; -} diff --git a/libkeccak_state_fast_free.c b/libkeccak_state_fast_free.c deleted file mode 100644 index db2e44f..0000000 --- a/libkeccak_state_fast_free.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_state_fast_free(struct libkeccak_state *); diff --git a/libkeccak_state_free.c b/libkeccak_state_free.c deleted file mode 100644 index 41e635e..0000000 --- a/libkeccak_state_free.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_state_free(volatile struct libkeccak_state *); diff --git a/libkeccak_state_marshal.c b/libkeccak_state_marshal.c deleted file mode 100644 index 480b4a4..0000000 --- a/libkeccak_state_marshal.c +++ /dev/null @@ -1,55 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wcast-align" -#endif - - -/** - * Marshal a `struct libkeccak_state` into a buffer - * - * @param state The state to marshal - * @param data_ The output buffer, can be `NULL` - * @return The number of bytes stored to `data` - */ -size_t -libkeccak_state_marshal(const struct libkeccak_state *restrict state, void *restrict data_) -{ -#define set(VAR)\ - do {\ - __builtin_memcpy(data, &state->VAR, sizeof(state->VAR));\ - data += sizeof(state->VAR);\ - } while (0) - - unsigned char *restrict start = data_; - unsigned char *restrict data = start; - - if (!data) { - return 7 * sizeof(long int) + - 1 * sizeof(int64_t) + - sizeof(state->S) + - 2 * sizeof(size_t) + - state->mptr; - } - - set(r); - set(c); - set(n); - set(b); - set(w); - set(wmod); - set(l); - set(nr); - __builtin_memcpy(data, state->S, sizeof(state->S)); - data += sizeof(state->S); - set(mptr); - set(mlen); - memcpy(data, state->M, state->mptr * sizeof(char)); - data += state->mptr; - - return (size_t)(data - start); - -#undef set -} diff --git a/libkeccak_state_reset.c b/libkeccak_state_reset.c deleted file mode 100644 index bfbbfbd..0000000 --- a/libkeccak_state_reset.c +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -extern inline void libkeccak_state_reset(struct libkeccak_state *); diff --git a/libkeccak_state_unmarshal.c b/libkeccak_state_unmarshal.c deleted file mode 100644 index f9604a2..0000000 --- a/libkeccak_state_unmarshal.c +++ /dev/null @@ -1,66 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wcast-align" -#endif - - -/** - * Unmarshal a `struct libkeccak_state` from a buffer - * - * @param state The slot for the unmarshalled state, must not be - * initialised (memory leak otherwise), can be `NULL` - * @param data_ The input buffer - * @return The number of bytes read from `data`, 0 on error - */ -size_t -libkeccak_state_unmarshal(struct libkeccak_state *restrict state, const void *restrict data_) -{ -#define get(VAR) \ - do {\ - __builtin_memcpy(&state->VAR, data, sizeof(state->VAR));\ - data += sizeof(state->VAR);\ - } while (0) - - const unsigned char *restrict start = data_; - const unsigned char *restrict data = start; - size_t mptr; - - if (!state) { - data += 7U * sizeof(long int); - data += 1U * sizeof(int64_t); - data += sizeof(state->S); - mptr = *(const size_t *)data; - data += 2U * sizeof(size_t); - data += mptr; - return (size_t)(data - start); - } - - get(r); - get(c); - get(n); - get(b); - get(w); - get(wmod); - get(l); - get(nr); - memcpy(state->S, data, sizeof(state->S)); - data += sizeof(state->S); - get(mptr); - get(mlen); - if (state->mptr) { - state->M = malloc(state->mptr * sizeof(char)); - if (!state->M) - return 0; - memcpy(state->M, data, state->mptr * sizeof(char)); - data += state->mptr; - } else { - state->M = NULL; - } - - return (size_t)(data - start); - -#undef get -} diff --git a/libkeccak_state_wipe.c b/libkeccak_state_wipe.c deleted file mode 100644 index e46a25d..0000000 --- a/libkeccak_state_wipe.c +++ /dev/null @@ -1,15 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Wipe sensitive data wihout freeing any data - * - * @param state The state that should be wipe - */ -void -libkeccak_state_wipe(volatile struct libkeccak_state *state) -{ - libkeccak_state_wipe_message(state); - libkeccak_state_wipe_sponge(state); -} diff --git a/libkeccak_state_wipe_message.c b/libkeccak_state_wipe_message.c deleted file mode 100644 index 135960c..0000000 --- a/libkeccak_state_wipe_message.c +++ /dev/null @@ -1,18 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Wipe data in the state's message wihout freeing any data - * - * @param state The state that should be wipe - */ -void -libkeccak_state_wipe_message(volatile struct libkeccak_state *state) -{ - volatile unsigned char *restrict M = state->M; - size_t i; - - for (i = 0; i < state->mptr; i++) - M[i] = 0; -} diff --git a/libkeccak_state_wipe_sponge.c b/libkeccak_state_wipe_sponge.c deleted file mode 100644 index f57ec26..0000000 --- a/libkeccak_state_wipe_sponge.c +++ /dev/null @@ -1,18 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Wipe data in the state's sponge wihout freeing any data - * - * @param state The state that should be wipe - */ -void -libkeccak_state_wipe_sponge(volatile struct libkeccak_state *state) -{ - volatile int64_t *restrict S = state->S; - size_t i; - - for (i = 0; i < 25; i++) - S[i] = 0; -} diff --git a/libkeccak_unhex.c b/libkeccak_unhex.c deleted file mode 100644 index 26a6e7d..0000000 --- a/libkeccak_unhex.c +++ /dev/null @@ -1,30 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "common.h" - - -/** - * Convert a hexadecimal hashsum (both lower case, upper - * case and mixed is supported) to binary representation - * - * @param output_ Output array, should have an allocation size of at least `strlen(hashsum) / 2` - * @param hashsum The hashsum to convert - */ -void -libkeccak_unhex(void *restrict output_, const char *restrict hashsum) -{ - unsigned char *restrict output = output_; - size_t n = strlen(hashsum) / 2; - unsigned char a, b; - - while (n--) { - a = (unsigned char)hashsum[2 * n + 0]; - b = (unsigned char)hashsum[2 * n + 1]; - - a = (unsigned char)((a & 15) + (a > '9' ? 9 : 0)); - b = (unsigned char)((b & 15) + (b > '9' ? 9 : 0)); - - a = (unsigned char)(a << 4); - a |= b; - output[n] = a; - } -} diff --git a/spec/libkeccak_cshake_suffix.c b/spec/libkeccak_cshake_suffix.c new file mode 100644 index 0000000..c7e8c51 --- /dev/null +++ b/spec/libkeccak_cshake_suffix.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline const char *libkeccak_cshake_suffix(size_t, size_t); diff --git a/spec/libkeccak_degeneralise_spec.c b/spec/libkeccak_degeneralise_spec.c new file mode 100644 index 0000000..2a719e9 --- /dev/null +++ b/spec/libkeccak_degeneralise_spec.c @@ -0,0 +1,120 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wconditional-uninitialized" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + +#define deft(v, dv) (have_##v ? v : (dv)) + + +/** + * Convert a `struct libkeccak_generalised_spec` to a `struct libkeccak_spec` + * + * If you are interrested in finding errors, you should call + * `libkeccak_spec_check(output)` if this function returns zero + * + * @param spec The generalised input specifications, will be update with resolved automatic values + * @param output_spec The specification datastructure to fill in + * @return Zero if `spec` is valid, a `LIBKECCAK_GENERALISED_SPEC_ERROR_*` if an error was found + */ +int +libkeccak_degeneralise_spec(struct libkeccak_generalised_spec *restrict spec, struct libkeccak_spec *restrict output_spec) +{ + long int state_size, word_size, capacity, bitrate, output; + int have_state_size = spec->state_size != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; + int have_word_size = spec->word_size != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; + int have_capacity = spec->capacity != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; + int have_bitrate = spec->bitrate != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; + int have_output = spec->output != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; + + + if (have_state_size) { + state_size = spec->state_size; + if (state_size <= 0) + return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_NONPOSITIVE; + if (state_size > 1600) + return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_TOO_LARGE; + if (state_size % 25) + return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_MOD_25; + } + + if (have_word_size) { + word_size = spec->word_size; + if (word_size <= 0) + return LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_NONPOSITIVE; + if (word_size > 64) + return LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_TOO_LARGE; + if (have_state_size && state_size != word_size * 25) + return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_WORD_INCOHERENCY; + else if (!have_state_size) { + have_state_size = 1; + state_size = word_size * 25; + } + } + + if (have_capacity) { + capacity = spec->capacity; + if (capacity <= 0) + return LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_NONPOSITIVE; + if (capacity & 7) + return LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_MOD_8; + } + + if (have_bitrate) { + bitrate = spec->bitrate; + if (bitrate <= 0) + return LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_NONPOSITIVE; + if (bitrate & 7) + return LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_MOD_8; + } + + if (have_output) { + output = spec->output; + if (output <= 0) + return LIBKECCAK_GENERALISED_SPEC_ERROR_OUTPUT_NONPOSITIVE; + } + + + if (have_bitrate + have_capacity == 2) { + if (!have_state_size) { + state_size = bitrate + capacity; + output = deft(output, capacity * 2L <= 8 ? 8 : capacity * 2L); + } else if (state_size != bitrate + capacity) { + return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_BITRATE_CAPACITY_INCONSISTENCY; + } + } else if (have_bitrate + have_capacity == 1) { + state_size = deft(state_size, 1600L); + capacity = deft(capacity, state_size - bitrate); + bitrate = deft(bitrate, state_size - capacity); + output = deft(output, capacity * 2L <= 8 ? 8 : capacity * 2L); + } else { + state_size = deft(state_size, 1600L); + capacity = state_size * 9 / 25; + bitrate = state_size - capacity; + output = deft(output, bitrate / 2L <= 8 ? 8 : bitrate / 2L); + } + + + spec->capacity = output_spec->capacity = capacity; + spec->bitrate = output_spec->bitrate = bitrate; + spec->output = output_spec->output = output; + spec->state_size = state_size; + spec->word_size = state_size / 25; + + return 0; +} + + +#undef deft + +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif diff --git a/spec/libkeccak_generalised_spec_initialise.c b/spec/libkeccak_generalised_spec_initialise.c new file mode 100644 index 0000000..b2ed3f0 --- /dev/null +++ b/spec/libkeccak_generalised_spec_initialise.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_generalised_spec_initialise(struct libkeccak_generalised_spec *); diff --git a/spec/libkeccak_spec_check.c b/spec/libkeccak_spec_check.c new file mode 100644 index 0000000..92b8e75 --- /dev/null +++ b/spec/libkeccak_spec_check.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline int libkeccak_spec_check(const struct libkeccak_spec *); diff --git a/spec/libkeccak_spec_rawshake.c b/spec/libkeccak_spec_rawshake.c new file mode 100644 index 0000000..434604c --- /dev/null +++ b/spec/libkeccak_spec_rawshake.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_spec_rawshake(struct libkeccak_spec *, long int, long int); diff --git a/spec/libkeccak_spec_sha3.c b/spec/libkeccak_spec_sha3.c new file mode 100644 index 0000000..fe18d72 --- /dev/null +++ b/spec/libkeccak_spec_sha3.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline void libkeccak_spec_sha3(struct libkeccak_spec *, long int); diff --git a/util/libkeccak_behex_lower.c b/util/libkeccak_behex_lower.c new file mode 100644 index 0000000..07593e8 --- /dev/null +++ b/util/libkeccak_behex_lower.c @@ -0,0 +1,22 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Convert a binary hashsum to lower case hexadecimal representation + * + * @param output Output array, should have an allocation size of at least `2 * n + 1` + * @param hashsum_ The hashsum to convert + * @param n The size of `hashsum` + */ +void +libkeccak_behex_lower(char *restrict output, const void *restrict hashsum_, size_t n) +{ + const unsigned char *restrict hashsum = hashsum_; + + output[2 * n] = '\0'; + while (n--) { + output[2 * n + 0] = "0123456789abcdef"[(hashsum[n] >> 4) & 15]; + output[2 * n + 1] = "0123456789abcdef"[(hashsum[n] >> 0) & 15]; + } +} diff --git a/util/libkeccak_behex_upper.c b/util/libkeccak_behex_upper.c new file mode 100644 index 0000000..5186a28 --- /dev/null +++ b/util/libkeccak_behex_upper.c @@ -0,0 +1,22 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Convert a binary hashsum to upper case hexadecimal representation + * + * @param output Output array, should have an allocation size of at least `2 * n + 1` + * @param hashsum_ The hashsum to convert + * @param n The size of `hashsum` + */ +void +libkeccak_behex_upper(char *restrict output, const void *restrict hashsum_, size_t n) +{ + const unsigned char *restrict hashsum = hashsum_; + + output[2 * n] = '\0'; + while (n--) { + output[2 * n + 0] = "0123456789ABCDEF"[(hashsum[n] >> 4) & 15]; + output[2 * n + 1] = "0123456789ABCDEF"[(hashsum[n] >> 0) & 15]; + } +} diff --git a/util/libkeccak_generalised_sum_fd.c b/util/libkeccak_generalised_sum_fd.c new file mode 100644 index 0000000..bad35e9 --- /dev/null +++ b/util/libkeccak_generalised_sum_fd.c @@ -0,0 +1,112 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" +#include + + +/** + * Calculate a Keccak-family hashsum of a file, + * the content of the file is assumed non-sensitive + * + * @param fd The file descriptor of the file to hash + * @param state The hashing state, should not be initialised unless + * `spec` is `NULL` (memory leak otherwise) + * @param spec Specifications for the hashing algorithm; or `NULL` + * if `spec` is already initialised + * @param suffix The data suffix, see `libkeccak_digest` + * @param hashsum Output array for the hashsum, have an allocation size of + * at least `((spec->output + 7) / 8) * sizeof(char)`, may be `NULL` + * @return Zero on success, -1 on error + */ +int +libkeccak_generalised_sum_fd(int fd, struct libkeccak_state *restrict state, const struct libkeccak_spec *restrict spec, + const char *restrict suffix, void *restrict hashsum) +{ + ssize_t got; + size_t offset; +#ifndef _WIN32 + struct stat attr; +#endif + size_t blksize = 4096; + unsigned char *restrict chunk; + size_t chunksize, extrasize, extrachunks; + size_t chunks, chunkmod; + + if (spec && libkeccak_state_initialise(state, spec) < 0) + return -1; + + chunksize = libkeccak_zerocopy_chunksize(state); + extrasize = ((suffix ? strlen(suffix) : 0) + 2 + 7) >> 3; + extrachunks = (extrasize + (chunksize - 1)) / chunksize; + +#ifndef _WIN32 + if (fstat(fd, &attr) == 0) + if (attr.st_blksize > 0) + blksize = (size_t)attr.st_blksize; +#endif + + chunks = blksize / chunksize; + chunkmod = blksize % chunksize; + if (chunkmod) { + blksize -= chunkmod; + blksize += chunksize; + chunks += 1; + } + if (chunks < extrachunks + 1) + blksize = (extrachunks + 1) * chunksize; + +#if ALLOCA_LIMIT > 0 + if (blksize > (size_t)ALLOCA_LIMIT) { + blksize = (size_t)ALLOCA_LIMIT; + blksize -= blksize % chunksize; + if (!blksize) + blksize = chunksize; + } +# if defined(__clang__) + /* We are using a limit so it's just like declaring an array + * in a function, except we might use less of the stack. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Walloca" +# endif + chunk = alloca(blksize); +# if defined(__clang__) +# pragma clang diagnostic pop +# endif +#else + chunk = malloc(blksize); + if (!chunk) + return -1; +#endif + + offset = 0; + for (;;) { + got = read(fd, &chunk[offset], blksize - offset); + if (got <= 0) { + if (!got) + break; + if (errno == EINTR) + continue; + goto fail; + } + offset += (size_t)got; + if (offset == blksize) { + libkeccak_zerocopy_update(state, chunk, blksize); + offset = 0; + } + } + + if (extrasize > blksize - offset) { + chunkmod = offset % chunksize; + libkeccak_zerocopy_update(state, chunk, offset - chunkmod); + __builtin_memcpy(chunk, &chunk[offset - chunkmod], chunkmod * sizeof(char)); + offset = chunkmod; + } + + libkeccak_zerocopy_digest(state, chunk, offset, 0, suffix, hashsum); + return 0; + +fail: +#if ALLOCA_LIMIT <= 0 + free(chunk); +#endif + return -1; +} diff --git a/util/libkeccak_keccaksum_fd.c b/util/libkeccak_keccaksum_fd.c new file mode 100644 index 0000000..560e390 --- /dev/null +++ b/util/libkeccak_keccaksum_fd.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline int libkeccak_keccaksum_fd(int, struct libkeccak_state *restrict, const struct libkeccak_spec *restrict, void *restrict); diff --git a/util/libkeccak_rawshakesum_fd.c b/util/libkeccak_rawshakesum_fd.c new file mode 100644 index 0000000..c9c66ec --- /dev/null +++ b/util/libkeccak_rawshakesum_fd.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline int libkeccak_rawshakesum_fd(int, struct libkeccak_state *restrict, long, long, void *restrict); diff --git a/util/libkeccak_sha3sum_fd.c b/util/libkeccak_sha3sum_fd.c new file mode 100644 index 0000000..43be4b7 --- /dev/null +++ b/util/libkeccak_sha3sum_fd.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline int libkeccak_sha3sum_fd(int, struct libkeccak_state *restrict, long, void *restrict); diff --git a/util/libkeccak_shakesum_fd.c b/util/libkeccak_shakesum_fd.c new file mode 100644 index 0000000..9bb4b80 --- /dev/null +++ b/util/libkeccak_shakesum_fd.c @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +extern inline int libkeccak_shakesum_fd(int, struct libkeccak_state *restrict, long, long, void *restrict); diff --git a/util/libkeccak_unhex.c b/util/libkeccak_unhex.c new file mode 100644 index 0000000..b32a3f3 --- /dev/null +++ b/util/libkeccak_unhex.c @@ -0,0 +1,30 @@ +/* See LICENSE file for copyright and license details. */ +#include "../common.h" + + +/** + * Convert a hexadecimal hashsum (both lower case, upper + * case and mixed is supported) to binary representation + * + * @param output_ Output array, should have an allocation size of at least `strlen(hashsum) / 2` + * @param hashsum The hashsum to convert + */ +void +libkeccak_unhex(void *restrict output_, const char *restrict hashsum) +{ + unsigned char *restrict output = output_; + size_t n = strlen(hashsum) / 2; + unsigned char a, b; + + while (n--) { + a = (unsigned char)hashsum[2 * n + 0]; + b = (unsigned char)hashsum[2 * n + 1]; + + a = (unsigned char)((a & 15) + (a > '9' ? 9 : 0)); + b = (unsigned char)((b & 15) + (b > '9' ? 9 : 0)); + + a = (unsigned char)(a << 4); + a |= b; + output[n] = a; + } +} -- cgit v1.2.3-70-g09d2