[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