aboutsummaryrefslogtreecommitdiff
path: root/src/common/aes.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-03-20 13:51:11 -0400
committerNick Mathewson <nickm@torproject.org>2012-03-27 22:38:06 -0400
commit55c3e29669214e7a51b16c7273caf30b29079157 (patch)
tree5774574b5a3911257a4fba324fbd0eafcf1433b9 /src/common/aes.c
parentde0dca0de76d9d50aeb5955fe3f435c6c190f8d7 (diff)
downloadtor-55c3e29669214e7a51b16c7273caf30b29079157.tar
tor-55c3e29669214e7a51b16c7273caf30b29079157.tar.gz
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.c87
1 files changed, 84 insertions, 3 deletions
diff --git a/src/common/aes.c b/src/common/aes.c
index 312189106..c6bc2a821 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