Page MenuHomeFreeBSD

D1956.id4108.diff
No OneTemporary

D1956.id4108.diff

Index: sys/dev/random/dummy_rng.c
===================================================================
--- sys/dev/random/dummy_rng.c
+++ sys/dev/random/dummy_rng.c
@@ -63,40 +63,6 @@
#ifdef RANDOM_DEBUG
printf("random: %s\n", __func__);
#endif
-
- randomdev_init_reader(dummy_random_read_phony);
-}
-
-/* This is used only by the internal read_random(9) call, and then only
- * if no entropy processor is loaded.
- *
- * Make a token effort to provide _some_ kind of output. No warranty of
- * the quality of this output is made, mainly because its lousy.
- *
- * This is only used by the internal read_random(9) call when no other
- * adaptor is active.
- *
- * It has external scope due to the way things work in
- * randomdev_[de]init_reader() that the rest of the world doesn't need to
- * know about.
- *
- * Caveat Emptor.
- */
-void
-dummy_random_read_phony(uint8_t *buf, u_int count)
-{
- /* If no entropy device is loaded, don't spam the console with warnings */
- u_long randval;
- size_t size, i;
-
- /* srandom() is called in kern/init_main.c:proc0_post() */
-
- /* Fill buf[] with random(9) output */
- for (i = 0; i < count; i += sizeof(randval)) {
- randval = random();
- size = MIN(count - i, sizeof(randval));
- memcpy(buf + i, &randval, (size_t)size);
- }
}
struct random_adaptor randomdev_dummy = {
Index: sys/dev/random/fortuna.c
===================================================================
--- sys/dev/random/fortuna.c
+++ sys/dev/random/fortuna.c
@@ -158,7 +158,7 @@
/* Set up a lock for the reseed process */
#ifdef _KERNEL
- mtx_init(&random_reseed_mtx, "reseed mutex", NULL, MTX_DEF);
+ mtx_init(&random_reseed_mtx, "reseed mutex", NULL, MTX_SPIN);
#else /* !_KERNEL */
mtx_init(&random_reseed_mtx, mtx_plain);
#endif /* _KERNEL */
@@ -220,7 +220,7 @@
u_int pl;
/* We must be locked for all this as plenty of state gets messed with */
- mtx_lock(&random_reseed_mtx);
+ mtx_lock_spin(&random_reseed_mtx);
/* Accumulate the event into the appropriate pool
* where each event carries the destination information
@@ -234,7 +234,7 @@
fortuna_state.pool[pl].length = MIN(fortuna_state.pool[pl].length, MAXPOOLSIZE);
/* Done with state-messing */
- mtx_unlock(&random_reseed_mtx);
+ mtx_unlock_spin(&random_reseed_mtx);
}
/* F&S - Reseed() */
@@ -327,7 +327,7 @@
u_int seedlength;
/* We must be locked for all this as plenty of state gets messed with */
- mtx_lock(&random_reseed_mtx);
+ mtx_lock_spin(&random_reseed_mtx);
/* if buf == NULL and bytecount == 0 then this is the pre-read. */
/* if buf == NULL and bytecount != 0 then this is the post-read; ignore. */
@@ -385,7 +385,7 @@
else
random_fortuna_genrandom(buf, bytecount);
- mtx_unlock(&random_reseed_mtx);
+ mtx_unlock_spin(&random_reseed_mtx);
}
/* Internal function to hand external entropy to the PRNG */
@@ -416,14 +416,14 @@
memset(temp, 0, KEYSIZE);
/* We must be locked for all this as plenty of state gets messed with */
- mtx_lock(&random_reseed_mtx);
+ mtx_lock_spin(&random_reseed_mtx);
randomdev_hash_init(&fortuna_start_cache.hash);
reseed(fortuna_start_cache.junk, MIN(PAGE_SIZE, fortuna_start_cache.length));
memset(fortuna_start_cache.junk, 0, sizeof(fortuna_start_cache.junk));
- mtx_unlock(&random_reseed_mtx);
+ mtx_unlock_spin(&random_reseed_mtx);
}
void
Index: sys/dev/random/randomdev.h
===================================================================
--- sys/dev/random/randomdev.h
+++ sys/dev/random/randomdev.h
@@ -41,9 +41,6 @@
void randomdev_deinit_harvester(void);
void randomdev_deinit_reader(void);
-/* Stub/fake routines for when no entropy processor is loaded */
-extern void dummy_random_read_phony(uint8_t *, u_int);
-
/* kern.random sysctls */
#ifdef SYSCTL_DECL /* from sysctl.h */
SYSCTL_DECL(_kern_random);
Index: sys/dev/random/randomdev.c
===================================================================
--- sys/dev/random/randomdev.c
+++ sys/dev/random/randomdev.c
@@ -214,7 +214,7 @@
*/
/* Hold the address of the routine which is actually called */
-static void (*read_func)(uint8_t *, u_int) = dummy_random_read_phony;
+static void (*read_func)(uint8_t *, u_int);
/* Initialise the reader when/if it is loaded */
void
@@ -229,7 +229,7 @@
randomdev_deinit_reader(void)
{
- read_func = dummy_random_read_phony;
+ read_func = NULL;
}
/* Kernel API version of read_random().
@@ -237,10 +237,10 @@
* the entropy device.
*/
int
-read_random(void *buf, int count)
+priv_read_random(void *buf, int count)
{
- if (count < 0)
+ if (count <= 0 || read_func == NULL)
return 0;
read_func(buf, count);
Index: sys/dev/random/yarrow.c
===================================================================
--- sys/dev/random/yarrow.c
+++ sys/dev/random/yarrow.c
@@ -147,7 +147,7 @@
/* Set up the lock for the reseed/gate state */
#ifdef _KERNEL
- mtx_init(&random_reseed_mtx, "reseed mutex", NULL, MTX_DEF);
+ mtx_init(&random_reseed_mtx, "reseed mutex", NULL, MTX_SPIN);
#else /* !_KERNEL */
mtx_init(&random_reseed_mtx, mtx_plain);
#endif /* _KERNEL */
@@ -265,7 +265,7 @@
{
u_int pl;
- mtx_lock(&random_reseed_mtx);
+ mtx_lock_spin(&random_reseed_mtx);
/* Accumulate the event into the appropriate pool
* where each event carries the destination information.
@@ -278,7 +278,7 @@
random_yarrow_post_insert();
- mtx_unlock(&random_reseed_mtx);
+ mtx_unlock_spin(&random_reseed_mtx);
}
/* Process a block of data suspected to be slightly stochastic */
@@ -440,7 +440,7 @@
return;
/* The reseed task must not be jumped on */
- mtx_lock(&random_reseed_mtx);
+ mtx_lock_spin(&random_reseed_mtx);
blockcount = (bytecount + BLOCKSIZE - 1)/BLOCKSIZE;
for (i = 0; i < blockcount; i++) {
@@ -461,7 +461,7 @@
}
}
- mtx_unlock(&random_reseed_mtx);
+ mtx_unlock_spin(&random_reseed_mtx);
}
/* Internal function to hand external entropy to the PRNG */
@@ -471,7 +471,7 @@
uintmax_t timestamp;
/* We must be locked for all this as plenty of state gets messed with */
- mtx_lock(&random_reseed_mtx);
+ mtx_lock_spin(&random_reseed_mtx);
timestamp = get_cyclecount();
randomdev_hash_iterate(&yarrow_state.start_cache.hash, &timestamp, sizeof(timestamp));
@@ -495,7 +495,7 @@
random_yarrow_process_buffer(yarrow_state.start_cache.junk, KEYSIZE);
memset(yarrow_state.start_cache.junk, 0, KEYSIZE);
- mtx_unlock(&random_reseed_mtx);
+ mtx_unlock_spin(&random_reseed_mtx);
}
static void
@@ -517,9 +517,9 @@
random_yarrow_reseed(void)
{
- mtx_lock(&random_reseed_mtx);
+ mtx_lock_spin(&random_reseed_mtx);
reseed(SLOW);
- mtx_unlock(&random_reseed_mtx);
+ mtx_unlock_spin(&random_reseed_mtx);
}
int
Index: sys/libkern/arc4random.c
===================================================================
--- sys/libkern/arc4random.c
+++ sys/libkern/arc4random.c
@@ -14,12 +14,17 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/endian.h>
#include <sys/random.h>
#include <sys/libkern.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/time.h>
+#include <machine/cpu.h>
+
+#include <crypto/sha2/sha256.h>
+
#define ARC4_RESEED_BYTES 65536
#define ARC4_RESEED_SECONDS 300
#define ARC4_KEYBYTES (256 / 8)
@@ -44,6 +49,29 @@
*b = c;
}
+static int
+get_last_resort_seed(uint8_t *key, int cnt)
+{
+ struct timespec ts;
+ uint8_t buf[8 + sizeof ts];
+ int pos;
+
+ KASSERT(cnt >= 32, ("not enough space for sha256 digest"));
+
+ pos = 0;
+
+ be64enc(&buf[pos], get_cyclecount());
+ pos += 8;
+
+ nanotime(&ts);
+ memcpy(&buf[pos], &ts, sizeof ts);
+ pos += sizeof ts;
+
+ SHA256_Data(&buf[0], pos, key);
+
+ return 32;
+}
+
/*
* Stir our S-box.
*/
@@ -58,15 +86,18 @@
* XXX read_random() returns unsafe numbers if the entropy
* device is not loaded -- MarkM.
*/
- r = read_random(key, ARC4_KEYBYTES);
+ r = priv_read_random(key, ARC4_KEYBYTES);
getmicrouptime(&tv_now);
- mtx_lock(&arc4_mtx);
- /* If r == 0 || -1, just use what was on the stack. */
- if (r > 0) {
- for (n = r; n < sizeof(key); n++)
- key[n] = key[n % r];
+ mtx_lock_spin(&arc4_mtx);
+ if (r <= 0) {
+ r = get_last_resort_seed(key, sizeof key);
+
+ /* XXX - we should always reseed till random(4) is ready */
}
+ for (n = r; n < sizeof(key); n++)
+ key[n] = key[n % r];
+
for (n = 0; n < 256; n++) {
arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256;
arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]);
@@ -84,7 +115,7 @@
*/
for (n = 0; n < 256*4; n++)
arc4_randbyte();
- mtx_unlock(&arc4_mtx);
+ mtx_unlock_spin(&arc4_mtx);
}
/*
@@ -95,7 +126,7 @@
{
int n;
- mtx_init(&arc4_mtx, "arc4_mtx", NULL, MTX_DEF);
+ mtx_init(&arc4_mtx, "arc4_mtx", NULL, MTX_SPIN);
arc4_i = arc4_j = 0;
for (n = 0; n < 256; n++)
arc4_sbox[n] = (u_int8_t) n;
@@ -138,12 +169,12 @@
(tv.tv_sec > arc4_t_reseed))
arc4_randomstir();
- mtx_lock(&arc4_mtx);
+ mtx_lock_spin(&arc4_mtx);
arc4_numruns += len;
p = ptr;
while (len--)
*p++ = arc4_randbyte();
- mtx_unlock(&arc4_mtx);
+ mtx_unlock_spin(&arc4_mtx);
}
uint32_t
Index: sys/libkern/random.c
===================================================================
--- sys/libkern/random.c
+++ sys/libkern/random.c
@@ -32,47 +32,110 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#ifndef UNIT_TEST
#include <sys/libkern.h>
+#endif
-#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */
+#ifdef UNIT_TEST
+#include <sys/param.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
-static u_long randseed = 937186357; /* after srandom(1), NSHUFF counted */
+uint64_t
+random64(void)
+{
+ uint64_t b;
+
+ arc4random_buf(&b, sizeof b);
+
+ return b;
+}
+#endif
void
-srandom(seed)
- u_long seed;
+srandom(u_long seed __unused)
{
- int i;
-
- randseed = seed;
- for (i = 0; i < NSHUFF; i++)
- (void)random();
}
/*
- * Pseudo-random number generator for randomizing the profiling clock,
- * and whatever else we might use it for. The result is uniform on
- * [0, 2^31 - 1].
+ * Return a uniformly random value over [0, top).
+ *
+ * Use the simple algorithm that if random value v is in the range
+ * [0, n * top) where n is an integer, return v % top. If v is
+ * equal to or larger than n * top, it would not be uniform, so pick a
+ * new v and try again.
*/
-u_long
-random()
+uint64_t
+random_uniform(uint64_t top)
+{
+ uint64_t r;
+ uint64_t min;
+
+ if (top > 0x8000000000000000ULL)
+ min = 1 + ~top;
+ else
+ min = ((0xffffffffffffffffULL - (top * 2)) + 1) % top;
+
+ for (;;) {
+ r = random64();
+ if (r >= min)
+ return r % top;
+ }
+}
+
+#ifdef UNIT_TEST
+int
+testuniform(int cnt, uint64_t top)
{
- register long x, hi, lo, t;
+ int i;
+ uint64_t v;
+
+ printf("testing: %zu\n", (uintmax_t)top);
+
+ for (i = 0; i < cnt; i++) {
+ v = random_uniform(top);
+ if (v >= top)
+ return 0;
+ }
+
+ return 0;
+}
+
+#define NTESTS 10000000
+
+struct {
+ int cnt;
+ uint64_t top;
+} testvect[] = {
+ { 10000, 2 },
+ { 10000, 3 },
+ { 10000, 4 },
+ { 10000, 5 },
+ { 10000, 17 },
+ { 100000, 997 },
+ { NTESTS, 6287 },
+ { NTESTS, 65536 },
+ { NTESTS, 0x8000000000000000ULL + 1 },
+ { NTESTS, 0x8000000000000000ULL + 1001 },
+ { NTESTS, -1ULL },
+ { NTESTS, -1001ULL },
+};
+
+int
+main()
+{
+ int i;
+ int err;
+
+ for (i = 0; i < nitems(testvect); i++) {
+ if (testuniform(testvect[i].cnt, testvect[i].top)) {
+ printf("failed on %zu\n", (uintmax_t)testvect[i].top);
+ err = 1;
+ }
+ }
- /*
- * Compute x[n + 1] = (7^5 * x[n]) mod (2^31 - 1).
- * From "Random number generators: good ones are hard to find",
- * Park and Miller, Communications of the ACM, vol. 31, no. 10,
- * October 1988, p. 1195.
- */
- /* Can't be initialized with 0, so use another value. */
- if ((x = randseed) == 0)
- x = 123459876;
- hi = x / 127773;
- lo = x % 127773;
- t = 16807 * lo - 2836 * hi;
- if (t < 0)
- t += 0x7fffffff;
- randseed = t;
- return (t);
+ return err;
}
+#endif
Index: sys/sys/libkern.h
===================================================================
--- sys/sys/libkern.h
+++ sys/sys/libkern.h
@@ -75,10 +75,43 @@
#define ARC4_ENTR_SEED 2 /* Reseeding. */
extern int arc4rand_iniseed_state;
-/* Prototypes for non-quad routines. */
-struct malloc_type;
+/* Deprecated random functions */
uint32_t arc4random(void);
void arc4rand(void *ptr, u_int len, int reseed);
+void srandom(u_long);
+
+/* Random functions */
+static __inline uint32_t
+random(void)
+{
+ uint32_t r;
+
+ arc4rand((uint8_t *)&r, sizeof r, 0);
+
+ return r;
+}
+
+static __inline uint64_t
+random64(void)
+{
+ uint64_t r;
+
+ arc4rand((uint8_t *)&r, sizeof r, 0);
+
+ return r;
+}
+
+static __inline void
+random_buf(uint8_t *buf, size_t cnt)
+{
+
+ arc4rand(buf, cnt, 0);
+}
+
+uint64_t random_uniform(uint64_t);
+
+/* Prototypes for non-quad routines. */
+struct malloc_type;
int bcmp(const void *, const void *, size_t);
int timingsafe_bcmp(const void *, const void *, size_t);
void *bsearch(const void *, const void *, size_t,
@@ -109,9 +142,7 @@
int (*compar)(const void *, const void *));
void qsort_r(void *base, size_t nmemb, size_t size, void *thunk,
int (*compar)(void *, const void *, const void *));
-u_long random(void);
int scanc(u_int, const u_char *, const u_char *, int);
-void srandom(u_long);
int strcasecmp(const char *, const char *);
char *strcat(char * __restrict, const char * __restrict);
char *strchr(const char *, int);
Index: sys/sys/random.h
===================================================================
--- sys/sys/random.h
+++ sys/sys/random.h
@@ -31,7 +31,20 @@
#ifdef _KERNEL
-int read_random(void *, int);
+#include <sys/libkern.h>
+
+/* Deprecated */
+static __inline int
+read_random(void *buf, int cnt)
+{
+
+ arc4rand(buf, cnt, 0);
+
+ return cnt;
+}
+
+/* Temporary internal interface to random adaptors */
+int priv_read_random(void *, int);
/*
* Note: if you add or remove members of random_entropy_source, remember to also update the

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 17, 3:26 PM (2 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25408985
Default Alt Text
D1956.id4108.diff (13 KB)

Event Timeline