Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: crypto/ec_private_key_nss.cc

Issue 1882433002: Removing NSS files and USE_OPENSSL flag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « crypto/ec_private_key.h ('k') | crypto/ec_private_key_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "crypto/ec_private_key.h"
6
7 extern "C" {
8 // Work around NSS missing SEC_BEGIN_PROTOS in secmodt.h. This must come before
9 // other NSS headers.
10 #include <secmodt.h>
11 }
12
13 #include <cryptohi.h>
14 #include <keyhi.h>
15 #include <pk11pub.h>
16 #include <secmod.h>
17 #include <stddef.h>
18 #include <stdint.h>
19
20 #include <memory>
21
22 #include "base/logging.h"
23 #include "crypto/nss_util.h"
24 #include "crypto/nss_util_internal.h"
25 #include "crypto/scoped_nss_types.h"
26 #include "crypto/third_party/nss/chromium-nss.h"
27
28 namespace {
29
30 static bool AppendAttribute(SECKEYPrivateKey* key,
31 CK_ATTRIBUTE_TYPE type,
32 std::vector<uint8_t>* output) {
33 SECItem item;
34 SECStatus rv;
35 rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
36 if (rv != SECSuccess) {
37 DLOG(ERROR) << "PK11_ReadRawAttribute: " << PORT_GetError();
38 return false;
39 }
40
41 output->insert(output->end(), item.data, item.data + item.len);
42 SECITEM_FreeItem(&item, PR_FALSE);
43 return true;
44 }
45
46 } // namespace
47
48 namespace crypto {
49
50 ECPrivateKey::~ECPrivateKey() {
51 if (key_)
52 SECKEY_DestroyPrivateKey(key_);
53 if (public_key_)
54 SECKEY_DestroyPublicKey(public_key_);
55 }
56
57 // static
58 ECPrivateKey* ECPrivateKey::Create() {
59 EnsureNSSInit();
60
61 ScopedPK11Slot slot(PK11_GetInternalSlot());
62 if (!slot)
63 return nullptr;
64
65 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey);
66
67 SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
68 if (!oid_data) {
69 DLOG(ERROR) << "SECOID_FindOIDByTag: " << PORT_GetError();
70 return nullptr;
71 }
72
73 // SECKEYECParams is a SECItem containing the DER encoded ASN.1 ECParameters
74 // value. For a named curve, that is just the OBJECT IDENTIFIER of the curve.
75 // In addition to the oid data, the encoding requires one byte for the ASN.1
76 // tag and one byte for the length (assuming the length is <= 127).
77 CHECK_LE(oid_data->oid.len, 127U);
78 std::vector<unsigned char> parameters_buf(2 + oid_data->oid.len);
79 SECKEYECParams ec_parameters = {
80 siDEROID, &parameters_buf[0],
81 static_cast<unsigned>(parameters_buf.size())
82 };
83
84 ec_parameters.data[0] = SEC_ASN1_OBJECT_ID;
85 ec_parameters.data[1] = static_cast<unsigned char>(oid_data->oid.len);
86 memcpy(ec_parameters.data + 2, oid_data->oid.data, oid_data->oid.len);
87
88 result->key_ = PK11_GenerateKeyPair(slot.get(),
89 CKM_EC_KEY_PAIR_GEN,
90 &ec_parameters,
91 &result->public_key_,
92 PR_FALSE /* not permanent */,
93 PR_FALSE /* not sensitive */,
94 NULL);
95 if (!result->key_) {
96 DLOG(ERROR) << "PK11_GenerateKeyPair: " << PORT_GetError();
97 return nullptr;
98 }
99 CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_));
100
101 return result.release();
102 }
103
104 // static
105 ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
106 const std::string& password,
107 const std::vector<uint8_t>& encrypted_private_key_info,
108 const std::vector<uint8_t>& subject_public_key_info) {
109 EnsureNSSInit();
110
111 ScopedPK11Slot slot(PK11_GetInternalSlot());
112 if (!slot)
113 return nullptr;
114
115 std::unique_ptr<ECPrivateKey> result(new ECPrivateKey);
116
117 SECItem encoded_spki = {
118 siBuffer,
119 const_cast<unsigned char*>(&subject_public_key_info[0]),
120 static_cast<unsigned>(subject_public_key_info.size())
121 };
122 CERTSubjectPublicKeyInfo* decoded_spki = SECKEY_DecodeDERSubjectPublicKeyInfo(
123 &encoded_spki);
124 if (!decoded_spki) {
125 DLOG(ERROR) << "SECKEY_DecodeDERSubjectPublicKeyInfo: " << PORT_GetError();
126 return nullptr;
127 }
128
129 bool success = ImportFromEncryptedPrivateKeyInfo(
130 slot.get(),
131 password,
132 &encrypted_private_key_info[0],
133 encrypted_private_key_info.size(),
134 decoded_spki,
135 false /* not permanent */,
136 false /* not sensitive */,
137 &result->key_,
138 &result->public_key_);
139
140 SECKEY_DestroySubjectPublicKeyInfo(decoded_spki);
141
142 if (success) {
143 CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(result->public_key_));
144 return result.release();
145 }
146
147 return nullptr;
148 }
149
150 // static
151 bool ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
152 PK11SlotInfo* slot,
153 const std::string& password,
154 const uint8_t* encrypted_private_key_info,
155 size_t encrypted_private_key_info_len,
156 CERTSubjectPublicKeyInfo* decoded_spki,
157 bool permanent,
158 bool sensitive,
159 SECKEYPrivateKey** key,
160 SECKEYPublicKey** public_key) {
161 if (!slot)
162 return false;
163
164 *public_key = SECKEY_ExtractPublicKey(decoded_spki);
165
166 if (!*public_key) {
167 DLOG(ERROR) << "SECKEY_ExtractPublicKey: " << PORT_GetError();
168 return false;
169 }
170
171 if (SECKEY_GetPublicKeyType(*public_key) != ecKey) {
172 DLOG(ERROR) << "The public key is not an EC key";
173 SECKEY_DestroyPublicKey(*public_key);
174 *public_key = NULL;
175 return false;
176 }
177
178 SECItem encoded_epki = {
179 siBuffer,
180 const_cast<unsigned char*>(encrypted_private_key_info),
181 static_cast<unsigned>(encrypted_private_key_info_len)
182 };
183 SECKEYEncryptedPrivateKeyInfo epki;
184 memset(&epki, 0, sizeof(epki));
185
186 ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
187
188 SECStatus rv = SEC_QuickDERDecodeItem(
189 arena.get(),
190 &epki,
191 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate),
192 &encoded_epki);
193 if (rv != SECSuccess) {
194 DLOG(ERROR) << "SEC_QuickDERDecodeItem: " << PORT_GetError();
195 SECKEY_DestroyPublicKey(*public_key);
196 *public_key = NULL;
197 return false;
198 }
199
200 SECItem password_item = {
201 siBuffer,
202 reinterpret_cast<unsigned char*>(const_cast<char*>(password.data())),
203 static_cast<unsigned>(password.size())
204 };
205
206 rv = ImportEncryptedECPrivateKeyInfoAndReturnKey(
207 slot,
208 &epki,
209 &password_item,
210 NULL, // nickname
211 &(*public_key)->u.ec.publicValue,
212 permanent,
213 sensitive,
214 key,
215 NULL); // wincx
216 if (rv != SECSuccess) {
217 DLOG(ERROR) << "ImportEncryptedECPrivateKeyInfoAndReturnKey: "
218 << PORT_GetError();
219 SECKEY_DestroyPublicKey(*public_key);
220 *public_key = NULL;
221 return false;
222 }
223
224 return true;
225 }
226
227 ECPrivateKey* ECPrivateKey::Copy() const {
228 std::unique_ptr<ECPrivateKey> copy(new ECPrivateKey);
229 if (key_) {
230 copy->key_ = SECKEY_CopyPrivateKey(key_);
231 if (!copy->key_)
232 return NULL;
233 }
234 if (public_key_) {
235 copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
236 if (!copy->public_key_)
237 return NULL;
238 }
239 return copy.release();
240 }
241
242 bool ECPrivateKey::ExportEncryptedPrivateKey(const std::string& password,
243 int iterations,
244 std::vector<uint8_t>* output) {
245 // We export as an EncryptedPrivateKeyInfo bundle instead of a plain PKCS #8
246 // PrivateKeyInfo because PK11_ImportDERPrivateKeyInfoAndReturnKey doesn't
247 // support EC keys.
248 // https://bugzilla.mozilla.org/show_bug.cgi?id=327773
249 SECItem password_item = {
250 siBuffer,
251 reinterpret_cast<unsigned char*>(const_cast<char*>(password.data())),
252 static_cast<unsigned>(password.size())
253 };
254
255 SECKEYEncryptedPrivateKeyInfo* encrypted = PK11_ExportEncryptedPrivKeyInfo(
256 NULL, // Slot, optional.
257 SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC,
258 &password_item,
259 key_,
260 iterations,
261 NULL); // wincx.
262
263 if (!encrypted) {
264 DLOG(ERROR) << "PK11_ExportEncryptedPrivKeyInfo: " << PORT_GetError();
265 return false;
266 }
267
268 ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
269 SECItem der_key = {siBuffer, NULL, 0};
270 SECItem* encoded_item = SEC_ASN1EncodeItem(
271 arena.get(),
272 &der_key,
273 encrypted,
274 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate));
275 SECKEY_DestroyEncryptedPrivateKeyInfo(encrypted, PR_TRUE);
276 if (!encoded_item) {
277 DLOG(ERROR) << "SEC_ASN1EncodeItem: " << PORT_GetError();
278 return false;
279 }
280
281 output->assign(der_key.data, der_key.data + der_key.len);
282
283 return true;
284 }
285
286 bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) {
287 ScopedSECItem der_pubkey(
288 SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
289 if (!der_pubkey.get()) {
290 return false;
291 }
292
293 output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
294 return true;
295 }
296
297 bool ECPrivateKey::ExportRawPublicKey(std::string* output) {
298 // public_key_->u.ec.publicValue is an ANSI X9.62 public key which, for
299 // a P-256 key, is 0x04 (meaning uncompressed) followed by the x and y field
300 // elements as 32-byte, big-endian numbers.
301 static const unsigned int kExpectedKeyLength = 65;
302
303 CHECK_EQ(ecKey, SECKEY_GetPublicKeyType(public_key_));
304 const unsigned char* const data = public_key_->u.ec.publicValue.data;
305 const unsigned int len = public_key_->u.ec.publicValue.len;
306 if (len != kExpectedKeyLength || data[0] != 0x04)
307 return false;
308
309 output->assign(reinterpret_cast<const char*>(data + 1),
310 kExpectedKeyLength - 1);
311 return true;
312 }
313
314 bool ECPrivateKey::ExportValueForTesting(std::vector<uint8_t>* output) {
315 // This serialization format is purely for testing equality, so just
316 // concatenate the raw private key (always 32 bytes for P-256) with the
317 // parameters.
318 output->clear();
319 return AppendAttribute(key_, CKA_VALUE, output) &&
320 output->size() == 32 &&
321 AppendAttribute(key_, CKA_EC_PARAMS, output);
322 }
323
324 ECPrivateKey::ECPrivateKey() : key_(NULL), public_key_(NULL) {}
325
326 } // namespace crypto
OLDNEW
« no previous file with comments | « crypto/ec_private_key.h ('k') | crypto/ec_private_key_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698