diff options
author | Nick Mathewson <nickm@torproject.org> | 2012-03-20 13:51:11 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2012-03-27 22:38:06 -0400 |
commit | 55c3e29669214e7a51b16c7273caf30b29079157 (patch) | |
tree | 5774574b5a3911257a4fba324fbd0eafcf1433b9 /src/common/aes.c | |
parent | de0dca0de76d9d50aeb5955fe3f435c6c190f8d7 (diff) | |
download | tor-55c3e29669214e7a51b16c7273caf30b29079157.tar.gz tor-55c3e29669214e7a51b16c7273caf30b29079157.zip |
Use OpenSSL 1.0.1's EVP aes_ctr implementation when available
This should be really fast on Intel chips.
Diffstat (limited to 'src/common/aes.c')
-rw-r--r-- | src/common/aes.c | 87 |
1 files changed, 84 insertions, 3 deletions
diff --git a/src/common/aes.c b/src/common/aes.c index 3121891068..c6bc2a821e 100644 --- a/src/common/aes.c +++ b/src/common/aes.c @@ -33,15 +33,35 @@ #define DISABLE_ENGINES #endif -/* We have 2 strategies for getting AES: Via OpenSSL's AES_encrypt function, - * via OpenSSL's EVP_EncryptUpdate function. +/* We have five strategies for implementing AES counter mode. + * + * Best with x86 and x86_64: Use EVP_aes_ctr128() and EVP_EncryptUpdate(). + * This is possible with OpenSSL 1.0.1, where the counter-mode implementation + * can use bit-sliced or vectorized AES or AESNI as appropriate. + * + * Otherwise: Pick the best possible AES block implementation that OpenSSL + * gives us, and the best possible counter-mode implementation, and combine + * them. + */ +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,0,1) && \ + (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(_M_AMD64) || defined(_M_X64) || defined(__INTEL__)) \ + +#define USE_EVP_AES_CTR + +#endif + +/* We have 2 strategies for getting the AES block cipher: Via OpenSSL's + * AES_encrypt function, or via OpenSSL's EVP_EncryptUpdate function. * * If there's any hardware acceleration in play, we want to be using EVP_* so * we can get it. Otherwise, we'll want AES_*, which seems to be about 5% * faster than indirecting through the EVP layer. */ -/* We have 2 strategies for counter mode: use our own, or use OpenSSL's. +/* We have 2 strategies for getting a plug-in counter mode: use our own, or + * use OpenSSL's. * * Here we have a counter mode that's faster than the one shipping with * OpenSSL pre-1.0 (by about 10%!). But OpenSSL 1.0.0 added a counter mode @@ -51,6 +71,66 @@ * make sure that we have a fixed version.) */ +#ifdef USE_EVP_AES_CTR + +struct aes_cnt_cipher { + EVP_CIPHER_CTX evp; +}; + +aes_cnt_cipher_t * +aes_new_cipher(const char *key, const char *iv) +{ + aes_cnt_cipher_t *cipher; + cipher = tor_malloc_zero(sizeof(aes_cnt_cipher_t)); + EVP_EncryptInit(&cipher->evp, EVP_aes_128_ctr(), + (const unsigned char*)key, (const unsigned char *)iv); + return cipher; +} +void +aes_cipher_free(aes_cnt_cipher_t *cipher) +{ + if (!cipher) + return; + EVP_CIPHER_CTX_cleanup(&cipher->evp); + memset(cipher, 0, sizeof(aes_cnt_cipher_t)); + tor_free(cipher); +} +void +aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, + char *output) +{ + int outl; + + tor_assert(len < INT_MAX); + + EVP_EncryptUpdate(&cipher->evp, (unsigned char*)output, + &outl, (const unsigned char *)input, (int)len); +} +void +aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) +{ + int outl; + + tor_assert(len < INT_MAX); + + EVP_EncryptUpdate(&cipher->evp, (unsigned char*)data, + &outl, (unsigned char*)data, (int)len); +} +int +evaluate_evp_for_aes(int force_val) +{ + (void) force_val; + log_notice(LD_CRYPTO, "This version of OpenSSL has a known-good EVP " + "counter-mode implementation. Using it."); + return 0; +} +int +evaluate_ctr_for_aes(void) +{ + return 0; +} +#else + /*======================================================================*/ /* Interface to AES code, and counter implementation */ @@ -424,3 +504,4 @@ aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv) _aes_fill_buf(cipher); } +#endif |