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/ec_private_key.h" | 5 #include "crypto/ec_private_key.h" |
6 | 6 |
7 extern "C" { | 7 extern "C" { |
8 // Work around NSS missing SEC_BEGIN_PROTOS in secmodt.h. This must come before | 8 // Work around NSS missing SEC_BEGIN_PROTOS in secmodt.h. This must come before |
9 // other NSS headers. | 9 // other NSS headers. |
10 #include <secmodt.h> | 10 #include <secmodt.h> |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 PR_TRUE /* permanent */, | 97 PR_TRUE /* permanent */, |
98 PR_TRUE /* sensitive */); | 98 PR_TRUE /* sensitive */); |
99 #else | 99 #else |
100 // If USE_NSS is not defined, we initialize NSS with no databases, so we can't | 100 // If USE_NSS is not defined, we initialize NSS with no databases, so we can't |
101 // create permanent keys. | 101 // create permanent keys. |
102 NOTREACHED(); | 102 NOTREACHED(); |
103 return NULL; | 103 return NULL; |
104 #endif | 104 #endif |
105 } | 105 } |
106 | 106 |
| 107 // static |
| 108 bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( |
| 109 const std::string& password, |
| 110 const std::vector<uint8>& encrypted_private_key_info, |
| 111 CERTSubjectPublicKeyInfo* decoded_spki, |
| 112 bool permanent, |
| 113 bool sensitive, |
| 114 SECKEYPrivateKey** key, |
| 115 SECKEYPublicKey** public_key) { |
| 116 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); |
| 117 if (!slot.get()) |
| 118 return false; |
| 119 |
| 120 *public_key = SECKEY_ExtractPublicKey(decoded_spki); |
| 121 |
| 122 if (!*public_key) { |
| 123 DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError(); |
| 124 return false; |
| 125 } |
| 126 |
| 127 SECItem encoded_epki = { |
| 128 siBuffer, |
| 129 const_cast<unsigned char*>(&encrypted_private_key_info[0]), |
| 130 encrypted_private_key_info.size() |
| 131 }; |
| 132 SECKEYEncryptedPrivateKeyInfo epki; |
| 133 memset(&epki, 0, sizeof(epki)); |
| 134 |
| 135 ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); |
| 136 |
| 137 SECStatus rv = SEC_QuickDERDecodeItem( |
| 138 arena.get(), |
| 139 &epki, |
| 140 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), |
| 141 &encoded_epki); |
| 142 if (rv != SECSuccess) { |
| 143 DLOG(ERROR) << "SEC_QuickDERDecodeItem: " << PORT_GetError(); |
| 144 SECKEY_DestroyPublicKey(*public_key); |
| 145 *public_key = NULL; |
| 146 return false; |
| 147 } |
| 148 |
| 149 SECItem password_item = { |
| 150 siBuffer, |
| 151 reinterpret_cast<unsigned char*>(const_cast<char*>(password.data())), |
| 152 password.size() |
| 153 }; |
| 154 |
| 155 rv = ImportEncryptedECPrivateKeyInfoAndReturnKey( |
| 156 slot.get(), |
| 157 &epki, |
| 158 &password_item, |
| 159 NULL, // nickname |
| 160 &(*public_key)->u.ec.publicValue, |
| 161 permanent, |
| 162 sensitive, |
| 163 key, |
| 164 NULL); // wincx |
| 165 if (rv != SECSuccess) { |
| 166 DLOG(ERROR) << "ImportEncryptedECPrivateKeyInfoAndReturnKey: " |
| 167 << PORT_GetError(); |
| 168 SECKEY_DestroyPublicKey(*public_key); |
| 169 *public_key = NULL; |
| 170 return false; |
| 171 } |
| 172 |
| 173 return true; |
| 174 } |
| 175 |
107 bool ECPrivateKey::ExportEncryptedPrivateKey( | 176 bool ECPrivateKey::ExportEncryptedPrivateKey( |
108 const std::string& password, | 177 const std::string& password, |
109 int iterations, | 178 int iterations, |
110 std::vector<uint8>* output) { | 179 std::vector<uint8>* output) { |
111 // We export as an EncryptedPrivateKeyInfo bundle instead of a plain PKCS #8 | 180 // We export as an EncryptedPrivateKeyInfo bundle instead of a plain PKCS #8 |
112 // PrivateKeyInfo because PK11_ImportDERPrivateKeyInfoAndReturnKey doesn't | 181 // PrivateKeyInfo because PK11_ImportDERPrivateKeyInfoAndReturnKey doesn't |
113 // support EC keys. | 182 // support EC keys. |
114 // https://bugzilla.mozilla.org/show_bug.cgi?id=327773 | 183 // https://bugzilla.mozilla.org/show_bug.cgi?id=327773 |
115 SECItem password_item = { | 184 SECItem password_item = { |
116 siBuffer, | 185 siBuffer, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfoWithParams( | 289 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfoWithParams( |
221 const std::string& password, | 290 const std::string& password, |
222 const std::vector<uint8>& encrypted_private_key_info, | 291 const std::vector<uint8>& encrypted_private_key_info, |
223 const std::vector<uint8>& subject_public_key_info, | 292 const std::vector<uint8>& subject_public_key_info, |
224 bool permanent, | 293 bool permanent, |
225 bool sensitive) { | 294 bool sensitive) { |
226 EnsureNSSInit(); | 295 EnsureNSSInit(); |
227 | 296 |
228 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); | 297 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); |
229 | 298 |
230 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); | |
231 if (!slot.get()) | |
232 return NULL; | |
233 | |
234 SECItem encoded_spki = { | 299 SECItem encoded_spki = { |
235 siBuffer, | 300 siBuffer, |
236 const_cast<unsigned char*>(&subject_public_key_info[0]), | 301 const_cast<unsigned char*>(&subject_public_key_info[0]), |
237 subject_public_key_info.size() | 302 subject_public_key_info.size() |
238 }; | 303 }; |
239 CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo( | 304 CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo( |
240 &encoded_spki); | 305 &encoded_spki); |
241 if (!decoded_spki) { | 306 if (!decoded_spki) { |
242 DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError(); | 307 DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError(); |
243 return NULL; | 308 return NULL; |
244 } | 309 } |
245 | 310 |
246 result->public_key_ = SECKEY_ExtractPublicKey(decoded_spki); | 311 bool success = ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( |
| 312 password, encrypted_private_key_info, decoded_spki, permanent, sensitive, |
| 313 &result->key_, &result->public_key_); |
247 | 314 |
248 SECKEY_DestroySubjectPublicKeyInfo(decoded_spki); | 315 SECKEY_DestroySubjectPublicKeyInfo(decoded_spki); |
249 | 316 |
250 if (!result->public_key_) { | 317 if (success) |
251 DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError(); | 318 return result.release(); |
252 return NULL; | |
253 } | |
254 | 319 |
255 SECItem encoded_epki = { | 320 return NULL; |
256 siBuffer, | |
257 const_cast<unsigned char*>(&encrypted_private_key_info[0]), | |
258 encrypted_private_key_info.size() | |
259 }; | |
260 SECKEYEncryptedPrivateKeyInfo epki; | |
261 memset(&epki, 0, sizeof(epki)); | |
262 | |
263 ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); | |
264 | |
265 SECStatus rv = SEC_QuickDERDecodeItem( | |
266 arena.get(), | |
267 &epki, | |
268 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), | |
269 &encoded_epki); | |
270 if (rv != SECSuccess) { | |
271 DLOG(ERROR) << "SEC_ASN1DecodeItem: " << PORT_GetError(); | |
272 return NULL; | |
273 } | |
274 | |
275 SECItem password_item = { | |
276 siBuffer, | |
277 reinterpret_cast<unsigned char*>(const_cast<char*>(password.data())), | |
278 password.size() | |
279 }; | |
280 | |
281 rv = ImportEncryptedECPrivateKeyInfoAndReturnKey( | |
282 slot.get(), | |
283 &epki, | |
284 &password_item, | |
285 NULL, // nickname | |
286 &result->public_key_->u.ec.publicValue, | |
287 permanent, | |
288 sensitive, | |
289 &result->key_, | |
290 NULL); // wincx | |
291 if (rv != SECSuccess) { | |
292 DLOG(ERROR) << "ImportEncryptedECPrivateKeyInfoAndReturnKey: " | |
293 << PORT_GetError(); | |
294 return NULL; | |
295 } | |
296 | |
297 return result.release(); | |
298 } | 321 } |
299 | 322 |
300 } // namespace crypto | 323 } // namespace crypto |
OLD | NEW |