1- /* $NetBSD: arc4random.c,v 1.17 2012/08/18 15:55:07 dsl Exp $ */
1+ /* $NetBSD: arc4random.c,v 1.18 2012/08/20 20:27:46 dsl Exp $ */
22/* $OpenBSD: arc4random.c,v 1.6 2001/06/05 05:05:38 pvalchev Exp $ */
33
44/*
2727
2828#include <sys/cdefs.h>
2929#if defined(LIBC_SCCS ) && !defined(lint )
30- __RCSID ("$NetBSD: arc4random.c,v 1.17 2012/08/18 15:55:07 dsl Exp $" );
30+ __RCSID ("$NetBSD: arc4random.c,v 1.18 2012/08/20 20:27:46 dsl Exp $" );
3131#endif /* LIBC_SCCS and not lint */
3232
3333#include "namespace.h"
@@ -44,13 +44,13 @@ __RCSID("$NetBSD: arc4random.c,v 1.17 2012/08/18 15:55:07 dsl Exp $");
4444__weak_alias (arc4random ,_arc4random )
4545#endif
4646
47- #define RSIZE 256
4847struct arc4_stream {
49- mutex_t mtx ;
50- int initialized ;
48+ uint8_t stirred ;
49+ uint8_t pad ;
5150 uint8_t i ;
5251 uint8_t j ;
53- uint8_t s [RSIZE ];
52+ uint8_t s [(uint8_t )~0u + 1u ]; /* 256 to you and me */
53+ mutex_t mtx ;
5454};
5555
5656#ifdef _REENTRANT
@@ -67,56 +67,52 @@ struct arc4_stream {
6767#define UNLOCK(rs)
6868#endif
6969
70+ #define S (n ) (n)
71+ #define S4 (n ) S(n), S(n + 1), S(n + 2), S(n + 3)
72+ #define S16 (n ) S4(n), S4(n + 4), S4(n + 8), S4(n + 12)
73+ #define S64 (n ) S16(n), S16(n + 16), S16(n + 32), S16(n + 48)
74+ #define S256 S64(0), S64(64), S64(128), S64(192)
75+
76+ static struct arc4_stream rs = { .i = 0xff , .j = 0 , .s = { S256 },
77+ .stirred = 0 , .mtx = MUTEX_INITIALIZER };
7078
71- /* XXX lint explodes with an internal error if only mtx is initialized! */
72- static struct arc4_stream rs = { .i = 0 , .mtx = MUTEX_INITIALIZER };
79+ #undef S
80+ #undef S4
81+ #undef S16
82+ #undef S64
83+ #undef S256
7384
7485static inline void arc4_addrandom (struct arc4_stream * , u_char * , int );
75- static void arc4_stir (struct arc4_stream * );
86+ static __noinline void arc4_stir (struct arc4_stream * );
7687static inline uint8_t arc4_getbyte (struct arc4_stream * );
7788static inline uint32_t arc4_getword (struct arc4_stream * );
7889
79- static __noinline void
80- arc4_init (struct arc4_stream * as )
81- {
82- int n ;
83- for (n = 0 ; n < RSIZE ; n ++ )
84- as -> s [n ] = n ;
85- as -> i = 0 ;
86- as -> j = 0 ;
87-
88- as -> initialized = 1 ;
89- arc4_stir (as );
90- }
91-
9290static inline int
9391arc4_check_init (struct arc4_stream * as )
9492{
95- if (__predict_true (rs .initialized ))
93+ if (__predict_true (rs .stirred ))
9694 return 0 ;
9795
98- arc4_init (as );
96+ arc4_stir (as );
9997 return 1 ;
10098}
10199
102100static inline void
103101arc4_addrandom (struct arc4_stream * as , u_char * dat , int datlen )
104102{
105103 uint8_t si ;
106- int n ;
104+ size_t n ;
107105
108- as -> i -- ;
109- for (n = 0 ; n < RSIZE ; n ++ ) {
106+ for (n = 0 ; n < __arraycount (as -> s ); n ++ ) {
110107 as -> i = (as -> i + 1 );
111108 si = as -> s [as -> i ];
112109 as -> j = (as -> j + si + dat [n % datlen ]);
113110 as -> s [as -> i ] = as -> s [as -> j ];
114111 as -> s [as -> j ] = si ;
115112 }
116- as -> j = as -> i ;
117113}
118114
119- static void
115+ static __noinline void
120116arc4_stir (struct arc4_stream * as )
121117{
122118 int rdat [32 ];
@@ -146,8 +142,10 @@ arc4_stir(struct arc4_stream *as)
146142 * paper "Weaknesses in the Key Scheduling Algorithm of RC4"
147143 * by Fluher, Mantin, and Shamir. (N = 256 in our case.)
148144 */
149- for (j = 0 ; j < RSIZE * 4 ; j ++ )
145+ for (j = 0 ; j < __arraycount ( as -> s ) * 4 ; j ++ )
150146 arc4_getbyte (as );
147+
148+ as -> stirred = 1 ;
151149}
152150
153151static __always_inline uint8_t
185183arc4random_stir (void )
186184{
187185 LOCK (& rs );
188- if (__predict_false (!arc4_check_init (& rs ))) /* init() stirs */
189- arc4_stir (& rs );
186+ arc4_stir (& rs );
190187 UNLOCK (& rs );
191188}
192189
0 commit comments