Skip to content

Commit 2f0a15c

Browse files
author
tls
committed
Fix bug in previous: don't reinitialize on every call! Fix arc4random_buf so it actually ever initializes -- a security problem with revisions 1.9 and 1.10.
1 parent 9c4e192 commit 2f0a15c

File tree

1 file changed

+23
-13
lines changed

1 file changed

+23
-13
lines changed

lib/libc/gen/arc4random.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: arc4random.c,v 1.11 2012/02/27 04:25:12 tls Exp $ */
1+
/* $NetBSD: arc4random.c,v 1.12 2012/03/04 00:36:43 tls Exp $ */
22
/* $OpenBSD: arc4random.c,v 1.6 2001/06/05 05:05:38 pvalchev Exp $ */
33

44
/*
@@ -27,7 +27,7 @@
2727

2828
#include <sys/cdefs.h>
2929
#if defined(LIBC_SCCS) && !defined(lint)
30-
__RCSID("$NetBSD: arc4random.c,v 1.11 2012/02/27 04:25:12 tls Exp $");
30+
__RCSID("$NetBSD: arc4random.c,v 1.12 2012/03/04 00:36:43 tls Exp $");
3131
#endif /* LIBC_SCCS and not lint */
3232

3333
#include "namespace.h"
@@ -46,12 +46,12 @@ __weak_alias(arc4random,_arc4random)
4646

4747
struct arc4_stream {
4848
mutex_t mtx;
49+
int initialized;
4950
uint8_t i;
5051
uint8_t j;
5152
uint8_t s[256];
5253
};
5354

54-
static int rs_initialized;
5555
/* XXX lint explodes with an internal error if only mtx is initialized! */
5656
static struct arc4_stream rs = { .i = 0, .mtx = MUTEX_INITIALIZER };
5757

@@ -70,6 +70,9 @@ arc4_init(struct arc4_stream *as)
7070
as->s[n] = n;
7171
as->i = 0;
7272
as->j = 0;
73+
74+
as->initialized = 1;
75+
arc4_stir(as);
7376
}
7477

7578
static inline void
@@ -155,11 +158,11 @@ arc4_getword(struct arc4_stream *as)
155158
static inline void
156159
_arc4random_stir_unlocked(void)
157160
{
158-
if (!rs_initialized) {
159-
arc4_init(&rs);
160-
rs_initialized = 1;
161+
if (__predict_false(!rs.initialized)) {
162+
arc4_init(&rs); /* stirs */
163+
} else {
164+
arc4_stir(&rs);
161165
}
162-
arc4_stir(&rs);
163166
}
164167

165168
void
@@ -179,8 +182,9 @@ arc4random_stir(void)
179182
static inline void
180183
_arc4random_addrandom_unlocked(u_char *dat, int datlen)
181184
{
182-
if (!rs_initialized)
183-
arc4_stir(&rs);
185+
if (__predict_false(rs.initialized)) {
186+
arc4_init(&rs);
187+
}
184188
arc4_addrandom(&rs, dat, datlen);
185189
}
186190

@@ -201,8 +205,9 @@ arc4random_addrandom(u_char *dat, int datlen)
201205
static inline uint32_t
202206
_arc4random_unlocked(void)
203207
{
204-
if (!rs_initialized)
205-
arc4_stir(&rs);
208+
if (__predict_false(!rs.initialized)) {
209+
arc4_init(&rs);
210+
}
206211
return arc4_getword(&rs);
207212
}
208213

@@ -228,6 +233,10 @@ _arc4random_buf_unlocked(void *buf, size_t len)
228233
uint8_t *bp = buf;
229234
uint8_t *ep = bp + len;
230235

236+
if (__predict_false(!rs.initialized)) {
237+
arc4_init(&rs);
238+
}
239+
231240
bp[0] = arc4_getbyte(&rs) % 3;
232241
while (bp[0]--)
233242
(void)arc4_getbyte(&rs);
@@ -292,8 +301,9 @@ _arc4random_uniform_unlocked(uint32_t upper_bound)
292301
* number inside the range we need, so it should rarely need
293302
* to re-roll (at all).
294303
*/
295-
if (!rs_initialized)
296-
arc4_stir(&rs);
304+
if (__predict_false(!rs.initialized)) {
305+
arc4_init(&rs);
306+
}
297307
if (arc4_getbyte(&rs) & 1)
298308
(void)arc4_getbyte(&rs);
299309
do

0 commit comments

Comments
 (0)