mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 06:48:05 +01:00
r15231@catbus: nickm | 2007-09-20 16:04:30 -0400
Patch from karsten: remove cbc and make unit tests handle aes-ctr-with-iv. svn:r11538
This commit is contained in:
parent
f0634bb7ca
commit
fc5dd0cdbb
3 changed files with 64 additions and 203 deletions
|
@ -1077,15 +1077,17 @@ crypto_cipher_set_key(crypto_cipher_env_t *env, const char *key)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
/** Generate an initialization vector for our AES-CTR cipher; store it
|
||||
* in the first CIPHER_IV_LEN bytes of <b>iv_out</b>. */
|
||||
void
|
||||
crypto_cipher_generate_iv(char *iv_out)
|
||||
{
|
||||
/* XXXX020 It's possible we want to get fancier here. */
|
||||
crypto_rand(iv_out, CIPHER_IV_LEN);
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
/** Adjust the counter of <b>env</b> to point to the first byte of the block
|
||||
* corresponding to the encryption of the CIPHER_IV_LEN bytes at
|
||||
* <b>iv</b>. */
|
||||
int
|
||||
crypto_cipher_set_iv(crypto_cipher_env_t *env, const char *iv)
|
||||
{
|
||||
|
@ -1161,7 +1163,6 @@ crypto_cipher_decrypt(crypto_cipher_env_t *env, char *to,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the key in
|
||||
* <b>cipher</b> to the buffer in <b>to</b> of length
|
||||
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> plus
|
||||
|
@ -1180,6 +1181,8 @@ crypto_cipher_encrypt_with_iv(crypto_cipher_env_t *cipher,
|
|||
tor_assert(from);
|
||||
tor_assert(to);
|
||||
|
||||
if (fromlen < 1)
|
||||
return -1;
|
||||
if (tolen < fromlen + CIPHER_IV_LEN)
|
||||
return -1;
|
||||
|
||||
|
@ -1187,11 +1190,10 @@ crypto_cipher_encrypt_with_iv(crypto_cipher_env_t *cipher,
|
|||
if (crypto_cipher_set_iv(cipher, to)<0)
|
||||
return -1;
|
||||
crypto_cipher_encrypt(cipher, to+CIPHER_IV_LEN, from, fromlen);
|
||||
crypto_free_cipher_env(cipher);
|
||||
return fromlen + CIPHER_IV_LEN;
|
||||
}
|
||||
|
||||
/** Encrypt <b>fromlen</b> bytes (at least 1+CIPHER_IV_LEN) from <b>from</b>
|
||||
/** Decrypt <b>fromlen</b> bytes (at least 1+CIPHER_IV_LEN) from <b>from</b>
|
||||
* with the key in <b>cipher</b> to the buffer in <b>to</b> of length
|
||||
* <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> minus
|
||||
* CIPHER_IV_LEN bytes for the initialization vector. On success, return the
|
||||
|
@ -1209,7 +1211,7 @@ crypto_cipher_decrypt_with_iv(crypto_cipher_env_t *cipher,
|
|||
tor_assert(from);
|
||||
tor_assert(to);
|
||||
|
||||
if (fromlen < CIPHER_IV_LEN)
|
||||
if (fromlen <= CIPHER_IV_LEN)
|
||||
return -1;
|
||||
if (tolen < fromlen - CIPHER_IV_LEN)
|
||||
return -1;
|
||||
|
@ -1217,173 +1219,9 @@ crypto_cipher_decrypt_with_iv(crypto_cipher_env_t *cipher,
|
|||
if (crypto_cipher_set_iv(cipher, from)<0)
|
||||
return -1;
|
||||
crypto_cipher_encrypt(cipher, to, from+CIPHER_IV_LEN, fromlen-CIPHER_IV_LEN);
|
||||
crypto_free_cipher_env(cipher);
|
||||
return fromlen - CIPHER_IV_LEN;
|
||||
}
|
||||
|
||||
#define AES_CIPHER_BLOCK_SIZE 16
|
||||
#define AES_IV_SIZE 16
|
||||
|
||||
/** Encrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the
|
||||
* symmetric key <b>key</b> of 16 bytes length to <b>to</b> of length
|
||||
* <b>tolen</b> which needs to be <b>fromlen</b>, padded to the next 16
|
||||
* bytes, plus exactly 16 bytes for the initialization vector. On success,
|
||||
* return the number of bytes written, on failure, return -1.
|
||||
*/
|
||||
int
|
||||
crypto_cipher_encrypt_cbc(const char *key, char *to, size_t tolen,
|
||||
const char *from, size_t fromlen)
|
||||
{
|
||||
|
||||
EVP_CIPHER_CTX ctx_msg, ctx_iv; /* cipher contexts for message and IV */
|
||||
unsigned char iv[AES_IV_SIZE]; /* initialization vector */
|
||||
int outlen, tmplen; /* length of encrypted strings (w/ and w/o final data) */
|
||||
|
||||
tor_assert(key);
|
||||
tor_assert(to);
|
||||
tor_assert(tolen >= fromlen + AES_IV_SIZE +
|
||||
(AES_CIPHER_BLOCK_SIZE - fromlen % AES_CIPHER_BLOCK_SIZE));
|
||||
tor_assert(from);
|
||||
tor_assert(fromlen > 0);
|
||||
|
||||
/* generate random initialization vector */
|
||||
crypto_rand((char *)iv, AES_IV_SIZE);
|
||||
|
||||
/* initialize cipher context for the initialization vector */
|
||||
EVP_CIPHER_CTX_init(&ctx_iv);
|
||||
|
||||
/* disable padding for encryption of initialization vector */
|
||||
EVP_CIPHER_CTX_set_padding(&ctx_iv, 0);
|
||||
|
||||
/* set up cipher context for the initialization vector for encryption with
|
||||
* cipher type AES-128 in ECB mode, default implementation, given key, and
|
||||
* no initialization vector */
|
||||
EVP_EncryptInit_ex(&ctx_iv, EVP_aes_128_ecb(), NULL, (unsigned char *)key,
|
||||
NULL);
|
||||
|
||||
/* encrypt initialization vector (no padding necessary) and write it to the
|
||||
* first 16 bytes of the result */
|
||||
if (!EVP_EncryptUpdate(&ctx_iv, (unsigned char *)to, &outlen, iv,
|
||||
AES_IV_SIZE)) {
|
||||
crypto_log_errors(LOG_WARN, "encrypting initialization vector");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* clear all information from cipher context for the initialization vector
|
||||
* and free up any allocated memory associated with it */
|
||||
EVP_CIPHER_CTX_cleanup(&ctx_iv);
|
||||
|
||||
/* initialize cipher context for the message */
|
||||
EVP_CIPHER_CTX_init(&ctx_msg);
|
||||
|
||||
/* set up cipher context for encryption with cipher type AES-128 in CBC mode,
|
||||
* default implementation, given key, and initialization vector */
|
||||
EVP_EncryptInit_ex(&ctx_msg, EVP_aes_128_cbc(), NULL, (unsigned char *)key,
|
||||
iv);
|
||||
|
||||
/* encrypt fromlen bytes from buffer from and write the encrypted version to
|
||||
* buffer to */
|
||||
if (!EVP_EncryptUpdate(&ctx_msg,
|
||||
((unsigned char *)to) + AES_IV_SIZE, &outlen,
|
||||
(const unsigned char *)from, (int)fromlen)) {
|
||||
crypto_log_errors(LOG_WARN, "encrypting");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* encrypt the final data */
|
||||
if (!EVP_EncryptFinal_ex(&ctx_msg,
|
||||
((unsigned char *)to) + AES_IV_SIZE + outlen,
|
||||
&tmplen)) {
|
||||
crypto_log_errors(LOG_WARN, "encrypting the final data");
|
||||
return -1;
|
||||
}
|
||||
outlen += tmplen;
|
||||
|
||||
/* clear all information from cipher context and free up any allocated memory
|
||||
* associated with it */
|
||||
EVP_CIPHER_CTX_cleanup(&ctx_msg);
|
||||
|
||||
/* return number of written bytes */
|
||||
return outlen + AES_IV_SIZE;
|
||||
}
|
||||
|
||||
/** Decrypt <b>fromlen</b> bytes (at least 1) from <b>from</b> with the
|
||||
* symmetric key <b>key</b> of 16 bytes length to <b>to</b> of length
|
||||
* <b>tolen</b> which may be <b>fromlen</b> minus 16 for the initialization
|
||||
* vector (the size of padding cannot be determined in advance). On success,
|
||||
* return the number of bytes written, on failure (NOT including providing
|
||||
* the wrong key, which occasionally returns the correct length!), return -1.
|
||||
*/
|
||||
int
|
||||
crypto_cipher_decrypt_cbc(const char *key, char *to, size_t tolen,
|
||||
const char *from, size_t fromlen)
|
||||
{
|
||||
EVP_CIPHER_CTX ctx_msg, ctx_iv; /* cipher contexts for message and IV */
|
||||
unsigned char iv[AES_IV_SIZE]; /* initialization vector */
|
||||
int outlen, tmplen; /* length of decrypted strings (w/ and wo/ final data) */
|
||||
|
||||
tor_assert(key);
|
||||
tor_assert(to);
|
||||
tor_assert(tolen >= fromlen - AES_IV_SIZE);
|
||||
tor_assert(from);
|
||||
tor_assert(fromlen > 0);
|
||||
|
||||
/* initialize cipher context for the initialization vector */
|
||||
EVP_CIPHER_CTX_init(&ctx_iv);
|
||||
|
||||
/* disable padding for decryption of initialization vector */
|
||||
EVP_CIPHER_CTX_set_padding(&ctx_iv, 0);
|
||||
|
||||
/* set up cipher context for the initialization vector for decryption with
|
||||
* cipher type AES-128 in ECB mode, default implementation, given key, and
|
||||
* no initialization vector */
|
||||
EVP_DecryptInit_ex(&ctx_iv, EVP_aes_128_ecb(), NULL, (unsigned char *)key,
|
||||
NULL);
|
||||
|
||||
/* decrypt initialization vector (is not padded) */
|
||||
if (!EVP_DecryptUpdate(&ctx_iv, iv, &outlen, (const unsigned char *)from,
|
||||
AES_IV_SIZE)) {
|
||||
crypto_log_errors(LOG_WARN, "decrypting initialization vector");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* clear all information from cipher context for the initialization vector
|
||||
* and free up any allocated memory associate with it */
|
||||
EVP_CIPHER_CTX_cleanup(&ctx_iv);
|
||||
|
||||
/* initialize cipher context for the message */
|
||||
EVP_CIPHER_CTX_init(&ctx_msg);
|
||||
|
||||
/* set up cipher context for decryption with cipher type AES-128 in CBC mode,
|
||||
* default implementation, given key, and initialization vector */
|
||||
EVP_DecryptInit_ex(&ctx_msg, EVP_aes_128_cbc(), NULL, (unsigned char *)key,
|
||||
iv);
|
||||
|
||||
/* decrypt fromlen-16 bytes from buffer from and write the decrypted version
|
||||
* to buffer to */
|
||||
if (!EVP_DecryptUpdate(&ctx_msg, (unsigned char *)to, &outlen,
|
||||
((const unsigned char *)from) + AES_IV_SIZE,
|
||||
(int)fromlen - AES_IV_SIZE)) {
|
||||
crypto_log_errors(LOG_INFO, "decrypting");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* decrypt the final data */
|
||||
if (!EVP_DecryptFinal_ex(&ctx_msg, ((unsigned char *)to) + outlen,
|
||||
&tmplen)) {
|
||||
crypto_log_errors(LOG_INFO, "decrypting the final data");
|
||||
return -1;
|
||||
}
|
||||
outlen += tmplen;
|
||||
|
||||
/* clear all information from cipher context and free up any allocated memory
|
||||
* associate with it */
|
||||
EVP_CIPHER_CTX_cleanup(&ctx_msg);
|
||||
|
||||
/* return number of written bytes */
|
||||
return outlen;
|
||||
}
|
||||
|
||||
/* SHA-1 */
|
||||
|
||||
/** Compute the SHA1 digest of <b>len</b> bytes in data stored in
|
||||
|
|
|
@ -135,11 +135,6 @@ int crypto_cipher_decrypt_with_iv(crypto_cipher_env_t *env,
|
|||
char *to, size_t tolen,
|
||||
const char *from, size_t fromlen);
|
||||
|
||||
int crypto_cipher_encrypt_cbc(const char *key, char *to, size_t tolen,
|
||||
const char *from, size_t fromlen);
|
||||
int crypto_cipher_decrypt_cbc(const char *key, char *to, size_t tolen,
|
||||
const char *from, size_t fromlen);
|
||||
|
||||
/* SHA-1 */
|
||||
int crypto_digest(char *digest, const char *m, size_t len);
|
||||
crypto_digest_env_t *crypto_new_digest_env(void);
|
||||
|
|
|
@ -3033,10 +3033,11 @@ test_util_mempool(void)
|
|||
smartlist_free(allocated);
|
||||
}
|
||||
|
||||
/* Test AES-CBC encryption and decryption. */
|
||||
/* Test AES-CTR encryption and decryption with IV. */
|
||||
static void
|
||||
test_crypto_aes_cbc(void)
|
||||
test_crypto_aes_iv(void)
|
||||
{
|
||||
crypto_cipher_env_t *cipher;
|
||||
char *plain, *encrypted1, *encrypted2, *decrypted1, *decrypted2;
|
||||
char plain_1[1], plain_15[15], plain_16[16], plain_17[17];
|
||||
char key1[16], key2[16];
|
||||
|
@ -3055,61 +3056,88 @@ test_crypto_aes_cbc(void)
|
|||
crypto_rand(plain_17, 17);
|
||||
key1[0] = key2[0] + 128; /* Make sure that contents are different. */
|
||||
/* Encrypt and decrypt with the same key. */
|
||||
encrypted_size = crypto_cipher_encrypt_cbc(key1, encrypted1, 4095 + 1 + 16,
|
||||
cipher = crypto_create_init_cipher(key1, 1);
|
||||
encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 4095,
|
||||
plain, 4095);
|
||||
test_eq(encrypted_size, 4095 + 1 + 16);
|
||||
decrypted_size = crypto_cipher_decrypt_cbc(key1, decrypted1, 4095 + 1,
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(encrypted_size, 16 + 4095);
|
||||
cipher = crypto_create_init_cipher(key1, 0);
|
||||
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 4095,
|
||||
encrypted1, encrypted_size);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(decrypted_size, 4095);
|
||||
test_memeq(plain, decrypted1, 4095);
|
||||
/* Encrypt a second time (with a new random initialization vector). */
|
||||
encrypted_size = crypto_cipher_encrypt_cbc(key1, encrypted2, 4095 + 1 + 16,
|
||||
cipher = crypto_create_init_cipher(key1, 1);
|
||||
encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted2, 16 + 4095,
|
||||
plain, 4095);
|
||||
test_eq(encrypted_size, 4095 + 1 + 16);
|
||||
decrypted_size = crypto_cipher_decrypt_cbc(key1, decrypted2, 4095 + 1,
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(encrypted_size, 16 + 4095);
|
||||
cipher = crypto_create_init_cipher(key1, 0);
|
||||
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted2, 4095,
|
||||
encrypted2, encrypted_size);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(decrypted_size, 4095);
|
||||
test_memeq(plain, decrypted2, 4095);
|
||||
test_memneq(encrypted1, encrypted2, encrypted_size);
|
||||
/* Decrypt with the wrong key. */
|
||||
decrypted_size = crypto_cipher_decrypt_cbc(key2, decrypted2, 4095 + 1,
|
||||
cipher = crypto_create_init_cipher(key2, 0);
|
||||
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted2, 4095,
|
||||
encrypted1, encrypted_size);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_memneq(plain, decrypted2, encrypted_size);
|
||||
/* Alter the initialization vector. */
|
||||
encrypted1[0] += 42;
|
||||
decrypted_size = crypto_cipher_decrypt_cbc(key1, decrypted1, 4095 + 1,
|
||||
cipher = crypto_create_init_cipher(key1, 0);
|
||||
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 4095,
|
||||
encrypted1, encrypted_size);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_memneq(plain, decrypted2, 4095);
|
||||
/* Special length case: 1. */
|
||||
encrypted_size = crypto_cipher_encrypt_cbc(key1, encrypted1, 32,
|
||||
cipher = crypto_create_init_cipher(key1, 1);
|
||||
encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 1,
|
||||
plain_1, 1);
|
||||
test_eq(encrypted_size, 32);
|
||||
decrypted_size = crypto_cipher_decrypt_cbc(key1, decrypted1, 16,
|
||||
encrypted1, 32);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(encrypted_size, 16 + 1);
|
||||
cipher = crypto_create_init_cipher(key1, 0);
|
||||
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 1,
|
||||
encrypted1, encrypted_size);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(decrypted_size, 1);
|
||||
test_memeq(plain_1, decrypted1, 1);
|
||||
/* Special length case: 15. */
|
||||
encrypted_size = crypto_cipher_encrypt_cbc(key1, encrypted1, 32,
|
||||
cipher = crypto_create_init_cipher(key1, 1);
|
||||
encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 15,
|
||||
plain_15, 15);
|
||||
test_eq(encrypted_size, 32);
|
||||
decrypted_size = crypto_cipher_decrypt_cbc(key1, decrypted1, 16,
|
||||
encrypted1, 32);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(encrypted_size, 16 + 15);
|
||||
cipher = crypto_create_init_cipher(key1, 0);
|
||||
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 15,
|
||||
encrypted1, encrypted_size);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(decrypted_size, 15);
|
||||
test_memeq(plain_15, decrypted1, 15);
|
||||
/* Special length case: 16. */
|
||||
encrypted_size = crypto_cipher_encrypt_cbc(key1, encrypted1, 48,
|
||||
cipher = crypto_create_init_cipher(key1, 1);
|
||||
encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 16,
|
||||
plain_16, 16);
|
||||
test_eq(encrypted_size, 48);
|
||||
decrypted_size = crypto_cipher_decrypt_cbc(key1, decrypted1, 32,
|
||||
encrypted1, 48);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(encrypted_size, 16 + 16);
|
||||
cipher = crypto_create_init_cipher(key1, 0);
|
||||
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 16,
|
||||
encrypted1, encrypted_size);
|
||||
test_eq(decrypted_size, 16);
|
||||
test_memeq(plain_16, decrypted1, 16);
|
||||
/* Special length case: 17. */
|
||||
encrypted_size = crypto_cipher_encrypt_cbc(key1, encrypted1, 48,
|
||||
cipher = crypto_create_init_cipher(key1, 1);
|
||||
encrypted_size = crypto_cipher_encrypt_with_iv(cipher, encrypted1, 16 + 17,
|
||||
plain_17, 17);
|
||||
test_eq(encrypted_size, 48);
|
||||
decrypted_size = crypto_cipher_decrypt_cbc(key1, decrypted1, 32,
|
||||
encrypted1, 48);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(encrypted_size, 16 + 17);
|
||||
cipher = crypto_create_init_cipher(key1, 0);
|
||||
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 17,
|
||||
encrypted1, encrypted_size);
|
||||
crypto_free_cipher_env(cipher);
|
||||
test_eq(decrypted_size, 17);
|
||||
test_memeq(plain_17, decrypted1, 17);
|
||||
/* Free memory. */
|
||||
|
@ -3155,7 +3183,7 @@ static struct {
|
|||
ENT(crypto),
|
||||
SUBENT(crypto, dh),
|
||||
SUBENT(crypto, s2k),
|
||||
SUBENT(crypto, aes_cbc),
|
||||
SUBENT(crypto, aes_iv),
|
||||
SUBENT(crypto, base32_decode),
|
||||
ENT(util),
|
||||
SUBENT(util, ip6_helpers),
|
||||
|
|
Loading…
Add table
Reference in a new issue