|
@@ -8,6 +8,7 @@
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
- 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)
|