| 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 |