Пример #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);
}
Пример #2
0
static void
bench_cell_aes(void)
{
  uint64_t start, end;
  const int len = 509;
  const int iters = (1<<16);
  const int max_misalign = 15;
  char *b = tor_malloc(len+max_misalign);
  crypto_cipher_t *c;
  int i, misalign;

  c = crypto_cipher_new(NULL);

  reset_perftime();
  for (misalign = 0; misalign <= max_misalign; ++misalign) {
    start = perftime();
    for (i = 0; i < iters; ++i) {
      crypto_cipher_crypt_inplace(c, b+misalign, len);
    }
    end = perftime();
    printf("%d bytes, misaligned by %d: %.2f nsec per byte\n", len, misalign,
           NANOCOUNT(start, end, iters*len));
  }

  crypto_cipher_free(c);
  tor_free(b);
}
Пример #3
0
/**
 * Extract <b>n</b> bytes from <b>rng</b> into the buffer at <b>out</b>.
 **/
void
crypto_fast_rng_getbytes(crypto_fast_rng_t *rng, uint8_t *out, size_t n)
{
  if (PREDICT_UNLIKELY(n > BUFLEN)) {
    /* The user has asked for a lot of output; generate it from a stream
     * cipher seeded by the PRNG rather than by pulling it out of the PRNG
     * directly.
     */
    uint8_t seed[SEED_LEN];
    crypto_fast_rng_getbytes_impl(rng, seed, SEED_LEN);
    crypto_cipher_t *c = cipher_from_seed(seed);
    memset(out, 0, n);
    crypto_cipher_crypt_inplace(c, (char*)out, n);
    crypto_cipher_free(c);
    memwipe(seed, 0, sizeof(seed));
    return;
  }

  crypto_fast_rng_getbytes_impl(rng, out, n);
}
Пример #4
0
/** Run unit tests for our AES functionality */
static void
test_crypto_aes(void *arg)
{
  char *data1 = NULL, *data2 = NULL, *data3 = NULL;
  crypto_cipher_t *env1 = NULL, *env2 = NULL;
  int i, j;
  char *mem_op_hex_tmp=NULL;

  int use_evp = !strcmp(arg,"evp");
  evaluate_evp_for_aes(use_evp);
  evaluate_ctr_for_aes();

  data1 = tor_malloc(1024);
  data2 = tor_malloc(1024);
  data3 = tor_malloc(1024);

  /* Now, test encryption and decryption with stream cipher. */
  data1[0]='\0';
  for (i = 1023; i>0; i -= 35)
    strncat(data1, "Now is the time for all good onions", i);

  memset(data2, 0, 1024);
  memset(data3, 0, 1024);
  env1 = crypto_cipher_new(NULL);
  test_neq_ptr(env1, 0);
  env2 = crypto_cipher_new(crypto_cipher_get_key(env1));
  test_neq_ptr(env2, 0);

  /* Try encrypting 512 chars. */
  crypto_cipher_encrypt(env1, data2, data1, 512);
  crypto_cipher_decrypt(env2, data3, data2, 512);
  test_memeq(data1, data3, 512);
  test_memneq(data1, data2, 512);

  /* Now encrypt 1 at a time, and get 1 at a time. */
  for (j = 512; j < 560; ++j) {
    crypto_cipher_encrypt(env1, data2+j, data1+j, 1);
  }
  for (j = 512; j < 560; ++j) {
    crypto_cipher_decrypt(env2, data3+j, data2+j, 1);
  }
  test_memeq(data1, data3, 560);
  /* Now encrypt 3 at a time, and get 5 at a time. */
  for (j = 560; j < 1024-5; j += 3) {
    crypto_cipher_encrypt(env1, data2+j, data1+j, 3);
  }
  for (j = 560; j < 1024-5; j += 5) {
    crypto_cipher_decrypt(env2, data3+j, data2+j, 5);
  }
  test_memeq(data1, data3, 1024-5);
  /* Now make sure that when we encrypt with different chunk sizes, we get
     the same results. */
  crypto_cipher_free(env2);
  env2 = NULL;

  memset(data3, 0, 1024);
  env2 = crypto_cipher_new(crypto_cipher_get_key(env1));
  test_neq_ptr(env2, NULL);
  for (j = 0; j < 1024-16; j += 17) {
    crypto_cipher_encrypt(env2, data3+j, data1+j, 17);
  }
  for (j= 0; j < 1024-16; ++j) {
    if (data2[j] != data3[j]) {
      printf("%d:  %d\t%d\n", j, (int) data2[j], (int) data3[j]);
    }
  }
  test_memeq(data2, data3, 1024-16);
  crypto_cipher_free(env1);
  env1 = NULL;
  crypto_cipher_free(env2);
  env2 = NULL;

  /* NIST test vector for aes. */
  /* IV starts at 0 */
  env1 = crypto_cipher_new("\x80\x00\x00\x00\x00\x00\x00\x00"
                           "\x00\x00\x00\x00\x00\x00\x00\x00");
  crypto_cipher_encrypt(env1, data1,
                        "\x00\x00\x00\x00\x00\x00\x00\x00"
                        "\x00\x00\x00\x00\x00\x00\x00\x00", 16);
  test_memeq_hex(data1, "0EDD33D3C621E546455BD8BA1418BEC8");

  /* Now test rollover.  All these values are originally from a python
   * script. */
  crypto_cipher_free(env1);
  env1 = crypto_cipher_new_with_iv(
                                   "\x80\x00\x00\x00\x00\x00\x00\x00"
                                   "\x00\x00\x00\x00\x00\x00\x00\x00",
                                   "\x00\x00\x00\x00\x00\x00\x00\x00"
                                   "\xff\xff\xff\xff\xff\xff\xff\xff");
  memset(data2, 0,  1024);
  crypto_cipher_encrypt(env1, data1, data2, 32);
  test_memeq_hex(data1, "335fe6da56f843199066c14a00a40231"
                        "cdd0b917dbc7186908a6bfb5ffd574d3");
  crypto_cipher_free(env1);
  env1 = crypto_cipher_new_with_iv(
                                   "\x80\x00\x00\x00\x00\x00\x00\x00"
                                   "\x00\x00\x00\x00\x00\x00\x00\x00",
                                   "\x00\x00\x00\x00\xff\xff\xff\xff"
                                   "\xff\xff\xff\xff\xff\xff\xff\xff");
  memset(data2, 0,  1024);
  crypto_cipher_encrypt(env1, data1, data2, 32);
  test_memeq_hex(data1, "e627c6423fa2d77832a02b2794094b73"
                        "3e63c721df790d2c6469cc1953a3ffac");
  crypto_cipher_free(env1);
  env1 = crypto_cipher_new_with_iv(
                                   "\x80\x00\x00\x00\x00\x00\x00\x00"
                                   "\x00\x00\x00\x00\x00\x00\x00\x00",
                                   "\xff\xff\xff\xff\xff\xff\xff\xff"
                                   "\xff\xff\xff\xff\xff\xff\xff\xff");
  memset(data2, 0,  1024);
  crypto_cipher_encrypt(env1, data1, data2, 32);
  test_memeq_hex(data1, "2aed2bff0de54f9328efd070bf48f70a"
                        "0EDD33D3C621E546455BD8BA1418BEC8");

  /* Now check rollover on inplace cipher. */
  crypto_cipher_free(env1);
  env1 = crypto_cipher_new_with_iv(
                                   "\x80\x00\x00\x00\x00\x00\x00\x00"
                                   "\x00\x00\x00\x00\x00\x00\x00\x00",
                                   "\xff\xff\xff\xff\xff\xff\xff\xff"
                                   "\xff\xff\xff\xff\xff\xff\xff\xff");
  crypto_cipher_crypt_inplace(env1, data2, 64);
  test_memeq_hex(data2, "2aed2bff0de54f9328efd070bf48f70a"
                        "0EDD33D3C621E546455BD8BA1418BEC8"
                        "93e2c5243d6839eac58503919192f7ae"
                        "1908e67cafa08d508816659c2e693191");
  crypto_cipher_free(env1);
  env1 = crypto_cipher_new_with_iv(
                                   "\x80\x00\x00\x00\x00\x00\x00\x00"
                                   "\x00\x00\x00\x00\x00\x00\x00\x00",
                                   "\xff\xff\xff\xff\xff\xff\xff\xff"
                                   "\xff\xff\xff\xff\xff\xff\xff\xff");
  crypto_cipher_crypt_inplace(env1, data2, 64);
  test_assert(tor_mem_is_zero(data2, 64));

 done:
  tor_free(mem_op_hex_tmp);
  if (env1)
    crypto_cipher_free(env1);
  if (env2)
    crypto_cipher_free(env2);
  tor_free(data1);
  tor_free(data2);
  tor_free(data3);
}
Пример #5
0
/**
 * Make an authenticated passphrase-encrypted blob to encode the
 * <b>input_len</b> bytes in <b>input</b> using the passphrase
 * <b>secret</b> of <b>secret_len</b> bytes.  Allocate a new chunk of memory
 * to hold the encrypted data, and store a pointer to that memory in
 * *<b>out</b>, and its size in <b>outlen_out</b>.  Use <b>s2k_flags</b> as an
 * argument to the passphrase-hashing function.
 */
