From 5f7950e8744a8c59ede2da56d99d0e878f00d18a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 19 Sep 2007 15:53:41 +0000 Subject: [PATCH] r15172@catbus: nickm | 2007-09-19 11:50:02 -0400 New (untested) code to implement AES-with-IV. Currently, IVs are generated randomly. Once tested, should be (almost) a drop-in replacement for the CBC functions. svn:r11519 --- src/common/crypto.c | 78 ++++++++++++++++++++++++++++++++++++++++++++- src/common/crypto.h | 11 +++++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/common/crypto.c b/src/common/crypto.c index 0e78c76af7..fb47dc4040 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1074,7 +1074,24 @@ crypto_cipher_set_key(crypto_cipher_env_t *env, const char *key) return -1; memcpy(env->key, key, CIPHER_KEY_LEN); + return 0; +} +/** DOCDOC */ +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 */ +int +crypto_cipher_set_iv(crypto_cipher_env_t *env, const char *iv) +{ + tor_assert(env); + tor_assert(iv); + aes_set_iv(env->cipher, iv); return 0; } @@ -1144,8 +1161,67 @@ crypto_cipher_decrypt(crypto_cipher_env_t *env, char *to, return 0; } -#define AES_CIPHER_BLOCK_SIZE 16 +/** Encrypt fromlen bytes (at least 1) from from with the key in + * cipher to the buffer in to of length + * tolen. tolen must be at least fromlen plus + * CIPHER_IV_LEN bytes for the initialization vector. On success, return the + * number of bytes written, on failure, return -1. + * + * This function adjusts the current position of the counter in cipher + * to immediately after the encrypted data. + */ +int +crypto_cipher_encrypt_with_iv(crypto_cipher_env_t *cipher, + char *to, size_t tolen, + const char *from, size_t fromlen) +{ + tor_assert(cipher); + tor_assert(from); + tor_assert(to); + + if (tolen < fromlen + CIPHER_IV_LEN) + return -1; + + crypto_cipher_generate_iv(to); + 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 fromlen bytes (at least 1+CIPHER_IV_LEN) from from + * with the key in cipher to the buffer in to of length + * tolen. tolen must be at least fromlen minus + * CIPHER_IV_LEN bytes for the initialization vector. On success, return the + * number of bytes written, on failure, return -1. + * + * This function adjusts the current position of the counter in cipher + * to immediately after the decrypted data. + */ +int +crypto_cipher_decrypt_with_iv(crypto_cipher_env_t *cipher, + char *to, size_t tolen, + const char *from, size_t fromlen) +{ + tor_assert(cipher); + tor_assert(from); + tor_assert(to); + + if (fromlen < CIPHER_IV_LEN) + return -1; + if (tolen < fromlen - CIPHER_IV_LEN) + return -1; + + 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 fromlen bytes (at least 1) from from with the diff --git a/src/common/crypto.h b/src/common/crypto.h index 1d1f758fcb..b548978aaa 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -21,6 +21,8 @@ #define DIGEST_LEN 20 /** Length of our symmetric cipher's keys. */ #define CIPHER_KEY_LEN 16 +/** Length of our symmetric cipher's IV. */ +#define CIPHER_IV_LEN 16 /** Length of our public keys. */ #define PK_BYTES (1024/8) /** Length of our DH keys. */ @@ -115,6 +117,8 @@ int crypto_pk_check_fingerprint_syntax(const char *s); /* symmetric crypto */ int crypto_cipher_generate_key(crypto_cipher_env_t *env); int crypto_cipher_set_key(crypto_cipher_env_t *env, const char *key); +void crypto_cipher_generate_iv(char *iv_out); +int crypto_cipher_set_iv(crypto_cipher_env_t *env, const char *iv); const char *crypto_cipher_get_key(crypto_cipher_env_t *env); int crypto_cipher_encrypt_init_cipher(crypto_cipher_env_t *env); int crypto_cipher_decrypt_init_cipher(crypto_cipher_env_t *env); @@ -124,6 +128,13 @@ int crypto_cipher_encrypt(crypto_cipher_env_t *env, char *to, int crypto_cipher_decrypt(crypto_cipher_env_t *env, char *to, const char *from, size_t fromlen); +int crypto_cipher_encrypt_with_iv(crypto_cipher_env_t *env, + char *to, size_t tolen, + const char *from, size_t fromlen); +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,