1ee3fd601SDan Moschuk /*- 2ee3fd601SDan Moschuk * THE BEER-WARE LICENSE 3ee3fd601SDan Moschuk * 4ee3fd601SDan Moschuk * <dan@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5ee3fd601SDan Moschuk * can do whatever you want with this stuff. If we meet some day, and you 6ee3fd601SDan Moschuk * think this stuff is worth it, you can buy me a beer in return. 7ee3fd601SDan Moschuk * 8ee3fd601SDan Moschuk * Dan Moschuk 9ee3fd601SDan Moschuk * 10ee3fd601SDan Moschuk * $FreeBSD$ 11ee3fd601SDan Moschuk */ 12ee3fd601SDan Moschuk 13bf3191e9SMark Murray #include <sys/types.h> 14bf3191e9SMark Murray #include <sys/random.h> 15ee3fd601SDan Moschuk #include <sys/libkern.h> 16d65b1670SDan Moschuk 17d65b1670SDan Moschuk #define ARC4_MAXRUNS 64 18ee3fd601SDan Moschuk 19ee3fd601SDan Moschuk static u_int8_t arc4_i, arc4_j; 20ee3fd601SDan Moschuk static int arc4_initialized = 0; 21d65b1670SDan Moschuk static int arc4_numruns = 0; 22ee3fd601SDan Moschuk static u_int8_t arc4_sbox[256]; 23ee3fd601SDan Moschuk 24ee3fd601SDan Moschuk static __inline void 25ee3fd601SDan Moschuk arc4_swap(u_int8_t *a, u_int8_t *b) 26ee3fd601SDan Moschuk { 27ee3fd601SDan Moschuk u_int8_t c; 28ee3fd601SDan Moschuk 29ee3fd601SDan Moschuk c = *a; 30ee3fd601SDan Moschuk *a = *b; 31ee3fd601SDan Moschuk *b = c; 32ee3fd601SDan Moschuk } 33ee3fd601SDan Moschuk 34ee3fd601SDan Moschuk /* 35d65b1670SDan Moschuk * Stir our S-box. 36d65b1670SDan Moschuk */ 37d65b1670SDan Moschuk static void 38d65b1670SDan Moschuk arc4_randomstir (void) 39d65b1670SDan Moschuk { 40d65b1670SDan Moschuk u_int8_t key[256]; 41d65b1670SDan Moschuk int r, n; 42d65b1670SDan Moschuk 43bf3191e9SMark Murray /* r = read_random(key, sizeof(key)); */ 44bf3191e9SMark Murray r = 0; /* XXX MarkM - revisit this when /dev/random is done */ 45e6082d19SDan Moschuk /* if r == 0 || -1, just use what was on the stack */ 46e6082d19SDan Moschuk if (r > 0) 47e6082d19SDan Moschuk { 48d65b1670SDan Moschuk for (n = r; n < sizeof(key); n++) 49d65b1670SDan Moschuk key[n] = key[n % r]; 50e6082d19SDan Moschuk } 51d65b1670SDan Moschuk 52d65b1670SDan Moschuk for (n = 0; n < 256; n++) 53d65b1670SDan Moschuk { 54d65b1670SDan Moschuk arc4_j = (arc4_j + arc4_sbox[n] + key[n]) % 256; 55d65b1670SDan Moschuk arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]); 56d65b1670SDan Moschuk } 57d65b1670SDan Moschuk } 58d65b1670SDan Moschuk 59d65b1670SDan Moschuk /* 60ee3fd601SDan Moschuk * Initialize our S-box to its beginning defaults. 61ee3fd601SDan Moschuk */ 62ee3fd601SDan Moschuk static void 63ee3fd601SDan Moschuk arc4_init(void) 64ee3fd601SDan Moschuk { 65ee3fd601SDan Moschuk int n; 66ee3fd601SDan Moschuk 67ee3fd601SDan Moschuk arc4_i = arc4_j = 0; 68ee3fd601SDan Moschuk for (n = 0; n < 256; n++) 69d65b1670SDan Moschuk arc4_sbox[n] = (u_int8_t) n; 70d65b1670SDan Moschuk 71d65b1670SDan Moschuk arc4_randomstir(); 72ee3fd601SDan Moschuk arc4_initialized = 1; 73ee3fd601SDan Moschuk } 74ee3fd601SDan Moschuk 75ee3fd601SDan Moschuk /* 76ee3fd601SDan Moschuk * Generate a random byte. 77ee3fd601SDan Moschuk */ 78ee3fd601SDan Moschuk static u_int8_t 79ee3fd601SDan Moschuk arc4_randbyte(void) 80ee3fd601SDan Moschuk { 81ee3fd601SDan Moschuk u_int8_t arc4_t; 82ee3fd601SDan Moschuk 83ee3fd601SDan Moschuk arc4_i = (arc4_i + 1) % 256; 84ee3fd601SDan Moschuk arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256; 85ee3fd601SDan Moschuk 86ee3fd601SDan Moschuk arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]); 87ee3fd601SDan Moschuk 88ee3fd601SDan Moschuk arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256; 89ee3fd601SDan Moschuk return arc4_sbox[arc4_t]; 90ee3fd601SDan Moschuk } 91ee3fd601SDan Moschuk 92ee3fd601SDan Moschuk u_int32_t 93ee3fd601SDan Moschuk arc4random(void) 94ee3fd601SDan Moschuk { 95ee3fd601SDan Moschuk u_int32_t ret; 96ee3fd601SDan Moschuk 97ee3fd601SDan Moschuk /* Initialize array if needed. */ 98ee3fd601SDan Moschuk if (!arc4_initialized) 99ee3fd601SDan Moschuk arc4_init(); 100d65b1670SDan Moschuk if (++arc4_numruns > ARC4_MAXRUNS) 101d65b1670SDan Moschuk { 102d65b1670SDan Moschuk arc4_randomstir(); 103d65b1670SDan Moschuk arc4_numruns = 0; 104d65b1670SDan Moschuk } 105ee3fd601SDan Moschuk 106ee3fd601SDan Moschuk ret = arc4_randbyte(); 107ee3fd601SDan Moschuk ret |= arc4_randbyte() << 8; 108ee3fd601SDan Moschuk ret |= arc4_randbyte() << 16; 109ee3fd601SDan Moschuk ret |= arc4_randbyte() << 24; 110ee3fd601SDan Moschuk 111ee3fd601SDan Moschuk return ret; 112ee3fd601SDan Moschuk } 113