[Cryptography] RFC possible changes for Linux random device
Sandy Harris
sandyinchina at gmail.com
Fri Sep 12 19:24:03 EDT 2014
Sandy Harris <sandyinchina at gmail.com> wrote:
> I have some experimental code to replace parts of random.c ...
> Next two posts will be the main code and a support program it uses.
/*
Program to select numbers for initialising things
limits the range of Hamming weights
every byte has at least one bit 1, one 0
different every time it runs
writes to stdout, expecting makefile to redirect
results suitable for inclusion by random.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
/*
amount of data to output
depends how much random.c will use
*/
#define NPOOLS 3 // input, blocking & nonblocking
#define POOL_ROWS 4 // 128-bit rows per pool
#define ARRAY_ROWS (POOL_ROWS*NPOOLS)
#define ARRAY_WORDS (ARRAY_ROWS*4)
#define ARRAY_BYTES (ARRAY_WORDS*4)
unsigned data[ARRAY_WORDS] ;
int accept(unsigned) ;
void swap(int, int) ;
int fillarray( unsigned *, int) ;
main(int argc, char **argv)
{
int urandom, i ;
unsigned *p ;
if(argc > 1) {
fprintf(stderr, "usage: getrand\n") ;
exit(1) ;
}
if( (urandom = open("/dev/urandom", O_RDONLY)) == -1 ) {
fprintf(stderr, "getrand: no /dev/urandom, cannot continue\n") ;
exit(1) ;
}
/*
normal case: development machine has /dev/urandom
*/
read(urandom, data, ARRAY_BYTES) ;
for( i = 0, p = data ; i < ARRAY_WORDS ; i++, p++ ) {
// replace any entries that fail criteria
while( !accept(*p) )
read( urandom, (char *) p, 4) ;
}
/*
output an array of random data
*/
printf( "#define POOL_ROWS\t %d\n", POOL_ROWS ) ;
printf( "#define ARRAY_ROWS\t%d\n", ARRAY_ROWS ) ;
printf( "#define ARRAY_WORDS\t%d\n\n", ARRAY_WORDS ) ;
printf("static unsigned int init_data[] = {\n" ) ;
for( i = 0 ; i < ARRAY_WORDS ; i ++ )
printf("0x%08x%s", data[i], (i == (ARRAY_WORDS-1) ? "\n" : ",\n") ) ;
printf("} ;\n") ;
exit(0) ;
}
/*
Choose from a range of Hamming weights around 16
*/
#define MIN 6
#define MAX (32-MIN)
int accept(unsigned u)
{
int h,i ;
char *p ;
// reject low or high Hamming weights
h = hamming(u) ;
if( ( h < MIN ) || ( h > MAX ) )
return(0) ;
// at least one 1 and at least one 0 per byte
for( i = 0, p = (char *) &u ; i < 4 ; i++, p++ ) {
switch(*p) {
case '\0':
case '\255':
return(0) ;
default:
break ;
}
}
return(1) ;
}
/*
Kernighan's method
http://graphics.stanford.edu/~seander/bithacks.html
*/
int hamming( unsigned x )
{
int h ;
for (h = 0 ; x ; h++)
x &= (x-1) ; // clear the least significant bit set
return(h) ;
}
More information about the cryptography
mailing list