]>
git.saurik.com Git - apple/network_cmds.git/blob - unbound/compat/arc4random.c
1 /* $OpenBSD: arc4random.c,v 1.41 2014/07/12 13:24:54 deraadt Exp $ */
4 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * ChaCha based random number generator for OpenBSD.
33 #include <sys/types.h>
34 #include <sys/param.h>
40 #define KEYSTREAM_ONLY
41 #include "chacha_private.h"
43 #define arc4_min(a, b) ((a) < (b) ? (a) : (b))
45 #define inline __inline
48 #endif /* !__GNUC__ */
53 #define RSBUFSZ (16*BLOCKSZ)
55 /* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
57 size_t rs_have
; /* valid bytes at end of rs_buf */
58 size_t rs_count
; /* bytes till reseed */
61 /* Preserved in fork children. */
63 chacha_ctx rs_chacha
; /* chacha context for random keystream */
64 u_char rs_buf
[RSBUFSZ
]; /* keystream blocks */
67 static inline void _rs_rekey(u_char
*dat
, size_t datlen
);
70 _rs_init(u_char
*buf
, size_t n
)
77 if ((rs
= mmap(NULL
, sizeof(*rs
), PROT_READ
|PROT_WRITE
,
78 MAP_ANON
|MAP_PRIVATE
, -1, 0)) == MAP_FAILED
)
80 #ifdef MAP_INHERIT_ZERO
81 if (minherit(rs
, sizeof(*rs
), MAP_INHERIT_ZERO
) == -1)
85 rs
= malloc(sizeof(*rs
));
92 if ((rsx
= mmap(NULL
, sizeof(*rsx
), PROT_READ
|PROT_WRITE
,
93 MAP_ANON
|MAP_PRIVATE
, -1, 0)) == MAP_FAILED
)
96 rsx
= malloc(sizeof(*rsx
));
102 chacha_keysetup(&rsx
->rs_chacha
, buf
, KEYSZ
* 8, 0);
103 chacha_ivsetup(&rsx
->rs_chacha
, buf
+ KEYSZ
);
109 u_char rnd
[KEYSZ
+ IVSZ
];
111 if (getentropy(rnd
, sizeof rnd
) == -1) {
115 exit(9); /* windows */
120 _rs_init(rnd
, sizeof(rnd
));
122 _rs_rekey(rnd
, sizeof(rnd
));
123 explicit_bzero(rnd
, sizeof(rnd
)); /* discard source seed */
125 /* invalidate rs_buf */
127 memset(rsx
->rs_buf
, 0, sizeof(rsx
->rs_buf
));
129 rs
->rs_count
= 1600000;
133 _rs_stir_if_needed(size_t len
)
135 #ifndef MAP_INHERIT_ZERO
136 static pid_t _rs_pid
= 0;
137 pid_t pid
= getpid();
139 /* If a system lacks MAP_INHERIT_ZERO, resort to getpid() */
140 if (_rs_pid
== 0 || _rs_pid
!= pid
) {
146 if (!rs
|| rs
->rs_count
<= len
)
148 if (rs
->rs_count
<= len
)
155 _rs_rekey(u_char
*dat
, size_t datlen
)
157 #ifndef KEYSTREAM_ONLY
158 memset(rsx
->rs_buf
, 0, sizeof(rsx
->rs_buf
));
160 /* fill rs_buf with the keystream */
161 chacha_encrypt_bytes(&rsx
->rs_chacha
, rsx
->rs_buf
,
162 rsx
->rs_buf
, sizeof(rsx
->rs_buf
));
163 /* mix in optional user provided data */
167 m
= arc4_min(datlen
, KEYSZ
+ IVSZ
);
168 for (i
= 0; i
< m
; i
++)
169 rsx
->rs_buf
[i
] ^= dat
[i
];
171 /* immediately reinit for backtracking resistance */
172 _rs_init(rsx
->rs_buf
, KEYSZ
+ IVSZ
);
173 memset(rsx
->rs_buf
, 0, KEYSZ
+ IVSZ
);
174 rs
->rs_have
= sizeof(rsx
->rs_buf
) - KEYSZ
- IVSZ
;
178 _rs_random_buf(void *_buf
, size_t n
)
180 u_char
*buf
= (u_char
*)_buf
;
184 _rs_stir_if_needed(n
);
186 if (rs
->rs_have
> 0) {
187 m
= arc4_min(n
, rs
->rs_have
);
188 keystream
= rsx
->rs_buf
+ sizeof(rsx
->rs_buf
)
190 memcpy(buf
, keystream
, m
);
191 memset(keystream
, 0, m
);
196 if (rs
->rs_have
== 0)
202 _rs_random_u32(uint32_t *val
)
205 _rs_stir_if_needed(sizeof(*val
));
206 if (rs
->rs_have
< sizeof(*val
))
208 keystream
= rsx
->rs_buf
+ sizeof(rsx
->rs_buf
) - rs
->rs_have
;
209 memcpy(val
, keystream
, sizeof(*val
));
210 memset(keystream
, 0, sizeof(*val
));
211 rs
->rs_have
-= sizeof(*val
);
220 _rs_random_u32(&val
);
226 arc4random_buf(void *buf
, size_t n
)
229 _rs_random_buf(buf
, n
);