summaryrefslogtreecommitdiff
path: root/libtomcrypt/src/prngs/fortuna.c
diff options
context:
space:
mode:
Diffstat (limited to 'libtomcrypt/src/prngs/fortuna.c')
-rw-r--r--libtomcrypt/src/prngs/fortuna.c72
1 files changed, 60 insertions, 12 deletions
diff --git a/libtomcrypt/src/prngs/fortuna.c b/libtomcrypt/src/prngs/fortuna.c
index 7b1ecb6..1f07233 100644
--- a/libtomcrypt/src/prngs/fortuna.c
+++ b/libtomcrypt/src/prngs/fortuna.c
@@ -66,9 +66,9 @@ static int _fortuna_reseed(prng_state *prng)
{
unsigned char tmp[MAXBLOCKSIZE];
hash_state md;
+ ulong64 reset_cnt;
int err, x;
- ++prng->fortuna.reset_cnt;
/* new K == LTC_SHA256(K || s) where s == LTC_SHA256(P0) || LTC_SHA256(P1) ... */
sha256_init(&md);
@@ -77,8 +77,10 @@ static int _fortuna_reseed(prng_state *prng)
return err;
}
+ reset_cnt = prng->fortuna.reset_cnt + 1;
+
for (x = 0; x < LTC_FORTUNA_POOLS; x++) {
- if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) {
+ if (x == 0 || ((reset_cnt >> (x-1)) & 1) == 0) {
/* terminate this hash */
if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) {
sha256_done(&md, tmp);
@@ -108,9 +110,10 @@ static int _fortuna_reseed(prng_state *prng)
}
_fortuna_update_iv(prng);
- /* reset pool len */
+ /* reset/update internals */
prng->fortuna.pool0_len = 0;
prng->fortuna.wd = 0;
+ prng->fortuna.reset_cnt = reset_cnt;
#ifdef LTC_CLEAN_STACK
@@ -122,6 +125,46 @@ static int _fortuna_reseed(prng_state *prng)
}
/**
+ "Update Seed File"-compliant update of K
+
+ @param in The PRNG state
+ @param inlen Size of the state
+ @param prng The PRNG to import
+ @return CRYPT_OK if successful
+*/
+static int _fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+ int err;
+ unsigned char tmp[MAXBLOCKSIZE];
+ hash_state md;
+
+ LTC_MUTEX_LOCK(&prng->lock);
+ /* new K = LTC_SHA256(K || in) */
+ sha256_init(&md);
+ if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) {
+ sha256_done(&md, tmp);
+ goto LBL_UNLOCK;
+ }
+ if ((err = sha256_process(&md, in, inlen)) != CRYPT_OK) {
+ sha256_done(&md, tmp);
+ goto LBL_UNLOCK;
+ }
+ /* finish key */
+ if ((err = sha256_done(&md, prng->fortuna.K)) != CRYPT_OK) {
+ goto LBL_UNLOCK;
+ }
+ _fortuna_update_iv(prng);
+
+LBL_UNLOCK:
+ LTC_MUTEX_UNLOCK(&prng->lock);
+#ifdef LTC_CLEAN_STACK
+ zeromem(&md, sizeof(md));
+#endif
+
+ return err;
+}
+
+/**
Start the PRNG
@param prng [out] The PRNG state to initialize
@return CRYPT_OK if successful
@@ -245,12 +288,17 @@ unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state
}
/* do we have to reseed? */
- if (++prng->fortuna.wd == LTC_FORTUNA_WD || prng->fortuna.pool0_len >= 64) {
+ if ((++prng->fortuna.wd == LTC_FORTUNA_WD) && (prng->fortuna.pool0_len >= 64)) {
if (_fortuna_reseed(prng) != CRYPT_OK) {
goto LBL_UNLOCK;
}
}
+ /* ensure that one reseed happened before allowing to read */
+ if (prng->fortuna.reset_cnt == 0) {
+ goto LBL_UNLOCK;
+ }
+
/* now generate the blocks required */
tlen = outlen;
@@ -404,10 +452,10 @@ LBL_UNLOCK:
*/
int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
{
- int err, x;
+ int err;
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(prng != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(prng != NULL);
if (inlen < (unsigned long)fortuna_desc.export_size) {
return CRYPT_INVALID_ARG;
@@ -416,12 +464,12 @@ int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prn
if ((err = fortuna_start(prng)) != CRYPT_OK) {
return err;
}
- for (x = 0; x < LTC_FORTUNA_POOLS; x++) {
- if ((err = fortuna_add_entropy(in+x*32, 32, prng)) != CRYPT_OK) {
- return err;
- }
+
+ if ((err = _fortuna_update_seed(in, inlen, prng)) != CRYPT_OK) {
+ return err;
}
- return CRYPT_OK;
+
+ return err;
}
/**