[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