Mercurial > dropbear
comparison libtomcrypt/src/prngs/fortuna.c @ 382:0cbe8f6dbf9e
propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head 2af22fb4e878750b88f80f90d439b316d229796f)
to branch 'au.asn.ucc.matt.dropbear' (head 02c413252c90e9de8e03d91e9939dde3029f5c0a)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 11 Jan 2007 02:41:05 +0000 |
parents | 1b9e69c058d2 |
children | f849a5ca2efc |
comparison
equal
deleted
inserted
replaced
379:b66a00272a90 | 382:0cbe8f6dbf9e |
---|---|
4 * algorithms in a highly modular and flexible manner. | 4 * algorithms in a highly modular and flexible manner. |
5 * | 5 * |
6 * The library is free for all purposes without any express | 6 * The library is free for all purposes without any express |
7 * guarantee it works. | 7 * guarantee it works. |
8 * | 8 * |
9 * Tom St Denis, [email protected], http://libtomcrypt.org | 9 * Tom St Denis, [email protected], http://libtomcrypt.com |
10 */ | 10 */ |
11 #include "tomcrypt.h" | 11 #include "tomcrypt.h" |
12 | 12 |
13 /** | 13 /** |
14 @file fortuna.c | 14 @file fortuna.c |
72 ++prng->fortuna.reset_cnt; | 72 ++prng->fortuna.reset_cnt; |
73 | 73 |
74 /* new K == SHA256(K || s) where s == SHA256(P0) || SHA256(P1) ... */ | 74 /* new K == SHA256(K || s) where s == SHA256(P0) || SHA256(P1) ... */ |
75 sha256_init(&md); | 75 sha256_init(&md); |
76 if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) { | 76 if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) { |
77 sha256_done(&md, tmp); | |
77 return err; | 78 return err; |
78 } | 79 } |
79 | 80 |
80 for (x = 0; x < FORTUNA_POOLS; x++) { | 81 for (x = 0; x < FORTUNA_POOLS; x++) { |
81 if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) { | 82 if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) { |
82 /* terminate this hash */ | 83 /* terminate this hash */ |
83 if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) { | 84 if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) { |
85 sha256_done(&md, tmp); | |
84 return err; | 86 return err; |
85 } | 87 } |
86 /* add it to the string */ | 88 /* add it to the string */ |
87 if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) { | 89 if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) { |
90 sha256_done(&md, tmp); | |
88 return err; | 91 return err; |
89 } | 92 } |
90 /* reset this pool */ | 93 /* reset this pool */ |
91 sha256_init(&prng->fortuna.pool[x]); | 94 if ((err = sha256_init(&prng->fortuna.pool[x])) != CRYPT_OK) { |
95 sha256_done(&md, tmp); | |
96 return err; | |
97 } | |
92 } else { | 98 } else { |
93 break; | 99 break; |
94 } | 100 } |
95 } | 101 } |
96 | 102 |
121 @param prng [out] The PRNG state to initialize | 127 @param prng [out] The PRNG state to initialize |
122 @return CRYPT_OK if successful | 128 @return CRYPT_OK if successful |
123 */ | 129 */ |
124 int fortuna_start(prng_state *prng) | 130 int fortuna_start(prng_state *prng) |
125 { | 131 { |
126 int err, x; | 132 int err, x, y; |
133 unsigned char tmp[MAXBLOCKSIZE]; | |
127 | 134 |
128 LTC_ARGCHK(prng != NULL); | 135 LTC_ARGCHK(prng != NULL); |
129 | 136 |
130 /* initialize the pools */ | 137 /* initialize the pools */ |
131 for (x = 0; x < FORTUNA_POOLS; x++) { | 138 for (x = 0; x < FORTUNA_POOLS; x++) { |
132 sha256_init(&prng->fortuna.pool[x]); | 139 if ((err = sha256_init(&prng->fortuna.pool[x])) != CRYPT_OK) { |
133 } | 140 for (y = 0; y < x; y++) { |
134 prng->fortuna.pool_idx = prng->fortuna.pool0_len = prng->fortuna.reset_cnt = | 141 sha256_done(&prng->fortuna.pool[y], tmp); |
135 prng->fortuna.wd = 0; | 142 } |
143 return err; | |
144 } | |
145 } | |
146 prng->fortuna.pool_idx = prng->fortuna.pool0_len = prng->fortuna.wd = 0; | |
147 prng->fortuna.reset_cnt = 0; | |
136 | 148 |
137 /* reset bufs */ | 149 /* reset bufs */ |
138 zeromem(prng->fortuna.K, 32); | 150 zeromem(prng->fortuna.K, 32); |
139 if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { | 151 if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { |
152 for (x = 0; x < FORTUNA_POOLS; x++) { | |
153 sha256_done(&prng->fortuna.pool[x], tmp); | |
154 } | |
140 return err; | 155 return err; |
141 } | 156 } |
142 zeromem(prng->fortuna.IV, 16); | 157 zeromem(prng->fortuna.IV, 16); |
143 | 158 |
159 LTC_MUTEX_INIT(&prng->fortuna.prng_lock) | |
160 | |
144 return CRYPT_OK; | 161 return CRYPT_OK; |
145 } | 162 } |
146 | 163 |
147 /** | 164 /** |
148 Add entropy to the PRNG state | 165 Add entropy to the PRNG state |
157 int err; | 174 int err; |
158 | 175 |
159 LTC_ARGCHK(in != NULL); | 176 LTC_ARGCHK(in != NULL); |
160 LTC_ARGCHK(prng != NULL); | 177 LTC_ARGCHK(prng != NULL); |
161 | 178 |
179 LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | |
180 | |
162 /* ensure inlen <= 32 */ | 181 /* ensure inlen <= 32 */ |
163 if (inlen > 32) { | 182 if (inlen > 32) { |
183 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
164 return CRYPT_INVALID_ARG; | 184 return CRYPT_INVALID_ARG; |
165 } | 185 } |
166 | 186 |
167 /* add s || length(in) || in to pool[pool_idx] */ | 187 /* add s || length(in) || in to pool[pool_idx] */ |
168 tmp[0] = 0; | 188 tmp[0] = 0; |
169 tmp[1] = inlen; | 189 tmp[1] = (unsigned char)inlen; |
170 if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], tmp, 2)) != CRYPT_OK) { | 190 if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], tmp, 2)) != CRYPT_OK) { |
191 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
171 return err; | 192 return err; |
172 } | 193 } |
173 if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], in, inlen)) != CRYPT_OK) { | 194 if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], in, inlen)) != CRYPT_OK) { |
195 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
174 return err; | 196 return err; |
175 } | 197 } |
176 if (prng->fortuna.pool_idx == 0) { | 198 if (prng->fortuna.pool_idx == 0) { |
177 prng->fortuna.pool0_len += inlen; | 199 prng->fortuna.pool0_len += inlen; |
178 } | 200 } |
179 if (++(prng->fortuna.pool_idx) == FORTUNA_POOLS) { | 201 if (++(prng->fortuna.pool_idx) == FORTUNA_POOLS) { |
180 prng->fortuna.pool_idx = 0; | 202 prng->fortuna.pool_idx = 0; |
181 } | 203 } |
182 | 204 |
205 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
183 return CRYPT_OK; | 206 return CRYPT_OK; |
184 } | 207 } |
185 | 208 |
186 /** | 209 /** |
187 Make the PRNG ready to read from | 210 Make the PRNG ready to read from |
207 unsigned long tlen; | 230 unsigned long tlen; |
208 | 231 |
209 LTC_ARGCHK(out != NULL); | 232 LTC_ARGCHK(out != NULL); |
210 LTC_ARGCHK(prng != NULL); | 233 LTC_ARGCHK(prng != NULL); |
211 | 234 |
235 LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | |
236 | |
212 /* do we have to reseed? */ | 237 /* do we have to reseed? */ |
213 if (++prng->fortuna.wd == FORTUNA_WD || prng->fortuna.pool0_len >= 64) { | 238 if (++prng->fortuna.wd == FORTUNA_WD || prng->fortuna.pool0_len >= 64) { |
214 if ((err = fortuna_reseed(prng)) != CRYPT_OK) { | 239 if ((err = fortuna_reseed(prng)) != CRYPT_OK) { |
240 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
215 return 0; | 241 return 0; |
216 } | 242 } |
217 } | 243 } |
218 | 244 |
219 /* now generate the blocks required */ | 245 /* now generate the blocks required */ |
220 tlen = outlen; | 246 tlen = outlen; |
221 | 247 |
222 /* handle whole blocks without the extra memcpy */ | 248 /* handle whole blocks without the extra XMEMCPY */ |
223 while (outlen >= 16) { | 249 while (outlen >= 16) { |
224 /* encrypt the IV and store it */ | 250 /* encrypt the IV and store it */ |
225 rijndael_ecb_encrypt(prng->fortuna.IV, out, &prng->fortuna.skey); | 251 rijndael_ecb_encrypt(prng->fortuna.IV, out, &prng->fortuna.skey); |
226 out += 16; | 252 out += 16; |
227 outlen -= 16; | 253 outlen -= 16; |
237 | 263 |
238 /* generate new key */ | 264 /* generate new key */ |
239 rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K , &prng->fortuna.skey); fortuna_update_iv(prng); | 265 rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K , &prng->fortuna.skey); fortuna_update_iv(prng); |
240 rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K+16, &prng->fortuna.skey); fortuna_update_iv(prng); | 266 rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K+16, &prng->fortuna.skey); fortuna_update_iv(prng); |
241 if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { | 267 if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { |
268 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
242 return 0; | 269 return 0; |
243 } | 270 } |
244 | 271 |
245 #ifdef LTC_CLEAN_STACK | 272 #ifdef LTC_CLEAN_STACK |
246 zeromem(tmp, sizeof(tmp)); | 273 zeromem(tmp, sizeof(tmp)); |
247 #endif | 274 #endif |
275 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
248 return tlen; | 276 return tlen; |
249 } | 277 } |
250 | 278 |
251 /** | 279 /** |
252 Terminate the PRNG | 280 Terminate the PRNG |
257 { | 285 { |
258 int err, x; | 286 int err, x; |
259 unsigned char tmp[32]; | 287 unsigned char tmp[32]; |
260 | 288 |
261 LTC_ARGCHK(prng != NULL); | 289 LTC_ARGCHK(prng != NULL); |
290 LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | |
262 | 291 |
263 /* terminate all the hashes */ | 292 /* terminate all the hashes */ |
264 for (x = 0; x < FORTUNA_POOLS; x++) { | 293 for (x = 0; x < FORTUNA_POOLS; x++) { |
265 if ((err = sha256_done(&(prng->fortuna.pool[x]), tmp)) != CRYPT_OK) { | 294 if ((err = sha256_done(&(prng->fortuna.pool[x]), tmp)) != CRYPT_OK) { |
295 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
266 return err; | 296 return err; |
267 } | 297 } |
268 } | 298 } |
269 /* call cipher done when we invent one ;-) */ | 299 /* call cipher done when we invent one ;-) */ |
270 | 300 |
271 #ifdef LTC_CLEAN_STACK | 301 #ifdef LTC_CLEAN_STACK |
272 zeromem(tmp, sizeof(tmp)); | 302 zeromem(tmp, sizeof(tmp)); |
273 #endif | 303 #endif |
274 | 304 |
305 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
275 return CRYPT_OK; | 306 return CRYPT_OK; |
276 } | 307 } |
277 | 308 |
278 /** | 309 /** |
279 Export the PRNG state | 310 Export the PRNG state |
289 | 320 |
290 LTC_ARGCHK(out != NULL); | 321 LTC_ARGCHK(out != NULL); |
291 LTC_ARGCHK(outlen != NULL); | 322 LTC_ARGCHK(outlen != NULL); |
292 LTC_ARGCHK(prng != NULL); | 323 LTC_ARGCHK(prng != NULL); |
293 | 324 |
325 LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | |
326 | |
294 /* we'll write bytes for s&g's */ | 327 /* we'll write bytes for s&g's */ |
295 if (*outlen < 32*FORTUNA_POOLS) { | 328 if (*outlen < 32*FORTUNA_POOLS) { |
329 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
330 *outlen = 32*FORTUNA_POOLS; | |
296 return CRYPT_BUFFER_OVERFLOW; | 331 return CRYPT_BUFFER_OVERFLOW; |
297 } | 332 } |
298 | 333 |
299 md = XMALLOC(sizeof(hash_state)); | 334 md = XMALLOC(sizeof(hash_state)); |
300 if (md == NULL) { | 335 if (md == NULL) { |
336 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
301 return CRYPT_MEM; | 337 return CRYPT_MEM; |
302 } | 338 } |
303 | 339 |
304 /* to emit the state we copy each pool, terminate it then hash it again so | 340 /* to emit the state we copy each pool, terminate it then hash it again so |
305 * an attacker who sees the state can't determine the current state of the PRNG | 341 * an attacker who sees the state can't determine the current state of the PRNG |
330 LBL_ERR: | 366 LBL_ERR: |
331 #ifdef LTC_CLEAN_STACK | 367 #ifdef LTC_CLEAN_STACK |
332 zeromem(md, sizeof(*md)); | 368 zeromem(md, sizeof(*md)); |
333 #endif | 369 #endif |
334 XFREE(md); | 370 XFREE(md); |
371 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | |
335 return err; | 372 return err; |
336 } | 373 } |
337 | 374 |
338 /** | 375 /** |
339 Import a PRNG state | 376 Import a PRNG state |
384 | 421 |
385 #endif | 422 #endif |
386 | 423 |
387 | 424 |
388 /* $Source: /cvs/libtom/libtomcrypt/src/prngs/fortuna.c,v $ */ | 425 /* $Source: /cvs/libtom/libtomcrypt/src/prngs/fortuna.c,v $ */ |
389 /* $Revision: 1.3 $ */ | 426 /* $Revision: 1.12 $ */ |
390 /* $Date: 2005/05/05 14:35:59 $ */ | 427 /* $Date: 2006/12/04 21:34:03 $ */ |