OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "crypto/nss_key_util.h" | |
6 | |
7 #include <cryptohi.h> | |
8 #include <keyhi.h> | |
9 #include <pk11pub.h> | |
10 | |
11 #include "base/logging.h" | |
12 #include "crypto/nss_util.h" | |
13 | |
14 #if defined(USE_NSS_CERTS) | |
15 #include <secmod.h> | |
16 #include "crypto/nss_util_internal.h" | |
17 #endif | |
18 | |
19 namespace crypto { | |
20 | |
21 namespace { | |
22 | |
23 #if defined(USE_NSS_CERTS) | |
24 | |
25 struct PublicKeyInfoDeleter { | |
26 inline void operator()(CERTSubjectPublicKeyInfo* spki) { | |
27 SECKEY_DestroySubjectPublicKeyInfo(spki); | |
28 } | |
29 }; | |
30 | |
31 typedef scoped_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter> | |
32 ScopedPublicKeyInfo; | |
33 | |
34 // Decodes |input| as a SubjectPublicKeyInfo and returns a SECItem containing | |
35 // the CKA_ID of that public key or null on error. | |
Ryan Sleevi
2015/04/27 19:11:27
s/null/nullptr/ (or NULL)
davidben
2015/04/27 19:53:44
Done.
| |
36 ScopedSECItem MakeIDFromSPKI(const std::vector<uint8_t> input) { | |
37 // First, decode and save the public key. | |
38 SECItem key_der; | |
39 key_der.type = siBuffer; | |
40 key_der.data = const_cast<unsigned char*>(&input[0]); | |
41 key_der.len = input.size(); | |
42 | |
43 ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der)); | |
44 if (!spki) | |
45 return nullptr; | |
46 | |
47 ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get())); | |
48 if (!result) | |
49 return nullptr; | |
50 | |
51 // See pk11_MakeIDFromPublicKey from NSS. | |
52 SECItem* pub_key_index; | |
53 switch (SECKEY_GetPublicKeyType(result.get())) { | |
54 case rsaKey: | |
55 pub_key_index = &result->u.rsa.modulus; | |
56 break; | |
57 default: | |
58 // Unsupported key type. | |
59 return nullptr; | |
60 } | |
61 | |
62 return ScopedSECItem(PK11_MakeIDFromPubKey(pub_key_index)); | |
63 } | |
64 | |
65 #endif // defined(USE_NSS_CERTS) | |
66 | |
67 } // namespace | |
68 | |
69 bool GenerateRSAKeyPairNSS(PK11SlotInfo* slot, | |
70 uint16_t num_bits, | |
71 bool permanent, | |
72 ScopedSECKEYPublicKey* out_public_key, | |
73 ScopedSECKEYPrivateKey* out_private_key) { | |
74 PK11RSAGenParams param; | |
75 param.keySizeInBits = num_bits; | |
76 param.pe = 65537L; | |
77 SECKEYPublicKey* public_key_raw; | |
78 ScopedSECKEYPrivateKey private_key(PK11_GenerateKeyPair( | |
79 slot, CKM_RSA_PKCS_KEY_PAIR_GEN, ¶m, &public_key_raw, permanent, | |
80 permanent /* sensitive */, nullptr)); | |
81 if (!private_key) | |
82 return false; | |
83 | |
84 out_public_key->reset(public_key_raw); | |
85 *out_private_key = private_key.Pass(); | |
86 return true; | |
87 } | |
88 | |
89 ScopedSECKEYPrivateKey ImportNSSKeyFromPrivateKeyInfo( | |
90 PK11SlotInfo* slot, | |
91 const std::vector<uint8_t>& input, | |
92 bool permanent) { | |
93 ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); | |
94 if (!arena) { | |
95 NOTREACHED(); | |
96 return nullptr; | |
97 } | |
98 | |
99 // Excess data is illegal, but NSS silently accepts it, so first ensure that | |
100 // |input| consists of a single ASN.1 element. | |
101 SECItem input_item; | |
102 input_item.data = const_cast<unsigned char*>(&input.front()); | |
103 input_item.len = input.size(); | |
104 SECItem der_private_key_info; | |
105 SECStatus rv = | |
106 SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info, | |
107 SEC_ASN1_GET(SEC_AnyTemplate), &input_item); | |
108 if (rv != SECSuccess) | |
109 return nullptr; | |
110 | |
111 // Allow the private key to be used for key unwrapping, data decryption, | |
112 // and signature generation. | |
113 const unsigned int key_usage = | |
114 KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE; | |
115 SECKEYPrivateKey* key_raw; | |
116 rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( | |
117 slot, &der_private_key_info, nullptr, nullptr, permanent, | |
118 permanent /* sensitive */, key_usage, &key_raw, nullptr); | |
119 if (rv != SECSuccess) | |
120 return nullptr; | |
121 return ScopedSECKEYPrivateKey(key_raw); | |
122 } | |
123 | |
124 #if defined(USE_NSS_CERTS) | |
125 | |
126 ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo( | |
127 const std::vector<uint8_t>& input) { | |
128 EnsureNSSInit(); | |
129 | |
130 ScopedSECItem cka_id(MakeIDFromSPKI(input)); | |
131 if (!cka_id) { | |
132 NOTREACHED(); | |
133 return nullptr; | |
134 } | |
135 | |
136 // Search all slots in all modules for the key with the given ID. | |
137 AutoSECMODListReadLock auto_lock; | |
138 SECMODModuleList* head = SECMOD_GetDefaultModuleList(); | |
139 for (SECMODModuleList* item = head; item != nullptr; item = item->next) { | |
140 int slot_count = item->module->loaded ? item->module->slotCount : 0; | |
141 for (int i = 0; i < slot_count; i++) { | |
142 // Look for the key in slot |i|. | |
143 ScopedSECKEYPrivateKey key( | |
144 PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr)); | |
145 if (key) | |
146 return key.Pass(); | |
147 } | |
148 } | |
149 | |
150 // The key wasn't found in any module. | |
151 return nullptr; | |
152 } | |
153 | |
154 ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfoInSlot( | |
155 const std::vector<uint8_t>& input, | |
156 PK11SlotInfo* slot) { | |
157 ScopedSECItem cka_id(MakeIDFromSPKI(input)); | |
158 if (!cka_id.get()) { | |
Ryan Sleevi
2015/04/27 19:11:27
s/.get()//
davidben
2015/04/27 19:53:44
Done.
| |
159 NOTREACHED(); | |
160 return nullptr; | |
161 } | |
162 | |
163 return ScopedSECKEYPrivateKey( | |
164 PK11_FindKeyByKeyID(slot, cka_id.get(), nullptr)); | |
165 } | |
166 | |
167 #endif // defined(USE_NSS_CERTS) | |
168 | |
169 } // namespace crypto | |
OLD | NEW |