Exemplo n.º 1
0
/**
 * Helper: refill the seed bytes and output buffer of <b>rng</b>, using
 * the input seed bytes as input (key and IV) for the stream cipher.
 *
 * If the n_till_reseed counter has reached zero, mix more random bytes into
 * the seed before refilling the buffer.
 **/
static void
crypto_fast_rng_refill(crypto_fast_rng_t *rng)
{
  if (rng->n_till_reseed-- == 0) {
    /* It's time to reseed the RNG.  We'll do this by using our XOF to mix the
     * old value for the seed with some additional bytes from
     * crypto_strongest_rand(). */
    crypto_xof_t *xof = crypto_xof_new();
    crypto_xof_add_bytes(xof, rng->buf.seed, SEED_LEN);
    {
      uint8_t seedbuf[SEED_LEN];
      crypto_strongest_rand(seedbuf, SEED_LEN);
      crypto_xof_add_bytes(xof, seedbuf, SEED_LEN);
      memwipe(seedbuf, 0, SEED_LEN);
    }
    crypto_xof_squeeze_bytes(xof, rng->buf.seed, SEED_LEN);
    crypto_xof_free(xof);

    rng->n_till_reseed = RESEED_AFTER;
  }
  /* Now fill rng->buf with output from our stream cipher, initialized from
   * that seed value. */
  crypto_cipher_t *c = cipher_from_seed(rng->buf.seed);
  memset(&rng->buf, 0, sizeof(rng->buf));
  crypto_cipher_crypt_inplace(c, (char*)&rng->buf, sizeof(rng->buf));
  crypto_cipher_free(c);

  rng->bytes_left = sizeof(rng->buf.bytes);
}
Exemplo n.º 2
0
/**
 * Initialize and return a new fast PRNG, using a strong random seed.
 *
 * Note that this object is NOT thread-safe.  If you need a thread-safe
 * prng, use crypto_rand(), or wrap this in a mutex.
 **/
crypto_fast_rng_t *
crypto_fast_rng_new(void)
{
  uint8_t seed[SEED_LEN];
  crypto_strongest_rand(seed, sizeof(seed));
  crypto_fast_rng_t *result = crypto_fast_rng_new_from_seed(seed);
  memwipe(seed, 0, sizeof(seed));
  return result;
}
Exemplo n.º 3
0
static void
test_crypto_rng_strongest(void *arg)
{
  const char *how = arg;
  int broken = 0;

  if (how == NULL) {
    ;
  } else if (!strcmp(how, "nosyscall")) {
    break_strongest_rng_syscall = 1;
  } else if (!strcmp(how, "nofallback")) {
    break_strongest_rng_fallback = 1;
  } else if (!strcmp(how, "broken")) {
    broken = break_strongest_rng_syscall = break_strongest_rng_fallback = 1;
  }

#define N 128
  uint8_t combine_and[N];
  uint8_t combine_or[N];
  int i, j;

  memset(combine_and, 0xff, N);
  memset(combine_or, 0, N);

  for (i = 0; i < 100; ++i) { /* 2^-100 chances just don't happen. */
    uint8_t output[N];
    memset(output, 0, N);
    if (how == NULL) {
      /* this one can't fail. */
      crypto_strongest_rand(output, sizeof(output));
    } else {
      int r = crypto_strongest_rand_raw(output, sizeof(output));
      if (r == -1) {
        if (broken) {
          goto done; /* we're fine. */
        }
        /* This function is allowed to break, but only if it always breaks. */
        tt_int_op(i, OP_EQ, 0);
        tt_skip();
      } else {
        tt_assert(! broken);
      }
    }
    for (j = 0; j < N; ++j) {
      combine_and[j] &= output[j];
      combine_or[j] |= output[j];
    }
  }

  for (j = 0; j < N; ++j) {
    tt_int_op(combine_and[j], OP_EQ, 0);
    tt_int_op(combine_or[j], OP_EQ, 0xff);
  }
 done:
  ;
#undef N
}
Exemplo n.º 4
0
/**
 * Generate CURVE25519_SECKEY_LEN random bytes in <b>out</b>. If
 * <b>extra_strong</b> is true, this key is possibly going to get used more
 * than once, so use a better-than-usual RNG. Return 0 on success, -1 on
 * failure.
 *
 * This function does not adjust the output of the RNG at all; the will caller
 * will need to clear or set the appropriate bits to make curve25519 work.
 */
int
curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong)
{
  if (extra_strong)
    crypto_strongest_rand(out, CURVE25519_SECKEY_LEN);
  else
    crypto_rand((char*)out, CURVE25519_SECKEY_LEN);

  return 0;
}
Exemplo n.º 5
0
int
ed25519_donna_seckey(unsigned char *sk)
{
  ed25519_secret_key seed;

  crypto_strongest_rand(seed, 32);

  ed25519_extsk(sk, seed);

  memwipe(seed, 0, sizeof(seed));

  return 0;
}
Exemplo n.º 6
0
/**
 * Initialize a new ed25519 secret key in <b>seckey_out</b>.  If
 * <b>extra_strong</b>, take the RNG inputs directly from the operating
 * system.  Return 0 on success, -1 on failure.
 */
int
ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out,
                        int extra_strong)
{
  int r;
  uint8_t seed[32];
  if (! extra_strong || crypto_strongest_rand(seed, sizeof(seed)) < 0)
    crypto_rand((char*)seed, sizeof(seed));

  r = get_ed_impl()->seckey_expand(seckey_out->seckey, seed);
  memwipe(seed, 0, sizeof(seed));

  return r < 0 ? -1 : 0;
}
Exemplo n.º 7
0
/**
 * Generate CURVE25519_SECKEY_LEN random bytes in <b>out</b>. If
 * <b>extra_strong</b> is true, this key is possibly going to get used more
 * than once, so use a better-than-usual RNG. Return 0 on success, -1 on
 * failure.
 *
 * This function does not adjust the output of the RNG at all; the will caller
 * will need to clear or set the appropriate bits to make curve25519 work.
 */
int
curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong)
{
  uint8_t k_tmp[CURVE25519_SECKEY_LEN];

  if (crypto_rand((char*)out, CURVE25519_SECKEY_LEN) < 0)
    return -1;
  if (extra_strong && !crypto_strongest_rand(k_tmp, CURVE25519_SECKEY_LEN)) {
    /* If they asked for extra-strong entropy and we have some, use it as an
     * HMAC key to improve not-so-good entropy rather than using it directly,
     * just in case the extra-strong entropy is less amazing than we hoped. */
    crypto_hmac_sha256((char*) out,
                       (const char *)k_tmp, sizeof(k_tmp),
                       (const char *)out, CURVE25519_SECKEY_LEN);
  }
  memwipe(k_tmp, 0, sizeof(k_tmp));
  return 0;
}