Changeset 5be87b2 for unix.c


Ignore:
Timestamp:
2008-04-02T15:03:02Z (16 years ago)
Author:
Jelmer Vernooij <jelmer@…>
Branches:
master
Children:
1a57b893, 69aaf14
Parents:
fa75134
Message:

Move unix-specific random_bytes() implementation to unix.c.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • unix.c

    rfa75134 r5be87b2  
    219219        return( (double) time->tv_sec + (double) time->tv_usec / 1000000 );
    220220}
     221
     222/* A pretty reliable random number generator. Tries to use the /dev/random
     223   devices first, and falls back to the random number generator from libc
     224   when it fails. Opens randomizer devices with O_NONBLOCK to make sure a
     225   lack of entropy won't halt BitlBee. */
     226void random_bytes( unsigned char *buf, int count )
     227{
     228        static int use_dev = -1;
     229       
     230        /* Actually this probing code isn't really necessary, is it? */
     231        if( use_dev == -1 )
     232        {
     233                if( access( "/dev/random", R_OK ) == 0 || access( "/dev/urandom", R_OK ) == 0 )
     234                        use_dev = 1;
     235                else
     236                {
     237                        use_dev = 0;
     238                        srand( ( getpid() << 16 ) ^ time( NULL ) );
     239                }
     240        }
     241       
     242        if( use_dev )
     243        {
     244                int fd;
     245               
     246                /* At least on Linux, /dev/random can block if there's not
     247                   enough entropy. We really don't want that, so if it can't
     248                   give anything, use /dev/urandom instead. */
     249                if( ( fd = open( "/dev/random", O_RDONLY | O_NONBLOCK ) ) >= 0 )
     250                        if( read( fd, buf, count ) == count )
     251                        {
     252                                close( fd );
     253                                return;
     254                        }
     255                close( fd );
     256               
     257                /* urandom isn't supposed to block at all, but just to be
     258                   sure. If it blocks, we'll disable use_dev and use the libc
     259                   randomizer instead. */
     260                if( ( fd = open( "/dev/urandom", O_RDONLY | O_NONBLOCK ) ) >= 0 )
     261                        if( read( fd, buf, count ) == count )
     262                        {
     263                                close( fd );
     264                                return;
     265                        }
     266                close( fd );
     267               
     268                /* If /dev/random blocks once, we'll still try to use it
     269                   again next time. If /dev/urandom also fails for some
     270                   reason, stick with libc during this session. */
     271               
     272                use_dev = 0;
     273                srand( ( getpid() << 16 ) ^ time( NULL ) );
     274        }
     275       
     276        if( !use_dev )
     277        {
     278                int i;
     279               
     280                /* Possibly the LSB of rand() isn't very random on some
     281                   platforms. Seems okay on at least Linux and OSX though. */
     282                for( i = 0; i < count; i ++ )
     283                        buf[i] = rand() & 0xff;
     284        }
     285}
     286
     287
Note: See TracChangeset for help on using the changeset viewer.