Index: crypto/ec_private_key_nss.cc |
diff --git a/crypto/ec_private_key_nss.cc b/crypto/ec_private_key_nss.cc |
index c6c476325bb7b52ed7ee4ff0013e6346e2244559..9bb9df124e497ca4a3c6077bbc88575bd6f16729 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; |