OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "crypto/rsa_private_key.h" | 5 #include "crypto/rsa_private_key.h" |
6 | 6 |
7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
8 #include <keyhi.h> | 8 #include <keyhi.h> |
9 #include <pk11pub.h> | 9 #include <pk11pub.h> |
10 | 10 |
11 #include <list> | 11 #include <list> |
12 | 12 |
13 #include "base/debug/leak_annotations.h" | 13 #include "base/debug/leak_annotations.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
17 #include "crypto/nss_util.h" | 17 #include "crypto/nss_util.h" |
18 #include "crypto/nss_util_internal.h" | 18 #include "crypto/nss_util_internal.h" |
19 #include "crypto/scoped_nss_types.h" | |
19 | 20 |
20 // TODO(rafaelw): Consider refactoring common functions and definitions from | 21 // TODO(rafaelw): Consider refactoring common functions and definitions from |
21 // rsa_private_key_win.cc or using NSS's ASN.1 encoder. | 22 // rsa_private_key_win.cc or using NSS's ASN.1 encoder. |
22 namespace { | 23 namespace { |
23 | 24 |
24 static bool ReadAttribute(SECKEYPrivateKey* key, | 25 static bool ReadAttribute(SECKEYPrivateKey* key, |
25 CK_ATTRIBUTE_TYPE type, | 26 CK_ATTRIBUTE_TYPE type, |
26 std::vector<uint8>* output) { | 27 std::vector<uint8>* output) { |
27 SECItem item; | 28 SECItem item; |
28 SECStatus rv; | 29 SECStatus rv; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 EnsureNSSInit(); | 85 EnsureNSSInit(); |
85 | 86 |
86 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); | 87 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
87 | 88 |
88 // First, decode and save the public key. | 89 // First, decode and save the public key. |
89 SECItem key_der; | 90 SECItem key_der; |
90 key_der.type = siBuffer; | 91 key_der.type = siBuffer; |
91 key_der.data = const_cast<unsigned char*>(&input[0]); | 92 key_der.data = const_cast<unsigned char*>(&input[0]); |
92 key_der.len = input.size(); | 93 key_der.len = input.size(); |
93 | 94 |
94 CERTSubjectPublicKeyInfo *spki = | 95 CERTSubjectPublicKeyInfo* spki = |
95 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der); | 96 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der); |
96 if (!spki) { | 97 if (!spki) { |
97 NOTREACHED(); | 98 NOTREACHED(); |
98 return NULL; | 99 return NULL; |
99 } | 100 } |
100 | 101 |
101 result->public_key_ = SECKEY_ExtractPublicKey(spki); | 102 result->public_key_ = SECKEY_ExtractPublicKey(spki); |
102 SECKEY_DestroySubjectPublicKeyInfo(spki); | 103 SECKEY_DestroySubjectPublicKeyInfo(spki); |
103 if (!result->public_key_) { | 104 if (!result->public_key_) { |
104 NOTREACHED(); | 105 NOTREACHED(); |
105 return NULL; | 106 return NULL; |
106 } | 107 } |
107 | 108 |
108 // Now, look for the associated private key in the user's | |
109 // hardware-backed NSS DB. If it's not there, consider that an | |
110 // error. | |
111 PK11SlotInfo *slot = GetPrivateNSSKeySlot(); | |
112 if (!slot) { | |
113 NOTREACHED(); | |
114 return NULL; | |
115 } | |
116 | |
117 // Make sure the key is an RSA key. If not, that's an error | 109 // Make sure the key is an RSA key. If not, that's an error |
118 if (result->public_key_->keyType != rsaKey) { | 110 if (result->public_key_->keyType != rsaKey) { |
119 PK11_FreeSlot(slot); | |
120 NOTREACHED(); | 111 NOTREACHED(); |
121 return NULL; | 112 return NULL; |
122 } | 113 } |
123 | 114 |
124 SECItem *ck_id = PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)); | 115 ScopedSECItem ck_id( |
125 if (!ck_id) { | 116 PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus))); |
126 PK11_FreeSlot(slot); | 117 if (!ck_id.get()) { |
118 NOTREACHED(); | |
119 return NULL; | |
120 } | |
121 | |
122 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); | |
123 if (!slot.get()) { | |
127 NOTREACHED(); | 124 NOTREACHED(); |
128 return NULL; | 125 return NULL; |
129 } | 126 } |
130 | 127 |
131 // Finally...Look for the key! | 128 // Finally...Look for the key! |
132 result->key_ = PK11_FindKeyByKeyID(slot, ck_id, NULL); | 129 result->key_ = PK11_FindKeyByKeyID(slot.get(), ck_id.get(), NULL); |
133 | 130 |
134 // Cleanup... | 131 // If we don't find the matching key in the private slot, then we |
135 PK11_FreeSlot(slot); | 132 // look in the public slot. |
136 SECITEM_FreeItem(ck_id, PR_TRUE); | 133 if (!result->key_) { |
134 slot.reset(GetPublicNSSKeySlot()); | |
wtc
2011/05/25 23:34:01
If the computer doesn't have a TPM, GetPrivateNSSK
| |
135 if (!slot.get()) { | |
136 NOTREACHED(); | |
137 return NULL; | |
138 } | |
139 result->key_ = PK11_FindKeyByKeyID(slot.get(), ck_id.get(), NULL); | |
140 } | |
137 | 141 |
138 // If we didn't find it, that's ok. | 142 // If we didn't find it, that's ok. |
139 if (!result->key_) | 143 if (!result->key_) |
140 return NULL; | 144 return NULL; |
141 | 145 |
142 return result.release(); | 146 return result.release(); |
143 } | 147 } |
144 | 148 |
145 | 149 |
146 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { | 150 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { |
(...skipping 12 matching lines...) Expand all Loading... | |
159 !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || | 163 !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || |
160 !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { | 164 !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { |
161 NOTREACHED(); | 165 NOTREACHED(); |
162 return false; | 166 return false; |
163 } | 167 } |
164 | 168 |
165 return private_key_info.Export(output); | 169 return private_key_info.Export(output); |
166 } | 170 } |
167 | 171 |
168 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { | 172 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { |
169 SECItem* der_pubkey = SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_); | 173 ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_)); |
170 if (!der_pubkey) { | 174 if (!der_pubkey.get()) { |
171 NOTREACHED(); | 175 NOTREACHED(); |
172 return false; | 176 return false; |
173 } | 177 } |
174 | 178 |
175 for (size_t i = 0; i < der_pubkey->len; ++i) | 179 for (size_t i = 0; i < der_pubkey->len; ++i) |
176 output->push_back(der_pubkey->data[i]); | 180 output->push_back(der_pubkey->data[i]); |
177 | 181 |
178 SECITEM_FreeItem(der_pubkey, PR_TRUE); | |
179 return true; | 182 return true; |
180 } | 183 } |
181 | 184 |
182 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { | 185 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { |
183 EnsureNSSInit(); | 186 EnsureNSSInit(); |
184 } | 187 } |
185 | 188 |
186 // static | 189 // static |
187 RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits, | 190 RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits, |
188 bool permanent, | 191 bool permanent, |
189 bool sensitive) { | 192 bool sensitive) { |
190 EnsureNSSInit(); | 193 EnsureNSSInit(); |
191 | 194 |
192 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); | 195 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
193 | 196 |
194 PK11SlotInfo *slot = GetPrivateNSSKeySlot(); | 197 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); |
195 if (!slot) | 198 if (!slot.get()) |
196 return NULL; | 199 return NULL; |
197 | 200 |
198 PK11RSAGenParams param; | 201 PK11RSAGenParams param; |
199 param.keySizeInBits = num_bits; | 202 param.keySizeInBits = num_bits; |
200 param.pe = 65537L; | 203 param.pe = 65537L; |
201 result->key_ = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, ¶m, | 204 result->key_ = PK11_GenerateKeyPair(slot.get(), |
202 &result->public_key_, permanent, sensitive, NULL); | 205 CKM_RSA_PKCS_KEY_PAIR_GEN, |
203 PK11_FreeSlot(slot); | 206 ¶m, |
207 &result->public_key_, | |
208 permanent, | |
209 sensitive, | |
210 NULL); | |
204 if (!result->key_) | 211 if (!result->key_) |
205 return NULL; | 212 return NULL; |
206 | 213 |
207 return result.release(); | 214 return result.release(); |
208 } | 215 } |
209 | 216 |
210 // static | 217 // static |
211 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( | 218 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( |
212 const std::vector<uint8>& input, bool permanent, bool sensitive) { | 219 const std::vector<uint8>& input, bool permanent, bool sensitive) { |
213 // This method currently leaks some memory. | 220 // This method currently leaks some memory. |
214 // See http://crbug.com/34742. | 221 // See http://crbug.com/34742. |
215 ANNOTATE_SCOPED_MEMORY_LEAK; | 222 ANNOTATE_SCOPED_MEMORY_LEAK; |
216 EnsureNSSInit(); | 223 EnsureNSSInit(); |
217 | 224 |
218 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); | 225 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
219 | 226 |
220 PK11SlotInfo *slot = GetPrivateNSSKeySlot(); | 227 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); |
221 if (!slot) | 228 if (!slot.get()) |
222 return NULL; | 229 return NULL; |
223 | 230 |
224 SECItem der_private_key_info; | 231 SECItem der_private_key_info; |
225 der_private_key_info.data = const_cast<unsigned char*>(&input.front()); | 232 der_private_key_info.data = const_cast<unsigned char*>(&input.front()); |
226 der_private_key_info.len = input.size(); | 233 der_private_key_info.len = input.size(); |
227 // Allow the private key to be used for key unwrapping, data decryption, | 234 // Allow the private key to be used for key unwrapping, data decryption, |
228 // and signature generation. | 235 // and signature generation. |
229 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | | 236 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | |
230 KU_DIGITAL_SIGNATURE; | 237 KU_DIGITAL_SIGNATURE; |
231 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( | 238 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( |
232 slot, &der_private_key_info, NULL, NULL, permanent, sensitive, | 239 slot.get(), &der_private_key_info, NULL, NULL, permanent, sensitive, |
233 key_usage, &result->key_, NULL); | 240 key_usage, &result->key_, NULL); |
234 PK11_FreeSlot(slot); | |
235 if (rv != SECSuccess) { | 241 if (rv != SECSuccess) { |
236 NOTREACHED(); | 242 NOTREACHED(); |
237 return NULL; | 243 return NULL; |
238 } | 244 } |
239 | 245 |
240 result->public_key_ = SECKEY_ConvertToPublicKey(result->key_); | 246 result->public_key_ = SECKEY_ConvertToPublicKey(result->key_); |
241 if (!result->public_key_) { | 247 if (!result->public_key_) { |
242 NOTREACHED(); | 248 NOTREACHED(); |
243 return NULL; | 249 return NULL; |
244 } | 250 } |
245 | 251 |
246 return result.release(); | 252 return result.release(); |
247 } | 253 } |
248 | 254 |
249 } // namespace crypto | 255 } // namespace crypto |
OLD | NEW |