blob: a58b4641789d6e0059fb70ce04d8ca8783992965 [file] [log] [blame]
diff --git a/crypto/rsa_private_key.h b/crypto/rsa_private_key.h
index ff368d8..b8ce169 100644
--- a/crypto/rsa_private_key.h
+++ b/crypto/rsa_private_key.h
@@ -12,8 +12,8 @@
typedef struct evp_pkey_st EVP_PKEY;
#elif defined(USE_NSS)
// Forward declaration.
-struct SECKEYPrivateKeyStr;
-struct SECKEYPublicKeyStr;
+typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
+typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
#elif defined(OS_IOS)
#include <Security/Security.h>
#elif defined(OS_MACOSX)
@@ -200,6 +200,12 @@ class CRYPTO_EXPORT RSAPrivateKey {
static RSAPrivateKey* CreateSensitiveFromPrivateKeyInfo(
const std::vector<uint8>& input);
+#if defined(USE_NSS)
+ // Create a new instance by referencing an existing private key
+ // structure. Does not import the key.
+ static RSAPrivateKey* CreateFromKey(SECKEYPrivateKey* key);
+#endif
+
// Import an existing public key, and then search for the private
// half in the key database. The format of the public key blob is is
// an X509 SubjectPublicKeyInfo block. This can return NULL if
@@ -214,8 +220,8 @@ class CRYPTO_EXPORT RSAPrivateKey {
#if defined(USE_OPENSSL)
EVP_PKEY* key() { return key_; }
#elif defined(USE_NSS)
- SECKEYPrivateKeyStr* key() { return key_; }
- SECKEYPublicKeyStr* public_key() { return public_key_; }
+ SECKEYPrivateKey* key() { return key_; }
+ SECKEYPublicKey* public_key() { return public_key_; }
#elif defined(OS_WIN)
HCRYPTPROV provider() { return provider_; }
HCRYPTKEY key() { return key_; }
@@ -261,8 +267,8 @@ class CRYPTO_EXPORT RSAPrivateKey {
#if defined(USE_OPENSSL)
EVP_PKEY* key_;
#elif defined(USE_NSS)
- SECKEYPrivateKeyStr* key_;
- SECKEYPublicKeyStr* public_key_;
+ SECKEYPrivateKey* key_;
+ SECKEYPublicKey* public_key_;
#elif defined(OS_WIN)
bool InitProvider();
diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc
index 3b8bd44..ea2b432 100644
--- a/crypto/rsa_private_key_nss.cc
+++ b/crypto/rsa_private_key_nss.cc
@@ -81,6 +81,22 @@ RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
}
// static
+RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
+ DCHECK(key);
+ if (SECKEY_GetPrivateKeyType(key) != rsaKey)
+ return NULL;
+ RSAPrivateKey* copy = new RSAPrivateKey();
+ copy->key_ = SECKEY_CopyPrivateKey(key);
+ copy->public_key_ = SECKEY_ConvertToPublicKey(key);
+ if (!copy->key_ || !copy->public_key_) {
+ NOTREACHED();
+ delete copy;
+ return NULL;
+ }
+ return copy;
+}
+
+// static
RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
const std::vector<uint8>& input) {
EnsureNSSInit();
diff --git a/crypto/rsa_private_key_nss_unittest.cc b/crypto/rsa_private_key_nss_unittest.cc
index 0ec801d..66d352a 100644
--- a/crypto/rsa_private_key_nss_unittest.cc
+++ b/crypto/rsa_private_key_nss_unittest.cc
@@ -25,9 +25,32 @@ class RSAPrivateKeyNSSTest : public testing::Test {
}
private:
+ ScopedTestNSSDB test_nssdb_;
+
DISALLOW_COPY_AND_ASSIGN(RSAPrivateKeyNSSTest);
};
+TEST_F(RSAPrivateKeyNSSTest, CreateFromKeyTest) {
+ scoped_ptr<crypto::RSAPrivateKey> key_pair(RSAPrivateKey::Create(256));
+
+ scoped_ptr<crypto::RSAPrivateKey> key_copy(
+ RSAPrivateKey::CreateFromKey(key_pair->key()));
+ ASSERT_TRUE(key_copy.get());
+
+ std::vector<uint8> privkey;
+ std::vector<uint8> pubkey;
+ ASSERT_TRUE(key_pair->ExportPrivateKey(&privkey));
+ ASSERT_TRUE(key_pair->ExportPublicKey(&pubkey));
+
+ std::vector<uint8> privkey_copy;
+ std::vector<uint8> pubkey_copy;
+ ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy));
+ ASSERT_TRUE(key_copy->ExportPublicKey(&pubkey_copy));
+
+ ASSERT_EQ(privkey, privkey_copy);
+ ASSERT_EQ(pubkey, pubkey_copy);
+}
+
TEST_F(RSAPrivateKeyNSSTest, FindFromPublicKey) {
// Create a keypair, which will put the keys in the user's NSSDB.
scoped_ptr<crypto::RSAPrivateKey> key_pair(RSAPrivateKey::Create(256));