bsd-arc4random.c revision 162853
1/* 2 * Copyright (c) 1999,2000,2004 Damien Miller <djm@mindrot.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#include "includes.h" 18 19#include <sys/types.h> 20 21#include <string.h> 22#include <stdarg.h> 23 24#include "log.h" 25 26#ifndef HAVE_ARC4RANDOM 27 28#include <openssl/rand.h> 29#include <openssl/rc4.h> 30#include <openssl/err.h> 31 32/* Size of key to use */ 33#define SEED_SIZE 20 34 35/* Number of bytes to reseed after */ 36#define REKEY_BYTES (1 << 24) 37 38static int rc4_ready = 0; 39static RC4_KEY rc4; 40 41unsigned int 42arc4random(void) 43{ 44 unsigned int r = 0; 45 static int first_time = 1; 46 47 if (rc4_ready <= 0) { 48 if (first_time) 49 seed_rng(); 50 first_time = 0; 51 arc4random_stir(); 52 } 53 54 RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r); 55 56 rc4_ready -= sizeof(r); 57 58 return(r); 59} 60 61void 62arc4random_stir(void) 63{ 64 unsigned char rand_buf[SEED_SIZE]; 65 int i; 66 67 memset(&rc4, 0, sizeof(rc4)); 68 if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) 69 fatal("Couldn't obtain random bytes (error %ld)", 70 ERR_get_error()); 71 RC4_set_key(&rc4, sizeof(rand_buf), rand_buf); 72 73 /* 74 * Discard early keystream, as per recommendations in: 75 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps 76 */ 77 for(i = 0; i <= 256; i += sizeof(rand_buf)) 78 RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf); 79 80 memset(rand_buf, 0, sizeof(rand_buf)); 81 82 rc4_ready = REKEY_BYTES; 83} 84#endif /* !HAVE_ARC4RANDOM */ 85