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