summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkurt <>2008-01-01 00:43:39 +0000
committerkurt <>2008-01-01 00:43:39 +0000
commitd08c4e4910d78ef0ddd9e7917c1f2d61b0021d4a (patch)
tree1b1ce1f0d947d24732897206517a88ade3843c65
parentdea3d5b72ccc6bd1dad92e25f49aaa4f48cc4064 (diff)
downloadopenbsd-d08c4e4910d78ef0ddd9e7917c1f2d61b0021d4a.tar.gz
openbsd-d08c4e4910d78ef0ddd9e7917c1f2d61b0021d4a.tar.bz2
openbsd-d08c4e4910d78ef0ddd9e7917c1f2d61b0021d4a.zip
- make arc4random*() functions thread safe. Use a custom spinlock function
instead of the generic pthread macros since free(3) uses __arc4_getbyte() when freeing small sized allocations and the generic pthread macros call malloc(3). - eliminate passing pointers to a static variable with global scope (rs) for additional code clarity and reduction. - shlib minor bumps for libc and libpthread due to new functions. From andreas@ with some bits from me. okay tedu@ marc@ w/some spot checking from millert@
-rw-r--r--src/lib/libc/crypt/arc4random.c97
-rw-r--r--src/lib/libc/include/thread_private.h14
2 files changed, 69 insertions, 42 deletions
diff --git a/src/lib/libc/crypt/arc4random.c b/src/lib/libc/crypt/arc4random.c
index 35d7953002..8604548f3f 100644
--- a/src/lib/libc/crypt/arc4random.c
+++ b/src/lib/libc/crypt/arc4random.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: arc4random.c,v 1.16 2007/02/12 19:58:47 otto Exp $ */ 1/* $OpenBSD: arc4random.c,v 1.17 2008/01/01 00:43:39 kurt Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996, David Mazieres <dm@uun.org> 4 * Copyright (c) 1996, David Mazieres <dm@uun.org>
@@ -40,6 +40,7 @@
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/time.h> 41#include <sys/time.h>
42#include <sys/sysctl.h> 42#include <sys/sysctl.h>
43#include "thread_private.h"
43 44
44#ifdef __GNUC__ 45#ifdef __GNUC__
45#define inline __inline 46#define inline __inline
@@ -58,43 +59,48 @@ static struct arc4_stream rs;
58static pid_t arc4_stir_pid; 59static pid_t arc4_stir_pid;
59static int arc4_count; 60static int arc4_count;
60 61
61static inline u_int8_t arc4_getbyte(struct arc4_stream *); 62static inline u_int8_t arc4_getbyte(void);
62 63
63static inline void 64static inline void
64arc4_init(struct arc4_stream *as) 65arc4_init(void)
65{ 66{
66 int n; 67 int n;
67 68
68 for (n = 0; n < 256; n++) 69 for (n = 0; n < 256; n++)
69 as->s[n] = n; 70 rs.s[n] = n;
70 as->i = 0; 71 rs.i = 0;
71 as->j = 0; 72 rs.j = 0;
72} 73}
73 74
74static inline void 75static inline void
75arc4_addrandom(struct arc4_stream *as, u_char *dat, int datlen) 76arc4_addrandom(u_char *dat, int datlen)
76{ 77{
77 int n; 78 int n;
78 u_int8_t si; 79 u_int8_t si;
79 80
80 as->i--; 81 rs.i--;
81 for (n = 0; n < 256; n++) { 82 for (n = 0; n < 256; n++) {
82 as->i = (as->i + 1); 83 rs.i = (rs.i + 1);
83 si = as->s[as->i]; 84 si = rs.s[rs.i];
84 as->j = (as->j + si + dat[n % datlen]); 85 rs.j = (rs.j + si + dat[n % datlen]);
85 as->s[as->i] = as->s[as->j]; 86 rs.s[rs.i] = rs.s[rs.j];
86 as->s[as->j] = si; 87 rs.s[rs.j] = si;
87 } 88 }
88 as->j = as->i; 89 rs.j = rs.i;
89} 90}
90 91
91static void 92static void
92arc4_stir(struct arc4_stream *as) 93arc4_stir(void)
93{ 94{
94 int i, mib[2]; 95 int i, mib[2];
95 size_t len; 96 size_t len;
96 u_char rnd[128]; 97 u_char rnd[128];
97 98
99 if (!rs_initialized) {
100 arc4_init();
101 rs_initialized = 1;
102 }
103
98 mib[0] = CTL_KERN; 104 mib[0] = CTL_KERN;
99 mib[1] = KERN_ARND; 105 mib[1] = KERN_ARND;
100 106
@@ -102,75 +108,84 @@ arc4_stir(struct arc4_stream *as)
102 sysctl(mib, 2, rnd, &len, NULL, 0); 108 sysctl(mib, 2, rnd, &len, NULL, 0);
103 109
104 arc4_stir_pid = getpid(); 110 arc4_stir_pid = getpid();
105 arc4_addrandom(as, rnd, sizeof(rnd)); 111 arc4_addrandom(rnd, sizeof(rnd));
106 112
107 /* 113 /*
108 * Discard early keystream, as per recommendations in: 114 * Discard early keystream, as per recommendations in:
109 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps 115 * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
110 */ 116 */
111 for (i = 0; i < 256; i++) 117 for (i = 0; i < 256; i++)
112 (void)arc4_getbyte(as); 118 (void)arc4_getbyte();
113 arc4_count = 1600000; 119 arc4_count = 1600000;
114} 120}
115 121
116static inline u_int8_t 122static inline u_int8_t
117arc4_getbyte(struct arc4_stream *as) 123arc4_getbyte(void)
118{ 124{
119 u_int8_t si, sj; 125 u_int8_t si, sj;
120 126
121 as->i = (as->i + 1); 127 rs.i = (rs.i + 1);
122 si = as->s[as->i]; 128 si = rs.s[rs.i];
123 as->j = (as->j + si); 129 rs.j = (rs.j + si);
124 sj = as->s[as->j]; 130 sj = rs.s[rs.j];
125 as->s[as->i] = sj; 131 rs.s[rs.i] = sj;
126 as->s[as->j] = si; 132 rs.s[rs.j] = si;
127 return (as->s[(si + sj) & 0xff]); 133 return (rs.s[(si + sj) & 0xff]);
128} 134}
129 135
130u_int8_t 136u_int8_t
131__arc4_getbyte(void) 137__arc4_getbyte(void)
132{ 138{
139 u_int8_t val;
140
141 _ARC4_LOCK();
133 if (--arc4_count == 0 || !rs_initialized) 142 if (--arc4_count == 0 || !rs_initialized)
134 arc4random_stir(); 143 arc4_stir();
135 return arc4_getbyte(&rs); 144 val = arc4_getbyte();
145 _ARC4_UNLOCK();
146 return val;
136} 147}
137 148
138static inline u_int32_t 149static inline u_int32_t
139arc4_getword(struct arc4_stream *as) 150arc4_getword(void)
140{ 151{
141 u_int32_t val; 152 u_int32_t val;
142 val = arc4_getbyte(as) << 24; 153 val = arc4_getbyte() << 24;
143 val |= arc4_getbyte(as) << 16; 154 val |= arc4_getbyte() << 16;
144 val |= arc4_getbyte(as) << 8; 155 val |= arc4_getbyte() << 8;
145 val |= arc4_getbyte(as); 156 val |= arc4_getbyte();
146 return val; 157 return val;
147} 158}
148 159
149void 160void
150arc4random_stir(void) 161arc4random_stir(void)
151{ 162{
152 if (!rs_initialized) { 163 _ARC4_LOCK();
153 arc4_init(&rs); 164 arc4_stir();
154 rs_initialized = 1; 165 _ARC4_UNLOCK();
155 }
156 arc4_stir(&rs);
157} 166}
158 167
159void 168void
160arc4random_addrandom(u_char *dat, int datlen) 169arc4random_addrandom(u_char *dat, int datlen)
161{ 170{
171 _ARC4_LOCK();
162 if (!rs_initialized) 172 if (!rs_initialized)
163 arc4random_stir(); 173 arc4_stir();
164 arc4_addrandom(&rs, dat, datlen); 174 arc4_addrandom(dat, datlen);
175 _ARC4_UNLOCK();
165} 176}
166 177
167u_int32_t 178u_int32_t
168arc4random(void) 179arc4random(void)
169{ 180{
181 u_int32_t val;
182 _ARC4_LOCK();
170 arc4_count -= 4; 183 arc4_count -= 4;
171 if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != getpid()) 184 if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != getpid())
172 arc4random_stir(); 185 arc4_stir();
173 return arc4_getword(&rs); 186 val = arc4_getword();
187 _ARC4_UNLOCK();
188 return val;
174} 189}
175 190
176#if 0 191#if 0
diff --git a/src/lib/libc/include/thread_private.h b/src/lib/libc/include/thread_private.h
index 146f0b0a01..f55880f7ba 100644
--- a/src/lib/libc/include/thread_private.h
+++ b/src/lib/libc/include/thread_private.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: thread_private.h,v 1.21 2007/11/19 02:54:19 kurt Exp $ */ 1/* $OpenBSD: thread_private.h,v 1.22 2008/01/01 00:43:39 kurt Exp $ */
2 2
3/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ 3/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
4 4
@@ -150,4 +150,16 @@ void _thread_atexit_unlock(void);
150 _thread_atexit_unlock();\ 150 _thread_atexit_unlock();\
151 } while (0) 151 } while (0)
152 152
153void _thread_arc4_lock(void);
154void _thread_arc4_unlock(void);
155
156#define _ARC4_LOCK() do { \
157 if (__isthreaded) \
158 _thread_arc4_lock(); \
159 } while (0)
160#define _ARC4_UNLOCK() do { \
161 if (__isthreaded) \
162 _thread_arc4_unlock();\
163 } while (0)
164
153#endif /* _THREAD_PRIVATE_H_ */ 165#endif /* _THREAD_PRIVATE_H_ */