 cc17b27a2b
			
		
	
	
		cc17b27a2b
		
	
	
	
	
		
			
			3 sets of libraries are built now: . ack: all libraries that ack can compile (/usr/lib/i386/) . clang+elf: all libraries with minix headers (/usr/lib/) . clang+elf: all libraries with netbsd headers (/usr/netbsd/) Once everything can be compiled with netbsd libraries and headers, the /usr/netbsd hierarchy will be obsolete and its libraries compiled with netbsd headers will be installed in /usr/lib, and its headers in /usr/include. (i.e. minix libc and current minix headers set will be gone.) To use the NetBSD libc system (libraries + headers) before it is the default libc, see: http://wiki.minix3.org/en/DevelopersGuide/UsingNetBSDCode This wiki page also documents the maintenance of the patch files of minix-specific changes to imported NetBSD code. Changes in this commit: . libsys: Add NBSD compilation and create a safe NBSD-based libc. . Port rest of libraries (except libddekit) to new header system. . Enable compilation of libddekit with new headers. . Enable kernel compilation with new headers. . Enable drivers compilation with new headers. . Port legacy commands to new headers and libc. . Port servers to new headers. . Add <sys/sigcontext.h> in compat library. . Remove dependency file in tree. . Enable compilation of common/lib/libc/atomic in libsys . Do not generate RCSID strings in libc. . Temporarily disable zoneinfo as they are incompatible with NetBSD format . obj-nbsd for .gitignore . Procfs: use only integer arithmetic. (Antoine Leca) . Increase ramdisk size to create NBSD-based images. . Remove INCSYMLINKS handling hack. . Add nbsd_include/sys/exec_elf.h . Enable ELF compilation with NBSD libc. . Add 'make nbsdsrc' in tools to download reference NetBSD sources. . Automate minix-port.patch creation. . Avoid using fstavfs() as it is *extremely* slow and unneeded. . Set err() as PRIVATE to avoid name clash with libc. . [NBSD] servers/vm: remove compilation warnings. . u32 is not a long in NBSD headers. . UPDATING info on netbsd hierarchy . commands fixes for netbsd libc
		
			
				
	
	
		
			243 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| random.c
 | |
| 
 | |
| Random number generator.
 | |
| 
 | |
| The random number generator collects data from the kernel and compressed
 | |
| that data into a seed for a psuedo random number generator.
 | |
| */
 | |
| 
 | |
| #include <minix/drivers.h>
 | |
| #include "kernel/const.h"
 | |
| #include "assert.h"
 | |
| 
 | |
| #include "random.h"
 | |
| #ifdef __NBSD_LIBC
 | |
| #include <sys/sha2.h>
 | |
| #else
 | |
| #include <minix/sha2.h>
 | |
| #endif
 | |
| #include "aes/rijndael.h"
 | |
| 
 | |
| #define N_DERIV	16
 | |
| #define NR_POOLS 32
 | |
| #define MIN_SAMPLES	256	/* Number of samples needed in pool 0 for a
 | |
| 				 * re-seed.
 | |
| 				 */
 | |
| 
 | |
| PRIVATE unsigned long deriv[TOTAL_SOURCES][N_DERIV];
 | |
| PRIVATE int pool_ind[TOTAL_SOURCES];
 | |
| PRIVATE SHA256_CTX pool_ctx[NR_POOLS];
 | |
| PRIVATE unsigned samples= 0;
 | |
| PRIVATE int got_seeded= 0;
 | |
| PRIVATE u8_t random_key[2*AES_BLOCKSIZE];
 | |
| PRIVATE u32_t count_lo, count_hi;
 | |
| PRIVATE u32_t reseed_count;
 | |
| 
 | |
| FORWARD _PROTOTYPE( void add_sample, (int source, unsigned long sample)	);
 | |
| FORWARD _PROTOTYPE( void data_block, (rd_keyinstance *keyp,
 | |
| 							void *data)	);
 | |
| FORWARD _PROTOTYPE( void reseed, (void)					);
 | |
| 
 | |
| PUBLIC void random_init()
 | |
