diff 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
line wrap: on
line diff
--- a/libtomcrypt/src/prngs/fortuna.c	Thu Jan 04 02:01:09 2007 +0000
+++ b/libtomcrypt/src/prngs/fortuna.c	Thu Jan 11 02:41:05 2007 +0000
@@ -6,7 +6,7 @@
  * The library is free for all purposes without any express
  * guarantee it works.
  *
- * Tom St Denis, [email protected], http://libtomcrypt.org
+ * Tom St Denis, [email protected], http://libtomcrypt.com
  */
 #include "tomcrypt.h"
 
@@ -74,6 +74,7 @@
    /* new K == SHA256(K || s) where s == SHA256(P0) || SHA256(P1) ... */
    sha256_init(&md);
    if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) {
+      sha256_done(&md, tmp);
       return err;
    }
 
@@ -81,14 +82,19 @@
        if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) { 
           /* terminate this hash */
           if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) {
+             sha256_done(&md, tmp);
              return err; 
           }
           /* add it to the string */
           if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) {
+             sha256_done(&md, tmp);
              return err;
           }
           /* reset this pool */
-          sha256_init(&prng->fortuna.pool[x]);
+          if ((err = sha256_init(&prng->fortuna.pool[x])) != CRYPT_OK) {
+             sha256_done(&md, tmp);
+             return err;
+          }
        } else {
           break;
        }
@@ -123,24 +129,35 @@
 */  
 int fortuna_start(prng_state *prng)
 {
-   int err, x;
+   int err, x, y;
+   unsigned char tmp[MAXBLOCKSIZE];
 
    LTC_ARGCHK(prng != NULL);
    
    /* initialize the pools */
    for (x = 0; x < FORTUNA_POOLS; x++) {
-       sha256_init(&prng->fortuna.pool[x]);
+       if ((err = sha256_init(&prng->fortuna.pool[x])) != CRYPT_OK) {
+          for (y = 0; y < x; y++) {
+              sha256_done(&prng->fortuna.pool[y], tmp);
+          }
+          return err;
+       }
    }
-   prng->fortuna.pool_idx = prng->fortuna.pool0_len = prng->fortuna.reset_cnt = 
-   prng->fortuna.wd = 0;
+   prng->fortuna.pool_idx = prng->fortuna.pool0_len = prng->fortuna.wd = 0;
+   prng->fortuna.reset_cnt = 0;
 
    /* reset bufs */
    zeromem(prng->fortuna.K, 32);
    if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
+      for (x = 0; x < FORTUNA_POOLS; x++) {
+          sha256_done(&prng->fortuna.pool[x], tmp);
+      }
       return err;
    }
    zeromem(prng->fortuna.IV, 16);
-
+   
+   LTC_MUTEX_INIT(&prng->fortuna.prng_lock)
+   
    return CRYPT_OK;
 }
 
@@ -159,18 +176,23 @@
    LTC_ARGCHK(in  != NULL);
    LTC_ARGCHK(prng != NULL);
 
+   LTC_MUTEX_LOCK(&prng->fortuna.prng_lock);
+
    /* ensure inlen <= 32 */
    if (inlen > 32) {
+      LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
       return CRYPT_INVALID_ARG;
    }
 
    /* add s || length(in) || in to pool[pool_idx] */
    tmp[0] = 0;
-   tmp[1] = inlen;
+   tmp[1] = (unsigned char)inlen;
    if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], tmp, 2)) != CRYPT_OK) {
+      LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
       return err;
    }
    if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], in, inlen)) != CRYPT_OK) {
+      LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
       return err;
    }
    if (prng->fortuna.pool_idx == 0) {
@@ -180,6 +202,7 @@
       prng->fortuna.pool_idx = 0;
    }
 
+   LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
    return CRYPT_OK;
 }
 
@@ -209,9 +232,12 @@
    LTC_ARGCHK(out  != NULL);
    LTC_ARGCHK(prng != NULL);
 
+   LTC_MUTEX_LOCK(&prng->fortuna.prng_lock);
+
    /* do we have to reseed? */
    if (++prng->fortuna.wd == FORTUNA_WD || prng->fortuna.pool0_len >= 64) {
       if ((err = fortuna_reseed(prng)) != CRYPT_OK) {
+         LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
          return 0;
       }
    }
@@ -219,7 +245,7 @@
    /* now generate the blocks required */
    tlen = outlen;
 
-   /* handle whole blocks without the extra memcpy */
+   /* handle whole blocks without the extra XMEMCPY */
    while (outlen >= 16) {
       /* encrypt the IV and store it */
       rijndael_ecb_encrypt(prng->fortuna.IV, out, &prng->fortuna.skey);
@@ -239,12 +265,14 @@
    rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K   , &prng->fortuna.skey); fortuna_update_iv(prng);
    rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K+16, &prng->fortuna.skey); fortuna_update_iv(prng);
    if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) {
+      LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
       return 0;
    }
 
 #ifdef LTC_CLEAN_STACK
    zeromem(tmp, sizeof(tmp));
 #endif
+   LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
    return tlen;
 }   
 
@@ -259,10 +287,12 @@
    unsigned char tmp[32];
 
    LTC_ARGCHK(prng != NULL);
+   LTC_MUTEX_LOCK(&prng->fortuna.prng_lock);
 
    /* terminate all the hashes */
    for (x = 0; x < FORTUNA_POOLS; x++) {
        if ((err = sha256_done(&(prng->fortuna.pool[x]), tmp)) != CRYPT_OK) {
+          LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
           return err; 
        }
    }
@@ -272,6 +302,7 @@
    zeromem(tmp, sizeof(tmp));
 #endif
 
+   LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
    return CRYPT_OK;
 }
 
@@ -291,13 +322,18 @@
    LTC_ARGCHK(outlen != NULL);
    LTC_ARGCHK(prng   != NULL);
 
+   LTC_MUTEX_LOCK(&prng->fortuna.prng_lock);
+
    /* we'll write bytes for s&g's */
    if (*outlen < 32*FORTUNA_POOLS) {
+      LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
+      *outlen = 32*FORTUNA_POOLS;
       return CRYPT_BUFFER_OVERFLOW;
    }
 
    md = XMALLOC(sizeof(hash_state));
    if (md == NULL) {
+      LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
       return CRYPT_MEM;
    }
 
@@ -332,6 +368,7 @@
    zeromem(md, sizeof(*md));
 #endif
    XFREE(md);
+   LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock);
    return err;
 }
  
@@ -386,5 +423,5 @@
 
 
 /* $Source: /cvs/libtom/libtomcrypt/src/prngs/fortuna.c,v $ */
-/* $Revision: 1.3 $ */
-/* $Date: 2005/05/05 14:35:59 $ */
+/* $Revision: 1.12 $ */
+/* $Date: 2006/12/04 21:34:03 $ */