1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "crypto/nss_key_util.h"
16 #include "base/logging.h"
17 #include "crypto/nss_util.h"
18 #include "crypto/nss_util_internal.h"
22 crypto::ScopedSECItem MakeNssIdFromPublicKey(SECKEYPublicKey* public_key) {
25 // See pk11_MakeIDFromPublicKey from NSS. For now, only RSA and EC public_keys
27 if (SECKEY_GetPublicKeyType(public_key) == rsaKey) {
28 return crypto::ScopedSECItem(
29 PK11_MakeIDFromPubKey(&public_key->u.rsa.modulus));
31 if (SECKEY_GetPublicKeyType(public_key) == ecKey) {
32 return crypto::ScopedSECItem(
33 PK11_MakeIDFromPubKey(&public_key->u.ec.publicValue));
38 ScopedSECItem MakeNssIdFromSpki(base::span<const uint8_t> input) {
39 ScopedCERTSubjectPublicKeyInfo spki = DecodeSubjectPublicKeyInfoNSS(input);
44 ScopedSECKEYPublicKey public_key(SECKEY_ExtractPublicKey(spki.get()));
49 return MakeNssIdFromPublicKey(public_key.get());
52 bool GenerateRSAKeyPairNSS(PK11SlotInfo* slot,
55 ScopedSECKEYPublicKey* public_key,
56 ScopedSECKEYPrivateKey* private_key) {
59 PK11RSAGenParams param;
60 param.keySizeInBits = num_bits;
62 SECKEYPublicKey* public_key_raw = nullptr;
63 private_key->reset(PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
64 ¶m, &public_key_raw, permanent,
65 permanent /* sensitive */, nullptr));
70 public_key->reset(public_key_raw);
74 bool GenerateECKeyPairNSS(PK11SlotInfo* slot,
75 const SECOidTag named_curve,
77 ScopedSECKEYPublicKey* public_key,
78 ScopedSECKEYPrivateKey* private_key) {
81 if (named_curve != SEC_OID_ANSIX962_EC_PRIME256V1) {
82 LOG(ERROR) << "SECOidTag: " << named_curve
83 << " is not supported. Only SEC_OID_ANSIX962_EC_PRIME256V1 is "
84 "supported for elliptic curve key pair generation.";
88 SECOidData* oid_data = SECOID_FindOIDByTag(named_curve);
90 LOG(ERROR) << "SECOID_FindOIDByTag: " << PORT_GetError();
94 std::vector<uint8_t> parameters_buf(2 + oid_data->oid.len);
95 SECKEYECParams ec_parameters = {siDEROID, parameters_buf.data(),
96 static_cast<unsigned>(parameters_buf.size())};
98 ec_parameters.data[0] = SEC_ASN1_OBJECT_ID;
99 ec_parameters.data[1] = oid_data->oid.len;
100 memcpy(ec_parameters.data + 2, oid_data->oid.data, oid_data->oid.len);
101 SECKEYPublicKey* public_key_raw = nullptr;
102 private_key->reset(PK11_GenerateKeyPair(slot, CKM_EC_KEY_PAIR_GEN,
103 &ec_parameters, &public_key_raw,
104 permanent, permanent, nullptr));
109 public_key->reset(public_key_raw);
113 ScopedSECKEYPrivateKey ImportNSSKeyFromPrivateKeyInfo(
115 base::span<const uint8_t> input,
119 ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
122 // Excess data is illegal, but NSS silently accepts it, so first ensure that
123 // |input| consists of a single ASN.1 element.
125 input_item.data = const_cast<unsigned char*>(input.data());
126 input_item.len = input.size();
127 SECItem der_private_key_info;
129 SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info,
130 SEC_ASN1_GET(SEC_AnyTemplate), &input_item);
131 if (rv != SECSuccess) {
135 // Allow the private key to be used for key unwrapping, data decryption,
136 // and signature generation.
137 const unsigned int key_usage =
138 KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
139 SECKEYPrivateKey* key_raw = nullptr;
140 rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
141 slot, &der_private_key_info, nullptr, nullptr, permanent,
142 permanent /* sensitive */, key_usage, &key_raw, nullptr);
143 if (rv != SECSuccess) {
146 return ScopedSECKEYPrivateKey(key_raw);
149 ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo(
150 base::span<const uint8_t> input) {
153 ScopedSECItem cka_id(MakeNssIdFromSpki(input));
158 // Search all slots in all modules for the key with the given ID.
159 AutoSECMODListReadLock auto_lock;
160 const SECMODModuleList* head = SECMOD_GetDefaultModuleList();
161 for (const SECMODModuleList* item = head; item != nullptr;
163 int slot_count = item->module->loaded ? item->module->slotCount : 0;
164 for (int i = 0; i < slot_count; i++) {
165 // Look for the key in slot |i|.
166 ScopedSECKEYPrivateKey key(
167 PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr));
174 // The key wasn't found in any module.
178 ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfoInSlot(
179 base::span<const uint8_t> input,
180 PK11SlotInfo* slot) {
183 ScopedSECItem cka_id(MakeNssIdFromSpki(input));
188 return ScopedSECKEYPrivateKey(
189 PK11_FindKeyByKeyID(slot, cka_id.get(), nullptr));
192 ScopedCERTSubjectPublicKeyInfo DecodeSubjectPublicKeyInfoNSS(
193 base::span<const uint8_t> input) {
194 // First, decode and save the public key.
196 key_der.type = siBuffer;
197 key_der.data = const_cast<unsigned char*>(input.data());
198 key_der.len = input.size();
200 ScopedCERTSubjectPublicKeyInfo spki(
201 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der));
205 } // namespace crypto