diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-09 23:12:14 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-09 23:12:14 +0000 |
commit | ab782c97959278a043adb66edec252b5cd83f3cc (patch) | |
tree | 0bfd6ce06ea5aea556d36b26c85b88b0eaa7a501 | |
parent | 228b038f0a4b4a5fc3ac68f94b97d1a8df63dad8 (diff) | |
download | chromium_src-ab782c97959278a043adb66edec252b5cd83f3cc.zip chromium_src-ab782c97959278a043adb66edec252b5cd83f3cc.tar.gz chromium_src-ab782c97959278a043adb66edec252b5cd83f3cc.tar.bz2 |
NSS Channel ID: don't check ECC support on every socket creation.
Add static function to ECPrivateKey to get which NSS slot it uses.
BUG=127506
Review URL: https://chromiumcodereview.appspot.com/10700099
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@145777 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | crypto/ec_private_key.h | 5 | ||||
-rw-r--r-- | crypto/ec_private_key_nss.cc | 38 | ||||
-rw-r--r-- | crypto/ec_private_key_openssl.cc | 7 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 11 |
4 files changed, 49 insertions, 12 deletions
diff --git a/crypto/ec_private_key.h b/crypto/ec_private_key.h index 44f754b..bfd0862 100644 --- a/crypto/ec_private_key.h +++ b/crypto/ec_private_key.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -34,6 +34,9 @@ class CRYPTO_EXPORT ECPrivateKey { public: ~ECPrivateKey(); + // Returns whether the system supports elliptic curve cryptography. + static bool IsSupported(); + // Creates a new random instance. Can return NULL if initialization fails. // The created key will use the NIST P-256 curve. // TODO(mattm): Add a curve parameter. diff --git a/crypto/ec_private_key_nss.cc b/crypto/ec_private_key_nss.cc index c6c4763..9bb9df1 100644 --- a/crypto/ec_private_key_nss.cc +++ b/crypto/ec_private_key_nss.cc @@ -15,6 +15,7 @@ extern "C" { #include <pk11pub.h> #include <secmod.h> +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "crypto/nss_util.h" @@ -24,6 +25,34 @@ extern "C" { namespace { +PK11SlotInfo* GetKeySlot() { + return crypto::GetPublicNSSKeySlot(); +} + +class EllipticCurveSupportChecker { + public: + EllipticCurveSupportChecker() { + // NOTE: we can do this check here only because we use the NSS internal + // slot. If we support other slots in the future, checking whether they + // support ECDSA may block NSS, and the value may also change as devices are + // inserted/removed, so we would need to re-check on every use. + crypto::EnsureNSSInit(); + crypto::ScopedPK11Slot slot(GetKeySlot()); + supported_ = PK11_DoesMechanism(slot.get(), CKM_EC_KEY_PAIR_GEN) && + PK11_DoesMechanism(slot.get(), CKM_ECDSA); + } + + bool Supported() { + return supported_; + } + + private: + bool supported_; +}; + +static base::LazyInstance<EllipticCurveSupportChecker>::Leaky + g_elliptic_curve_supported = LAZY_INSTANCE_INITIALIZER; + // Copied from rsa_private_key_nss.cc. static bool ReadAttribute(SECKEYPrivateKey* key, CK_ATTRIBUTE_TYPE type, @@ -53,6 +82,11 @@ ECPrivateKey::~ECPrivateKey() { } // static +bool ECPrivateKey::IsSupported() { + return g_elliptic_curve_supported.Get().Supported(); +} + +// static ECPrivateKey* ECPrivateKey::Create() { return CreateWithParams(PR_FALSE /* not permanent */, PR_FALSE /* not sensitive */); @@ -114,7 +148,7 @@ bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( bool sensitive, SECKEYPrivateKey** key, SECKEYPublicKey** public_key) { - ScopedPK11Slot slot(GetPublicNSSKeySlot()); + ScopedPK11Slot slot(GetKeySlot()); if (!slot.get()) return false; @@ -247,7 +281,7 @@ ECPrivateKey* ECPrivateKey::CreateWithParams(bool permanent, scoped_ptr<ECPrivateKey> result(new ECPrivateKey); - ScopedPK11Slot slot(GetPrivateNSSKeySlot()); + ScopedPK11Slot slot(GetKeySlot()); if (!slot.get()) return NULL; diff --git a/crypto/ec_private_key_openssl.cc b/crypto/ec_private_key_openssl.cc index 40e6f04..20214e6 100644 --- a/crypto/ec_private_key_openssl.cc +++ b/crypto/ec_private_key_openssl.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,6 +11,11 @@ namespace crypto { ECPrivateKey::~ECPrivateKey() {} // static +bool ECPrivateKey::IsSupported() { + return false; +} + +// static ECPrivateKey* ECPrivateKey::Create() { NOTIMPLEMENTED(); return NULL; diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index c303829..8d677ef 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -1074,13 +1074,7 @@ bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket, } if (ssl_config_.channel_id_enabled) { - // TODO(mattm): we can do this check on the network task runner only because - // we use the NSS internal slot. If we support other slots in the future, - // checking whether they support ECDSA may block NSS, and thus this check - // would have to be moved to the NSS task runner. - crypto::ScopedPK11Slot slot(crypto::GetPublicNSSKeySlot()); - if (PK11_DoesMechanism(slot.get(), CKM_EC_KEY_PAIR_GEN) && - PK11_DoesMechanism(slot.get(), CKM_ECDSA)) { + if (crypto::ECPrivateKey::IsSupported()) { rv = SSL_SetClientChannelIDCallback( nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this); if (rv != SECSuccess) @@ -2523,7 +2517,8 @@ void SSLClientSocketNSS::Core::RecordChannelIDSupport() const { } supported = DISABLED; if (channel_id_xtn_negotiated_) supported = CLIENT_AND_SERVER; - else if (ssl_config_.channel_id_enabled) + else if (ssl_config_.channel_id_enabled && + crypto::ECPrivateKey::IsSupported()) supported = CLIENT_ONLY; UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported, DOMAIN_BOUND_CERT_USAGE_MAX); |