aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libkeccak.h1
-rw-r--r--src/libkeccak/generalised-spec.c119
-rw-r--r--src/libkeccak/generalised-spec.h158
3 files changed, 278 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+ */
+#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 <http://www.gnu.org/licenses/>.
+ */
+#ifndef LIBKECCAK_GENERALISED_SPEC_H
+#define LIBKECCAK_GENERALISED_SPEC_H 1
+
+
+#include "spec.h"
+
+#include <inttypes.h>
+
+
+
+/**
+ * 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
+