Use openssl's RAND_load_file() and RAND_bytes() to get randomness.
[paraslash.git] / crypt.c
diff --git a/crypt.c b/crypt.c
index 73eebe180dbe2c32718b5dc7fd271f7ca4b329b1..580974d7d74a6b97d1f4b2d6a436adc98ba7408b 100644 (file)
--- a/crypt.c
+++ b/crypt.c
 #include "error.h"
 #include "string.h"
 #include "crypt.h"
+#include <openssl/rand.h>
+#include <openssl/err.h>
+
+/**
+ * Fill a buffer with random content.
+ *
+ * \param buf The buffer to fill.
+ * \param num The size of \a buf in bytes.
+ *
+ * This function puts \a num cryptographically strong pseudo-random bytes into
+ * buf. If libssl can not guarantee an unpredictable byte sequence (for example
+ * because the PRNG has not been seeded with enough randomness) the function
+ * logs an error message and calls exit().
+ */
+void get_random_bytes_or_die(unsigned char *buf, int num)
+{
+       unsigned long err;
+
+       /* RAND_bytes() returns 1 on success, 0 otherwise. */
+       if (RAND_bytes(buf, num) == 1)
+               return;
+       err = ERR_get_error();
+       PARA_EMERG_LOG("%s\n", ERR_reason_error_string(err));
+       exit(EXIT_FAILURE);
+}
+
+/**
+ * Seed pseudo random number generators.
+ *
+ * This function reads 64 bytes from /dev/urandom and adds them to the SSL
+ * PRNG. It also seeds the PRNG used by random() with a random seed obtained
+ * from SSL. If /dev/random could not be read, an error message is logged and
+ * the function calls exit().
+ *
+ * \sa RAND_load_file(3), \ref get_random_bytes_or_die(), srandom(3),
+ * random(3), \ref para_random().
+ */
+void init_random_seed_or_die(void)
+{
+       int seed, ret = RAND_load_file("/dev/urandom", 64);
+
+       if (ret != 64) {
+               PARA_EMERG_LOG("could not seed PRNG (ret = %d)\n", ret);
+               exit(EXIT_FAILURE);
+       }
+       get_random_bytes_or_die((unsigned char *)&seed, sizeof(seed));
+       srandom(seed);
+}
 
 static EVP_PKEY *load_key(const char *file, int private)
 {