1 // Copyright 2015 The Chromium Authors. All rights reserved.
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"
11 #include "base/logging.h"
12 #include "base/stl_util.h"
13 #include "crypto/nss_util.h"
15 #if defined(USE_NSS_CERTS)
17 #include "crypto/nss_util_internal.h"
24 #if defined(USE_NSS_CERTS)
26 struct PublicKeyInfoDeleter
{
27 inline void operator()(CERTSubjectPublicKeyInfo
* spki
) {
28 SECKEY_DestroySubjectPublicKeyInfo(spki
);
32 typedef scoped_ptr
<CERTSubjectPublicKeyInfo
, PublicKeyInfoDeleter
>
35 // Decodes |input| as a SubjectPublicKeyInfo and returns a SECItem containing
36 // the CKA_ID of that public key or nullptr on error.
37 ScopedSECItem
MakeIDFromSPKI(const std::vector
<uint8_t>& input
) {
38 // First, decode and save the public key.
40 key_der
.type
= siBuffer
;
41 key_der
.data
= const_cast<unsigned char*>(vector_as_array(&input
));
42 key_der
.len
= input
.size();
44 ScopedPublicKeyInfo
spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der
));
48 ScopedSECKEYPublicKey
result(SECKEY_ExtractPublicKey(spki
.get()));
52 // See pk11_MakeIDFromPublicKey from NSS. For now, only RSA keys are
54 if (SECKEY_GetPublicKeyType(result
.get()) != rsaKey
)
57 return ScopedSECItem(PK11_MakeIDFromPubKey(&result
->u
.rsa
.modulus
));
60 #endif // defined(USE_NSS_CERTS)
64 bool GenerateRSAKeyPairNSS(PK11SlotInfo
* slot
,
67 ScopedSECKEYPublicKey
* public_key
,
68 ScopedSECKEYPrivateKey
* private_key
) {
71 PK11RSAGenParams param
;
72 param
.keySizeInBits
= num_bits
;
74 SECKEYPublicKey
* public_key_raw
= nullptr;
75 private_key
->reset(PK11_GenerateKeyPair(slot
, CKM_RSA_PKCS_KEY_PAIR_GEN
,
76 ¶m
, &public_key_raw
, permanent
,
77 permanent
/* sensitive */, nullptr));
81 public_key
->reset(public_key_raw
);
85 ScopedSECKEYPrivateKey
ImportNSSKeyFromPrivateKeyInfo(
87 const std::vector
<uint8_t>& input
,
91 ScopedPLArenaPool
arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE
));
94 // Excess data is illegal, but NSS silently accepts it, so first ensure that
95 // |input| consists of a single ASN.1 element.
97 input_item
.data
= const_cast<unsigned char*>(vector_as_array(&input
));
98 input_item
.len
= input
.size();
99 SECItem der_private_key_info
;
101 SEC_QuickDERDecodeItem(arena
.get(), &der_private_key_info
,
102 SEC_ASN1_GET(SEC_AnyTemplate
), &input_item
);
103 if (rv
!= SECSuccess
)
106 // Allow the private key to be used for key unwrapping, data decryption,
107 // and signature generation.
108 const unsigned int key_usage
=
109 KU_KEY_ENCIPHERMENT
| KU_DATA_ENCIPHERMENT
| KU_DIGITAL_SIGNATURE
;
110 SECKEYPrivateKey
* key_raw
= nullptr;
111 rv
= PK11_ImportDERPrivateKeyInfoAndReturnKey(
112 slot
, &der_private_key_info
, nullptr, nullptr, permanent
,
113 permanent
/* sensitive */, key_usage
, &key_raw
, nullptr);
114 if (rv
!= SECSuccess
)
116 return ScopedSECKEYPrivateKey(key_raw
);
119 #if defined(USE_NSS_CERTS)
121 ScopedSECKEYPrivateKey
FindNSSKeyFromPublicKeyInfo(
122 const std::vector
<uint8_t>& input
) {
125 ScopedSECItem
cka_id(MakeIDFromSPKI(input
));
129 // Search all slots in all modules for the key with the given ID.
130 AutoSECMODListReadLock auto_lock
;
131 const SECMODModuleList
* head
= SECMOD_GetDefaultModuleList();
132 for (const SECMODModuleList
* item
= head
; item
!= nullptr;
134 int slot_count
= item
->module
->loaded
? item
->module
->slotCount
: 0;
135 for (int i
= 0; i
< slot_count
; i
++) {
136 // Look for the key in slot |i|.
137 ScopedSECKEYPrivateKey
key(
138 PK11_FindKeyByKeyID(item
->module
->slots
[i
], cka_id
.get(), nullptr));
144 // The key wasn't found in any module.
148 ScopedSECKEYPrivateKey
FindNSSKeyFromPublicKeyInfoInSlot(
149 const std::vector
<uint8_t>& input
,
150 PK11SlotInfo
* slot
) {
153 ScopedSECItem
cka_id(MakeIDFromSPKI(input
));
157 return ScopedSECKEYPrivateKey(
158 PK11_FindKeyByKeyID(slot
, cka_id
.get(), nullptr));
161 #endif // defined(USE_NSS_CERTS)
163 } // namespace crypto