| {
 | |
| 	int i, j;
 | |
| 
 | |
| 	assert(&deriv[TOTAL_SOURCES-1][N_DERIV-1] ==
 | |
| 		&deriv[0][0] + TOTAL_SOURCES*N_DERIV -1);
 | |
| 
 | |
| 	for (i= 0; i<TOTAL_SOURCES; i++)
 | |
| 	{
 | |
| 		for (j= 0; j<N_DERIV; j++)
 | |
| 			deriv[i][j]= 0;
 | |
| 		pool_ind[i]= 0;
 | |
| 	}
 | |
| 	for (i= 0; i<NR_POOLS; i++)
 | |
| 		SHA256_Init(&pool_ctx[i]);
 | |
| 	count_lo= 0;
 | |
| 	count_hi= 0;
 | |
| 	reseed_count= 0;
 | |
| }
 | |
| 
 | |
| PUBLIC int random_isseeded()
 | |
| {
 | |
| 	if (got_seeded)
 | |
| 		return 1;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| PUBLIC void random_update(source, buf, count)
 | |
| int source;
 | |
| rand_t *buf;
 | |
| int count;
 | |
| {
 | |
| 	int i;
 | |
| 
 | |
| #if 0
 | |
| 	printf("random_update: got %d samples for source %d\n", count, source);
 | |
| #endif
 | |
| 	if (source < 0 || source >= TOTAL_SOURCES)
 | |
| 		panic("random_update: bad source: %d", source);
 | |
| 	for (i= 0; i<count; i++)
 | |
| 		add_sample(source, buf[i]);
 | |
| 	reseed();
 | |
| }
 | |
| 
 | |
| PUBLIC void random_getbytes(buf, size)
 | |
| void *buf;
 | |
| size_t size;
 | |
| {
 | |
| 	int n, r;
 | |
| 	u8_t *cp;
 | |
| 	rd_keyinstance key;
 | |
| 	u8_t output[AES_BLOCKSIZE];
 | |
| 
 | |
| 	r= rijndael_makekey(&key, sizeof(random_key), random_key);
 | |
| 	assert(r == 0);
 | |
| 
 | |
| 	cp= buf;
 | |
| 	while (size > 0)
 | |
| 	{
 | |
| 		n= AES_BLOCKSIZE;
 | |
| 		if (n > size)
 | |
| 		{
 | |
| 			n= size;
 | |
| 			data_block(&key, output);
 | |
| 			memcpy(cp, output, n);
 | |
| 		}
 | |
| 		else
 | |
| 			data_block(&key, cp);
 | |
| 		cp += n;
 | |
| 		size -= n;
 | |
| 	}
 | |
| 
 | |
| 	/* Generate new key */
 | |
| 	assert(sizeof(random_key) == 2*AES_BLOCKSIZE);
 | |
| 	data_block(&key, random_key);
 | |
| 	data_block(&key, random_key+AES_BLOCKSIZE);
 | |
| }
 | |
| 
 | |
| PUBLIC void random_putbytes(buf, size)
 | |
| void *buf;
 | |
| size_t size;
 | |
| {
 | |
| 	/* Add bits to pool zero */
 | |
| 	SHA256_Update(&pool_ctx[0], buf, size);
 | |
| 
 | |
| 	/* Assume that these bits are truely random. Increment samples
 | |
| 	 * with the number of bits.
 | |
| 	 */
 | |
| 	samples += size*8;
 | |
| 
 | |
| 	reseed();
 | |
| }
 | |
| 
 | |
| PRIVATE void add_sample(source, sample)
 | |
| int source;
 | |
| unsigned long sample;
 | |
| {
 | |
| 	int i, pool_nr;
 | |
| 	unsigned long d, v, di, min;
 | |
| 
 | |
| 	/* Delete bad sample. Compute the Nth derivative. Delete the sample
 | |
| 	 * if any derivative is too small.
 | |
| 	 */
 | |
| 	min= (unsigned long)-1;
 | |
| 	v= sample;
 | |
| 	for (i= 0; i<N_DERIV; i++)
 | |
| 	{
 | |
| 		di= deriv[source][i];
 | |
| 
 | |
| 		/* Compute the difference */
 | |
| 		if (v >= di)
 | |
| 			d= v-di;
 | |
| 		else
 | |
| 			d= di-v;
 | |
| 		deriv[source][i]= v;
 | |
| 		v= d;
 | |
| 		if (v <min)
 | |
| 			min= v;
 | |
| 	}
 | |
| 	if (min < 2)
 | |
| 	{
 | |
| #if 0
 | |
| 		printf("ignoring sample '%u' from source %d\n",
 | |
| 			sample, source);
 | |
| #endif
 | |
| 		return;
 | |
| 	}
 | |
| #if 0
 | |
| 	printf("accepting sample '%u' from source %d\n", sample, source);
 | |
| #endif
 | |
| 
 | |
| 	pool_nr= pool_ind[source];
 | |
| 	assert(pool_nr >= 0 && pool_nr < NR_POOLS);
 | |
| 
 | |
| 	SHA256_Update(&pool_ctx[pool_nr], (unsigned char *)&sample,
 | |
| 		sizeof(sample));
 | |
| 	if (pool_nr == 0)
 | |
| 		samples++;
 | |
| 	pool_nr++;
 | |
| 	if (pool_nr >= NR_POOLS)
 | |
| 		pool_nr= 0;
 | |
| 	pool_ind[source]= pool_nr;
 | |
| }
 | |
| 
 | |
| PRIVATE void data_block(keyp, data)
 | |
| rd_keyinstance *keyp;
 | |
| void *data;
 | |
| {
 | |
| 	int r;
 | |
| 	u8_t input[AES_BLOCKSIZE];
 | |
| 
 | |
| 	memset(input, '\0', sizeof(input));
 | |
| 
 | |
| 	/* Do we want the output of the random numbers to be portable 
 | |
| 	 * across platforms (for example for RSA signatures)? At the moment
 | |
| 	 * we don't do anything special. Encrypt the counter with the AES
 | |
| 	 * key.
 | |
| 	 */
 | |
| 	assert(sizeof(count_lo)+sizeof(count_hi) <= AES_BLOCKSIZE);
 | |
| 	memcpy(input, &count_lo, sizeof(count_lo));
 | |
| 	memcpy(input+sizeof(count_lo), &count_hi, sizeof(count_hi));
 | |
| 	r= rijndael_ecb_encrypt(keyp, input, data, AES_BLOCKSIZE, NULL);
 | |
| 	assert(r == AES_BLOCKSIZE);
 | |
| 
 | |
| 	count_lo++;
 | |
| 	if (count_lo == 0)
 | |
| 		count_hi++;
 | |
| }
 | |
| 
 | |
| PRIVATE void reseed()
 | |
| {
 | |
| 	int i;
 | |
| 	SHA256_CTX ctx;
 | |
| 	u8_t digest[SHA256_DIGEST_LENGTH];
 | |
| 
 | |
| 	if (samples < MIN_SAMPLES)
 | |
| 		return;
 | |
| 
 | |
| 	reseed_count++;
 | |
| 	SHA256_Init(&ctx);
 | |
| 	if (got_seeded)
 | |
| 		SHA256_Update(&ctx, random_key, sizeof(random_key));
 | |
| 	SHA256_Final(digest, &pool_ctx[0]);
 | |
| 	SHA256_Update(&ctx, digest, sizeof(digest));
 | |
| 	SHA256_Init(&pool_ctx[0]);
 | |
| 	for (i= 1; i<NR_POOLS; i++)
 | |
| 	{
 | |
| 		if ((reseed_count & (1UL << (i-1))) != 0)
 | |
| 			break;
 | |
| 		SHA256_Final(digest, &pool_ctx[i]);
 | |
| 		SHA256_Update(&ctx, digest, sizeof(digest));
 | |
| 		SHA256_Init(&pool_ctx[i]);
 | |
| 	}
 | |
| 	SHA256_Final(digest, &ctx);
 | |
| 	assert(sizeof(random_key) == sizeof(digest));
 | |
| 	memcpy(random_key, &digest, sizeof(random_key));
 | |
| 	samples= 0;
 | |
| 
 | |
| 	got_seeded= 1;
 | |
| }
 | |
| 
 |