1 /*-
2 * Copyright (c) 2010, 2014
3 * Thorsten Glaser <tg@mirbsd.org>
4 *
5 * Provided that these terms and disclaimer and all copyright notices
6 * are retained or reproduced in an accompanying document, permission
7 * is granted to deal in this work without restriction, including un-
8 * limited rights to use, publicly perform, distribute, sell, modify,
9 * merge, give away, or sublicence.
10 *
11 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
12 * the utmost extent permitted by applicable law, neither express nor
13 * implied; without malicious intent or gross negligence. In no event
14 * may a licensor, author or contributor be held liable for indirect,
15 * direct, other damage, loss, or other issues arising in any way out
16 * of dealing in the work, even if advised of the possibility of such
17 * damage or existence of a defect, except proven that it results out
18 * of said person's immediate fault when using the work as intended.
19 *-
20 * Implement a useful arc4random(3) related API.
21 */
22
23 #include <syskern/libckern.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include "arc4random.h"
27 #include "thread_private.h"
28
29 __RCSID("$MirOS: src/lib/libc/crypt/arc4random_buf.c,v 1.5 2014/03/29 10:35:46 tg Exp $");
30
31 void
arc4random_buf(void * buf_,size_t len)32 arc4random_buf(void *buf_, size_t len)
33 {
34 uint8_t *buf = (uint8_t *)buf_;
35 pid_t mypid = 0;
36 size_t n;
37
38 /* reinitialise if necessary */
39 _ARC4_LOCK();
40 if (!a4state.a4s_initialised ||
41 (a4state.a4s_stir_pid != (mypid = getpid())))
42 arc4random_stir_locked(mypid);
43 _ARC4_UNLOCK();
44
45 while (len) {
46 _ARC4_LOCK();
47 /* randomly skip 1-4 bytes */
48 /*XXX this should be constant-time */
49 n = arcfour_byte(&a4state.cipher) & 3;
50 while (n--)
51 (void)arcfour_byte(&a4state.cipher);
52
53 /* fill the buffer in small increments */
54 n = len < 256 ? len : 256;
55 len -= n;
56 a4state.a4s_count -= n;
57 if (a4state.a4s_count < 0)
58 arc4random_stir_locked(mypid);
59 while (n--)
60 *buf++ = arcfour_byte(&a4state.cipher);
61 _ARC4_UNLOCK();
62 }
63 }
64