Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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> |
| 11 } | 11 } |
| 12 | 12 |
| 13 #include <cryptohi.h> | 13 #include <cryptohi.h> |
| 14 #include <keyhi.h> | 14 #include <keyhi.h> |
| 15 #include <pk11pub.h> | 15 #include <pk11pub.h> |
| 16 #include <secmod.h> | 16 #include <secmod.h> |
| 17 | 17 |
| 18 #include "base/lazy_instance.h" | 18 #include "base/lazy_instance.h" |
| 19 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/memory/scoped_ptr.h" | 20 #include "base/memory/scoped_ptr.h" |
| 21 #include "crypto/nss_util.h" | 21 #include "crypto/nss_util.h" |
| 22 #include "crypto/nss_util_internal.h" | 22 #include "crypto/nss_util_internal.h" |
| 23 #include "crypto/scoped_nss_types.h" | 23 #include "crypto/scoped_nss_types.h" |
| 24 #include "crypto/third_party/nss/chromium-nss.h" | 24 #include "crypto/third_party/nss/chromium-nss.h" |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 PK11SlotInfo* GetKeySlot() { | |
| 29 return crypto::GetPublicNSSKeySlot(); | |
| 30 } | |
| 31 | |
| 32 class EllipticCurveSupportChecker { | 28 class EllipticCurveSupportChecker { |
| 33 public: | 29 public: |
| 34 EllipticCurveSupportChecker() { | 30 EllipticCurveSupportChecker() { |
| 35 // NOTE: we can do this check here only because we use the NSS internal | 31 // NOTE: we can do this check here only because we use the NSS internal |
| 36 // slot. If we support other slots in the future, checking whether they | 32 // slot. If we support other slots in the future, checking whether they |
| 37 // support ECDSA may block NSS, and the value may also change as devices are | 33 // support ECDSA may block NSS, and the value may also change as devices are |
| 38 // inserted/removed, so we would need to re-check on every use. | 34 // inserted/removed, so we would need to re-check on every use. |
| 39 crypto::EnsureNSSInit(); | 35 crypto::EnsureNSSInit(); |
| 40 crypto::ScopedPK11Slot slot(GetKeySlot()); | 36 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
|
wtc
2013/11/11 20:56:25
It may be a good idea to keep the GetKeySlot() fun
mattm
2013/11/12 02:42:44
Done.
| |
| 41 supported_ = PK11_DoesMechanism(slot.get(), CKM_EC_KEY_PAIR_GEN) && | 37 supported_ = PK11_DoesMechanism(slot.get(), CKM_EC_KEY_PAIR_GEN) && |
| 42 PK11_DoesMechanism(slot.get(), CKM_ECDSA); | 38 PK11_DoesMechanism(slot.get(), CKM_ECDSA); |
| 43 } | 39 } |
| 44 | 40 |
| 45 bool Supported() { | 41 bool Supported() { |
| 46 return supported_; | 42 return supported_; |
| 47 } | 43 } |
| 48 | 44 |
| 49 private: | 45 private: |
| 50 bool supported_; | 46 bool supported_; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 81 SECKEY_DestroyPublicKey(public_key_); | 77 SECKEY_DestroyPublicKey(public_key_); |
| 82 } | 78 } |
| 83 | 79 |
| 84 // static | 80 // static |
| 85 bool ECPrivateKey::IsSupported() { | 81 bool ECPrivateKey::IsSupported() { |
| 86 return g_elliptic_curve_supported.Get().Supported(); | 82 return g_elliptic_curve_supported.Get().Supported(); |
| 87 } | 83 } |
| 88 | 84 |
| 89 // static | 85 // static |
| 90 ECPrivateKey* ECPrivateKey::Create() { | 86 ECPrivateKey* ECPrivateKey::Create() { |
| 91 return CreateWithParams(PR_FALSE /* not permanent */, | 87 EnsureNSSInit(); |
| 88 | |
| 89 return CreateWithParams(ScopedPK11Slot(PK11_GetInternalKeySlot()), | |
|
wtc
2013/11/11 20:56:25
IMPORTANT: I think this should be PK11_GetInternal
mattm
2013/11/12 02:42:44
Done.
| |
| 90 PR_FALSE /* not permanent */, | |
| 92 PR_FALSE /* not sensitive */); | 91 PR_FALSE /* not sensitive */); |
|
wtc
2013/11/11 20:56:25
Nit: these should be 'false' instead of 'PR_FALSE'
mattm
2013/11/12 02:42:44
Done.
| |
| 93 } | 92 } |
| 94 | 93 |
| 94 #if defined(USE_NSS) | |
| 95 // static | 95 // static |
| 96 ECPrivateKey* ECPrivateKey::CreateSensitive() { | 96 ECPrivateKey* ECPrivateKey::CreateSensitive(ScopedPK11Slot slot) { |
| 97 #if defined(USE_NSS) | 97 return CreateWithParams( |
| 98 return CreateWithParams(PR_TRUE /* permanent */, | 98 slot.Pass(), PR_TRUE /* permanent */, PR_TRUE /* sensitive */); |
|
wtc
2013/11/11 20:56:25
Nit: these should be 'true' instead of 'PR_TRUE'.
mattm
2013/11/12 02:42:44
Done.
| |
| 99 PR_TRUE /* sensitive */); | 99 } |
| 100 #else | |
| 101 // If USE_NSS is not defined, we initialize NSS with no databases, so we can't | |
| 102 // create permanent keys. | |
| 103 NOTREACHED(); | |
| 104 return NULL; | |
| 105 #endif | 100 #endif |
| 106 } | |
| 107 | 101 |
| 108 // static | 102 // static |
| 109 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | 103 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
| 110 const std::string& password, | 104 const std::string& password, |
| 111 const std::vector<uint8>& encrypted_private_key_info, | 105 const std::vector<uint8>& encrypted_private_key_info, |
| 112 const std::vector<uint8>& subject_public_key_info) { | 106 const std::vector<uint8>& subject_public_key_info) { |
| 107 EnsureNSSInit(); | |
| 108 | |
| 113 return CreateFromEncryptedPrivateKeyInfoWithParams( | 109 return CreateFromEncryptedPrivateKeyInfoWithParams( |
| 110 ScopedPK11Slot(PK11_GetInternalKeySlot()), | |
|
wtc
2013/11/11 20:56:25
IMPORTANT: I think this should be PK11_GetInternal
mattm
2013/11/12 02:42:44
Done.
| |
| 114 password, | 111 password, |
| 115 encrypted_private_key_info, | 112 encrypted_private_key_info, |
| 116 subject_public_key_info, | 113 subject_public_key_info, |
| 117 PR_FALSE /* not permanent */, | 114 PR_FALSE /* not permanent */, |
| 118 PR_FALSE /* not sensitive */); | 115 PR_FALSE /* not sensitive */); |
|
wtc
2013/11/11 20:56:25
Nit: these should be 'false' instead of 'PR_FALSE'
mattm
2013/11/12 02:42:44
Done.
| |
| 119 } | 116 } |
| 120 | 117 |
| 118 #if defined(USE_NSS) | |
| 121 // static | 119 // static |
| 122 ECPrivateKey* ECPrivateKey::CreateSensitiveFromEncryptedPrivateKeyInfo( | 120 ECPrivateKey* ECPrivateKey::CreateSensitiveFromEncryptedPrivateKeyInfo( |
| 121 ScopedPK11Slot slot, | |
| 123 const std::string& password, | 122 const std::string& password, |
| 124 const std::vector<uint8>& encrypted_private_key_info, | 123 const std::vector<uint8>& encrypted_private_key_info, |
| 125 const std::vector<uint8>& subject_public_key_info) { | 124 const std::vector<uint8>& subject_public_key_info) { |
| 126 #if defined(USE_NSS) | |
| 127 return CreateFromEncryptedPrivateKeyInfoWithParams( | 125 return CreateFromEncryptedPrivateKeyInfoWithParams( |
| 126 slot.Pass(), | |
| 128 password, | 127 password, |
| 129 encrypted_private_key_info, | 128 encrypted_private_key_info, |
| 130 subject_public_key_info, | 129 subject_public_key_info, |
| 131 PR_TRUE /* permanent */, | 130 PR_TRUE /* permanent */, |
| 132 PR_TRUE /* sensitive */); | 131 PR_TRUE /* sensitive */); |
|
wtc
2013/11/11 20:56:25
Nit: these should be 'true' instead of 'PR_TRUE'.
mattm
2013/11/12 02:42:44
Done.
| |
| 133 #else | 132 } |
| 134 // If USE_NSS is not defined, we initialize NSS with no databases, so we can't | |
| 135 // create permanent keys. | |
| 136 NOTREACHED(); | |
| 137 return NULL; | |
| 138 #endif | 133 #endif |
| 139 } | |
| 140 | 134 |
| 141 // static | 135 // static |
| 142 bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( | 136 bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( |
| 137 ScopedPK11Slot slot, | |
| 143 const std::string& password, | 138 const std::string& password, |
| 144 const uint8* encrypted_private_key_info, | 139 const uint8* encrypted_private_key_info, |
| 145 size_t encrypted_private_key_info_len, | 140 size_t encrypted_private_key_info_len, |
| 146 CERTSubjectPublicKeyInfo* decoded_spki, | 141 CERTSubjectPublicKeyInfo* decoded_spki, |
| 147 bool permanent, | 142 bool permanent, |
| 148 bool sensitive, | 143 bool sensitive, |
| 149 SECKEYPrivateKey** key, | 144 SECKEYPrivateKey** key, |
| 150 SECKEYPublicKey** public_key) { | 145 SECKEYPublicKey** public_key) { |
| 151 ScopedPK11Slot slot(GetKeySlot()); | |
| 152 if (!slot.get()) | 146 if (!slot.get()) |
| 153 return false; | 147 return false; |
| 154 | 148 |
| 155 *public_key = SECKEY_ExtractPublicKey(decoded_spki); | 149 *public_key = SECKEY_ExtractPublicKey(decoded_spki); |
| 156 | 150 |
| 157 if (!*public_key) { | 151 if (!*public_key) { |
| 158 DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError(); | 152 DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError(); |
| 159 return false; | 153 return false; |
| 160 } | 154 } |
| 161 | 155 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 return ReadAttribute(key_, CKA_VALUE, output); | 262 return ReadAttribute(key_, CKA_VALUE, output); |
| 269 } | 263 } |
| 270 | 264 |
| 271 bool ECPrivateKey::ExportECParams(std::vector<uint8>* output) { | 265 bool ECPrivateKey::ExportECParams(std::vector<uint8>* output) { |
| 272 return ReadAttribute(key_, CKA_EC_PARAMS, output); | 266 return ReadAttribute(key_, CKA_EC_PARAMS, output); |
| 273 } | 267 } |
| 274 | 268 |
| 275 ECPrivateKey::ECPrivateKey() : key_(NULL), public_key_(NULL) {} | 269 ECPrivateKey::ECPrivateKey() : key_(NULL), public_key_(NULL) {} |
| 276 | 270 |
| 277 // static | 271 // static |
| 278 ECPrivateKey* ECPrivateKey::CreateWithParams(bool permanent, | 272 ECPrivateKey* ECPrivateKey::CreateWithParams(ScopedPK11Slot slot, |
| 273 bool permanent, | |
| 279 bool sensitive) { | 274 bool sensitive) { |
| 280 EnsureNSSInit(); | |
| 281 | |
| 282 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); | 275 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); |
| 283 | 276 |
| 284 ScopedPK11Slot slot(GetKeySlot()); | |
| 285 if (!slot.get()) | 277 if (!slot.get()) |
| 286 return NULL; | 278 return NULL; |
| 287 | 279 |
| 288 SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); | 280 SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1); |
| 289 if (!oid_data) { | 281 if (!oid_data) { |
| 290 DLOG(ERROR) << "SECOID_FindOIDByTag: " << PORT_GetError(); | 282 DLOG(ERROR) << "SECOID_FindOIDByTag: " << PORT_GetError(); |
| 291 return NULL; | 283 return NULL; |
| 292 } | 284 } |
| 293 | 285 |
| 294 // SECKEYECParams is a SECItem containing the DER encoded ASN.1 ECParameters | 286 // SECKEYECParams is a SECItem containing the DER encoded ASN.1 ECParameters |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 316 if (!result->key_) { | 308 if (!result->key_) { |
| 317 DLOG(ERROR) << "PK11_GenerateKeyPair: " << PORT_GetError(); | 309 DLOG(ERROR) << "PK11_GenerateKeyPair: " << PORT_GetError(); |
| 318 return NULL; | 310 return NULL; |
| 319 } | 311 } |
| 320 | 312 |
| 321 return result.release(); | 313 return result.release(); |
| 322 } | 314 } |
| 323 | 315 |
| 324 // static | 316 // static |
| 325 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfoWithParams( | 317 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfoWithParams( |
| 318 ScopedPK11Slot slot, | |
| 326 const std::string& password, | 319 const std::string& password, |
| 327 const std::vector<uint8>& encrypted_private_key_info, | 320 const std::vector<uint8>& encrypted_private_key_info, |
| 328 const std::vector<uint8>& subject_public_key_info, | 321 const std::vector<uint8>& subject_public_key_info, |
| 329 bool permanent, | 322 bool permanent, |
| 330 bool sensitive) { | 323 bool sensitive) { |
| 331 EnsureNSSInit(); | |
| 332 | |
| 333 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); | 324 scoped_ptr<ECPrivateKey> result(new ECPrivateKey); |
| 334 | 325 |
| 335 SECItem encoded_spki = { | 326 SECItem encoded_spki = { |
| 336 siBuffer, | 327 siBuffer, |
| 337 const_cast<unsigned char*>(&subject_public_key_info[0]), | 328 const_cast<unsigned char*>(&subject_public_key_info[0]), |
| 338 static_cast<unsigned>(subject_public_key_info.size()) | 329 static_cast<unsigned>(subject_public_key_info.size()) |
| 339 }; | 330 }; |
| 340 CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo( | 331 CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo( |
| 341 &encoded_spki); | 332 &encoded_spki); |
| 342 if (!decoded_spki) { | 333 if (!decoded_spki) { |
| 343 DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError(); | 334 DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError(); |
| 344 return NULL; | 335 return NULL; |
| 345 } | 336 } |
| 346 | 337 |
| 347 bool success = ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( | 338 bool success = ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( |
|
wtc
2013/11/11 22:18:54
Could you take the opportunity to remove "ECPrivat
mattm
2013/11/12 02:42:44
Done.
| |
| 339 slot.Pass(), | |
| 348 password, | 340 password, |
| 349 &encrypted_private_key_info[0], | 341 &encrypted_private_key_info[0], |
| 350 encrypted_private_key_info.size(), | 342 encrypted_private_key_info.size(), |
| 351 decoded_spki, | 343 decoded_spki, |
| 352 permanent, | 344 permanent, |
| 353 sensitive, | 345 sensitive, |
| 354 &result->key_, | 346 &result->key_, |
| 355 &result->public_key_); | 347 &result->public_key_); |
| 356 | 348 |
| 357 SECKEY_DestroySubjectPublicKeyInfo(decoded_spki); | 349 SECKEY_DestroySubjectPublicKeyInfo(decoded_spki); |
| 358 | 350 |
| 359 if (success) | 351 if (success) |
| 360 return result.release(); | 352 return result.release(); |
| 361 | 353 |
| 362 return NULL; | 354 return NULL; |
| 363 } | 355 } |
| 364 | 356 |
| 365 } // namespace crypto | 357 } // namespace crypto |
| OLD | NEW |