aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2014-11-12 14:32:28 +0100
committerMattias Andrée <maandree@operamail.com>2014-11-12 14:32:28 +0100
commitd6f6a9031c9cb4ab0d67a21c23cc3f934ecc0065 (patch)
tree7d9a5c483664e57936a9da72afefc7379b1cc9dd
parentadd another test (diff)
downloadlibkeccak-d6f6a9031c9cb4ab0d67a21c23cc3f934ecc0065.tar.gz
libkeccak-d6f6a9031c9cb4ab0d67a21c23cc3f934ecc0065.tar.bz2
libkeccak-d6f6a9031c9cb4ab0d67a21c23cc3f934ecc0065.tar.xz
add secure variants of update and digest
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r--src/benchmark.c4
-rw-r--r--src/libkeccak/digest.c117
-rw-r--r--src/libkeccak/digest.h32
-rw-r--r--src/libkeccak/state.c36
-rw-r--r--src/libkeccak/state.h19
5 files changed, 193 insertions, 15 deletions
diff --git a/src/benchmark.c b/src/benchmark.c
index e126d44..17b2e4b 100644
--- a/src/benchmark.c
+++ b/src/benchmark.c
@@ -108,12 +108,12 @@ int main(void)
/* Updates. */
#if UPDATE_RUNS > 0
for (i = 0; i < UPDATE_RUNS; i++)
- if (libkeccak_update(&state, message, MESSAGE_LEN) < 0)
+ if (libkeccak_fast_update(&state, message, MESSAGE_LEN) < 0)
return perror("libkeccak_update"), 1;
#endif
/* Digest. */
- if (libkeccak_digest(&state, NULL, 0, 0, NULL, hashsum) < 0)
+ if (libkeccak_fast_digest(&state, NULL, 0, 0, NULL, hashsum) < 0)
return perror("libkeccak_digest"), 1;
#ifndef IGNORE_BEHEXING
libkeccak_behex_lower(hexsum, hashsum, OUTPUT / 8);
diff --git a/src/libkeccak/digest.c b/src/libkeccak/digest.c
index e001a35..61d0c58 100644
--- a/src/libkeccak/digest.c
+++ b/src/libkeccak/digest.c
@@ -18,6 +18,8 @@
*/
#include "digest.h"
+#include "state.h"
+
/**
@@ -362,6 +364,43 @@ void libkeccak_squeezing_phase(register libkeccak_state_t* restrict state, long
/**
* Absorb more of the message to the Keccak sponge
+ * without wiping sensitive data when possible
+ *
+ * @param state The hashing state
+ * @param msg The partial message
+ * @param msglen The length of the partial message
+ * @return Zero on success, -1 on error
+ */
+int libkeccak_fast_update(libkeccak_state_t* restrict state, const char* restrict msg, size_t msglen)
+{
+ size_t len;
+ auto char* restrict new;
+
+ if (__builtin_expect(state->mptr + msglen > state->mlen, 0))
+ {
+ state->mlen += msglen;
+ new = realloc(state->M, state->mlen * sizeof(char));
+ if (new == NULL)
+ return state->mlen -= msglen, -1;
+ state->M = new;
+ }
+
+ __builtin_memcpy(state->M + state->mptr, msg, msglen * sizeof(char));
+ state->mptr += msglen;
+ len = state->mptr;
+ len -= state->mptr % (size_t)((state->r * state->b) >> 3);
+ state->mptr -= len;
+
+ libkeccak_absorption_phase(state, len);
+ __builtin_memmove(state->M, state->M + len, state->mptr * sizeof(char));
+
+ return 0;
+}
+
+
+/**
+ * Absorb more of the message to the Keccak sponge
+ * and wipe sensitive data when possible
*
* @param state The hashing state
* @param msg The partial message
@@ -376,9 +415,11 @@ int libkeccak_update(libkeccak_state_t* restrict state, const char* restrict msg
if (__builtin_expect(state->mptr + msglen > state->mlen, 0))
{
state->mlen += msglen;
- new = realloc(state->M, state->mlen * sizeof(char)); /* FIXME insecure */
+ new = malloc(state->mlen * sizeof(char));
if (new == NULL)
return state->mlen -= msglen, -1;
+ libkeccak_state_wipe_message(state);
+ free(state->M);
state->M = new;
}
@@ -397,6 +438,76 @@ int libkeccak_update(libkeccak_state_t* restrict state, const char* restrict msg
/**
* Absorb the last part of the message and squeeze the Keccak sponge
+ * without wiping sensitive data when possible
+ *
+ * @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 paramter for the hashsum, may be `NULL`
+ * @return Zero on success, -1 on error
+ */
+int libkeccak_fast_digest(libkeccak_state_t* restrict state, const char* restrict msg, size_t msglen,
+ size_t bits, const char* restrict suffix, char* restrict hashsum)
+{
+ auto char* restrict new;
+ register long rr = state->r >> 3;
+ auto size_t suffix_len = suffix ? __builtin_strlen(suffix) : 0;
+ register size_t ext;
+ register long i;
+
+ if (msg == NULL)
+ msglen = bits = 0;
+ else
+ msglen += bits >> 3, bits &= 7;
+
+ ext = msglen + ((bits + suffix_len + 7) >> 3) + (size_t)rr;
+ if (__builtin_expect(state->mptr + ext > state->mlen, 0))
+ {
+ state->mlen += ext;
+ new = realloc(state->M, state->mlen * sizeof(char));
+ if (new == NULL)
+ return state->mlen -= ext, -1;
+ state->M = new;
+ }
+
+ if (msglen)
+ __builtin_memcpy(state->M + state->mptr, msg, msglen * sizeof(char));
+ state->mptr += msglen;
+
+ if (bits)
+ state->M[state->mptr] = msg[msglen] & (char)((1 << bits) - 1);
+ if (__builtin_expect(!!suffix_len, 1))
+ {
+ if (bits == 0)
+ state->M[state->mptr] = 0;
+ while (suffix_len--)
+ {
+ state->M[state->mptr] |= (char)((*suffix++ & 1) << bits++);
+ if (bits == 8)
+ bits = 0, state->M[++(state->mptr)] = 0;
+ }
+ }
+ if (bits)
+ state->mptr++;
+
+ libkeccak_pad10star1(state, bits);
+ libkeccak_absorption_phase(state, state->mptr);
+
+ if (hashsum != NULL)
+ libkeccak_squeezing_phase(state, rr, (state->n + 7) >> 3, state->w >> 3, hashsum);
+ else
+ for (i = (state->n - 1) / state->r; i--;)
+ libkeccak_f(state);
+
+ return 0;
+}
+
+
+/**
+ * Absorb the last part of the message and squeeze the Keccak sponge
+ * and wipe sensitive data when possible
*
* @param state The hashing state
* @param msg The rest of the message, may be `NULL`, may be modified
@@ -424,9 +535,11 @@ int libkeccak_digest(libkeccak_state_t* restrict state, const char* restrict msg
if (__builtin_expect(state->mptr + ext > state->mlen, 0))
{
state->mlen += ext;
- new = realloc(state->M, state->mlen * sizeof(char)); /* FIXME insecure */
+ new = malloc(state->mlen * sizeof(char));
if (new == NULL)
return state->mlen -= ext, -1;
+ libkeccak_state_wipe_message(state);
+ free(state->M);
state->M = new;
}
diff --git a/src/libkeccak/digest.h b/src/libkeccak/digest.h
index 4d4fe8e..b84370c 100644
--- a/src/libkeccak/digest.h
+++ b/src/libkeccak/digest.h
@@ -25,6 +25,20 @@
/**
* Absorb more of the message to the Keccak sponge
+ * without wiping sensitive data when possible
+ *
+ * @param state The hashing state
+ * @param msg The partial message
+ * @param msglen The length of the partial message
+ * @return Zero on success, -1 on error
+ */
+__attribute__((nonnull))
+int libkeccak_fast_update(libkeccak_state_t* restrict state, const char* restrict msg, size_t msglen);
+
+
+/**
+ * Absorb more of the message to the Keccak sponge
+ * and wipe sensitive data when possible
*
* @param state The hashing state
* @param msg The partial message
@@ -37,6 +51,24 @@ int libkeccak_update(libkeccak_state_t* restrict state, const char* restrict msg
/**
* Absorb the last part of the message and squeeze the Keccak sponge
+ * without wiping sensitive data when possible
+ *
+ * @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 paramter for the hashsum, may be `NULL`
+ * @return Zero on success, -1 on error
+ */
+__attribute__((nonnull(1)))
+int libkeccak_fast_digest(libkeccak_state_t* restrict state, const char* restrict msg, size_t msglen,
+ size_t bits, const char* restrict suffix, char* restrict hashsum);
+
+
+/**
+ * Absorb the last part of the message and squeeze the Keccak sponge
+ * and wipe sensitive data when possible
*
* @param state The hashing state
* @param msg The rest of the message, may be `NULL`, may be modified
diff --git a/src/libkeccak/state.c b/src/libkeccak/state.c
index da545d9..22a7d0c 100644
--- a/src/libkeccak/state.c
+++ b/src/libkeccak/state.c
@@ -53,24 +53,42 @@ int libkeccak_state_initialise(libkeccak_state_t* restrict state, const libkecca
/**
- * Wipe sensitive data wihout freeing any data, this is intended
- * be called from `libkeccak_state_destroy`
+ * Wipe data in the state's message wihout freeing any data
*
* @param state The state that should be wipe
*/
-void libkeccak_state_wipe(volatile libkeccak_state_t* restrict state)
+void libkeccak_state_wipe_message(volatile libkeccak_state_t* restrict state)
{
- volatile int_fast64_t* restrict S;
- volatile char* restrict M;
+ volatile char* restrict M = state->M;
size_t i;
- S = state->S;
- M = state->M;
- for (i = 0; i < 25; i++)
- S[i] = 0;
for (i = 0; i < state->mptr; i++)
M[i] = 0;
}
+/**
+ * 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 libkeccak_state_t* restrict state)
+{
+ volatile int_fast64_t* restrict S = state->S;
+ size_t i;
+ for (i = 0; i < 25; i++)
+ S[i] = 0;
+}
+
+/**
+ * Wipe sensitive data wihout freeing any data
+ *
+ * @param state The state that should be wipe
+ */
+void libkeccak_state_wipe(volatile libkeccak_state_t* restrict state)
+{
+ libkeccak_state_wipe_message(state);
+ libkeccak_state_wipe_sponge(state);
+}
+
/**
* Make a copy of a state
diff --git a/src/libkeccak/state.h b/src/libkeccak/state.h
index 8acb56b..74db7f9 100644
--- a/src/libkeccak/state.h
+++ b/src/libkeccak/state.h
@@ -141,12 +141,27 @@ void libkeccak_state_fast_destroy(libkeccak_state_t* restrict state)
/**
- * Wipe sensitive data wihout freeing any data, this is intended
- * be called from `libkeccak_state_destroy`
+ * Wipe data in the state's message wihout freeing any data
*
* @param state The state that should be wipe
*/
__attribute__((leaf, nonnull, nothrow, optimize("-O0")))
+void libkeccak_state_wipe_message(volatile libkeccak_state_t* restrict state);
+
+/**
+ * Wipe data in the state's sponge wihout freeing any data
+ *
+ * @param state The state that should be wipe
+ */
+__attribute__((leaf, nonnull, nothrow, optimize("-O0")))
+void libkeccak_state_wipe_sponge(volatile libkeccak_state_t* restrict state);
+
+/**
+ * Wipe sensitive data wihout freeing any data
+ *
+ * @param state The state that should be wipe
+ */
+__attribute__((nonnull, nothrow, optimize("-O0")))
void libkeccak_state_wipe(volatile libkeccak_state_t* restrict state);