Changeset 5eab298f for lib


Ignore:
Timestamp:
2015-01-26T03:27:24Z (10 years ago)
Author:
dequis <dx@…>
Branches:
master
Children:
73ee390
Parents:
11e7828
git-author:
dequis <dx@…> (10-07-14 11:07:51)
git-committer:
dequis <dx@…> (26-01-15 03:27:24)
Message:

random_bytes: Use /dev/urandom only, don't bother trying /dev/random

Also abort() if there's no /dev/urandom

See http://www.2uo.de/myths-about-urandom/ for details.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/misc.c

    r11e7828 r5eab298f  
    414414}
    415415
    416 /* A pretty reliable random number generator. Tries to use the /dev/random
    417    devices first, and falls back to the random number generator from libc
    418    when it fails. Opens randomizer devices with O_NONBLOCK to make sure a
    419    lack of entropy won't halt BitlBee. */
     416/* A wrapper for /dev/urandom.
     417 * If /dev/urandom is not present or not usable, it calls abort()
     418 * to prevent bitlbee from working without a decent entropy source */
    420419void random_bytes( unsigned char *buf, int count )
    421420{
    422         static int use_dev = -1;
    423        
    424         /* Actually this probing code isn't really necessary, is it? */
    425         if( use_dev == -1 )
    426         {
    427                 if( access( "/dev/random", R_OK ) == 0 || access( "/dev/urandom", R_OK ) == 0 )
    428                         use_dev = 1;
    429                 else
    430                 {
    431                         use_dev = 0;
    432                         srand( ( getpid() << 16 ) ^ time( NULL ) );
    433                 }
    434         }
    435        
    436         if( use_dev )
    437         {
    438                 int fd;
    439                
    440                 /* At least on Linux, /dev/random can block if there's not
    441                    enough entropy. We really don't want that, so if it can't
    442                    give anything, use /dev/urandom instead. */
    443                 if( ( fd = open( "/dev/random", O_RDONLY | O_NONBLOCK ) ) >= 0 )
    444                         if( read( fd, buf, count ) == count )
    445                         {
    446                                 close( fd );
    447                                 return;
    448                         }
    449                 close( fd );
    450                
    451                 /* urandom isn't supposed to block at all, but just to be
    452                    sure. If it blocks, we'll disable use_dev and use the libc
    453                    randomizer instead. */
    454                 if( ( fd = open( "/dev/urandom", O_RDONLY | O_NONBLOCK ) ) >= 0 )
    455                         if( read( fd, buf, count ) == count )
    456                         {
    457                                 close( fd );
    458                                 return;
    459                         }
    460                 close( fd );
    461                
    462                 /* If /dev/random blocks once, we'll still try to use it
    463                    again next time. If /dev/urandom also fails for some
    464                    reason, stick with libc during this session. */
    465                
    466                 use_dev = 0;
    467                 srand( ( getpid() << 16 ) ^ time( NULL ) );
    468         }
    469        
    470         if( !use_dev )
    471         {
    472                 int i;
    473                
    474                 /* Possibly the LSB of rand() isn't very random on some
    475                    platforms. Seems okay on at least Linux and OSX though. */
    476                 for( i = 0; i < count; i ++ )
    477                         buf[i] = rand() & 0xff;
    478         }
     421        int fd;
     422        if( ( ( fd = open( "/dev/urandom", O_RDONLY ) ) == -1 ) ||
     423            ( read( fd, buf, count ) == -1 ) )
     424        {
     425                log_message( LOGLVL_ERROR, "/dev/urandom not present - aborting" );
     426                abort();
     427        }
     428
     429        close( fd );
    479430}
    480431
Note: See TracChangeset for help on using the changeset viewer.