[tor-commits] [tor/master] Use OpenSSL 1.0.1's EVP aes_ctr implementation when available
nickm at torproject.org
nickm at torproject.org
Wed Mar 28 02:39:12 UTC 2012
commit 55c3e29669214e7a51b16c7273caf30b29079157
Author: Nick Mathewson <nickm at torproject.org>
Date: Tue Mar 20 13:51:11 2012 -0400
Use OpenSSL 1.0.1's EVP aes_ctr implementation when available
This should be really fast on Intel chips.
---
changes/openssl101_aes | 6 +++
src/common/aes.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 90 insertions(+), 3 deletions(-)
diff --git a/changes/openssl101_aes b/changes/openssl101_aes
new file mode 100644
index 0000000..565a48d
--- /dev/null
+++ b/changes/openssl101_aes
@@ -0,0 +1,6 @@
+ o Major features (performance):
+ - When built to use the newly OpenSSL 1.0.1, and built for an x86 or
+ x86_64 instruction set, take advantage of OpenSSL's AESNI, bitsliced,
+ or vectorized AES implementations as appropriate. These can be
+ much, much faster than other AES implementations.
+
diff --git a/src/common/aes.c b/src/common/aes.c
index 3121891..c6bc2a8 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
More information about the tor-commits
mailing list