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 13ee3fd601SDan Moschuk #include <sys/libkern.h> 14ee3fd601SDan Moschuk #include <sys/time.h> 15ee3fd601SDan Moschuk 16ee3fd601SDan Moschuk static u_int8_t arc4_i, arc4_j; 17ee3fd601SDan Moschuk static int arc4_initialized = 0; 18ee3fd601SDan Moschuk static u_int8_t arc4_sbox[256]; 19ee3fd601SDan Moschuk 20ee3fd601SDan Moschuk static __inline void 21ee3fd601SDan Moschuk arc4_swap(u_int8_t *a, u_int8_t *b) 22ee3fd601SDan Moschuk { 23ee3fd601SDan Moschuk u_int8_t c; 24ee3fd601SDan Moschuk 25ee3fd601SDan Moschuk c = *a; 26ee3fd601SDan Moschuk *a = *b; 27ee3fd601SDan Moschuk *b = c; 28ee3fd601SDan Moschuk } 29ee3fd601SDan Moschuk 30ee3fd601SDan Moschuk /* 31ee3fd601SDan Moschuk * Initialize our S-box to its beginning defaults. 32ee3fd601SDan Moschuk */ 33ee3fd601SDan Moschuk static void 34ee3fd601SDan Moschuk arc4_init(void) 35ee3fd601SDan Moschuk { 36ee3fd601SDan Moschuk struct timespec ts; 37ee3fd601SDan Moschuk u_int8_t key[256]; 38ee3fd601SDan Moschuk int n; 39ee3fd601SDan Moschuk 40ee3fd601SDan Moschuk for (n = 0; n < 256; n++) 41ee3fd601SDan Moschuk arc4_sbox[n] = (u_int8_t) n; 42ee3fd601SDan Moschuk 43ee3fd601SDan Moschuk nanotime(&ts); 44ee3fd601SDan Moschuk srandom(ts.tv_sec ^ ts.tv_nsec); 45ee3fd601SDan Moschuk for (n = 0; n < 256; n++) 46ee3fd601SDan Moschuk key[n] = random() % 256; 47ee3fd601SDan Moschuk 48ee3fd601SDan Moschuk arc4_i = arc4_j = 0; 49ee3fd601SDan Moschuk for (n = 0; n < 256; n++) 50ee3fd601SDan Moschuk { 51ee3fd601SDan Moschuk arc4_j = arc4_j + arc4_sbox[n] + key[n]; 52ee3fd601SDan Moschuk arc4_swap(&arc4_sbox[n], &arc4_sbox[arc4_j]); 53ee3fd601SDan Moschuk } 54ee3fd601SDan Moschuk arc4_initialized = 1; 55ee3fd601SDan Moschuk } 56ee3fd601SDan Moschuk 57ee3fd601SDan Moschuk /* 58ee3fd601SDan Moschuk * Generate a random byte. 59ee3fd601SDan Moschuk */ 60ee3fd601SDan Moschuk static u_int8_t 61ee3fd601SDan Moschuk arc4_randbyte(void) 62ee3fd601SDan Moschuk { 63ee3fd601SDan Moschuk u_int8_t arc4_t; 64ee3fd601SDan Moschuk 65ee3fd601SDan Moschuk arc4_i = (arc4_i + 1) % 256; 66ee3fd601SDan Moschuk arc4_j = (arc4_j + arc4_sbox[arc4_i]) % 256; 67ee3fd601SDan Moschuk 68ee3fd601SDan Moschuk arc4_swap(&arc4_sbox[arc4_i], &arc4_sbox[arc4_j]); 69ee3fd601SDan Moschuk 70ee3fd601SDan Moschuk arc4_t = (arc4_sbox[arc4_i] + arc4_sbox[arc4_j]) % 256; 71ee3fd601SDan Moschuk return arc4_sbox[arc4_t]; 72ee3fd601SDan Moschuk } 73ee3fd601SDan Moschuk 74ee3fd601SDan Moschuk u_int32_t 75ee3fd601SDan Moschuk arc4random(void) 76ee3fd601SDan Moschuk { 77ee3fd601SDan Moschuk u_int32_t ret; 78ee3fd601SDan Moschuk 79ee3fd601SDan Moschuk /* Initialize array if needed. */ 80ee3fd601SDan Moschuk if (!arc4_initialized) 81ee3fd601SDan Moschuk arc4_init(); 82ee3fd601SDan Moschuk 83ee3fd601SDan Moschuk ret = arc4_randbyte(); 84ee3fd601SDan Moschuk ret |= arc4_randbyte() << 8; 85ee3fd601SDan Moschuk ret |= arc4_randbyte() << 16; 86ee3fd601SDan Moschuk ret |= arc4_randbyte() << 24; 87ee3fd601SDan Moschuk 88ee3fd601SDan Moschuk return ret; 89ee3fd601SDan Moschuk } 90