Mercurial > dropbear
comparison libtomcrypt/src/prngs/fortuna.c @ 1471:6dba84798cd5
Update to libtomcrypt 1.18.1, merged with Dropbear changes
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 09 Feb 2018 21:44:05 +0800 |
parents | f849a5ca2efc |
children | e9dba7abd939 |
comparison
equal
deleted
inserted
replaced
1470:8bba51a55704 | 1471:6dba84798cd5 |
---|---|
3 * LibTomCrypt is a library that provides various cryptographic | 3 * LibTomCrypt is a library that provides various cryptographic |
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 * | |
9 * Tom St Denis, [email protected], http://libtom.org | |
10 */ | 8 */ |
11 #include "tomcrypt.h" | 9 #include "tomcrypt.h" |
12 | 10 |
13 /** | 11 /** |
14 @file fortuna.c | 12 @file fortuna.c |
15 Fortuna PRNG, Tom St Denis | 13 Fortuna PRNG, Tom St Denis |
16 */ | 14 */ |
17 | 15 |
18 /* Implementation of Fortuna by Tom St Denis | 16 /* Implementation of Fortuna by Tom St Denis |
19 | 17 |
20 We deviate slightly here for reasons of simplicity [and to fit in the API]. First all "sources" | 18 We deviate slightly here for reasons of simplicity [and to fit in the API]. First all "sources" |
21 in the AddEntropy function are fixed to 0. Second since no reliable timer is provided | 19 in the AddEntropy function are fixed to 0. Second since no reliable timer is provided |
22 we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to the read function */ | 20 we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to the read function */ |
23 | 21 |
24 #ifdef LTC_FORTUNA | 22 #ifdef LTC_FORTUNA |
25 | 23 |
26 /* requries LTC_SHA256 and AES */ | 24 /* requries LTC_SHA256 and AES */ |
27 #if !(defined(LTC_RIJNDAEL) && defined(LTC_SHA256)) | 25 #if !(defined(LTC_RIJNDAEL) && defined(LTC_SHA256)) |
28 #error LTC_FORTUNA requires LTC_SHA256 and LTC_RIJNDAEL (AES) | 26 #error LTC_FORTUNA requires LTC_SHA256 and LTC_RIJNDAEL (AES) |
29 #endif | 27 #endif |
36 #if LTC_FORTUNA_POOLS < 4 || LTC_FORTUNA_POOLS > 32 | 34 #if LTC_FORTUNA_POOLS < 4 || LTC_FORTUNA_POOLS > 32 |
37 #error LTC_FORTUNA_POOLS must be in [4..32] | 35 #error LTC_FORTUNA_POOLS must be in [4..32] |
38 #endif | 36 #endif |
39 | 37 |
40 const struct ltc_prng_descriptor fortuna_desc = { | 38 const struct ltc_prng_descriptor fortuna_desc = { |
41 "fortuna", 1024, | 39 "fortuna", |
40 (32 * LTC_FORTUNA_POOLS), /* default: 1024 */ | |
42 &fortuna_start, | 41 &fortuna_start, |
43 &fortuna_add_entropy, | 42 &fortuna_add_entropy, |
44 &fortuna_ready, | 43 &fortuna_ready, |
45 &fortuna_read, | 44 &fortuna_read, |
46 &fortuna_done, | 45 &fortuna_done, |
48 &fortuna_import, | 47 &fortuna_import, |
49 &fortuna_test | 48 &fortuna_test |
50 }; | 49 }; |
51 | 50 |
52 /* update the IV */ | 51 /* update the IV */ |
53 static void fortuna_update_iv(prng_state *prng) | 52 static void _fortuna_update_iv(prng_state *prng) |
54 { | 53 { |
55 int x; | 54 int x; |
56 unsigned char *IV; | 55 unsigned char *IV; |
57 /* update IV */ | 56 /* update IV */ |
58 IV = prng->fortuna.IV; | 57 IV = prng->fortuna.IV; |
61 if (IV[x] != 0) break; | 60 if (IV[x] != 0) break; |
62 } | 61 } |
63 } | 62 } |
64 | 63 |
65 /* reseed the PRNG */ | 64 /* reseed the PRNG */ |
66 static int fortuna_reseed(prng_state *prng) | 65 static int _fortuna_reseed(prng_state *prng) |
67 { | 66 { |
68 unsigned char tmp[MAXBLOCKSIZE]; | 67 unsigned char tmp[MAXBLOCKSIZE]; |
69 hash_state md; | 68 hash_state md; |
70 int err, x; | 69 int err, x; |
71 | 70 |
77 sha256_done(&md, tmp); | 76 sha256_done(&md, tmp); |
78 return err; | 77 return err; |
79 } | 78 } |
80 | 79 |
81 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { | 80 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { |
82 if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) { | 81 if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) { |
83 /* terminate this hash */ | 82 /* terminate this hash */ |
84 if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) { | 83 if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) { |
85 sha256_done(&md, tmp); | 84 sha256_done(&md, tmp); |
86 return err; | 85 return err; |
87 } | 86 } |
88 /* add it to the string */ | 87 /* add it to the string */ |
89 if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) { | 88 if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) { |
90 sha256_done(&md, tmp); | 89 sha256_done(&md, tmp); |
91 return err; | 90 return err; |
100 } | 99 } |
101 } | 100 } |
102 | 101 |
103 /* finish key */ | 102 /* finish key */ |
104 if ((err = sha256_done(&md, prng->fortuna.K)) != CRYPT_OK) { | 103 if ((err = sha256_done(&md, prng->fortuna.K)) != CRYPT_OK) { |
105 return err; | 104 return err; |
106 } | 105 } |
107 if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { | 106 if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { |
108 return err; | 107 return err; |
109 } | 108 } |
110 fortuna_update_iv(prng); | 109 _fortuna_update_iv(prng); |
111 | 110 |
112 /* reset pool len */ | 111 /* reset pool len */ |
113 prng->fortuna.pool0_len = 0; | 112 prng->fortuna.pool0_len = 0; |
114 prng->fortuna.wd = 0; | 113 prng->fortuna.wd = 0; |
115 | 114 |
124 | 123 |
125 /** | 124 /** |
126 Start the PRNG | 125 Start the PRNG |
127 @param prng [out] The PRNG state to initialize | 126 @param prng [out] The PRNG state to initialize |
128 @return CRYPT_OK if successful | 127 @return CRYPT_OK if successful |
129 */ | 128 */ |
130 int fortuna_start(prng_state *prng) | 129 int fortuna_start(prng_state *prng) |
131 { | 130 { |
132 int err, x, y; | 131 int err, x, y; |
133 unsigned char tmp[MAXBLOCKSIZE]; | 132 unsigned char tmp[MAXBLOCKSIZE]; |
134 | 133 |
135 LTC_ARGCHK(prng != NULL); | 134 LTC_ARGCHK(prng != NULL); |
136 | 135 prng->ready = 0; |
136 | |
137 /* initialize the pools */ | 137 /* initialize the pools */ |
138 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { | 138 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { |
139 if ((err = sha256_init(&prng->fortuna.pool[x])) != CRYPT_OK) { | 139 if ((err = sha256_init(&prng->fortuna.pool[x])) != CRYPT_OK) { |
140 for (y = 0; y < x; y++) { | 140 for (y = 0; y < x; y++) { |
141 sha256_done(&prng->fortuna.pool[y], tmp); | 141 sha256_done(&prng->fortuna.pool[y], tmp); |
153 sha256_done(&prng->fortuna.pool[x], tmp); | 153 sha256_done(&prng->fortuna.pool[x], tmp); |
154 } | 154 } |
155 return err; | 155 return err; |
156 } | 156 } |
157 zeromem(prng->fortuna.IV, 16); | 157 zeromem(prng->fortuna.IV, 16); |
158 | 158 |
159 LTC_MUTEX_INIT(&prng->fortuna.prng_lock) | 159 LTC_MUTEX_INIT(&prng->lock) |
160 | 160 |
161 return CRYPT_OK; | 161 return CRYPT_OK; |
162 } | 162 } |
163 | 163 |
164 /** | 164 /** |
165 Add entropy to the PRNG state | 165 Add entropy to the PRNG state |
166 @param in The data to add | 166 @param in The data to add |
167 @param inlen Length of the data to add | 167 @param inlen Length of the data to add |
168 @param prng PRNG state to update | 168 @param prng PRNG state to update |
169 @return CRYPT_OK if successful | 169 @return CRYPT_OK if successful |
170 */ | 170 */ |
171 int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) | 171 int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) |
172 { | 172 { |
173 unsigned char tmp[2]; | 173 unsigned char tmp[2]; |
174 int err; | 174 int err; |
175 | 175 |
176 LTC_ARGCHK(in != NULL); | |
177 LTC_ARGCHK(prng != NULL); | 176 LTC_ARGCHK(prng != NULL); |
178 | 177 LTC_ARGCHK(in != NULL); |
179 LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | 178 LTC_ARGCHK(inlen > 0); |
180 | 179 |
181 /* ensure inlen <= 32 */ | 180 /* ensure inlen <= 32 */ |
182 if (inlen > 32) { | 181 if (inlen > 32) { |
183 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 182 inlen = 32; |
184 return CRYPT_INVALID_ARG; | |
185 } | 183 } |
186 | 184 |
187 /* add s || length(in) || in to pool[pool_idx] */ | 185 /* add s || length(in) || in to pool[pool_idx] */ |
188 tmp[0] = 0; | 186 tmp[0] = 0; |
189 tmp[1] = (unsigned char)inlen; | 187 tmp[1] = (unsigned char)inlen; |
188 | |
189 LTC_MUTEX_LOCK(&prng->lock); | |
190 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); | 191 goto LBL_UNLOCK; |
192 return err; | |
193 } | 192 } |
194 if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], in, inlen)) != CRYPT_OK) { | 193 if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], in, inlen)) != CRYPT_OK) { |
195 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 194 goto LBL_UNLOCK; |
196 return err; | |
197 } | 195 } |
198 if (prng->fortuna.pool_idx == 0) { | 196 if (prng->fortuna.pool_idx == 0) { |
199 prng->fortuna.pool0_len += inlen; | 197 prng->fortuna.pool0_len += inlen; |
200 } | 198 } |
201 if (++(prng->fortuna.pool_idx) == LTC_FORTUNA_POOLS) { | 199 if (++(prng->fortuna.pool_idx) == LTC_FORTUNA_POOLS) { |
202 prng->fortuna.pool_idx = 0; | 200 prng->fortuna.pool_idx = 0; |
203 } | 201 } |
204 | 202 err = CRYPT_OK; /* success */ |
205 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 203 |
206 return CRYPT_OK; | 204 LBL_UNLOCK: |
205 LTC_MUTEX_UNLOCK(&prng->lock); | |
206 return err; | |
207 } | 207 } |
208 | 208 |
209 /** | 209 /** |
210 Make the PRNG ready to read from | 210 Make the PRNG ready to read from |
211 @param prng The PRNG to make active | 211 @param prng The PRNG to make active |
212 @return CRYPT_OK if successful | 212 @return CRYPT_OK if successful |
213 */ | 213 */ |
214 int fortuna_ready(prng_state *prng) | 214 int fortuna_ready(prng_state *prng) |
215 { | 215 { |
216 return fortuna_reseed(prng); | 216 int err; |
217 LTC_ARGCHK(prng != NULL); | |
218 | |
219 LTC_MUTEX_LOCK(&prng->lock); | |
220 err = _fortuna_reseed(prng); | |
221 prng->ready = (err == CRYPT_OK) ? 1 : 0; | |
222 | |
223 LTC_MUTEX_UNLOCK(&prng->lock); | |
224 return err; | |
217 } | 225 } |
218 | 226 |
219 /** | 227 /** |
220 Read from the PRNG | 228 Read from the PRNG |
221 @param out Destination | 229 @param out Destination |
222 @param outlen Length of output | 230 @param outlen Length of output |
223 @param prng The active PRNG to read from | 231 @param prng The active PRNG to read from |
224 @return Number of octets read | 232 @return Number of octets read |
225 */ | 233 */ |
226 unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng) | 234 unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng) |
227 { | 235 { |
228 unsigned char tmp[16]; | 236 unsigned char tmp[16]; |
229 int err; | 237 unsigned long tlen = 0; |
230 unsigned long tlen; | 238 |
231 | 239 if (outlen == 0 || prng == NULL || out == NULL) return 0; |
232 LTC_ARGCHK(out != NULL); | 240 |
233 LTC_ARGCHK(prng != NULL); | 241 LTC_MUTEX_LOCK(&prng->lock); |
234 | 242 |
235 LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | 243 if (!prng->ready) { |
244 goto LBL_UNLOCK; | |
245 } | |
236 | 246 |
237 /* do we have to reseed? */ | 247 /* do we have to reseed? */ |
238 if (++prng->fortuna.wd == LTC_FORTUNA_WD || prng->fortuna.pool0_len >= 64) { | 248 if (++prng->fortuna.wd == LTC_FORTUNA_WD || prng->fortuna.pool0_len >= 64) { |
239 if ((err = fortuna_reseed(prng)) != CRYPT_OK) { | 249 if (_fortuna_reseed(prng) != CRYPT_OK) { |
240 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 250 goto LBL_UNLOCK; |
241 return 0; | |
242 } | 251 } |
243 } | 252 } |
244 | 253 |
245 /* now generate the blocks required */ | 254 /* now generate the blocks required */ |
246 tlen = outlen; | 255 tlen = outlen; |
249 while (outlen >= 16) { | 258 while (outlen >= 16) { |
250 /* encrypt the IV and store it */ | 259 /* encrypt the IV and store it */ |
251 rijndael_ecb_encrypt(prng->fortuna.IV, out, &prng->fortuna.skey); | 260 rijndael_ecb_encrypt(prng->fortuna.IV, out, &prng->fortuna.skey); |
252 out += 16; | 261 out += 16; |
253 outlen -= 16; | 262 outlen -= 16; |
254 fortuna_update_iv(prng); | 263 _fortuna_update_iv(prng); |
255 } | 264 } |
256 | 265 |
257 /* left over bytes? */ | 266 /* left over bytes? */ |
258 if (outlen > 0) { | 267 if (outlen > 0) { |
259 rijndael_ecb_encrypt(prng->fortuna.IV, tmp, &prng->fortuna.skey); | 268 rijndael_ecb_encrypt(prng->fortuna.IV, tmp, &prng->fortuna.skey); |
260 XMEMCPY(out, tmp, outlen); | 269 XMEMCPY(out, tmp, outlen); |
261 fortuna_update_iv(prng); | 270 _fortuna_update_iv(prng); |
262 } | 271 } |
263 | 272 |
264 /* generate new key */ | 273 /* generate new key */ |
265 rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K , &prng->fortuna.skey); fortuna_update_iv(prng); | 274 rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K , &prng->fortuna.skey); |
266 rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K+16, &prng->fortuna.skey); fortuna_update_iv(prng); | 275 _fortuna_update_iv(prng); |
267 if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { | 276 |
268 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 277 rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K+16, &prng->fortuna.skey); |
269 return 0; | 278 _fortuna_update_iv(prng); |
270 } | 279 |
271 | 280 if (rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey) != CRYPT_OK) { |
281 tlen = 0; | |
282 } | |
283 | |
284 LBL_UNLOCK: | |
272 #ifdef LTC_CLEAN_STACK | 285 #ifdef LTC_CLEAN_STACK |
273 zeromem(tmp, sizeof(tmp)); | 286 zeromem(tmp, sizeof(tmp)); |
274 #endif | 287 #endif |
275 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 288 LTC_MUTEX_UNLOCK(&prng->lock); |
276 return tlen; | 289 return tlen; |
277 } | 290 } |
278 | 291 |
279 /** | 292 /** |
280 Terminate the PRNG | 293 Terminate the PRNG |
281 @param prng The PRNG to terminate | 294 @param prng The PRNG to terminate |
282 @return CRYPT_OK if successful | 295 @return CRYPT_OK if successful |
283 */ | 296 */ |
284 int fortuna_done(prng_state *prng) | 297 int fortuna_done(prng_state *prng) |
285 { | 298 { |
286 int err, x; | 299 int err, x; |
287 unsigned char tmp[32]; | 300 unsigned char tmp[32]; |
288 | 301 |
289 LTC_ARGCHK(prng != NULL); | 302 LTC_ARGCHK(prng != NULL); |
290 LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | 303 |
304 LTC_MUTEX_LOCK(&prng->lock); | |
305 prng->ready = 0; | |
291 | 306 |
292 /* terminate all the hashes */ | 307 /* terminate all the hashes */ |
293 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { | 308 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { |
294 if ((err = sha256_done(&(prng->fortuna.pool[x]), tmp)) != CRYPT_OK) { | 309 if ((err = sha256_done(&(prng->fortuna.pool[x]), tmp)) != CRYPT_OK) { |
295 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 310 goto LBL_UNLOCK; |
296 return err; | |
297 } | 311 } |
298 } | 312 } |
299 /* call cipher done when we invent one ;-) */ | 313 /* call cipher done when we invent one ;-) */ |
300 | 314 err = CRYPT_OK; /* success */ |
315 | |
316 LBL_UNLOCK: | |
301 #ifdef LTC_CLEAN_STACK | 317 #ifdef LTC_CLEAN_STACK |
302 zeromem(tmp, sizeof(tmp)); | 318 zeromem(tmp, sizeof(tmp)); |
303 #endif | 319 #endif |
304 | 320 LTC_MUTEX_UNLOCK(&prng->lock); |
305 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 321 LTC_MUTEX_DESTROY(&prng->lock); |
306 return CRYPT_OK; | 322 return err; |
307 } | 323 } |
308 | 324 |
309 /** | 325 /** |
310 Export the PRNG state | 326 Export the PRNG state |
311 @param out [out] Destination | 327 @param out [out] Destination |
312 @param outlen [in/out] Max size and resulting size of the state | 328 @param outlen [in/out] Max size and resulting size of the state |
313 @param prng The PRNG to export | 329 @param prng The PRNG to export |
314 @return CRYPT_OK if successful | 330 @return CRYPT_OK if successful |
315 */ | 331 */ |
316 int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng) | 332 int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng) |
317 { | 333 { |
318 int x, err; | 334 int x, err; |
319 hash_state *md; | 335 hash_state *md; |
336 unsigned long len = fortuna_desc.export_size; | |
320 | 337 |
321 LTC_ARGCHK(out != NULL); | 338 LTC_ARGCHK(out != NULL); |
322 LTC_ARGCHK(outlen != NULL); | 339 LTC_ARGCHK(outlen != NULL); |
323 LTC_ARGCHK(prng != NULL); | 340 LTC_ARGCHK(prng != NULL); |
324 | 341 |
325 LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); | 342 LTC_MUTEX_LOCK(&prng->lock); |
343 | |
344 if (!prng->ready) { | |
345 err = CRYPT_ERROR; | |
346 goto LBL_UNLOCK; | |
347 } | |
326 | 348 |
327 /* we'll write bytes for s&g's */ | 349 /* we'll write bytes for s&g's */ |
328 if (*outlen < 32*LTC_FORTUNA_POOLS) { | 350 if (*outlen < len) { |
329 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 351 *outlen = len; |
330 *outlen = 32*LTC_FORTUNA_POOLS; | 352 err = CRYPT_BUFFER_OVERFLOW; |
331 return CRYPT_BUFFER_OVERFLOW; | 353 goto LBL_UNLOCK; |
332 } | 354 } |
333 | 355 |
334 md = XMALLOC(sizeof(hash_state)); | 356 md = XMALLOC(sizeof(hash_state)); |
335 if (md == NULL) { | 357 if (md == NULL) { |
336 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 358 err = CRYPT_MEM; |
337 return CRYPT_MEM; | 359 goto LBL_UNLOCK; |
338 } | 360 } |
339 | 361 |
340 /* to emit the state we copy each pool, terminate it then hash it again so | 362 /* to emit the state we copy each pool, terminate it then hash it again so |
341 * an attacker who sees the state can't determine the current state of the PRNG | 363 * an attacker who sees the state can't determine the current state of the PRNG |
342 */ | 364 */ |
343 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { | 365 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { |
344 /* copy the PRNG */ | 366 /* copy the PRNG */ |
345 XMEMCPY(md, &(prng->fortuna.pool[x]), sizeof(*md)); | 367 XMEMCPY(md, &(prng->fortuna.pool[x]), sizeof(*md)); |
346 | 368 |
347 /* terminate it */ | 369 /* terminate it */ |
358 } | 380 } |
359 if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) { | 381 if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) { |
360 goto LBL_ERR; | 382 goto LBL_ERR; |
361 } | 383 } |
362 } | 384 } |
363 *outlen = 32*LTC_FORTUNA_POOLS; | 385 *outlen = len; |
364 err = CRYPT_OK; | 386 err = CRYPT_OK; |
365 | 387 |
366 LBL_ERR: | 388 LBL_ERR: |
367 #ifdef LTC_CLEAN_STACK | 389 #ifdef LTC_CLEAN_STACK |
368 zeromem(md, sizeof(*md)); | 390 zeromem(md, sizeof(*md)); |
369 #endif | 391 #endif |
370 XFREE(md); | 392 XFREE(md); |
371 LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); | 393 LBL_UNLOCK: |
394 LTC_MUTEX_UNLOCK(&prng->lock); | |
372 return err; | 395 return err; |
373 } | 396 } |
374 | 397 |
375 /** | 398 /** |
376 Import a PRNG state | 399 Import a PRNG state |
377 @param in The PRNG state | 400 @param in The PRNG state |
378 @param inlen Size of the state | 401 @param inlen Size of the state |
379 @param prng The PRNG to import | 402 @param prng The PRNG to import |
380 @return CRYPT_OK if successful | 403 @return CRYPT_OK if successful |
381 */ | 404 */ |
382 int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | 405 int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng) |
383 { | 406 { |
384 int err, x; | 407 int err, x; |
385 | 408 |
386 LTC_ARGCHK(in != NULL); | 409 LTC_ARGCHK(in != NULL); |
387 LTC_ARGCHK(prng != NULL); | 410 LTC_ARGCHK(prng != NULL); |
388 | 411 |
389 if (inlen != 32*LTC_FORTUNA_POOLS) { | 412 if (inlen < (unsigned long)fortuna_desc.export_size) { |
390 return CRYPT_INVALID_ARG; | 413 return CRYPT_INVALID_ARG; |
391 } | 414 } |
392 | 415 |
393 if ((err = fortuna_start(prng)) != CRYPT_OK) { | 416 if ((err = fortuna_start(prng)) != CRYPT_OK) { |
394 return err; | 417 return err; |
396 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { | 419 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { |
397 if ((err = fortuna_add_entropy(in+x*32, 32, prng)) != CRYPT_OK) { | 420 if ((err = fortuna_add_entropy(in+x*32, 32, prng)) != CRYPT_OK) { |
398 return err; | 421 return err; |
399 } | 422 } |
400 } | 423 } |
401 return err; | 424 return CRYPT_OK; |
402 } | 425 } |
403 | 426 |
404 /** | 427 /** |
405 PRNG self-test | 428 PRNG self-test |
406 @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled | 429 @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled |
407 */ | 430 */ |
408 int fortuna_test(void) | 431 int fortuna_test(void) |
409 { | 432 { |
410 #ifndef LTC_TEST | 433 #ifndef LTC_TEST |
411 return CRYPT_NOP; | 434 return CRYPT_NOP; |
412 #else | 435 #else |
420 } | 443 } |
421 | 444 |
422 #endif | 445 #endif |
423 | 446 |
424 | 447 |
425 /* $Source$ */ | 448 /* ref: $Format:%D$ */ |
426 /* $Revision$ */ | 449 /* git commit: $Format:%H$ */ |
427 /* $Date$ */ | 450 /* commit time: $Format:%ai$ */ |