diff options
author | Nick Mathewson <nickm@torproject.org> | 2012-03-20 15:35:43 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2012-03-27 22:37:56 -0400 |
commit | de0dca0de76d9d50aeb5955fe3f435c6c190f8d7 (patch) | |
tree | 8d7005e768bc04ac1695b72cf3970d552570016f /src/common | |
parent | 00b4784575c88d5de15886b440096c1e2b9fb080 (diff) | |
download | tor-de0dca0de76d9d50aeb5955fe3f435c6c190f8d7.tar.gz tor-de0dca0de76d9d50aeb5955fe3f435c6c190f8d7.zip |
Refactor the API for setting up a block cipher.
It allows us more flexibility on the backend if the user needs to
specify the key and IV at setup time.
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/aes.c | 16 | ||||
-rw-r--r-- | src/common/aes.h | 4 | ||||
-rw-r--r-- | src/common/crypto.c | 158 | ||||
-rw-r--r-- | src/common/crypto.h | 17 |
4 files changed, 54 insertions, 141 deletions
diff --git a/src/common/aes.c b/src/common/aes.c index cfd931fab1..3121891068 100644 --- a/src/common/aes.c +++ b/src/common/aes.c @@ -209,14 +209,22 @@ _aes_fill_buf(aes_cnt_cipher_t *cipher) } } +static void aes_set_key(aes_cnt_cipher_t *cipher, const char *key, + int key_bits); +static void aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv); + /** - * Return a newly allocated counter-mode AES128 cipher implementation. + * Return a newly allocated counter-mode AES128 cipher implementation, + * using the 128-bit key <b>key</b> and the 128-bit IV <b>iv</b>. */ aes_cnt_cipher_t* -aes_new_cipher(void) +aes_new_cipher(const char *key, const char *iv) { aes_cnt_cipher_t* result = tor_malloc_zero(sizeof(aes_cnt_cipher_t)); + aes_set_key(result, key, 128); + aes_set_iv(result, iv); + return result; } @@ -224,7 +232,7 @@ aes_new_cipher(void) * <b>key_bits</b> bits long (must be 128, 192, or 256). Also resets * the counter to 0. */ -void +static void aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits) { if (should_use_EVP) { @@ -398,7 +406,7 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) /** Reset the 128-bit counter of <b>cipher</b> to the 16-bit big-endian value * in <b>iv</b>. */ -void +static void aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv) { #ifdef USING_COUNTER_VARS diff --git a/src/common/aes.h b/src/common/aes.h index f9de68a1bf..04b424ec77 100644 --- a/src/common/aes.h +++ b/src/common/aes.h @@ -16,13 +16,11 @@ struct aes_cnt_cipher; typedef struct aes_cnt_cipher aes_cnt_cipher_t; -aes_cnt_cipher_t* aes_new_cipher(void); +aes_cnt_cipher_t* aes_new_cipher(const char *key, const char *iv); void aes_cipher_free(aes_cnt_cipher_t *cipher); -void aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits); void aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, char *output); void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len); -void aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv); int evaluate_evp_for_aes(int force_value); int evaluate_ctr_for_aes(void); diff --git a/src/common/crypto.c b/src/common/crypto.c index 02f3d2fbba..2bd2e1e4d2 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -119,6 +119,7 @@ struct crypto_pk_t struct crypto_cipher_t { char key[CIPHER_KEY_LEN]; /**< The raw key. */ + char iv[CIPHER_IV_LEN]; /**< The initial IV. */ aes_cnt_cipher_t *cipher; /**< The key in format usable for counter-mode AES * encryption */ }; @@ -383,48 +384,37 @@ crypto_pk_free(crypto_pk_t *env) tor_free(env); } -/** Create a new symmetric cipher for a given key and encryption flag - * (1=encrypt, 0=decrypt). Return the crypto object on success; NULL - * on failure. +/** Allocate and return a new symmetric cipher using the provided key and iv. + * The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. If you + * provide NULL in place of either one, it is generated at random. */ crypto_cipher_t * -crypto_create_init_cipher(const char *key, int encrypt_mode) +crypto_cipher_new_with_iv(const char *key, const char *iv) { - int r; - crypto_cipher_t *crypto = NULL; - - if (! (crypto = crypto_cipher_new())) { - log_warn(LD_CRYPTO, "Unable to allocate crypto object"); - return NULL; - } + crypto_cipher_t *env; - crypto_cipher_set_key(crypto, key); + env = tor_malloc_zero(sizeof(crypto_cipher_t)); - if (encrypt_mode) - r = crypto_cipher_encrypt_init_cipher(crypto); + if (key == NULL) + crypto_rand(env->key, CIPHER_KEY_LEN); + else + memcpy(env->key, key, CIPHER_KEY_LEN); + if (iv == NULL) + crypto_rand(env->iv, CIPHER_IV_LEN); else - r = crypto_cipher_decrypt_init_cipher(crypto); + memcpy(env->iv, iv, CIPHER_IV_LEN); - if (r) - goto error; - return crypto; + env->cipher = aes_new_cipher(env->key, env->iv); - error: - if (crypto) - crypto_cipher_free(crypto); - return NULL; + return env; } -/** Allocate and return a new symmetric cipher. - */ crypto_cipher_t * -crypto_cipher_new(void) +crypto_cipher_new(const char *key) { - crypto_cipher_t *env; - - env = tor_malloc_zero(sizeof(crypto_cipher_t)); - env->cipher = aes_new_cipher(); - return env; + char zeroiv[CIPHER_IV_LEN]; + memset(zeroiv, 0, sizeof(zeroiv)); + return crypto_cipher_new_with_iv(key, zeroiv); } /** Free a symmetric cipher. @@ -1043,12 +1033,8 @@ crypto_pk_public_hybrid_encrypt(crypto_pk_t *env, tor_assert(tolen >= fromlen + overhead + CIPHER_KEY_LEN); tor_assert(tolen >= pkeylen); - cipher = crypto_cipher_new(); - if (!cipher) return -1; - if (crypto_cipher_generate_key(cipher)<0) - goto err; - if (crypto_cipher_encrypt_init_cipher(cipher)<0) - goto err; + cipher = crypto_cipher_new(NULL); /* generate a new key. */ + buf = tor_malloc(pkeylen+1); memcpy(buf, cipher->key, CIPHER_KEY_LEN); memcpy(buf+CIPHER_KEY_LEN, from, pkeylen-overhead-CIPHER_KEY_LEN); @@ -1113,7 +1099,7 @@ crypto_pk_private_hybrid_decrypt(crypto_pk_t *env, "No room for a symmetric key"); goto err; } - cipher = crypto_create_init_cipher(buf, 0); + cipher = crypto_cipher_new(buf); if (!cipher) { goto err; } @@ -1301,49 +1287,6 @@ crypto_pk_check_fingerprint_syntax(const char *s) /* symmetric crypto */ -/** Generate a new random key for the symmetric cipher in <b>env</b>. - * Return 0 on success, -1 on failure. Does not initialize the cipher. - */ -int -crypto_cipher_generate_key(crypto_cipher_t *env) -{ - tor_assert(env); - - return crypto_rand(env->key, CIPHER_KEY_LEN); -} - -/** Set the symmetric key for the cipher in <b>env</b> to the first - * CIPHER_KEY_LEN bytes of <b>key</b>. Does not initialize the cipher. - */ -void -crypto_cipher_set_key(crypto_cipher_t *env, const char *key) -{ - tor_assert(env); - tor_assert(key); - - memcpy(env->key, key, CIPHER_KEY_LEN); -} - -/** 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) -{ - crypto_rand(iv_out, CIPHER_IV_LEN); -} - -/** 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_t *env, const char *iv) -{ - tor_assert(env); - tor_assert(iv); - aes_set_iv(env->cipher, iv); - return 0; -} - /** Return a pointer to the key set for the cipher in <b>env</b>. */ const char * @@ -1352,30 +1295,6 @@ crypto_cipher_get_key(crypto_cipher_t *env) return env->key; } -/** Initialize the cipher in <b>env</b> for encryption. Return 0 on - * success, -1 on failure. - */ -int -crypto_cipher_encrypt_init_cipher(crypto_cipher_t *env) -{ - tor_assert(env); - - aes_set_key(env->cipher, env->key, CIPHER_KEY_LEN*8); - return 0; -} - -/** Initialize the cipher in <b>env</b> for decryption. Return 0 on - * success, -1 on failure. - */ -int -crypto_cipher_decrypt_init_cipher(crypto_cipher_t *env) -{ - tor_assert(env); - - aes_set_key(env->cipher, env->key, CIPHER_KEY_LEN*8); - return 0; -} - /** Encrypt <b>fromlen</b> bytes from <b>from</b> using the cipher * <b>env</b>; on success, store the result to <b>to</b> and return 0. * On failure, return -1. @@ -1424,20 +1343,17 @@ crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len) } /** 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>key</b> to the buffer in <b>to</b> of length * <b>tolen</b>. <b>tolen</b> must be at least <b>fromlen</b> 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 <b>cipher</b> - * to immediately after the encrypted data. */ int -crypto_cipher_encrypt_with_iv(crypto_cipher_t *cipher, +crypto_cipher_encrypt_with_iv(const char *key, char *to, size_t tolen, const char *from, size_t fromlen) { - tor_assert(cipher); + crypto_cipher_t *cipher; tor_assert(from); tor_assert(to); tor_assert(fromlen < INT_MAX); @@ -1447,28 +1363,27 @@ crypto_cipher_encrypt_with_iv(crypto_cipher_t *cipher, if (tolen < fromlen + CIPHER_IV_LEN) return -1; - crypto_cipher_generate_iv(to); - if (crypto_cipher_set_iv(cipher, to)<0) - return -1; + cipher = crypto_cipher_new_with_iv(key, NULL); + + memcpy(to, cipher->iv, CIPHER_IV_LEN); crypto_cipher_encrypt(cipher, to+CIPHER_IV_LEN, from, fromlen); + crypto_cipher_free(cipher); return (int)(fromlen + CIPHER_IV_LEN); } /** 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 + * with the key in <b>key</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 * number of bytes written, on failure, return -1. - * - * This function adjusts the current position of the counter in <b>cipher</b> - * to immediately after the decrypted data. */ int -crypto_cipher_decrypt_with_iv(crypto_cipher_t *cipher, +crypto_cipher_decrypt_with_iv(const char *key, char *to, size_t tolen, const char *from, size_t fromlen) { - tor_assert(cipher); + crypto_cipher_t *cipher; + tor_assert(key); tor_assert(from); tor_assert(to); tor_assert(fromlen < INT_MAX); @@ -1478,9 +1393,10 @@ crypto_cipher_decrypt_with_iv(crypto_cipher_t *cipher, if (tolen < fromlen - CIPHER_IV_LEN) return -1; - if (crypto_cipher_set_iv(cipher, from)<0) - return -1; + cipher = crypto_cipher_new_with_iv(key, from); + crypto_cipher_encrypt(cipher, to, from+CIPHER_IV_LEN, fromlen-CIPHER_IV_LEN); + crypto_cipher_free(cipher); return (int)(fromlen - CIPHER_IV_LEN); } diff --git a/src/common/crypto.h b/src/common/crypto.h index 1c5ee0d23e..00ac26ba26 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -125,11 +125,8 @@ void crypto_pk_free(crypto_pk_t *env); void crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname); -/* convenience function: wraps crypto_cipher_new, set_key, and init. */ -crypto_cipher_t *crypto_create_init_cipher(const char *key, - int encrypt_mode); - -crypto_cipher_t *crypto_cipher_new(void); +crypto_cipher_t *crypto_cipher_new(const char *key); +crypto_cipher_t *crypto_cipher_new_with_iv(const char *key, const char *iv); void crypto_cipher_free(crypto_cipher_t *env); /* public key crypto */ @@ -189,13 +186,7 @@ int crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out,int add_space); int crypto_pk_check_fingerprint_syntax(const char *s); /* symmetric crypto */ -int crypto_cipher_generate_key(crypto_cipher_t *env); -void crypto_cipher_set_key(crypto_cipher_t *env, const char *key); -void crypto_cipher_generate_iv(char *iv_out); -int crypto_cipher_set_iv(crypto_cipher_t *env, const char *iv); const char *crypto_cipher_get_key(crypto_cipher_t *env); -int crypto_cipher_encrypt_init_cipher(crypto_cipher_t *env); -int crypto_cipher_decrypt_init_cipher(crypto_cipher_t *env); int crypto_cipher_encrypt(crypto_cipher_t *env, char *to, const char *from, size_t fromlen); @@ -203,10 +194,10 @@ int crypto_cipher_decrypt(crypto_cipher_t *env, char *to, const char *from, size_t fromlen); int crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *d, size_t len); -int crypto_cipher_encrypt_with_iv(crypto_cipher_t *env, +int crypto_cipher_encrypt_with_iv(const char *key, char *to, size_t tolen, const char *from, size_t fromlen); -int crypto_cipher_decrypt_with_iv(crypto_cipher_t *env, +int crypto_cipher_decrypt_with_iv(const char *key, char *to, size_t tolen, const char *from, size_t fromlen); |