aboutsummaryrefslogtreecommitdiff
path: root/util/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/random.c')
-rw-r--r--util/random.c84
1 files changed, 78 insertions, 6 deletions
diff --git a/util/random.c b/util/random.c
index 72c58a2b4df5..5d71fcfa4c12 100644
--- a/util/random.c
+++ b/util/random.c
@@ -60,10 +60,25 @@
#include "config.h"
#include "util/random.h"
#include "util/log.h"
+#ifdef HAVE_SSL
#include <openssl/rand.h>
#include <openssl/rc4.h>
#include <openssl/err.h>
+#elif defined(HAVE_NSS)
+/* nspr4 */
+#include "prerror.h"
+/* nss3 */
+#include "secport.h"
+#include "pk11pub.h"
+#endif
+/**
+ * Max random value. Similar to RAND_MAX, but more portable
+ * (mingw uses only 15 bits random).
+ */
+#define MAX_VALUE 0x7fffffff
+
+#ifdef HAVE_SSL
/**
* Struct with per-thread random state.
* Keeps SSL types away from the header file.
@@ -78,12 +93,6 @@ struct ub_randstate {
/** Size of key to use (must be multiple of 8) */
#define SEED_SIZE 24
-/**
- * Max random value. Similar to RAND_MAX, but more portable
- * (mingw uses only 15 bits random).
- */
-#define MAX_VALUE 0x7fffffff
-
/** Number of bytes to reseed after */
#define REKEY_BYTES (1 << 24)
@@ -140,6 +149,16 @@ ub_arc4random_stir(struct ub_randstate* s, struct ub_randstate* from)
return;
}
}
+#ifdef HAVE_FIPS_MODE
+ if(FIPS_mode()) {
+ /* RC4 is not allowed, get some trustworthy randomness */
+ /* double certainty here, this routine should not be
+ * called in FIPS_mode */
+ memset(rand_buf, 0, sizeof(rand_buf));
+ s->rc4_ready = REKEY_BYTES;
+ return;
+ }
+#endif /* FIPS_MODE */
RC4_set_key(&s->rc4, SEED_SIZE, (unsigned char*)rand_buf);
/*
@@ -164,6 +183,9 @@ ub_initstate(unsigned int seed, struct ub_randstate* from)
return NULL;
}
ub_systemseed(seed);
+#ifdef HAVE_FIPS_MODE
+ if(!FIPS_mode())
+#endif
ub_arc4random_stir(s, from);
return s;
}
@@ -172,6 +194,20 @@ long int
ub_random(struct ub_randstate* s)
{
unsigned int r = 0;
+#ifdef HAVE_FIPS_MODE
+ if(FIPS_mode()) {
+ /* RC4 is not allowed, get some trustworthy randomness */
+ /* we use pseudo bytes: it tries to return secure randomness
+ * but returns 'something' if that fails. We need something
+ * else if it fails, because we cannot block here */
+ if(RAND_pseudo_bytes((unsigned char*)&r, (int)sizeof(r))
+ == -1) {
+ log_err("FIPSmode, no arc4random but RAND failed "
+ "(error %ld)", ERR_get_error());
+ }
+ return (long int)((r) % (((unsigned)MAX_VALUE + 1)));
+ }
+#endif /* FIPS_MODE */
if (s->rc4_ready <= 0) {
ub_arc4random_stir(s, NULL);
}
@@ -182,6 +218,42 @@ ub_random(struct ub_randstate* s)
return (long int)((r) % (((unsigned)MAX_VALUE + 1)));
}
+#elif defined(HAVE_NSS)
+
+/* not much to remember for NSS since we use its pk11_random, placeholder */
+struct ub_randstate {
+ int ready;
+};
+
+void ub_systemseed(unsigned int ATTR_UNUSED(seed))
+{
+}
+
+struct ub_randstate* ub_initstate(unsigned int ATTR_UNUSED(seed),
+ struct ub_randstate* ATTR_UNUSED(from))
+{
+ struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s));
+ if(!s) {
+ log_err("malloc failure in random init");
+ return NULL;
+ }
+ return s;
+}
+
+long int ub_random(struct ub_randstate* ATTR_UNUSED(state))
+{
+ long int x;
+ /* random 31 bit value. */
+ SECStatus s = PK11_GenerateRandom((unsigned char*)&x, (int)sizeof(x));
+ if(s != SECSuccess) {
+ log_err("PK11_GenerateRandom error: %s",
+ PORT_ErrorToString(PORT_GetError()));
+ }
+ return x & MAX_VALUE;
+}
+
+#endif /* HAVE_SSL or HAVE_NSS */
+
long int
ub_random_max(struct ub_randstate* state, long int x)
{