diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-09-20 20:08:47 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-09-20 20:08:47 +0000 |
commit | fc5dd0cdbb06aa58aeb12306a0c5d50b581c7dcf (patch) | |
tree | 2c752fa07b4b324fd466b38382e4f3d6b3fa0901 | |
parent | f0634bb7ca54bf9d61ce376c821b41a21ccb4726 (diff) | |
download | tor-fc5dd0cdbb06aa58aeb12306a0c5d50b581c7dcf.tar tor-fc5dd0cdbb06aa58aeb12306a0c5d50b581c7dcf.tar.gz |
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
-rw-r--r-- | src/common/crypto.c | 180 | ||||
-rw-r--r-- | src/common/crypto.h | 5 | ||||
-rw-r--r-- | src/or/test.c | 82 |
3 files changed, 64 insertions, 203 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c index fb47dc404..45a962b63 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -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 diff --git a/src/common/crypto.h b/src/common/crypto.h index b548978aa..09cbbe704 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -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); diff --git a/src/or/test.c b/src/or/test.c index 124fdff72..6cdba3b26 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -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), |