Exemple #1
0
/** Given the rendezvous key seed in <b>ntor_key_seed</b> (of size
 *  DIGEST256_LEN), do the circuit key expansion as specified by section
 *  '4.2.1. Key expansion' and place the keys in <b>keys_out</b> (which must be
 *  of size HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN).
 *
 * Return 0 if things went well, else return -1. */
int
hs_ntor_circuit_key_expansion(const uint8_t *ntor_key_seed, size_t seed_len,
                              uint8_t *keys_out, size_t keys_out_len)
{
  uint8_t *ptr;
  uint8_t kdf_input[NTOR_KEY_EXPANSION_KDF_INPUT_LEN];
  crypto_xof_t *xof;

  /* Sanity checks on lengths to make sure we are good */
  if (BUG(seed_len != DIGEST256_LEN)) {
    return -1;
  }
  if (BUG(keys_out_len != HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN)) {
    return -1;
  }

  /* Let's build the input to the KDF */
  ptr = kdf_input;
  APPEND(ptr, ntor_key_seed, DIGEST256_LEN);
  APPEND(ptr, M_HSEXPAND, strlen(M_HSEXPAND));
  tor_assert(ptr == kdf_input + sizeof(kdf_input));

  /* Generate the keys */
  xof = crypto_xof_new();
  crypto_xof_add_bytes(xof, kdf_input, sizeof(kdf_input));
  crypto_xof_squeeze_bytes(xof, keys_out, HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN);
  crypto_xof_free(xof);

  return 0;
}
Exemple #2
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);
}
Exemple #3
0
/** Helper function: Compute the part of the HS ntor handshake that generates
 *  key material for creating and handling INTRODUCE1 cells. Function used
 *  by both client and service. Specifically, calculate the following:
 *
 *     info = m_hsexpand | subcredential
 *     hs_keys = KDF(intro_secret_hs_input | t_hsenc | info, S_KEY_LEN+MAC_LEN)
 *     ENC_KEY = hs_keys[0:S_KEY_LEN]
 *     MAC_KEY = hs_keys[S_KEY_LEN:S_KEY_LEN+MAC_KEY_LEN]
 *
 *  where intro_secret_hs_input is <b>secret_input</b> (of size
 *  INTRO_SECRET_HS_INPUT_LEN), and <b>subcredential</b> is of size
 *  DIGEST256_LEN.
 *
 * If everything went well, fill <b>hs_ntor_intro_cell_keys_out</b> with the
 * necessary key material, and return 0. */
static void
get_introduce1_key_material(const uint8_t *secret_input,
                        const uint8_t *subcredential,
                        hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out)
{
  uint8_t keystream[CIPHER256_KEY_LEN + DIGEST256_LEN];
  uint8_t info_blob[INFO_BLOB_LEN];
  uint8_t kdf_input[KDF_INPUT_LEN];
  crypto_xof_t *xof;
  uint8_t *ptr;

  /* Let's build info */
  ptr = info_blob;
  APPEND(ptr, M_HSEXPAND, strlen(M_HSEXPAND));
  APPEND(ptr, subcredential, DIGEST256_LEN);
  tor_assert(ptr == info_blob + sizeof(info_blob));

  /* Let's build the input to the KDF */
  ptr = kdf_input;
  APPEND(ptr, secret_input, INTRO_SECRET_HS_INPUT_LEN);
  APPEND(ptr, T_HSENC, strlen(T_HSENC));
  APPEND(ptr, info_blob, sizeof(info_blob));
  tor_assert(ptr == kdf_input + sizeof(kdf_input));

  /* Now we need to run kdf_input over SHAKE-256 */
  xof = crypto_xof_new();
  crypto_xof_add_bytes(xof, kdf_input, sizeof(kdf_input));
  crypto_xof_squeeze_bytes(xof, keystream, sizeof(keystream)) ;
  crypto_xof_free(xof);

  { /* Get the keys */
    memcpy(&hs_ntor_intro_cell_keys_out->enc_key, keystream,CIPHER256_KEY_LEN);
    memcpy(&hs_ntor_intro_cell_keys_out->mac_key,
           keystream+CIPHER256_KEY_LEN, DIGEST256_LEN);
  }

  memwipe(keystream,  0, sizeof(keystream));
  memwipe(kdf_input,  0, sizeof(kdf_input));
}