int
crypto_pwbox(uint8_t **out, size_t *outlen_out,
             const uint8_t *input, size_t input_len,
             const char *secret, size_t secret_len,
             unsigned s2k_flags)
{
  uint8_t *result = NULL, *encrypted_portion;
  size_t encrypted_len = 128 * CEIL_DIV(input_len+4, 128);
  ssize_t result_len;
  int spec_len;
  uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
  pwbox_encoded_t *enc = NULL;
  ssize_t enc_len;

  crypto_cipher_t *cipher;
  int rv;

  enc = pwbox_encoded_new();

  pwbox_encoded_setlen_skey_header(enc, S2K_MAXLEN);

  spec_len = secret_to_key_make_specifier(
                                      pwbox_encoded_getarray_skey_header(enc),
                                      S2K_MAXLEN,
                                      s2k_flags);
  if (BUG(spec_len < 0 || spec_len > S2K_MAXLEN))
    goto err;
  pwbox_encoded_setlen_skey_header(enc, spec_len);
  enc->header_len = spec_len;

  crypto_rand((char*)enc->iv, sizeof(enc->iv));

  pwbox_encoded_setlen_data(enc, encrypted_len);
  encrypted_portion = pwbox_encoded_getarray_data(enc);

  set_uint32(encrypted_portion, htonl((uint32_t)input_len));
  memcpy(encrypted_portion+4, input, input_len);

  /* Now that all the data is in position, derive some keys, encrypt, and
   * digest */
  const int s2k_rv = secret_to_key_derivekey(keys, sizeof(keys),
                              pwbox_encoded_getarray_skey_header(enc),
                              spec_len,
                              secret, secret_len);
  if (BUG(s2k_rv < 0))
    goto err;

  cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
  crypto_cipher_crypt_inplace(cipher, (char*)encrypted_portion, encrypted_len);
  crypto_cipher_free(cipher);

  result_len = pwbox_encoded_encoded_len(enc);
  if (BUG(result_len < 0))
    goto err;
  result = tor_malloc(result_len);
  enc_len = pwbox_encoded_encode(result, result_len, enc);
  if (BUG(enc_len < 0))
    goto err;
  tor_assert(enc_len == result_len);

  crypto_hmac_sha256((char*) result + result_len - 32,
                     (const char*)keys + CIPHER_KEY_LEN,
                     DIGEST256_LEN,
                     (const char*)result,
                     result_len - 32);

  *out = result;
  *outlen_out = result_len;
  rv = 0;
  goto out;

 err:
  /* LCOV_EXCL_START

     This error case is often unreachable if we're correctly coded, unless
     somebody adds a new error case somewhere, or unless you're building
     without scrypto support.

       - make_specifier can't fail, unless S2K_MAX_LEN is too short.
       - secret_to_key_derivekey can't really fail unless we're missing
         scrypt, or the underlying function fails, or we pass it a bogus
         algorithm or parameters.
       - pwbox_encoded_encoded_len can't fail unless we're using trunnel
         incorrectly.
       - pwbox_encoded_encode can't fail unless we're using trunnel wrong,
         or it's buggy.
   */
  tor_free(result);
  rv = -1;
  /* LCOV_EXCL_STOP */
 out:
  pwbox_encoded_free(enc);
  memwipe(keys, 0, sizeof(keys));
  return rv;
}
Пример #6
0
static void
test_crypto_rng_fast_whitebox(void *arg)
{
  (void)arg;
  const size_t buflen = crypto_fast_rng_get_bytes_used_per_stream();
  char *buf = tor_malloc_zero(buflen);
  char *buf2 = tor_malloc_zero(buflen);
  char *buf3 = NULL, *buf4 = NULL;

  crypto_cipher_t *cipher = NULL, *cipher2 = NULL;
  uint8_t seed[CRYPTO_FAST_RNG_SEED_LEN];
  memset(seed, 0, sizeof(seed));

  /* Start with a prng with zero key and zero IV. */
  crypto_fast_rng_t *rng = crypto_fast_rng_new_from_seed(seed);
  tt_assert(rng);

  /* We'll use a stream cipher to keep in sync */
  cipher = crypto_cipher_new_with_iv_and_bits(seed, seed+32, 256);

  /* The first 48 bytes are used for the next seed -- let's make sure we have
   * them.
   */
  memset(seed, 0, sizeof(seed));
  crypto_cipher_crypt_inplace(cipher, (char*)seed, sizeof(seed));

  /* if we get 128 bytes, they should match the bytes from the aes256-counter
   * stream, starting at position 48.
   */
  crypto_fast_rng_getbytes(rng, (uint8_t*)buf, 128);
  memset(buf2, 0, 128);
  crypto_cipher_crypt_inplace(cipher, buf2, 128);
  tt_mem_op(buf, OP_EQ, buf2, 128);

  /* Try that again, with an odd number of bytes. */
  crypto_fast_rng_getbytes(rng, (uint8_t*)buf, 199);
  memset(buf2, 0, 199);
  crypto_cipher_crypt_inplace(cipher, buf2, 199);
  tt_mem_op(buf, OP_EQ, buf2, 199);

  /* Make sure that refilling works as expected: skip all but the last 5 bytes
   * of this steam. */
  size_t skip = buflen - (199+128) - 5;
  crypto_fast_rng_getbytes(rng, (uint8_t*)buf, skip);
  crypto_cipher_crypt_inplace(cipher, buf2, skip);

  /* Now get the next 128 bytes. The first 5 will come from this stream, and
   * the next 5 will come from the stream keyed by the new value of 'seed'. */
  crypto_fast_rng_getbytes(rng, (uint8_t*)buf, 128);
  memset(buf2, 0, 128);
  crypto_cipher_crypt_inplace(cipher, buf2, 5);
  crypto_cipher_free(cipher);
  cipher = crypto_cipher_new_with_iv_and_bits(seed, seed+32, 256);
  memset(seed, 0, sizeof(seed));
  crypto_cipher_crypt_inplace(cipher, (char*)seed, sizeof(seed));
  crypto_cipher_crypt_inplace(cipher, buf2+5, 128-5);
  tt_mem_op(buf, OP_EQ, buf2, 128);

  /* And check the next 7 bytes to make sure we didn't discard anything. */
  crypto_fast_rng_getbytes(rng, (uint8_t*)buf, 7);
  memset(buf2, 0, 7);
  crypto_cipher_crypt_inplace(cipher, buf2, 7);
  tt_mem_op(buf, OP_EQ, buf2, 7);

  /* Now try the optimization for long outputs. */
  buf3 = tor_malloc(65536);
  crypto_fast_rng_getbytes(rng, (uint8_t*)buf3, 65536);

  buf4 = tor_malloc_zero(65536);
  uint8_t seed2[CRYPTO_FAST_RNG_SEED_LEN];
  memset(seed2, 0, sizeof(seed2));
  crypto_cipher_crypt_inplace(cipher, (char*)seed2, sizeof(seed2));
  cipher2 = crypto_cipher_new_with_iv_and_bits(seed2, seed2+32, 256);
  crypto_cipher_crypt_inplace(cipher2, buf4, 65536);
  tt_mem_op(buf3, OP_EQ, buf4, 65536);

 done:
  crypto_fast_rng_free(rng);
  crypto_cipher_free(cipher);
  crypto_cipher_free(cipher2);
  tor_free(buf);
  tor_free(buf2);
  tor_free(buf3);
  tor_free(buf4);
}
Пример #7
0
/** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b>
 * (in place).
 *
 * Note that we use the same operation for encrypting and for decrypting.
 */
static void
relay_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in)
{
  crypto_cipher_crypt_inplace(cipher, (char*) in, CELL_PAYLOAD_SIZE);
}