From bed4bc1327a43f8e4c494e7fdf71680ffcaa26f1 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 26 Mar 2013 19:25:55 +0100 Subject: [PATCH] Randomly allocate chunk_hash() key during first use This avoids hash flooding attacks. --- src/libstrongswan/utils/chunk.c | 47 ++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c index 9033cbdaf4..61c7bd5a51 100644 --- a/src/libstrongswan/utils/chunk.c +++ b/src/libstrongswan/utils/chunk.c @@ -16,9 +16,12 @@ */ #include +#include #include +#include #include #include +#include #include #include "chunk.h" @@ -698,15 +701,56 @@ u_int64_t chunk_mac(chunk_t chunk, u_char *key) } /** - * Key used for chunk_hash. + * Secret key allocated randomly during first use. */ static u_char key[16]; +/** + * Only allocate the key once + */ +static pthread_once_t key_allocated = PTHREAD_ONCE_INIT; + +/** + * Allocate a key on first use, we do this manually to avoid dependencies on + * plugins. + */ +static void allocate_key() +{ + ssize_t len; + size_t done = 0; + int fd; + + fd = open("/dev/urandom", O_RDONLY); + if (fd >= 0) + { + while (done < sizeof(key)) + { + len = read(fd, key + done, sizeof(key) - done); + if (len < 0) + { + break; + } + done += len; + } + close(fd); + } + /* on error we use random() to generate the key (better than nothing) */ + if (done < sizeof(key)) + { + srandom(time(NULL) + getpid()); + for (; done < sizeof(key); done++) + { + key[done] = (u_char)random(); + } + } +} + /** * Described in header. */ u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash) { + pthread_once(&key_allocated, allocate_key); /* we could use a mac of the previous hash, but this is faster */ return chunk_mac_inc(chunk, key, ((u_int64_t)hash) << 32 | hash); } @@ -716,6 +760,7 @@ u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash) */ u_int32_t chunk_hash(chunk_t chunk) { + pthread_once(&key_allocated, allocate_key); return chunk_mac(chunk, key); }