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 uint8* encrypted_private_key_info, |
| 111 size_t encrypted_private_key_info_len, |
| 112 CERTSubjectPublicKeyInfo* decoded_spki, |
| 113 bool permanent, |
| 114 bool sensitive, |
| 115 SECKEYPrivateKey** key, |
| 116 SECKEYPublicKey** public_key) { |
| 117 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); |
| 118 if (!slot.get()) |
| 119 return false; |
| 120 |
| 121 *public_key = SECKEY_ExtractPublicKey(decoded_spki); |
| 122 |
| 123 if (!*public_key) { |
| 124 DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError(); |
| 125 return false; |
| 126 } |
| 127 |
| 128 SECItem encoded_epki = { |
| 129 siBuffer, |
| 130 const_cast<unsigned char*>(encrypted_private_key_info), |
| 131 encrypted_private_key_info_len |
| 132 }; |
| 133 SECKEYEncryptedPrivateKeyInfo epki; |
| 134 memset(&epki, 0, sizeof(epki)); |
| 135 |
| 136 ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); |
| 137 |
| 138 SECStatus rv = SEC_QuickDERDecodeItem( |
| 139 arena.get(), |
| 140 &epki, |
| 141 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), |
| 142 &encoded_epki); |
| 143 if (rv != SECSuccess) { |
| 144 DLOG(ERROR) << "SEC_QuickDERDecodeItem: " << PORT_GetError(); |
| 145 SECKEY_DestroyPublicKey(*public_key); |
| 146 *public_key = NULL; |
| 147 return false; |
| 148 } |
| 149 |
| 150 SECItem password_item = { |
| 151 siBuffer, |
| 152 reinterpret_cast<unsigned char*>(const_cast<char*>(password.data())), |
| 153 password.size() |
| 154 }; |
| 155 |
| 156 rv = ImportEncryptedECPrivateKeyInfoAndReturnKey( |
| 157 slot.get(), |
| 158 &epki, |
| 159 &password_item, |
| 160 NULL, // nickname |
| 161 &(*public_key)->u.ec.publicValue, |
| 162 permanent, |
| 163 sensitive, |
| 164 key, |
| 165 NULL); // wincx |
| 166 if (rv != SECSuccess) { |
| 167 DLOG(ERROR) << "ImportEncryptedECPrivateKeyInfoAndReturnKey: " |
| 168 << PORT_GetError(); |
| 169 SECKEY_DestroyPublicKey(*public_key); |
| 170 *public_key = NULL; |
| 171 return false; |
| 172 } |
| 173 |
| 174 return true; |
| 175 } |
| 176 |
107 bool ECPrivateKey::ExportEncryptedPrivateKey( | 177 bool ECPrivateKey::ExportEncryptedPrivateKey( |
108 const std::string& password, | 178 const std::string& password, |
109 int iterations, | 179 int iterations, |
110 std::vector<uint8>* output) { | 180 std::vector<uint8>* output) { |
111 // We export as an EncryptedPrivateKeyInfo bundle instead of a plain PKCS #8 | 181 // We export as an EncryptedPrivateKeyInfo bundle instead of a plain PKCS #8 |
112 // PrivateKeyInfo because PK11_ImportDERPrivateKeyInfoAndReturnKey doesn't | 182 // PrivateKeyInfo because PK11_ImportDERPrivateKeyInfoAndReturnKey doesn't |
113 // support EC keys. | 183 // support EC keys. |
114 // https://bugzilla.mozilla.org/show_bug.cgi?id=327773 | 184 // https://bugzilla.mozilla.org/show_bug.cgi?id=327773 |
115 SECItem password_item = { | 185 SECItem password_item = { |
116 siBuffer, | 186 siBuffer, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfoWithParams( | 290 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfoWithParams( |
221 const std::string& password, | 291 const std::string& password, |
222 const std::vector<uint8>& encrypted_private_key_info, | 292 const std::vector<uint8>& encrypted_private_key_info, |
223 const std::vector<uint8>& subject_public_key_info, | 293 const std::vector<uint8>& subject_public_key_info, |
224 bool permanent, | 294 bool permanent, |
225 bool sensitive) { | 295 bool sensitive) { |
226 EnsureNSSInit(); | 296 EnsureNSSInit(); |
227 | 297 |
228 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); | 298 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); |
229 | 299 |
230 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); | |
231 if (!slot.get()) | |
232 return NULL; | |
233 | |
234 SECItem encoded_spki = { | 300 SECItem encoded_spki = { |
235 siBuffer, | 301 siBuffer, |
236 const_cast<unsigned char*>(&subject_public_key_info[0]), | 302 const_cast<unsigned char*>(&subject_public_key_info[0]), |
237 subject_public_key_info.size() | 303 subject_public_key_info.size() |
238 }; | 304 }; |
239 CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo( | 305 CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo( |
240 &encoded_spki); | 306 &encoded_spki); |
241 if (!decoded_spki) { | 307 if (!decoded_spki) { |
242 DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError(); | 308 DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError(); |
243 return NULL; | 309 return NULL; |
244 } | 310 } |
245 | 311 |
246 result->public_key_ = SECKEY_ExtractPublicKey(decoded_spki); | 312 bool success = ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( |
| 313 password, |
| 314 &encrypted_private_key_info[0], |
| 315 encrypted_private_key_info.size(), |
| 316 decoded_spki, |
| 317 permanent, |
| 318 sensitive, |
| 319 &result->key_, |
| 320 &result->public_key_); |
247 | 321 |
248 SECKEY_DestroySubjectPublicKeyInfo(decoded_spki); | 322 SECKEY_DestroySubjectPublicKeyInfo(decoded_spki); |
249 | 323 |
250 if (!result->public_key_) { | 324 if (success) |
251 DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError(); | 325 return result.release(); |
252 return NULL; | |
253 } | |
254 | 326 |
255 SECItem encoded_epki = { | 327 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 } | 328 } |
299 | 329 |
300 } // namespace crypto | 330 } // namespace crypto |
OLD | NEW |