Browse Source

add fortuna_add_random_event()

Steffen Jaeckel 7 years ago
parent
commit
ca91ae5a1f
3 changed files with 87 additions and 24 deletions
  1. 1 0
      src/headers/tomcrypt_prng.h
  2. 61 23
      src/prngs/fortuna.c
  3. 25 1
      tests/prng_test.c

+ 1 - 0
src/headers/tomcrypt_prng.h

@@ -148,6 +148,7 @@ extern const struct ltc_prng_descriptor yarrow_desc;
 #ifdef LTC_FORTUNA
 int fortuna_start(prng_state *prng);
 int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng);
+int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng);
 int fortuna_ready(prng_state *prng);
 unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng);
 int fortuna_done(prng_state *prng);

+ 61 - 23
src/prngs/fortuna.c

@@ -239,48 +239,86 @@ int fortuna_start(prng_state *prng)
    return CRYPT_OK;
 }
 
+static int _fortuna_add(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+   unsigned char tmp[2];
+   int err;
+
+   /* ensure inlen <= 32 */
+   if (inlen > 32) {
+      inlen = 32;
+   }
+
+   /* add s || length(in) || in to pool[pool_idx] */
+   tmp[0] = (unsigned char)source;
+   tmp[1] = (unsigned char)inlen;
+
+   if ((err = sha256_process(&prng->fortuna.pool[pool], tmp, 2)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = sha256_process(&prng->fortuna.pool[pool], in, inlen)) != CRYPT_OK) {
+      return err;
+   }
+   if (pool == 0) {
+      prng->fortuna.pool0_len += inlen;
+   }
+   return CRYPT_OK; /* success */
+}
+
 /**
-  Add entropy to the PRNG state
+  Add random event to the PRNG state as proposed by the original paper.
+  @param source   The source this random event comes from (0 .. 255)
+  @param pool     The pool where to add the data to (0 .. LTC_FORTUNA_POOLS)
   @param in       The data to add
   @param inlen    Length of the data to add
   @param prng     PRNG state to update
   @return CRYPT_OK if successful
 */
-int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
+int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng)
 {
-   unsigned char tmp[2];
    int           err;
 
    LTC_ARGCHK(prng != NULL);
    LTC_ARGCHK(in != NULL);
    LTC_ARGCHK(inlen > 0);
+   LTC_ARGCHK(source <= 255);
+   LTC_ARGCHK(pool < LTC_FORTUNA_POOLS);
 
-   /* ensure inlen <= 32 */
-   if (inlen > 32) {
-      inlen = 32;
-   }
+   LTC_MUTEX_LOCK(&prng->lock);
 
-   /* add s || length(in) || in to pool[pool_idx] */
-   tmp[0] = 0;
-   tmp[1] = (unsigned char)inlen;
+   err = _fortuna_add(source, pool, in, inlen, prng);
+
+   LTC_MUTEX_UNLOCK(&prng->lock);
+
+   return err;
+}
+
+/**
+  Add entropy to the PRNG state
+  @param in       The data to add
+  @param inlen    Length of the data to add
+  @param prng     PRNG state to update
+  @return CRYPT_OK if successful
+*/
+int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
+{
+   int err;
+
+   LTC_ARGCHK(prng != NULL);
+   LTC_ARGCHK(in != NULL);
+   LTC_ARGCHK(inlen > 0);
 
    LTC_MUTEX_LOCK(&prng->lock);
-   if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], tmp, 2)) != CRYPT_OK) {
-      goto LBL_UNLOCK;
-   }
-   if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], in, inlen)) != CRYPT_OK) {
-      goto LBL_UNLOCK;
-   }
-   if (prng->fortuna.pool_idx == 0) {
-      prng->fortuna.pool0_len += inlen;
-   }
-   if (++(prng->fortuna.pool_idx) == LTC_FORTUNA_POOLS) {
-      prng->fortuna.pool_idx = 0;
+
+   err = _fortuna_add(0, prng->fortuna.pool_idx, in, inlen, prng);
+
+   if (err == CRYPT_OK) {
+      ++(prng->fortuna.pool_idx);
+      prng->fortuna.pool_idx %= LTC_FORTUNA_POOLS;
    }
-   err = CRYPT_OK; /* success */
 
-LBL_UNLOCK:
    LTC_MUTEX_UNLOCK(&prng->lock);
+
    return err;
 }
 

+ 25 - 1
tests/prng_test.c

@@ -74,7 +74,7 @@ int prng_test(void)
       DOX(prng_descriptor[x].pexport(buf, &n, &nprng), prng_descriptor[x].name);
       prng_descriptor[x].done(&nprng);
       DOX(prng_descriptor[x].pimport(buf, n, &nprng), prng_descriptor[x].name);
-      DOX(prng_descriptor[x].pimport(buf, 4096, &nprng), prng_descriptor[x].name); /* try to import larger data */
+      DOX(prng_descriptor[x].pimport(buf, sizeof(buf), &nprng), prng_descriptor[x].name); /* try to import larger data */
       DOX(prng_descriptor[x].ready(&nprng), prng_descriptor[x].name);
       if (prng_descriptor[x].read(buf, 100, &nprng) != 100) {
          fprintf(stderr, "Error reading from imported PRNG (%s)!\n", prng_descriptor[x].name);
@@ -87,6 +87,30 @@ int prng_test(void)
       fprintf(stderr, "rng_make_prng(-1,..) with 'yarrow' failed: %s\n", error_to_string(err));
    }
    DO(yarrow_done(&nprng));
+
+#ifdef LTC_FORTUNA
+   DO(fortuna_start(&nprng));
+   DO(fortuna_add_entropy(buf, 32, &nprng));
+   DO(fortuna_ready(&nprng));
+   if (fortuna_read(buf + 32, 32, &nprng) != 32) {
+      fprintf(stderr, "Error reading from Fortuna after fortuna_add_entropy()!\n");
+      return CRYPT_ERROR;
+   }
+   DO(fortuna_done(&nprng));
+
+   DO(fortuna_start(&nprng));
+   DO(fortuna_add_random_event(0, 0, buf, 32, &nprng));
+   DO(fortuna_ready(&nprng));
+   if (fortuna_read(buf + 64, 32, &nprng) != 32) {
+      fprintf(stderr, "Error reading from Fortuna after fortuna_add_random_event()!\n");
+      return CRYPT_ERROR;
+   }
+   DO(fortuna_done(&nprng));
+
+   if (compare_testvector(buf + 64, 32, buf + 32, 32, "fortuna_add_entropy() vs. fortuna_add_random_event()", 0) != 0) {
+      err = CRYPT_FAIL_TESTVECTOR;
+   }
+#endif
    return err;
 }