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

Side by Side Diff: webrtc/base/nssidentity.cc

Issue 1189583002: Support generation of EC keys using P256 curve and support ECDSA certs. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 6 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
OLDNEW
1 /* 1 /*
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2012 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 29 matching lines...) Expand all
40 // This is to compensate for slightly incorrect system clocks. 40 // This is to compensate for slightly incorrect system clocks.
41 static const int CERTIFICATE_WINDOW = -60*60*24; 41 static const int CERTIFICATE_WINDOW = -60*60*24;
42 42
43 NSSKeyPair::~NSSKeyPair() { 43 NSSKeyPair::~NSSKeyPair() {
44 if (privkey_) 44 if (privkey_)
45 SECKEY_DestroyPrivateKey(privkey_); 45 SECKEY_DestroyPrivateKey(privkey_);
46 if (pubkey_) 46 if (pubkey_)
47 SECKEY_DestroyPublicKey(pubkey_); 47 SECKEY_DestroyPublicKey(pubkey_);
48 } 48 }
49 49
50 NSSKeyPair *NSSKeyPair::Generate() { 50 NSSKeyPair* NSSKeyPair::Generate(KeyType key_type) {
51 SECKEYPrivateKey *privkey = NULL; 51 SECKEYPrivateKey* privkey = nullptr;
52 SECKEYPublicKey *pubkey = NULL; 52 SECKEYPublicKey* pubkey = nullptr;
53 PK11RSAGenParams rsaparams; 53 SSLKEAType ssl_kea_type;
54 rsaparams.keySizeInBits = 1024; 54 if (key_type == KT_RSA) {
55 rsaparams.pe = 0x010001; // 65537 -- a common RSA public exponent. 55 PK11RSAGenParams rsa_params;
56 rsa_params.keySizeInBits = 1024;
57 rsa_params.pe = 0x010001; // 65537 -- a common RSA public exponent.
56 58
57 privkey = PK11_GenerateKeyPair(NSSContext::GetSlot(), 59 privkey = PK11_GenerateKeyPair(
58 CKM_RSA_PKCS_KEY_PAIR_GEN, 60 NSSContext::GetSlot(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsa_params, &pubkey,
59 &rsaparams, &pubkey, PR_FALSE /*permanent*/, 61 PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr);
60 PR_FALSE /*sensitive*/, NULL); 62
61 if (!privkey) { 63 ssl_kea_type = ssl_kea_rsa;
62 LOG(LS_ERROR) << "Couldn't generate key pair"; 64 } else if (key_type == KT_ECDSA) {
63 return NULL; 65 unsigned char param_buf[12]; // OIDs are small
66 SECItem ecdsa_params = {siBuffer, param_buf, sizeof(param_buf)};
67 SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
68 if (!oid_data || oid_data->oid.len > sizeof(param_buf) - 2) {
69 LOG(LS_ERROR) << "oid_data incorrect: " << oid_data->oid.len;
70 return nullptr;
71 }
72 ecdsa_params.data[0] = SEC_ASN1_OBJECT_ID;
73 ecdsa_params.data[1] = oid_data->oid.len;
74 memcpy(ecdsa_params.data + 2, oid_data->oid.data, oid_data->oid.len);
75 ecdsa_params.len = oid_data->oid.len + 2;
76
77 privkey = PK11_GenerateKeyPair(
78 NSSContext::GetSlot(), CKM_EC_KEY_PAIR_GEN, &ecdsa_params, &pubkey,
79 PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr);
80
81 ssl_kea_type = ssl_kea_ecdh;
82 } else {
83 LOG(LS_ERROR) << "Key type requested not understood";
tommi 2015/06/15 21:02:42 What about having something like this at the top o
juberti1 2015/06/16 02:45:04 Seems kind of drastic. If we added another key typ
tommi 2015/06/16 14:38:01 If we add a new key type and don't need to handle
84 return nullptr;
64 } 85 }
65 86
66 return new NSSKeyPair(privkey, pubkey); 87 if (!privkey) {
88 LOG(LS_ERROR) << "Couldn't generate key pair: " << PORT_GetError();
89 return nullptr;
90 }
91
92 return new NSSKeyPair(privkey, pubkey, ssl_kea_type);
67 } 93 }
68 94
69 // Just make a copy. 95 // Just make a copy.
70 NSSKeyPair *NSSKeyPair::GetReference() { 96 NSSKeyPair* NSSKeyPair::GetReference() {
71 SECKEYPrivateKey *privkey = SECKEY_CopyPrivateKey(privkey_); 97 SECKEYPrivateKey* privkey = SECKEY_CopyPrivateKey(privkey_);
72 if (!privkey) 98 if (!privkey)
73 return NULL; 99 return nullptr;
74 100
75 SECKEYPublicKey *pubkey = SECKEY_CopyPublicKey(pubkey_); 101 SECKEYPublicKey* pubkey = SECKEY_CopyPublicKey(pubkey_);
76 if (!pubkey) { 102 if (!pubkey) {
77 SECKEY_DestroyPrivateKey(privkey); 103 SECKEY_DestroyPrivateKey(privkey);
78 return NULL; 104 return nullptr;
79 } 105 }
80 106
81 return new NSSKeyPair(privkey, pubkey); 107 return new NSSKeyPair(privkey, pubkey, ssl_kea_type_);
82 } 108 }
83 109
84 NSSCertificate::NSSCertificate(CERTCertificate* cert) 110 NSSCertificate::NSSCertificate(CERTCertificate* cert)
85 : certificate_(CERT_DupCertificate(cert)) { 111 : certificate_(CERT_DupCertificate(cert)) {
86 ASSERT(certificate_ != NULL); 112 ASSERT(certificate_ != nullptr);
87 } 113 }
88 114
89 static void DeleteCert(SSLCertificate* cert) { 115 static void DeleteCert(SSLCertificate* cert) {
90 delete cert; 116 delete cert;
91 } 117 }
92 118
93 NSSCertificate::NSSCertificate(CERTCertList* cert_list) { 119 NSSCertificate::NSSCertificate(CERTCertList* cert_list) {
94 // Copy the first cert into certificate_. 120 // Copy the first cert into certificate_.
95 CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 121 CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
96 certificate_ = CERT_DupCertificate(node->cert); 122 certificate_ = CERT_DupCertificate(node->cert);
97 123
98 // Put any remaining certificates into the chain. 124 // Put any remaining certificates into the chain.
99 node = CERT_LIST_NEXT(node); 125 node = CERT_LIST_NEXT(node);
100 std::vector<SSLCertificate*> certs; 126 std::vector<SSLCertificate*> certs;
101 for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { 127 for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) {
102 certs.push_back(new NSSCertificate(node->cert)); 128 certs.push_back(new NSSCertificate(node->cert));
103 } 129 }
104 130
105 if (!certs.empty()) 131 if (!certs.empty())
106 chain_.reset(new SSLCertChain(certs)); 132 chain_.reset(new SSLCertChain(certs));
107 133
108 // The SSLCertChain constructor copies its input, so now we have to delete 134 // The SSLCertChain constructor copies its input, so now we have to delete
109 // the originals. 135 // the originals.
110 std::for_each(certs.begin(), certs.end(), DeleteCert); 136 std::for_each(certs.begin(), certs.end(), DeleteCert);
111 } 137 }
112 138
113 NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain) 139 NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain)
114 : certificate_(CERT_DupCertificate(cert)) { 140 : certificate_(CERT_DupCertificate(cert)) {
115 ASSERT(certificate_ != NULL); 141 ASSERT(certificate_ != nullptr);
tommi 2015/06/15 21:02:42 Can we switch over to using DCHECK instead of ASSE
juberti1 2015/06/16 02:45:04 I think that should be done globally (pthatcher/pb
116 if (chain) 142 if (chain)
117 chain_.reset(chain->Copy()); 143 chain_.reset(chain->Copy());
118 } 144 }
119 145
120 NSSCertificate::~NSSCertificate() { 146 NSSCertificate::~NSSCertificate() {
121 if (certificate_) 147 if (certificate_)
122 CERT_DestroyCertificate(certificate_); 148 CERT_DestroyCertificate(certificate_);
123 } 149 }
124 150
125 NSSCertificate *NSSCertificate::FromPEMString(const std::string &pem_string) { 151 NSSCertificate* NSSCertificate::FromPEMString(const std::string& pem_string) {
126 std::string der; 152 std::string der;
127 if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) 153 if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der))
128 return NULL; 154 return nullptr;
129 155
130 SECItem der_cert; 156 SECItem der_cert;
131 der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>( 157 der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>(
132 der.data())); 158 der.data()));
133 der_cert.len = checked_cast<unsigned int>(der.size()); 159 der_cert.len = checked_cast<unsigned int>(der.size());
134 CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 160 CERTCertificate* cert = CERT_NewTempCertificate(
135 &der_cert, NULL, PR_FALSE, PR_TRUE); 161 CERT_GetDefaultCertDB(), &der_cert, nullptr, PR_FALSE, PR_TRUE);
136 162
137 if (!cert) 163 if (!cert)
138 return NULL; 164 return nullptr;
139 165
140 NSSCertificate* ret = new NSSCertificate(cert); 166 NSSCertificate* ret = new NSSCertificate(cert);
141 CERT_DestroyCertificate(cert); 167 CERT_DestroyCertificate(cert);
142 return ret; 168 return ret;
143 } 169 }
144 170
145 NSSCertificate *NSSCertificate::GetReference() const { 171 NSSCertificate* NSSCertificate::GetReference() const {
146 return new NSSCertificate(certificate_, chain_.get()); 172 return new NSSCertificate(certificate_, chain_.get());
147 } 173 }
148 174
149 std::string NSSCertificate::ToPEMString() const { 175 std::string NSSCertificate::ToPEMString() const {
150 return SSLIdentity::DerToPem(kPemTypeCertificate, 176 return SSLIdentity::DerToPem(kPemTypeCertificate,
151 certificate_->derCert.data, 177 certificate_->derCert.data,
152 certificate_->derCert.len); 178 certificate_->derCert.len);
153 } 179 }
154 180
155 void NSSCertificate::ToDER(Buffer* der_buffer) const { 181 void NSSCertificate::ToDER(Buffer* der_buffer) const {
(...skipping 17 matching lines...) Expand all
173 return false; 199 return false;
174 200
175 // Extract the parent's public key, or fail if the key could not be read 201 // Extract the parent's public key, or fail if the key could not be read
176 // (e.g. certificate is corrupted). 202 // (e.g. certificate is corrupted).
177 SECKEYPublicKey* parent_key = CERT_ExtractPublicKey(parent); 203 SECKEYPublicKey* parent_key = CERT_ExtractPublicKey(parent);
178 if (!parent_key) 204 if (!parent_key)
179 return false; 205 return false;
180 206
181 // Check that the parent's privkey was actually used to generate the child's 207 // Check that the parent's privkey was actually used to generate the child's
182 // signature. 208 // signature.
183 SECStatus verified = CERT_VerifySignedDataWithPublicKey( 209 SECStatus verified = CERT_VerifySignedDataWithPublicKey(&child->signatureWrap,
184 &child->signatureWrap, parent_key, NULL); 210 parent_key, nullptr);
185 SECKEY_DestroyPublicKey(parent_key); 211 SECKEY_DestroyPublicKey(parent_key);
186 return verified == SECSuccess; 212 return verified == SECSuccess;
187 } 213 }
188 214
189 bool NSSCertificate::IsValidChain(const CERTCertList* cert_list) { 215 bool NSSCertificate::IsValidChain(const CERTCertList* cert_list) {
190 CERTCertListNode* child = CERT_LIST_HEAD(cert_list); 216 CERTCertListNode* child = CERT_LIST_HEAD(cert_list);
191 for (CERTCertListNode* parent = CERT_LIST_NEXT(child); 217 for (CERTCertListNode* parent = CERT_LIST_NEXT(child);
192 !CERT_LIST_END(parent, cert_list); 218 !CERT_LIST_END(parent, cert_list);
193 child = parent, parent = CERT_LIST_NEXT(parent)) { 219 child = parent, parent = CERT_LIST_NEXT(parent)) {
194 if (!Certifies(parent->cert, child->cert)) 220 if (!Certifies(parent->cert, child->cert))
195 return false; 221 return false;
196 } 222 }
197 return true; 223 return true;
198 } 224 }
199 225
200 bool NSSCertificate::GetDigestLength(const std::string& algorithm, 226 bool NSSCertificate::GetDigestLength(const std::string& algorithm,
201 size_t* length) { 227 size_t* length) {
202 const SECHashObject *ho; 228 const SECHashObject* ho;
tommi 2015/06/15 21:02:42 nit: initialize to nullptr
torbjorng (webrtc) 2015/06/16 14:11:51 A cleanup in old code, but OK...
203 229
204 if (!GetDigestObject(algorithm, &ho)) 230 if (!GetDigestObject(algorithm, &ho))
205 return false; 231 return false;
206 232
207 *length = ho->length; 233 *length = ho->length;
208 234
209 return true; 235 return true;
210 } 236 }
211 237
212 bool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const { 238 bool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 algorithm->clear(); 280 algorithm->clear();
255 return false; 281 return false;
256 } 282 }
257 return true; 283 return true;
258 } 284 }
259 285
260 bool NSSCertificate::ComputeDigest(const std::string& algorithm, 286 bool NSSCertificate::ComputeDigest(const std::string& algorithm,
261 unsigned char* digest, 287 unsigned char* digest,
262 size_t size, 288 size_t size,
263 size_t* length) const { 289 size_t* length) const {
264 const SECHashObject *ho; 290 const SECHashObject* ho;
265 291
266 if (!GetDigestObject(algorithm, &ho)) 292 if (!GetDigestObject(algorithm, &ho))
267 return false; 293 return false;
268 294
269 if (size < ho->length) // Sanity check for fit 295 if (size < ho->length) // Sanity check for fit
270 return false; 296 return false;
271 297
272 SECStatus rv = HASH_HashBuf(ho->type, digest, 298 SECStatus rv = HASH_HashBuf(ho->type, digest,
273 certificate_->derCert.data, 299 certificate_->derCert.data,
274 certificate_->derCert.len); 300 certificate_->derCert.len);
275 if (rv != SECSuccess) 301 if (rv != SECSuccess)
276 return false; 302 return false;
277 303
278 *length = ho->length; 304 *length = ho->length;
279 305
280 return true; 306 return true;
281 } 307 }
282 308
283 bool NSSCertificate::GetChain(SSLCertChain** chain) const { 309 bool NSSCertificate::GetChain(SSLCertChain** chain) const {
284 if (!chain_) 310 if (!chain_)
285 return false; 311 return false;
286 312
287 *chain = chain_->Copy(); 313 *chain = chain_->Copy();
288 return true; 314 return true;
289 } 315 }
290 316
291 bool NSSCertificate::Equals(const NSSCertificate *tocompare) const { 317 bool NSSCertificate::Equals(const NSSCertificate* tocompare) const {
tommi 2015/06/15 21:02:42 nit: to_compare
torbjorng (webrtc) 2015/06/16 14:11:51 I will defer this cleanup in old to separate CL.
torbjorng (webrtc) 2015/06/16 14:11:51 I don't understand this comment.
tommi 2015/06/16 14:38:01 the naming rules would be to use an underscore in
292 if (!certificate_->derCert.len) 318 if (!certificate_->derCert.len)
293 return false; 319 return false;
294 if (!tocompare->certificate_->derCert.len) 320 if (!tocompare->certificate_->derCert.len)
295 return false; 321 return false;
296 322
297 if (certificate_->derCert.len != tocompare->certificate_->derCert.len) 323 if (certificate_->derCert.len != tocompare->certificate_->derCert.len)
298 return false; 324 return false;
299 325
300 return memcmp(certificate_->derCert.data, 326 return memcmp(certificate_->derCert.data,
301 tocompare->certificate_->derCert.data, 327 tocompare->certificate_->derCert.data,
302 certificate_->derCert.len) == 0; 328 certificate_->derCert.len) == 0;
303 } 329 }
304 330
305 331 bool NSSCertificate::GetDigestObject(const std::string& algorithm,
306 bool NSSCertificate::GetDigestObject(const std::string &algorithm, 332 const SECHashObject** hop) {
307 const SECHashObject **hop) { 333 const SECHashObject* ho;
308 const SECHashObject *ho;
309 HASH_HashType hash_type; 334 HASH_HashType hash_type;
310 335
311 if (algorithm == DIGEST_SHA_1) { 336 if (algorithm == DIGEST_SHA_1) {
312 hash_type = HASH_AlgSHA1; 337 hash_type = HASH_AlgSHA1;
313 // HASH_AlgSHA224 is not supported in the chromium linux build system. 338 // HASH_AlgSHA224 is not supported in the chromium linux build system.
314 #if 0 339 #if 0
315 } else if (algorithm == DIGEST_SHA_224) { 340 } else if (algorithm == DIGEST_SHA_224) {
316 hash_type = HASH_AlgSHA224; 341 hash_type = HASH_AlgSHA224;
317 #endif 342 #endif
318 } else if (algorithm == DIGEST_SHA_256) { 343 } else if (algorithm == DIGEST_SHA_256) {
(...skipping 11 matching lines...) Expand all
330 ASSERT(ho->length >= 20); // Can't happen 355 ASSERT(ho->length >= 20); // Can't happen
331 *hop = ho; 356 *hop = ho;
332 357
333 return true; 358 return true;
334 } 359 }
335 360
336 NSSIdentity::NSSIdentity(NSSKeyPair* keypair, NSSCertificate* cert) 361 NSSIdentity::NSSIdentity(NSSKeyPair* keypair, NSSCertificate* cert)
337 : keypair_(keypair), certificate_(cert) { 362 : keypair_(keypair), certificate_(cert) {
338 } 363 }
339 364
340 NSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params) { 365 NSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params,
366 KeyType key_type) {
341 std::string subject_name_string = "CN=" + params.common_name; 367 std::string subject_name_string = "CN=" + params.common_name;
342 CERTName *subject_name = CERT_AsciiToName( 368 CERTName* subject_name =
343 const_cast<char *>(subject_name_string.c_str())); 369 CERT_AsciiToName(const_cast<char*>(subject_name_string.c_str()));
344 NSSIdentity *identity = NULL; 370 NSSIdentity* identity = nullptr;
345 CERTSubjectPublicKeyInfo *spki = NULL; 371 CERTSubjectPublicKeyInfo* spki = nullptr;
346 CERTCertificateRequest *certreq = NULL; 372 CERTCertificateRequest* certreq = nullptr;
347 CERTValidity *validity = NULL; 373 CERTValidity* validity = nullptr;
348 CERTCertificate *certificate = NULL; 374 CERTCertificate* certificate = nullptr;
349 NSSKeyPair *keypair = NSSKeyPair::Generate(); 375 NSSKeyPair* keypair = NSSKeyPair::Generate(key_type);
350 SECItem inner_der; 376 SECItem inner_der;
351 SECStatus rv; 377 SECStatus rv;
352 PLArenaPool* arena; 378 PLArenaPool* arena;
353 SECItem signed_cert; 379 SECItem signed_cert;
354 PRTime now = PR_Now(); 380 PRTime now = PR_Now();
355 PRTime not_before = 381 PRTime not_before =
356 now + static_cast<PRTime>(params.not_before) * PR_USEC_PER_SEC; 382 now + static_cast<PRTime>(params.not_before) * PR_USEC_PER_SEC;
357 PRTime not_after = 383 PRTime not_after =
358 now + static_cast<PRTime>(params.not_after) * PR_USEC_PER_SEC; 384 now + static_cast<PRTime>(params.not_after) * PR_USEC_PER_SEC;
359 385
360 inner_der.len = 0; 386 inner_der.len = 0;
361 inner_der.data = NULL; 387 inner_der.data = nullptr;
362 388
363 if (!keypair) { 389 if (!keypair) {
364 LOG(LS_ERROR) << "Couldn't generate key pair"; 390 LOG(LS_ERROR) << "Couldn't generate key pair";
365 goto fail; 391 goto fail;
366 } 392 }
367 393
368 if (!subject_name) { 394 if (!subject_name) {
369 LOG(LS_ERROR) << "Couldn't convert subject name " << subject_name; 395 LOG(LS_ERROR) << "Couldn't convert subject name " << subject_name;
370 goto fail; 396 goto fail;
371 } 397 }
372 398
373 spki = SECKEY_CreateSubjectPublicKeyInfo(keypair->pubkey()); 399 spki = SECKEY_CreateSubjectPublicKeyInfo(keypair->pubkey());
374 if (!spki) { 400 if (!spki) {
375 LOG(LS_ERROR) << "Couldn't create SPKI"; 401 LOG(LS_ERROR) << "Couldn't create SPKI";
376 goto fail; 402 goto fail;
377 } 403 }
378 404
379 certreq = CERT_CreateCertificateRequest(subject_name, spki, NULL); 405 certreq = CERT_CreateCertificateRequest(subject_name, spki, nullptr);
380 if (!certreq) { 406 if (!certreq) {
381 LOG(LS_ERROR) << "Couldn't create certificate signing request"; 407 LOG(LS_ERROR) << "Couldn't create certificate signing request";
382 goto fail; 408 goto fail;
383 } 409 }
384 410
385 validity = CERT_CreateValidity(not_before, not_after); 411 validity = CERT_CreateValidity(not_before, not_after);
386 if (!validity) { 412 if (!validity) {
387 LOG(LS_ERROR) << "Couldn't create validity"; 413 LOG(LS_ERROR) << "Couldn't create validity";
388 goto fail; 414 goto fail;
389 } 415 }
390 416
391 unsigned long serial; 417 unsigned long serial;
392 // Note: This serial in principle could collide, but it's unlikely 418 // Note: This serial in principle could collide, but it's unlikely
393 rv = PK11_GenerateRandom(reinterpret_cast<unsigned char *>(&serial), 419 rv = PK11_GenerateRandom(reinterpret_cast<unsigned char *>(&serial),
394 sizeof(serial)); 420 sizeof(serial));
395 if (rv != SECSuccess) { 421 if (rv != SECSuccess) {
396 LOG(LS_ERROR) << "Couldn't generate random serial"; 422 LOG(LS_ERROR) << "Couldn't generate random serial";
397 goto fail; 423 goto fail;
398 } 424 }
399 425
400 certificate = CERT_CreateCertificate(serial, subject_name, validity, certreq); 426 certificate = CERT_CreateCertificate(serial, subject_name, validity, certreq);
401 if (!certificate) { 427 if (!certificate) {
402 LOG(LS_ERROR) << "Couldn't create certificate"; 428 LOG(LS_ERROR) << "Couldn't create certificate";
403 goto fail; 429 goto fail;
404 } 430 }
405 431
406 arena = certificate->arena; 432 arena = certificate->arena;
407 433
408 rv = SECOID_SetAlgorithmID(arena, &certificate->signature, 434 rv = SECFailure; // Trigger failure for undefined key_type.
409 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, NULL); 435 if (key_type == KT_RSA) {
410 if (rv != SECSuccess) 436 rv = SECOID_SetAlgorithmID(arena, &certificate->signature,
437 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION,
juberti1 2015/06/16 02:45:04 This seems like it could be factored to simply set
torbjorng (webrtc) 2015/06/16 14:11:51 Done.
438 nullptr);
439 } else if (key_type == KT_ECDSA) {
440 rv =
441 SECOID_SetAlgorithmID(arena, &certificate->signature,
442 SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE, nullptr);
443 }
444 if (rv != SECSuccess) {
445 LOG(LS_ERROR) << "Couldn't set hashing algorithm";
tommi 2015/06/15 21:02:42 Are these errors something we should expect to hap
juberti1 2015/06/16 02:45:05 Caller needs to handle failure because keygen can
torbjorng (webrtc) 2015/06/16 14:11:51 Some of these "goto fail" could probably not happe
411 goto fail; 446 goto fail;
447 }
412 448
413 // Set version to X509v3. 449 // Set version to X509v3.
414 *(certificate->version.data) = 2; 450 *(certificate->version.data) = 2;
415 certificate->version.len = 1; 451 certificate->version.len = 1;
416 452
417 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate, 453 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate,
418 SEC_ASN1_GET(CERT_CertificateTemplate))) 454 SEC_ASN1_GET(CERT_CertificateTemplate))) {
455 LOG(LS_ERROR) << "Couldn't encode certificate";
419 goto fail; 456 goto fail;
457 }
420 458
421 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, 459 rv = SECFailure; // Trigger failure for undefined key_type.
422 keypair->privkey(), 460 if (key_type == KT_RSA) {
423 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION); 461 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len,
462 keypair->privkey(),
463 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION);
464 } else if (key_type == KT_ECDSA) {
465 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len,
466 keypair->privkey(),
467 SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE);
468 }
469
424 if (rv != SECSuccess) { 470 if (rv != SECSuccess) {
425 LOG(LS_ERROR) << "Couldn't sign certificate"; 471 LOG(LS_ERROR) << "Couldn't sign certificate";
426 goto fail; 472 goto fail;
427 } 473 }
428 certificate->derCert = signed_cert; 474 certificate->derCert = signed_cert;
429 475
430 identity = new NSSIdentity(keypair, new NSSCertificate(certificate)); 476 identity = new NSSIdentity(keypair, new NSSCertificate(certificate));
431 477
432 goto done; 478 goto done;
433 479
434 fail: 480 fail:
435 delete keypair; 481 delete keypair;
436 482
437 done: 483 done:
438 if (certificate) CERT_DestroyCertificate(certificate); 484 if (certificate) CERT_DestroyCertificate(certificate);
439 if (subject_name) CERT_DestroyName(subject_name); 485 if (subject_name) CERT_DestroyName(subject_name);
440 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki); 486 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki);
441 if (certreq) CERT_DestroyCertificateRequest(certreq); 487 if (certreq) CERT_DestroyCertificateRequest(certreq);
442 if (validity) CERT_DestroyValidity(validity); 488 if (validity) CERT_DestroyValidity(validity);
443 return identity; 489 return identity;
444 } 490 }
445 491
446 NSSIdentity* NSSIdentity::Generate(const std::string &common_name) { 492 NSSIdentity* NSSIdentity::Generate(const std::string& common_name,
493 KeyType key_type) {
447 SSLIdentityParams params; 494 SSLIdentityParams params;
448 params.common_name = common_name; 495 params.common_name = common_name;
449 params.not_before = CERTIFICATE_WINDOW; 496 params.not_before = CERTIFICATE_WINDOW;
450 params.not_after = CERTIFICATE_LIFETIME; 497 params.not_after = CERTIFICATE_LIFETIME;
451 return GenerateInternal(params); 498 return GenerateInternal(params, key_type);
452 } 499 }
453 500
454 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params) { 501 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params,
455 return GenerateInternal(params); 502 KeyType key_type) {
503 return GenerateInternal(params, key_type);
456 } 504 }
457 505
458 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, 506 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key,
459 const std::string& certificate) { 507 const std::string& certificate) {
460 std::string private_key_der; 508 std::string private_key_der;
461 if (!SSLIdentity::PemToDer( 509 if (!SSLIdentity::PemToDer(
462 kPemTypeRsaPrivateKey, private_key, &private_key_der)) 510 kPemTypeRsaPrivateKey, private_key, &private_key_der))
463 return NULL; 511 return nullptr;
464 512
465 SECItem private_key_item; 513 SECItem private_key_item;
466 private_key_item.data = reinterpret_cast<unsigned char *>( 514 private_key_item.data = reinterpret_cast<unsigned char *>(
467 const_cast<char *>(private_key_der.c_str())); 515 const_cast<char *>(private_key_der.c_str()));
468 private_key_item.len = checked_cast<unsigned int>(private_key_der.size()); 516 private_key_item.len = checked_cast<unsigned int>(private_key_der.size());
469 517
470 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | 518 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT |
471 KU_DIGITAL_SIGNATURE; 519 KU_DIGITAL_SIGNATURE;
472 520
473 SECKEYPrivateKey* privkey = NULL; 521 SECKEYPrivateKey* privkey = nullptr;
474 SECStatus rv = 522 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
475 PK11_ImportDERPrivateKeyInfoAndReturnKey(NSSContext::GetSlot(), 523 NSSContext::GetSlot(), &private_key_item, nullptr, nullptr, PR_FALSE,
476 &private_key_item, 524 PR_FALSE, key_usage, &privkey, nullptr);
477 NULL, NULL, PR_FALSE, PR_FALSE,
478 key_usage, &privkey, NULL);
479 if (rv != SECSuccess) { 525 if (rv != SECSuccess) {
480 LOG(LS_ERROR) << "Couldn't import private key"; 526 LOG(LS_ERROR) << "Couldn't import private key";
481 return NULL; 527 return nullptr;
482 } 528 }
483 529
484 SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(privkey); 530 SECKEYPublicKey* pubkey = SECKEY_ConvertToPublicKey(privkey);
485 if (rv != SECSuccess) { 531 if (rv != SECSuccess) {
486 SECKEY_DestroyPrivateKey(privkey); 532 SECKEY_DestroyPrivateKey(privkey);
487 LOG(LS_ERROR) << "Couldn't convert private key to public key"; 533 LOG(LS_ERROR) << "Couldn't convert private key to public key";
488 return NULL; 534 return nullptr;
535 }
536
537 SSLKEAType ssl_kea_type;
538 if (private_key.find("-----BEGIN RSA PRIVATE KEY-----") == 0) {
tommi 2015/06/15 21:02:42 nit: could use startswith as suggested in the othe
torbjorng (webrtc) 2015/06/16 14:11:51 Done.
539 ssl_kea_type = ssl_kea_rsa;
540 } else {
541 // We might want to check more key types here. But since we're moving to
542 // Open/BoringSSL, don't bother. Besides, this will likely be correct for
543 // any future key type, causing a test to do more harm than good.
544 ssl_kea_type = ssl_kea_ecdh;
489 } 545 }
490 546
491 // Assign to a scoped_ptr so we don't leak on error. 547 // Assign to a scoped_ptr so we don't leak on error.
492 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey)); 548 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey, ssl_kea_type));
493 549
494 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate)); 550 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate));
495 if (!cert) { 551 if (!cert) {
496 LOG(LS_ERROR) << "Couldn't parse certificate"; 552 LOG(LS_ERROR) << "Couldn't parse certificate";
497 return NULL; 553 return nullptr;
498 } 554 }
499 555
500 // TODO(ekr@rtfm.com): Check the public key against the certificate. 556 // TODO(ekr@rtfm.com): Check the public key against the certificate.
501
502 return new NSSIdentity(keypair.release(), cert.release()); 557 return new NSSIdentity(keypair.release(), cert.release());
503 } 558 }
504 559
505 NSSIdentity::~NSSIdentity() { 560 NSSIdentity::~NSSIdentity() {
506 LOG(LS_INFO) << "Destroying NSS identity"; 561 LOG(LS_INFO) << "Destroying NSS identity";
507 } 562 }
508 563
509 NSSIdentity *NSSIdentity::GetReference() const { 564 NSSIdentity* NSSIdentity::GetReference() const {
510 NSSKeyPair *keypair = keypair_->GetReference(); 565 NSSKeyPair* keypair = keypair_->GetReference();
511 if (!keypair) 566 if (!keypair)
512 return NULL; 567 return nullptr;
513 568
514 NSSCertificate *certificate = certificate_->GetReference(); 569 NSSCertificate* certificate = certificate_->GetReference();
515 if (!certificate) { 570 if (!certificate) {
516 delete keypair; 571 delete keypair;
517 return NULL; 572 return nullptr;
518 } 573 }
519 574
520 return new NSSIdentity(keypair, certificate); 575 return new NSSIdentity(keypair, certificate);
521 } 576 }
522 577
523 578
524 NSSCertificate &NSSIdentity::certificate() const { 579 NSSCertificate &NSSIdentity::certificate() const {
525 return *certificate_; 580 return *certificate_;
526 } 581 }
527 582
528 583
529 } // rtc namespace 584 } // rtc namespace
530 585
531 #endif // HAVE_NSS_SSL_H 586 #endif // HAVE_NSS_SSL_H
532
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698