summaryrefslogtreecommitdiffstats
path: root/crypto/rsa_private_key_nss.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/rsa_private_key_nss.cc')
-rw-r--r--crypto/rsa_private_key_nss.cc233
1 files changed, 207 insertions, 26 deletions
diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc
index 88e55fa..c9e6a87 100644
--- a/crypto/rsa_private_key_nss.cc
+++ b/crypto/rsa_private_key_nss.cc
@@ -7,6 +7,7 @@
#include <cryptohi.h>
#include <keyhi.h>
#include <pk11pub.h>
+#include <secmod.h>
#include <list>
@@ -14,8 +15,8 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
-#include "crypto/nss_key_util.h"
#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
#include "crypto/scoped_nss_types.h"
// TODO(rafaelw): Consider using NSS's ASN.1 encoder.
@@ -37,6 +38,37 @@ static bool ReadAttribute(SECKEYPrivateKey* key,
return true;
}
+#if defined(USE_NSS_CERTS)
+struct PublicKeyInfoDeleter {
+ inline void operator()(CERTSubjectPublicKeyInfo* spki) {
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ }
+};
+
+typedef scoped_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter>
+ ScopedPublicKeyInfo;
+
+// The function decodes RSA public key from the |input|.
+crypto::ScopedSECKEYPublicKey GetRSAPublicKey(const std::vector<uint8>& input) {
+ // First, decode and save the public key.
+ SECItem key_der;
+ key_der.type = siBuffer;
+ key_der.data = const_cast<unsigned char*>(&input[0]);
+ key_der.len = input.size();
+
+ ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der));
+ if (!spki)
+ return crypto::ScopedSECKEYPublicKey();
+
+ crypto::ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get()));
+
+ // Make sure the key is an RSA key.. If not, that's an error.
+ if (!result || result->keyType != rsaKey)
+ return crypto::ScopedSECKEYPublicKey();
+ return result.Pass();
+}
+#endif // defined(USE_NSS_CERTS)
+
} // namespace
namespace crypto {
@@ -53,22 +85,10 @@ RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
EnsureNSSInit();
ScopedPK11Slot slot(PK11_GetInternalSlot());
- if (!slot) {
- NOTREACHED();
- return nullptr;
- }
-
- ScopedSECKEYPublicKey public_key;
- ScopedSECKEYPrivateKey private_key;
- if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */,
- &public_key, &private_key)) {
- return nullptr;
- }
-
- RSAPrivateKey* rsa_key = new RSAPrivateKey;
- rsa_key->public_key_ = public_key.release();
- rsa_key->key_ = private_key.release();
- return rsa_key;
+ return CreateWithParams(slot.get(),
+ num_bits,
+ false /* not permanent */,
+ false /* not sensitive */);
}
// static
@@ -77,15 +97,11 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
EnsureNSSInit();
ScopedPK11Slot slot(PK11_GetInternalSlot());
- if (!slot) {
- NOTREACHED();
- return nullptr;
- }
- ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo(
- slot.get(), input, false /* not permanent */));
- if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey)
- return nullptr;
- return RSAPrivateKey::CreateFromKey(key.get());
+ return CreateFromPrivateKeyInfoWithParams(
+ slot.get(),
+ input,
+ false /* not permanent */,
+ false /* not sensitive */);
}
// static
@@ -104,6 +120,83 @@ RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
return copy;
}
+#if defined(USE_NSS_CERTS)
+// static
+RSAPrivateKey* RSAPrivateKey::CreateSensitive(PK11SlotInfo* slot,
+ uint16 num_bits) {
+ return CreateWithParams(slot,
+ num_bits,
+ true /* permanent */,
+ true /* sensitive */);
+}
+
+// static
+RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
+ PK11SlotInfo* slot,
+ const std::vector<uint8>& input) {
+ return CreateFromPrivateKeyInfoWithParams(slot,
+ input,
+ true /* permanent */,
+ true /* sensitive */);
+}
+
+// static
+RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
+ const std::vector<uint8>& input) {
+ scoped_ptr<RSAPrivateKey> result(InitPublicPart(input));
+ if (!result)
+ return NULL;
+
+ ScopedSECItem ck_id(
+ PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)));
+ if (!ck_id.get()) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ // Search all slots in all modules for the key with the given ID.
+ AutoSECMODListReadLock auto_lock;
+ SECMODModuleList* head = SECMOD_GetDefaultModuleList();
+ for (SECMODModuleList* item = head; item != NULL; item = item->next) {
+ int slot_count = item->module->loaded ? item->module->slotCount : 0;
+ for (int i = 0; i < slot_count; i++) {
+ // Finally...Look for the key!
+ result->key_ = PK11_FindKeyByKeyID(item->module->slots[i],
+ ck_id.get(), NULL);
+ if (result->key_)
+ return result.release();
+ }
+ }
+
+ // We didn't find the key.
+ return NULL;
+}
+
+// static
+RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfoInSlot(
+ const std::vector<uint8>& input,
+ PK11SlotInfo* slot) {
+ if (!slot)
+ return NULL;
+
+ scoped_ptr<RSAPrivateKey> result(InitPublicPart(input));
+ if (!result)
+ return NULL;
+
+ ScopedSECItem ck_id(
+ PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)));
+ if (!ck_id.get()) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ result->key_ = PK11_FindKeyByKeyID(slot, ck_id.get(), NULL);
+ if (!result->key_)
+ return NULL;
+ return result.release();
+}
+#endif
+
RSAPrivateKey* RSAPrivateKey::Copy() const {
RSAPrivateKey* copy = new RSAPrivateKey();
copy->key_ = SECKEY_CopyPrivateKey(key_);
@@ -148,4 +241,92 @@ RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
EnsureNSSInit();
}
+// static
+RSAPrivateKey* RSAPrivateKey::CreateWithParams(PK11SlotInfo* slot,
+ uint16 num_bits,
+ bool permanent,
+ bool sensitive) {
+ if (!slot)
+ return NULL;
+
+ scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
+
+ PK11RSAGenParams param;
+ param.keySizeInBits = num_bits;
+ param.pe = 65537L;
+ result->key_ = PK11_GenerateKeyPair(slot,
+ CKM_RSA_PKCS_KEY_PAIR_GEN,
+ &param,
+ &result->public_key_,
+ permanent,
+ sensitive,
+ NULL);
+ if (!result->key_)
+ return NULL;
+
+ return result.release();
+}
+
+// static
+RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
+ PK11SlotInfo* slot,
+ const std::vector<uint8>& input,
+ bool permanent,
+ bool sensitive) {
+ if (!slot)
+ return NULL;
+
+ scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
+
+ ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+ if (!arena) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ // Excess data is illegal, but NSS silently accepts it, so first ensure that
+ // |input| consists of a single ASN.1 element.
+ SECItem input_item;
+ input_item.data = const_cast<unsigned char*>(&input.front());
+ input_item.len = input.size();
+ SECItem der_private_key_info;
+ SECStatus rv = SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info,
+ SEC_ASN1_GET(SEC_AnyTemplate),
+ &input_item);
+ if (rv != SECSuccess)
+ return NULL;
+
+ // Allow the private key to be used for key unwrapping, data decryption,
+ // and signature generation.
+ const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT |
+ KU_DIGITAL_SIGNATURE;
+ rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
+ slot, &der_private_key_info, NULL, NULL, permanent, sensitive,
+ key_usage, &result->key_, NULL);
+ if (rv != SECSuccess)
+ return NULL;
+
+ result->public_key_ = SECKEY_ConvertToPublicKey(result->key_);
+ if (!result->public_key_)
+ return NULL;
+
+ return result.release();
+}
+
+#if defined(USE_NSS_CERTS)
+// static
+RSAPrivateKey* RSAPrivateKey::InitPublicPart(const std::vector<uint8>& input) {
+ EnsureNSSInit();
+
+ scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey());
+ result->public_key_ = GetRSAPublicKey(input).release();
+ if (!result->public_key_) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ return result.release();
+}
+#endif // defined(USE_NSS_CERTS)
+
} // namespace crypto