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 |