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 $ */