From 301114940143b0d950b3a8dd69e2d6ee0bc6244d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 23 Sep 2014 14:47:23 -0400 Subject: Adjust pwbox format: use a random IV each time Suggested by yawning --- src/common/crypto_pwbox.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/common/crypto_pwbox.c b/src/common/crypto_pwbox.c index 61b6ebe96f..c021974632 100644 --- a/src/common/crypto_pwbox.c +++ b/src/common/crypto_pwbox.c @@ -8,6 +8,7 @@ /* 7 bytes "TORBOX0" 1 byte: header len (H) H bytes: header, denoting secret key algorithm. + 16 bytes: IV Round up to multiple of 128 bytes, then encrypt: 4 bytes: data len data @@ -15,7 +16,7 @@ 32 bytes: HMAC-SHA256 of all previous bytes. */ -#define MAX_OVERHEAD (S2K_MAXLEN + 8 + 32) +#define MAX_OVERHEAD (S2K_MAXLEN + 8 + 32 + CIPHER_IV_LEN) /** * Make an authenticated passphrase-encrypted blob to encode the @@ -31,7 +32,7 @@ crypto_pwbox(uint8_t **out, size_t *outlen_out, const char *secret, size_t secret_len, unsigned s2k_flags) { - uint8_t *result, *encrypted_portion, *hmac; + uint8_t *result, *encrypted_portion, *hmac, *iv; size_t encrypted_len = 128 * CEIL_DIV(input_len+4, 128); size_t result_len = encrypted_len + MAX_OVERHEAD; int spec_len; @@ -51,9 +52,10 @@ crypto_pwbox(uint8_t **out, size_t *outlen_out, goto err; result[7] = (uint8_t) spec_len; - tor_assert(8 + spec_len + encrypted_len <= result_len); + tor_assert(8 + spec_len + CIPHER_IV_LEN + encrypted_len <= result_len); - encrypted_portion = result + 8 + spec_len; + iv = result + 8 + spec_len; + encrypted_portion = result + 8 + spec_len + CIPHER_IV_LEN; hmac = encrypted_portion + encrypted_len; set_uint32(encrypted_portion, htonl(input_len)); @@ -66,17 +68,20 @@ crypto_pwbox(uint8_t **out, size_t *outlen_out, secret, secret_len) < 0) goto err; - cipher = crypto_cipher_new((char*)keys); + crypto_rand((char*)iv, CIPHER_IV_LEN); + + cipher = crypto_cipher_new_with_iv((char*)keys, (char*)iv); crypto_cipher_crypt_inplace(cipher, (char*)encrypted_portion, encrypted_len); crypto_cipher_free(cipher); crypto_hmac_sha256((char*)hmac, (const char*)keys + CIPHER_KEY_LEN, sizeof(keys)-CIPHER_KEY_LEN, - (const char*)result, 8 + spec_len + encrypted_len); + (const char*)result, + 8 + CIPHER_IV_LEN + spec_len + encrypted_len); *out = result; - *outlen_out = 8 + spec_len + encrypted_len + DIGEST256_LEN; + *outlen_out = 8 + CIPHER_IV_LEN + spec_len + encrypted_len + DIGEST256_LEN; rv = 0; goto out; @@ -104,7 +109,7 @@ crypto_unpwbox(uint8_t **out, size_t *outlen_out, const char *secret, size_t secret_len) { uint8_t *result = NULL; - const uint8_t *encrypted; + const uint8_t *encrypted, *iv; uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN]; size_t spec_bytes; uint8_t hmac[DIGEST256_LEN]; @@ -137,10 +142,11 @@ crypto_unpwbox(uint8_t **out, size_t *outlen_out, goto err; } - encrypted = inp + 8 + spec_bytes; + iv = inp + 8 + spec_bytes; + encrypted = inp + 8 + spec_bytes + CIPHER_IV_LEN; /* How long is the plaintext? */ - cipher = crypto_cipher_new((char*)keys); + cipher = crypto_cipher_new_with_iv((char*)keys, (char*)iv); crypto_cipher_decrypt(cipher, (char*)&result_len, (char*)encrypted, 4); result_len = ntohl(result_len); if (input_len < 8 + spec_bytes + 4 + result_len + 32) -- cgit v1.2.3-54-g00ecf