2 * THE BEER-WARE LICENSE
4 * <dan@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you
6 * think this stuff is worth it, you can buy me a beer in return.
10 * $FreeBSD: src/sys/libkern/arc4random.c,v 1.3.2.2 2001/09/17 07:06:50 silby Exp $
11 * $DragonFly: src/sys/libkern/arc4random.c,v 1.3 2006/09/03 17:31:55 dillon Exp $
14 #include <sys/types.h>
15 #include <sys/systm.h>
16 #include <sys/random.h>
17 #include <sys/libkern.h>
20 #include <vm/vm_extern.h>
22 #define ARC4_MAXRUNS 16384
23 #define ARC4_RESEED_SECONDS 300
24 #define ARC4_KEYBYTES 32 /* 256 bit key */
30 time_t arc4_nextreseed
;
31 uint8_t arc4_sbox
[256];
34 static struct arc4_data
*arc4_data_pcpu
[MAXCPU
];
36 static uint8_t arc4_randbyte(struct arc4_data
*);
39 arc4_swap(uint8_t *a
, uint8_t *b
)
52 arc4_randomstir(struct arc4_data
*d
)
58 * XXX read_random() returns unsafe numbers if the entropy
59 * device is not loaded -- MarkM.
61 r
= read_random_unlimited(key
, ARC4_KEYBYTES
);
62 /* If r == 0 || -1, just use what was on the stack. */
64 for (n
= r
; n
< sizeof(key
); n
++)
68 for (n
= 0; n
< 256; n
++) {
69 d
->arc4_j
= (d
->arc4_j
+ d
->arc4_sbox
[n
] + key
[n
]) % 256;
70 arc4_swap(&d
->arc4_sbox
[n
], &d
->arc4_sbox
[d
->arc4_j
]);
74 * Discard early keystream, as per recommendations in:
75 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
77 for (n
= 0; n
< 768 * 4; n
++)
80 /* Reset for next reseed cycle. */
81 d
->arc4_nextreseed
= time_uptime
+ ARC4_RESEED_SECONDS
;
86 * Generate a random byte.
89 arc4_randbyte(struct arc4_data
*d
)
93 d
->arc4_i
= (d
->arc4_i
+ 1) % 256;
94 d
->arc4_j
= (d
->arc4_j
+ d
->arc4_sbox
[d
->arc4_i
]) % 256;
96 arc4_swap(&d
->arc4_sbox
[d
->arc4_i
], &d
->arc4_sbox
[d
->arc4_j
]);
98 arc4_t
= (d
->arc4_sbox
[d
->arc4_i
] + d
->arc4_sbox
[d
->arc4_j
]) % 256;
99 return d
->arc4_sbox
[arc4_t
];
105 struct arc4_data
*d
= arc4_data_pcpu
[mycpuid
];
109 /* No one call this function in ISR/ithread. */
113 if (++(d
->arc4_numruns
) > ARC4_MAXRUNS
||
114 time_uptime
> d
->arc4_nextreseed
)
117 ret
= arc4_randbyte(d
);
118 ret
|= arc4_randbyte(d
) << 8;
119 ret
|= arc4_randbyte(d
) << 16;
120 ret
|= arc4_randbyte(d
) << 24;
130 karc4rand(void *ptr
, size_t len
)
132 struct arc4_data
*d
= arc4_data_pcpu
[mycpuid
];
136 /* No one call this function in ISR/ithread. */
140 if (++(d
->arc4_numruns
) > ARC4_MAXRUNS
||
141 time_uptime
> d
->arc4_nextreseed
)
145 *p
++ = arc4_randbyte(d
);
153 * Initialize our S-box to its beginning defaults.
156 arc4_init_pcpu(int cpuid
)
161 KASSERT(arc4_data_pcpu
[cpuid
] == NULL
,
162 ("arc4 was initialized on cpu%d", cpuid
));
164 d
= (void *)kmem_alloc3(&kernel_map
, sizeof(*d
), VM_SUBSYS_GD
,
166 memset(d
, 0, sizeof(*d
));
168 for (n
= 0; n
< 256; n
++)
169 d
->arc4_sbox
[n
] = (uint8_t)n
;
174 * Discard early keystream, as per recommendations in:
175 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
177 for (n
= 0; n
< 768 * 4; n
++)
180 arc4_data_pcpu
[cpuid
] = d
;