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

Unified Diff: net/socket/nss_ssl_util.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: ... 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/nss_ssl_util.cc
diff --git a/net/socket/nss_ssl_util.cc b/net/socket/nss_ssl_util.cc
index 8547d4dc1cf493f167c4a2ebb731c809029870dc..48de03f6741157b64a846c962bd8dc9ce3343c74 100644
--- a/net/socket/nss_ssl_util.cc
+++ b/net/socket/nss_ssl_util.cc
@@ -13,6 +13,7 @@
#include <string>
#include "base/bind.h"
+#include "base/cpu.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
@@ -27,6 +28,59 @@
#include "base/win/windows_version.h"
#endif
+namespace {
+
+// 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;
+ }
+ }
+ }
wtc 2013/11/22 01:14:16 I think it is less work to reverse the nested for
agl 2013/11/22 17:53:49 Done.
+
+ 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--) {
wtc 2013/11/22 01:14:16 The i < num check looks wrong at first glance. You
agl 2013/11/22 17:53:49 Yes.
+ if (ciphers[i] == 0)
+ continue;
+ ciphers[j--] = ciphers[i];
+ }
+ return j+1;
wtc 2013/11/22 01:14:16 Nit: the Style Guide recommends spaces around '+'
agl 2013/11/22 17:53:49 Done.
+}
+
+// CiphersCopy copies the zero-terminated array |in| to |out|.
wtc 2013/11/22 01:14:16 Document the return value.
agl 2013/11/22 17:53:49 Done.
+size_t CiphersCopy(const uint16* in, uint16* out) {
+ for (size_t i = 0; ; i++) {
+ if (in[i] == 0)
+ return i;
+ out[i] = in[i];
+ }
+}
+
+} // anonymous namespace
+
+
wtc 2013/11/22 01:14:16 Nit: delete one blank line
agl 2013/11/22 17:53:49 Done.
namespace net {
class NSSSSLInitSingleton {
@@ -86,14 +140,64 @@ class NSSSSLInitSingleton {
// Enable SSL.
SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
+ // Calculate the order of ciphers that we'll use for NSS sockets. (Note
+ // that, even if a cipher is specified in the ordering, it won't be
+ // included if it is disabled.)
wtc 2013/11/22 01:14:16 "it won't be included if it is disabled" sounds wr
agl 2013/11/22 17:53:49 I really did mean that, but it's clearly confusing
+ //
+ // Our top preference cipher suites are either forward-secure AES-GCM or
+ // forward secure ChaCha20-Poly1305. If the local machine has AES-NI then
wtc 2013/11/22 01:14:16 Nit: forward secure => forward secret (two occurre
agl 2013/11/22 17:53:49 Done.
+ // 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 */,
wtc 2013/11/22 01:14:16 You should be able to use TLS_ECDHE_ECDSA_WITH_CHA
agl 2013/11/22 17:53:49 Done.
+ 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();
wtc 2013/11/22 01:14:16 Nit: put '*' next to the type. Also fix lines 171-
agl 2013/11/22 17:53:49 Done.
+ num_ciphers_ = SSL_GetNumImplementedCiphers();
+ ciphers_.reset(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_)) {
wtc 2013/11/22 01:14:16 Nit: We can pass the sizes of chacha_ciphers and a
agl 2013/11/22 17:53:49 By reordering the for loops in CiphersRemove, as y
+ CiphersCompact(ciphers_.get(), num_ciphers_);
+
+ const uint16 *preference_ciphers = chacha_ciphers;
+ const uint16 *other_ciphers = aes_gcm_ciphers;
+ if (base::CPU().has_aesni()) {
+ preference_ciphers = aes_gcm_ciphers;
+ other_ciphers = chacha_ciphers;
+ }
+ unsigned i = CiphersCopy(preference_ciphers, ciphers_.get());
+ CiphersCopy(other_ciphers, &ciphers_[i]);
+ } else {
+ ciphers_.reset();
+ num_ciphers_ = 0;
+ }
+
// All other SSL options are set per-session by SSLClientSocket and
// SSLServerSocket.
}
+ const uint16* GetNSSCipherOrder(size_t* out_length) {
+ *out_length = num_ciphers_;
+ return ciphers_.get();
+ }
+
~NSSSSLInitSingleton() {
// Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY.
SSL_ClearSessionCache();
}
+
+ private:
+ scoped_ptr<uint16[]> ciphers_;
+ size_t num_ciphers_;
};
static base::LazyInstance<NSSSSLInitSingleton> g_nss_ssl_init_singleton =
@@ -112,6 +216,10 @@ void EnsureNSSSSLInit() {
g_nss_ssl_init_singleton.Get();
}
+const uint16* GetNSSCipherOrder(size_t* out_length) {
+ return g_nss_ssl_init_singleton.Get().GetNSSCipherOrder(out_length);
+}
+
// Map a Chromium net error code to an NSS error code.
// See _MD_unix_map_default_error in the NSS source
// tree for inspiration.

Powered by Google App Engine
This is Rietveld 408576698