aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2013-03-26 19:25:55 +0100
committerTobias Brunner <tobias@strongswan.org>2013-06-11 11:03:11 +0200
commitbed4bc1327a43f8e4c494e7fdf71680ffcaa26f1 (patch)
tree2d36c42703a5dab1e61227f8c68fa354c5a4a01d
parentd1953fe403a91d6f7a08fd4cdd0b01cf7106733d (diff)
downloadstrongswan-bed4bc1327a43f8e4c494e7fdf71680ffcaa26f1.tar.bz2
strongswan-bed4bc1327a43f8e4c494e7fdf71680ffcaa26f1.tar.xz
Randomly allocate chunk_hash() key during first use
This avoids hash flooding attacks.
-rw-r--r--src/libstrongswan/utils/chunk.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c
index 9033cbdaf..61c7bd5a5 100644
--- a/src/libstrongswan/utils/chunk.c
+++ b/src/libstrongswan/utils/chunk.c
@@ -16,9 +16,12 @@
*/
#include <stdio.h>
+#include <sys/types.h>
#include <sys/stat.h>
+#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
+#include <pthread.h>
#include <ctype.h>
#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);
}