Browse Source

add possibility to seed PRNG as if it's imported

Steffen Jaeckel 7 years ago
parent
commit
979a36b9bb
2 changed files with 40 additions and 13 deletions
  1. 33 11
      src/prngs/rng_make_prng.c
  2. 7 2
      tests/prng_test.c

+ 33 - 11
src/prngs/rng_make_prng.c

@@ -16,7 +16,12 @@
 
 /**
   Create a PRNG from a RNG
-  @param bits     Number of bits of entropy desired (64 ... 1024)
+
+     In case you pass bits as '-1' the PRNG will be setup
+     as if the export/import functionality has been used,
+     but the imported data comes directly from the RNG.
+
+  @param bits     Number of bits of entropy desired (-1 or 64 ... 1024)
   @param wprng    Index of which PRNG to setup
   @param prng     [out] PRNG state to initialize
   @param callback A pointer to a void function for when the RNG is slow, this can be NULL
@@ -25,7 +30,8 @@
 int rng_make_prng(int bits, int wprng, prng_state *prng,
                   void (*callback)(void))
 {
-   unsigned char buf[256];
+   unsigned char* buf;
+   unsigned long bytes;
    int err;
 
    LTC_ARGCHK(prng != NULL);
@@ -35,31 +41,47 @@ int rng_make_prng(int bits, int wprng, prng_state *prng,
       return err;
    }
 
-   if (bits < 64 || bits > 1024) {
+   if (bits == -1) {
+      bytes = prng_descriptor[wprng].export_size;
+   } else if (bits < 64 || bits > 1024) {
       return CRYPT_INVALID_PRNGSIZE;
+   } else {
+      bytes = (unsigned long)((bits+7)/8) * 2;
    }
 
    if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) {
       return err;
    }
 
-   bits = ((bits+7)/8) * 2;
-   if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) {
-      return CRYPT_ERROR_READPRNG;
+   buf = XMALLOC(bytes);
+   if (buf == NULL) {
+      return CRYPT_MEM;
    }
 
-   if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) {
-      return err;
+   if (rng_get_bytes(buf, bytes, callback) != bytes) {
+      err = CRYPT_ERROR_READPRNG;
+      goto LBL_ERR;
    }
 
+   if (bits == -1) {
+      if ((err = prng_descriptor[wprng].pimport(buf, bytes, prng)) != CRYPT_OK) {
+         goto LBL_ERR;
+      }
+   } else {
+      if ((err = prng_descriptor[wprng].add_entropy(buf, bytes, prng)) != CRYPT_OK) {
+         goto LBL_ERR;
+      }
+   }
    if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) {
-      return err;
+      goto LBL_ERR;
    }
 
+LBL_ERR:
    #ifdef LTC_CLEAN_STACK
-      zeromem(buf, sizeof(buf));
+   zeromem(buf, bytes);
    #endif
-   return CRYPT_OK;
+   XFREE(buf);
+   return err;
 }
 #endif /* #ifdef LTC_RNG_MAKE_PRNG */
 

+ 7 - 2
tests/prng_test.c

@@ -42,10 +42,11 @@ int prng_test(void)
 
    before = my_test_rng_read;
 
-   if ((err = rng_make_prng(128, find_prng("yarrow"), &yarrow_prng, NULL)) != CRYPT_OK) {
+   if ((err = rng_make_prng(128, find_prng("yarrow"), &nprng, NULL)) != CRYPT_OK) {
       fprintf(stderr, "rng_make_prng with 'my_test_rng' failed: %s\n", error_to_string(err));
       exit(EXIT_FAILURE);
    }
+   DO(yarrow_done(&nprng));
 
    if (before == my_test_rng_read) {
       fprintf(stderr, "somehow there was no read from the ltc_rng! %lu == %lu\n", before, my_test_rng_read);
@@ -58,7 +59,6 @@ int prng_test(void)
    /* test prngs (test, import/export) */
    for (x = 0; prng_descriptor[x].name != NULL; x++) {
       if(strstr(prng_descriptor[x].name, "no_prng") == prng_descriptor[x].name) continue;
-      err = CRYPT_OK;
       DOX(prng_descriptor[x].test(), prng_descriptor[x].name);
       DOX(prng_descriptor[x].start(&nprng), prng_descriptor[x].name);
       DOX(prng_descriptor[x].add_entropy((unsigned char *)"helloworld12", 12, &nprng), prng_descriptor[x].name);
@@ -82,6 +82,11 @@ int prng_test(void)
       }
       prng_descriptor[x].done(&nprng);
    }
+
+   if ((err = rng_make_prng(-1, find_prng("yarrow"), &nprng, NULL)) != CRYPT_OK) {
+      fprintf(stderr, "rng_make_prng(-1,..) with 'yarrow' failed: %s\n", error_to_string(err));
+   }
+   DO(yarrow_done(&nprng));
    return err;
 }