From e550dbc53ff138c8085a3421bd48f86c4c7766f2 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 4 Nov 2014 17:48:22 +0100 Subject: add generalised-spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/libkeccak.h | 1 + src/libkeccak/generalised-spec.c | 119 +++++++++++++++++++++++++++++ src/libkeccak/generalised-spec.h | 158 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 src/libkeccak/generalised-spec.c create mode 100644 src/libkeccak/generalised-spec.h diff --git a/src/libkeccak.h b/src/libkeccak.h index af6bfac..cd401c5 100644 --- a/src/libkeccak.h +++ b/src/libkeccak.h @@ -21,6 +21,7 @@ #include "libkeccak/spec.h" +#include "libkeccak/generalised-spec.h" #include "libkeccak/state.h" #include "libkeccak/digest.h" #include "libkeccak/hex.h" diff --git a/src/libkeccak/generalised-spec.c b/src/libkeccak/generalised-spec.c new file mode 100644 index 0000000..f793c71 --- /dev/null +++ b/src/libkeccak/generalised-spec.c @@ -0,0 +1,119 @@ +/** + * libkeccak – Keccak-family hashing library + * + * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include "generalised-spec.h" + + +#define have(v) (spec->v != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC) +#define copy(v) (spec->v = v) +#define deft(v, dv) (have(v) ? v : (dv)) + + +/** + * Convert a `libkeccak_generalised_spec_t` to a `libkeccak_spec_t` + * + * 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, may be modified + * @param output 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(libkeccak_generalised_spec_t* restrict spec, + libkeccak_spec_t* restrict output) +{ + long state_size, word_size, capacity, bitrate, output; + + if (have(state_size)) + { + copy(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)) + { + copy(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)) + spec->state_size = 1, state_size = word_size * 25; + } + + if (have(capacity)) + { + copy(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)) + { + copy(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)) + { + copy(output); + if (output <= 0) return LIBKECCAK_GENERALISED_SPEC_ERROR_OUTPUT_NONPOSITIVE; + } + + + if (!have(bitrate) && !have(capacity) && !have(opacity)) /* state_size? */ + { + state_size = deft(state_size, 1600L); + output = ((state_size << 5) / 100L + 7L) & ~0x07L; + bitrate = output << 1; + capacity = state_size - bitrate; + output = output >= 8 ? output : 8; + } + else if (!have(bitrate) && !have(capacity)) /* have(output) state_size? */ + { + bitrate = 1024; + capacity = 1600 - 1024; + state_size = deft(state_size, bitrate + capacity); + } + else if (!have(bitrate)) /* have(capacity) output? state_size? */ + { + state_size = deft(state_size, 1600L); + bitrate = state_size - capacity; + output = deft(output, capacity == 8 ? 8 : (capacity << 1)); + } + else if (!have(capacity)) /* have(bitrate) output? state_size? */ + { + state_size = deft(state_size, 1600L); + capacity = state_size - bitrate; + output = deft(output, capacity == 8 ? 8 : (capacity << 1)); + } + else /* have(bitrate) have(capacity) output? state_size? */ + { + state_size = deft(state_size, bitrate + capacity); + output = deft(output, capacity == 8 ? 8 : (capacity << 1)); + } +} + + +#undef deft +#undef copy +#undef have + diff --git a/src/libkeccak/generalised-spec.h b/src/libkeccak/generalised-spec.h new file mode 100644 index 0000000..d460e0d --- /dev/null +++ b/src/libkeccak/generalised-spec.h @@ -0,0 +1,158 @@ +/** + * libkeccak – Keccak-family hashing library + * + * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBKECCAK_GENERALISED_SPEC_H +#define LIBKECCAK_GENERALISED_SPEC_H 1 + + +#include "spec.h" + +#include + + + +/** + * Value for `libkeccak_generalised_spec_t` member that + * is used to automatically select the value + */ +#define LIBKECCAK_GENERALISED_SPEC_AUTOMATIC (-65536L) + + +/** + * Invalid `libkeccak_generalised_spec_t.state_size`: non-positive + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_NONPOSITIVE 1 + +/** + * Invalid `libkeccak_generalised_spec_t.state_size`: larger than 1600 + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_TOO_LARGE 2 + +/** + * Invalid `libkeccak_generalised_spec_t.state_size`: not a multiple of 25 + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_MOD_25 3 + +/** + * Invalid `libkeccak_generalised_spec_t.word_size`: non-positive + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_NONPOSITIVE 4 + +/** + * Invalid `libkeccak_generalised_spec_t.word_size`: larger than 1600 / 25 + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_TOO_LARGE 5 + +/** + * Invalid `libkeccak_generalised_spec_t.word_size` and + * `libkeccak_generalised_spec_t.state_size`: `.word_size * 25 != .state_size` + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_WORD_INCOHERENCY 6 + +/** + * Invalid `libkeccak_generalised_spec_t.capacity`: non-positive + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_NONPOSITIVE 7 + +/** + * Invalid `libkeccak_generalised_spec_t.capacity`: not a multiple of 8 + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_MOD_8 8 + +/** + * Invalid `libkeccak_generalised_spec_t.bitrate`: non-positive + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_NONPOSITIVE 9 + +/** + * Invalid `libkeccak_generalised_spec_t.bitrate`: not a multiple of 8 + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_MOD_8 10 + +/** + * Invalid `libkeccak_generalised_spec_t.output`: non-positive + */ +#define LIBKECCAK_GENERALISED_SPEC_ERROR_OUTPUT_NONPOSITIVE 11 + + + +/** + * Generalised datastructure that describes the + * parameters that should be used when hashing + */ +typedef struct libkeccak_generalised_spec +{ + /** + * The bitrate + */ + long bitrate; + + /** + * The capacity + */ + long capacity; + + /** + * The output size + */ + long output; + + /** + * The state size + */ + long state_size; + + /** + * The word size + */ + long word_size; + +} libkeccak_generalised_spec_t; + + + +/** + * Set all specification pameters to automatic + * + * @param spec The specification datastructure to fill in + */ +static inline __attribute__((leaf, nonnull, nothrow, unused)) +void libkeccak_generalised_spec_initialise(libkeccak_generalised_spec_t* restrict spec) +{ + spec->bitrate = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; + spec->capacity = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; + spec->output = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; + spec->state_size = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; + spec->word_size = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; +} + + +/** + * Convert a `libkeccak_generalised_spec_t` to a `libkeccak_spec_t` + * + * @param spec The generalised input specifications, may be modified + * @param output The specification datastructure to fill in + * @return Zero if `spec` is valid, a `LIBKECCAK_GENERALISED_SPEC_ERROR_*` if an error was found + */ +__attribute__((leaf, nonnull, nothrow)) +int libkeccak_degeneralise_spec(libkeccak_generalised_spec_t* restrict spec, + libkeccak_spec_t* restrict output); + + +#undef + -- cgit v1.2.3-70-g09d2