From 9647fbc94e6bbef6553efe93a3fe0249a7c9fa47 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Thu, 2 Apr 2009 15:24:44 +0000 Subject: [PATCH] moved type and constants for random data to include file; added consistency check in random; added source of randomness internal to random using timing; only retrieve random bins that are full. --- drivers/random/main.c | 102 ++++++++++++++++++++++++++--------- drivers/random/random.c | 14 ++--- drivers/random/random.h | 8 ++- include/minix/com.h | 1 + include/minix/syslib.h | 1 + include/minix/sysutil.h | 2 + include/minix/type.h | 16 ++++++ kernel/arch/i386/do_int86.c | 2 +- kernel/config.h | 5 -- kernel/const.h | 3 -- kernel/glo.h | 2 +- kernel/main.c | 2 + kernel/proto.h | 1 - kernel/system.c | 22 -------- kernel/system/do_getinfo.c | 30 +++++++++-- kernel/system/do_irqctl.c | 2 +- kernel/type.h | 9 +--- lib/sysutil/Makefile.in | 1 + lib/sysutil/get_randomness.c | 34 ++++++++++++ 19 files changed, 177 insertions(+), 80 deletions(-) create mode 100644 lib/sysutil/get_randomness.c diff --git a/drivers/random/main.c b/drivers/random/main.c index a032205f5..d1d135eef 100644 --- a/drivers/random/main.c +++ b/drivers/random/main.c @@ -6,9 +6,7 @@ #include "../drivers.h" #include "../libdriver/driver.h" #include -#include "../../kernel/const.h" -#include "../../kernel/config.h" -#include "../../kernel/type.h" +#include #include "assert.h" #include "random.h" @@ -32,6 +30,7 @@ FORWARD _PROTOTYPE( void r_init, (void) ); FORWARD _PROTOTYPE( int r_ioctl, (struct driver *dp, message *m_ptr, int safe) ); FORWARD _PROTOTYPE( void r_geometry, (struct partition *entry) ); FORWARD _PROTOTYPE( void r_random, (struct driver *dp, message *m_ptr) ); +FORWARD _PROTOTYPE( void r_updatebin, (int source, struct k_randomness_bin *rb)); /* Entry points to this driver. */ PRIVATE struct driver r_dtab = { @@ -197,9 +196,30 @@ message *m_ptr; *===========================================================================*/ PRIVATE void r_init() { - /* Initialize this task. All minor devices are initialized one by one. */ + static struct k_randomness krandom; + int i, s; + random_init(); r_random(NULL, NULL); /* also set periodic timer */ + + /* Retrieve first randomness buffer with parameters. */ + if (OK != (s=sys_getrandomness(&krandom))) { + report("RANDOM", "sys_getrandomness failed", s); + exit(1); + } + + /* Do sanity check on parameters. */ + if(krandom.random_sources != RANDOM_SOURCES || + krandom.random_elements != RANDOM_ELEMENTS) { + printf("random: parameters (%d, %d) don't match kernel's (%d, %d)\n", + RANDOM_SOURCES, RANDOM_ELEMENTS, + krandom.random_sources, krandom.random_elements); + exit(1); + } + + /* Feed initial batch. */ + for(i = 0; i < RANDOM_SOURCES; i++) + r_updatebin(i, &krandom.bin[i]); } /*===========================================================================* @@ -221,6 +241,45 @@ int safe; /* safe i/o? */ return(OK); } +#define UPDATE(binnumber, bp, startitem, elems) { \ + rand_t *r, *r2; \ + int n = elems, item = startitem;\ + int high; \ + assert(binnumber >= 0 && binnumber < RANDOM_SOURCES); \ + assert(item >= 0 && item < RANDOM_ELEMENTS); \ + if(n > 0) { \ + high = item+n-1; \ + assert(high >= item); \ + assert(high >= 0 && high < RANDOM_ELEMENTS); \ + r = &bp->r_buf[item]; \ + r2 = &bp->r_buf[high]; \ + random_update(binnumber, r, n); \ + } \ +} + +PRIVATE void r_updatebin(int source, struct k_randomness_bin *rb) +{ + int r_next, r_size, r_high; + + r_next= rb->r_next; + r_size= rb->r_size; + + assert(r_next >= 0 && r_next < RANDOM_ELEMENTS); + assert(r_size >= 0 && r_size <= RANDOM_ELEMENTS); + + r_high= r_next+r_size; + + if (r_high <= RANDOM_ELEMENTS) { + UPDATE(source, rb, r_next, r_size); + } else { + assert(r_next < RANDOM_ELEMENTS); + UPDATE(source, rb, r_next, RANDOM_ELEMENTS-r_next); + UPDATE(source, rb, 0, r_high-RANDOM_ELEMENTS); + } + + return; +} + /*============================================================================* * r_random * *============================================================================*/ @@ -229,30 +288,21 @@ struct driver *dp; /* pointer to driver structure */ message *m_ptr; /* pointer to alarm message */ { /* Fetch random information from the kernel to update /dev/random. */ - int i, s, r_next, r_size, r_high; - struct randomness krandom; + int s; + static int bin = 0; + static struct k_randomness_bin krandom_bin; + u32_t hi, lo; + rand_t r; - if (OK != (s=sys_getrandomness(&krandom))) - report("RANDOM", "sys_getrandomness failed", s); + bin = (bin+1) % RANDOM_SOURCES; - for (i= 0; i= RANDOM_SOURCES) + if (source < 0 || source >= TOTAL_SOURCES) panic("memory", "random_update: bad source", source); for (i= 0; i + +/* randomness struct: random sources after interrupts: */ +#define RANDOM_SOURCES NR_IRQ_VECTORS +#define RANDOM_ELEMENTS 64 + +typedef unsigned short rand_t; + +struct k_randomness { + int random_elements, random_sources; + struct k_randomness_bin { + int r_next; /* next index to write */ + int r_size; /* number of random elements */ + rand_t r_buf[RANDOM_ELEMENTS]; /* buffer for random info */ + } bin[RANDOM_SOURCES]; +}; #endif /* _TYPE_H */ diff --git a/kernel/arch/i386/do_int86.c b/kernel/arch/i386/do_int86.c index 9ff1db876..6b7510e1a 100644 --- a/kernel/arch/i386/do_int86.c +++ b/kernel/arch/i386/do_int86.c @@ -36,7 +36,7 @@ register message *m_ptr; /* pointer to request message */ * not very random. */ lock; - get_randomness(CLOCK_IRQ); + get_randomness(&krandom, CLOCK_IRQ); unlock; return(OK); diff --git a/kernel/config.h b/kernel/config.h index 0fb906db7..2c0203930 100644 --- a/kernel/config.h +++ b/kernel/config.h @@ -49,11 +49,6 @@ */ #define P_NAME_LEN 8 -/* Buffer to gather randomness. This is used to generate a random stream by - * the MEMORY driver when reading from /dev/random. - */ -#define RANDOM_ELEMENTS 32 - /* This section contains defines for valuable system resources that are used * by device drivers. The number of elements of the vectors is determined by * the maximum needed by any given driver. The number of interrupt hooks may diff --git a/kernel/const.h b/kernel/const.h index 62588b35c..c3f1ea008 100755 --- a/kernel/const.h +++ b/kernel/const.h @@ -25,9 +25,6 @@ #define _SRC_ 0 #define _DST_ 1 -/* Number of random sources */ -#define RANDOM_SOURCES 16 - #define get_sys_bit(map,bit) \ ( MAP_CHUNK(map.chunk,bit) & (1 << CHUNK_OFFSET(bit) ) #define get_sys_bits(map,bit) \ diff --git a/kernel/glo.h b/kernel/glo.h index 8e240324d..e3ed5735b 100755 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -25,7 +25,7 @@ EXTERN char shutdown_started; /* TRUE after shutdowns / reboots */ EXTERN struct kinfo kinfo; /* kernel information for users */ EXTERN struct machine machine; /* machine information for users */ EXTERN struct kmessages kmess; /* diagnostic messages in kernel */ -EXTERN struct randomness krandom; /* gather kernel random information */ +EXTERN struct k_randomness krandom; /* gather kernel random information */ EXTERN struct loadinfo kloadinfo; /* status of load average */ /* Process scheduling information and the kernel reentry count. */ diff --git a/kernel/main.c b/kernel/main.c index 05bf762fd..1ef2474aa 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -175,6 +175,8 @@ PUBLIC void main() cprof_procs_no = 0; /* init nr of hash table slots used */ vm_running = 0; + krandom.random_sources = RANDOM_SOURCES; + krandom.random_elements = RANDOM_ELEMENTS; /* MINIX is now ready. All boot image processes are on the ready queue. * Return to the assembly code to start running the current process. diff --git a/kernel/proto.h b/kernel/proto.h index 71edffa56..a3070efdd 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -58,7 +58,6 @@ _PROTOTYPE( int get_priv, (register struct proc *rc, int proc_type) ); _PROTOTYPE( void send_sig, (int proc_nr, int sig_nr) ); _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) ); _PROTOTYPE( void sys_task, (void) ); -_PROTOTYPE( void get_randomness, (int source) ); #define numap_local(proc_nr, vir_addr, bytes) \ umap_local(proc_addr(proc_nr), D, (vir_addr), (bytes)) _PROTOTYPE( phys_bytes umap_grant, (struct proc *, cp_grant_id_t, diff --git a/kernel/system.c b/kernel/system.c index 03f4f9d3c..77642f62b 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -290,28 +290,6 @@ int proc_type; /* system or user process flag */ return(OK); } -/*===========================================================================* - * get_randomness * - *===========================================================================*/ -PUBLIC void get_randomness(source) -int source; -{ -/* Use architecture-dependent high-resolution clock for - * raw entropy gathering. - */ - int r_next; - unsigned long tsc_high, tsc_low; - - source %= RANDOM_SOURCES; - r_next= krandom.bin[source].r_next; - read_tsc(&tsc_high, &tsc_low); - krandom.bin[source].r_buf[r_next] = tsc_low; - if (krandom.bin[source].r_size < RANDOM_ELEMENTS) { - krandom.bin[source].r_size ++; - } - krandom.bin[source].r_next = (r_next + 1 ) % RANDOM_ELEMENTS; -} - /*===========================================================================* * send_sig * *===========================================================================*/ diff --git a/kernel/system/do_getinfo.c b/kernel/system/do_getinfo.c index 5c4062e10..e40889e1c 100644 --- a/kernel/system/do_getinfo.c +++ b/kernel/system/do_getinfo.c @@ -31,6 +31,7 @@ register message *m_ptr; /* pointer to request message */ int proc_nr, nr_e, nr; struct proc *caller; phys_bytes ph; + int wipe_rnd_bin = -1; caller = proc_addr(who_p); @@ -112,7 +113,7 @@ register message *m_ptr; /* pointer to request message */ break; } case GET_RANDOMNESS: { - static struct randomness copy; /* copy to keep counters */ + static struct k_randomness copy; /* copy to keep counters */ int i; copy = krandom; @@ -120,10 +121,28 @@ register message *m_ptr; /* pointer to request message */ krandom.bin[i].r_size = 0; /* invalidate random data */ krandom.bin[i].r_next = 0; } - length = sizeof(struct randomness); + length = sizeof(copy); src_vir = (vir_bytes) © break; } + case GET_RANDOMNESS_BIN: { + int i, bin = m_ptr->I_VAL_LEN2_E; + + if(bin < 0 || bin >= RANDOM_SOURCES) { + kprintf("SYSTEM: GET_RANDOMNESS_BIN: %d out of range\n", bin); + return EINVAL; + } + + if(krandom.bin[bin].r_size < RANDOM_ELEMENTS) + return ENOENT; + + length = sizeof(krandom.bin[bin]); + src_vir = (vir_bytes) &krandom.bin[bin]; + + wipe_rnd_bin = bin; + + break; + } case GET_KMESSAGES: { length = sizeof(struct kmessages); src_vir = (vir_bytes) &kmess; @@ -158,7 +177,12 @@ register message *m_ptr; /* pointer to request message */ if((ph=umap_local(caller, D, (vir_bytes) m_ptr->I_VAL_PTR,length)) == 0) return EFAULT; CHECKRANGE_OR_SUSPEND(caller, ph, length, 1); - data_copy(SYSTEM, src_vir, who_e, (vir_bytes) m_ptr->I_VAL_PTR, length); + if(data_copy(SYSTEM, src_vir, who_e, (vir_bytes) m_ptr->I_VAL_PTR, length) == OK) { + if(wipe_rnd_bin >= 0 && wipe_rnd_bin < RANDOM_SOURCES) { + krandom.bin[wipe_rnd_bin].r_size = 0; + krandom.bin[wipe_rnd_bin].r_next = 0; + } + } return(OK); } diff --git a/kernel/system/do_irqctl.c b/kernel/system/do_irqctl.c index 9625a9825..53893c391 100644 --- a/kernel/system/do_irqctl.c +++ b/kernel/system/do_irqctl.c @@ -142,7 +142,7 @@ irq_hook_t *hook; /* As a side-effect, the interrupt handler gathers random information by * timestamping the interrupt events. This is used for /dev/random. */ - get_randomness(hook->irq); + get_randomness(&krandom, hook->irq); /* Check if the handler is still alive. * If it's dead, this should never happen, as processes that die diff --git a/kernel/type.h b/kernel/type.h index 8f3b6864b..f09939737 100755 --- a/kernel/type.h +++ b/kernel/type.h @@ -2,6 +2,7 @@ #define TYPE_H #include +#include typedef _PROTOTYPE( void task_t, (void) ); @@ -27,14 +28,6 @@ struct boot_image { endpoint_t endpoint; /* endpoint number when started */ }; -struct randomness { - struct { - int r_next; /* next index to write */ - int r_size; /* number of random elements */ - unsigned short r_buf[RANDOM_ELEMENTS]; /* buffer for random info */ - } bin[RANDOM_SOURCES]; -}; - typedef unsigned long irq_policy_t; typedef unsigned long irq_id_t; diff --git a/lib/sysutil/Makefile.in b/lib/sysutil/Makefile.in index 4f348804f..a44addf98 100644 --- a/lib/sysutil/Makefile.in +++ b/lib/sysutil/Makefile.in @@ -10,6 +10,7 @@ libsys_FILES=" \ kprintf.c \ kputc.c \ tickdelay.c \ + get_randomness.c \ getuptime.c \ getuptime2.c \ env_get_prm.c \ diff --git a/lib/sysutil/get_randomness.c b/lib/sysutil/get_randomness.c new file mode 100644 index 000000000..a52a1e267 --- /dev/null +++ b/lib/sysutil/get_randomness.c @@ -0,0 +1,34 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +/*===========================================================================* + * get_randomness * + *===========================================================================*/ +PUBLIC void get_randomness(rand, source) +struct k_randomness *rand; +int source; +{ +/* Use architecture-dependent high-resolution clock for + * raw entropy gathering. + */ + int r_next; + unsigned long tsc_high, tsc_low; + + source %= RANDOM_SOURCES; + r_next= rand->bin[source].r_next; + read_tsc(&tsc_high, &tsc_low); + rand->bin[source].r_buf[r_next] = tsc_low; + if (rand->bin[source].r_size < RANDOM_ELEMENTS) { + rand->bin[source].r_size ++; + } + rand->bin[source].r_next = (r_next + 1 ) % RANDOM_ELEMENTS; +} + +