Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(568)

Unified Diff: net/socket/ssl_client_socket_nss.cc

Issue 75663004: net: boost AES-GCM ciphers if the machine has AES-NI. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove unused variable Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/socket/ssl_client_socket_nss.cc
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 60f03240ab9e07f0496a1ffd71a6ec0c5cab599a..13c33950ac851582b6dd7d34d3a7c635b606df23 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -68,6 +68,7 @@
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
+#include "base/cpu.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
@@ -490,6 +491,55 @@ int MapNSSClientHandshakeError(PRErrorCode err) {
}
}
+// CiphersRemove takes a zero-terminated array of cipher suite ids in
+// |to_remove| and sets every instance of them in |ciphers| to zero. It returns
+// true if it found and removed every element of |to_remove|. It assumes that
+// there are no duplicates in |ciphers| nor in |to_remove|.
+bool CiphersRemove(const uint16* to_remove, uint16* ciphers, size_t num) {
+ size_t num_remove, found = 0;
+
+ for (num_remove = 0; ; num_remove++) {
+ if (to_remove[num_remove] == 0)
+ break;
+ }
+
+ for (size_t i = 0; i < num; i++) {
+ for (size_t j = 0; j < num_remove; j++) {
+ if (to_remove[j] == ciphers[i]) {
+ ciphers[i] = 0;
+ found++;
+ break;
+ }
+ }
+ }
+
+ return found == num_remove;
+}
+
+// CiphersCompact takes an array of cipher suite ids in |ciphers|, where some
+// entries are zero, and moves the entries so that all the non-zero elements
+// are compacted at the end of the array.
+size_t CiphersCompact(uint16* ciphers, size_t num) {
+ size_t j = num - 1;
+
+ for (size_t i = num - 1; i < num; i--) {
+ printf("@%u %d %u\n", (unsigned) i, ciphers[i], (unsigned) j);
+ if (ciphers[i] == 0)
+ continue;
+ ciphers[j--] = ciphers[i];
+ }
+ return j+1;
+}
+
+// CiphersCopy copies the zero-terminated array |in| to |out|.
+size_t CiphersCopy(const uint16* in, uint16* out) {
+ for (size_t i = 0; ; i++) {
+ if (in[i] == 0)
+ return i;
+ out[i] = in[i];
+ }
+}
+
} // namespace
// SSLClientSocketNSS::Core provides a thread-safe, ref-counted core that is
@@ -3118,6 +3168,45 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
}
+ /* Our top preference cipher suites are either forward-secure AES-GCM or
+ * forward secure ChaCha20-Poly1305. If the local machine has AES-NI then we
+ * prefer AES-GCM, otherwise ChaCha20. The remainder of the cipher suite
+ * preference is inheriented from NSS. */
+ static const uint16 chacha_ciphers[] = {
+ 0xcc14 /* TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 */,
+ 0xcc13 /* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 */,
+ 0,
+ };
+ static const uint16 aes_gcm_ciphers[] = {
+ 0xc02b /* TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 */,
+ 0xc02f /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */,
+ 0x9e /* TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 */,
+ 0,
+ };
+ const PRUint16 *all_ciphers = SSL_GetImplementedCiphers();
+ const size_t num_ciphers = SSL_GetNumImplementedCiphers();
+ scoped_ptr<uint16[]> ciphers(new uint16[num_ciphers]);
+ memcpy(ciphers.get(), all_ciphers, sizeof(uint16)*num_ciphers);
+
+ if (CiphersRemove(chacha_ciphers, ciphers.get(), num_ciphers) &&
+ CiphersRemove(aes_gcm_ciphers, ciphers.get(), num_ciphers)) {
+ CiphersCompact(ciphers.get(), num_ciphers);
+
+ const uint16 *preference_ciphers = chacha_ciphers;
+ const uint16 *other_ciphers = aes_gcm_ciphers;
+ if (base::CPU().has_aesni()) {
wtc 2013/11/19 23:00:44 Since this won't change over time, we should ideal
agl 2013/11/20 18:21:07 Done.
+ preference_ciphers = aes_gcm_ciphers;
+ other_ciphers = chacha_ciphers;
+ }
+ unsigned i = CiphersCopy(preference_ciphers, ciphers.get());
+ CiphersCopy(other_ciphers, &ciphers[i]);
+
+ rv = SSL_CipherOrderSet(nss_fd_, ciphers.get(), num_ciphers);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_CipherOrderSet", "");
+ }
+ }
+
// Support RFC 5077
rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
if (rv != SECSuccess) {

Powered by Google App Engine
This is Rietveld 408576698