Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F136199466
D1956.id4108.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D1956.id4108.diff
View Options
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, ×tamp, 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
Details
Attached
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)
Attached To
Mode
D1956: Unify kernel randomness API
Attached
Detach File
Event Timeline
Log In to Comment