/** * 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); }
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); }
/** * 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); }
/** 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); }
/** * 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; }
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); }
/** 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); }