Mercurial > dropbear
comparison libtomcrypt/src/prngs/fortuna.c @ 1711:e9dba7abd939
Merge libtomcrypt v1.18.2
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 10 Jun 2020 23:16:13 +0800 |
parents | 6dba84798cd5 |
children |
comparison
equal
deleted
inserted
replaced
1710:1ff2a1034c52 | 1711:e9dba7abd939 |
---|---|
64 /* reseed the PRNG */ | 64 /* reseed the PRNG */ |
65 static int _fortuna_reseed(prng_state *prng) | 65 static int _fortuna_reseed(prng_state *prng) |
66 { | 66 { |
67 unsigned char tmp[MAXBLOCKSIZE]; | 67 unsigned char tmp[MAXBLOCKSIZE]; |
68 hash_state md; | 68 hash_state md; |
69 ulong64 reset_cnt; | |
69 int err, x; | 70 int err, x; |
70 | 71 |
71 ++prng->fortuna.reset_cnt; | |
72 | 72 |
73 /* new K == LTC_SHA256(K || s) where s == LTC_SHA256(P0) || LTC_SHA256(P1) ... */ | 73 /* new K == LTC_SHA256(K || s) where s == LTC_SHA256(P0) || LTC_SHA256(P1) ... */ |
74 sha256_init(&md); | 74 sha256_init(&md); |
75 if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) { | 75 if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) { |
76 sha256_done(&md, tmp); | 76 sha256_done(&md, tmp); |
77 return err; | 77 return err; |
78 } | 78 } |
79 | 79 |
80 reset_cnt = prng->fortuna.reset_cnt + 1; | |
81 | |
80 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { | 82 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { |
81 if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) { | 83 if (x == 0 || ((reset_cnt >> (x-1)) & 1) == 0) { |
82 /* terminate this hash */ | 84 /* terminate this hash */ |
83 if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) { | 85 if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) { |
84 sha256_done(&md, tmp); | 86 sha256_done(&md, tmp); |
85 return err; | 87 return err; |
86 } | 88 } |
106 if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { | 108 if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { |
107 return err; | 109 return err; |
108 } | 110 } |
109 _fortuna_update_iv(prng); | 111 _fortuna_update_iv(prng); |
110 | 112 |
111 /* reset pool len */ | 113 /* reset/update internals */ |
112 prng->fortuna.pool0_len = 0; | 114 prng->fortuna.pool0_len = 0; |
113 prng->fortuna.wd = 0; | 115 prng->fortuna.wd = 0; |
116 prng->fortuna.reset_cnt = reset_cnt; | |
114 | 117 |
115 | 118 |
116 #ifdef LTC_CLEAN_STACK | 119 #ifdef LTC_CLEAN_STACK |
117 zeromem(&md, sizeof(md)); | 120 zeromem(&md, sizeof(md)); |
118 zeromem(tmp, sizeof(tmp)); | 121 zeromem(tmp, sizeof(tmp)); |
119 #endif | 122 #endif |
120 | 123 |
121 return CRYPT_OK; | 124 return CRYPT_OK; |
125 } | |
126 | |
127 /** | |
128 "Update Seed File"-compliant update of K | |
129 | |
130 @param in The PRNG state | |
131 @param inlen Size of the state | |
132 @param prng The PRNG to import | |
133 @return CRYPT_OK if successful | |
134 */ | |
135 static int _fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng) | |
136 { | |
137 int err; | |
138 unsigned char tmp[MAXBLOCKSIZE]; | |
139 hash_state md; | |
140 | |
141 LTC_MUTEX_LOCK(&prng->lock); | |
142 /* new K = LTC_SHA256(K || in) */ | |
143 sha256_init(&md); | |
144 if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) { | |
145 sha256_done(&md, tmp); | |
146 goto LBL_UNLOCK; | |
147 } | |
148 if ((err = sha256_process(&md, in, inlen)) != CRYPT_OK) { | |
149 sha256_done(&md, tmp); | |
150 goto LBL_UNLOCK; | |
151 } | |
152 /* finish key */ | |
153 if ((err = sha256_done(&md, prng->fortuna.K)) != CRYPT_OK) { | |
154 goto LBL_UNLOCK; | |
155 } | |
156 _fortuna_update_iv(prng); | |
157 | |
158 LBL_UNLOCK: | |
159 LTC_MUTEX_UNLOCK(&prng->lock); | |
160 #ifdef LTC_CLEAN_STACK | |
161 zeromem(&md, sizeof(md)); | |
162 #endif | |
163 | |
164 return err; | |
122 } | 165 } |
123 | 166 |
124 /** | 167 /** |
125 Start the PRNG | 168 Start the PRNG |
126 @param prng [out] The PRNG state to initialize | 169 @param prng [out] The PRNG state to initialize |
243 if (!prng->ready) { | 286 if (!prng->ready) { |
244 goto LBL_UNLOCK; | 287 goto LBL_UNLOCK; |
245 } | 288 } |
246 | 289 |
247 /* do we have to reseed? */ | 290 /* do we have to reseed? */ |
248 if (++prng->fortuna.wd == LTC_FORTUNA_WD || prng->fortuna.pool0_len >= 64) { | 291 if ((++prng->fortuna.wd == LTC_FORTUNA_WD) && (prng->fortuna.pool0_len >= 64)) { |
249 if (_fortuna_reseed(prng) != CRYPT_OK) { | 292 if (_fortuna_reseed(prng) != CRYPT_OK) { |
250 goto LBL_UNLOCK; | 293 goto LBL_UNLOCK; |
251 } | 294 } |
295 } | |
296 | |
297 /* ensure that one reseed happened before allowing to read */ | |
298 if (prng->fortuna.reset_cnt == 0) { | |
299 goto LBL_UNLOCK; | |
252 } | 300 } |
253 | 301 |
254 /* now generate the blocks required */ | 302 /* now generate the blocks required */ |
255 tlen = outlen; | 303 tlen = outlen; |
256 | 304 |
402 @param prng The PRNG to import | 450 @param prng The PRNG to import |
403 @return CRYPT_OK if successful | 451 @return CRYPT_OK if successful |
404 */ | 452 */ |
405 int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng) | 453 int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng) |
406 { | 454 { |
407 int err, x; | 455 int err; |
408 | 456 |
409 LTC_ARGCHK(in != NULL); | 457 LTC_ARGCHK(in != NULL); |
410 LTC_ARGCHK(prng != NULL); | 458 LTC_ARGCHK(prng != NULL); |
411 | 459 |
412 if (inlen < (unsigned long)fortuna_desc.export_size) { | 460 if (inlen < (unsigned long)fortuna_desc.export_size) { |
413 return CRYPT_INVALID_ARG; | 461 return CRYPT_INVALID_ARG; |
414 } | 462 } |
415 | 463 |
416 if ((err = fortuna_start(prng)) != CRYPT_OK) { | 464 if ((err = fortuna_start(prng)) != CRYPT_OK) { |
417 return err; | 465 return err; |
418 } | 466 } |
419 for (x = 0; x < LTC_FORTUNA_POOLS; x++) { | 467 |
420 if ((err = fortuna_add_entropy(in+x*32, 32, prng)) != CRYPT_OK) { | 468 if ((err = _fortuna_update_seed(in, inlen, prng)) != CRYPT_OK) { |
421 return err; | 469 return err; |
422 } | 470 } |
423 } | 471 |
424 return CRYPT_OK; | 472 return err; |
425 } | 473 } |
426 | 474 |
427 /** | 475 /** |
428 PRNG self-test | 476 PRNG self-test |
429 @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled | 477 @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled |