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

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: rebase, glue to hbos's changes Created 5 years, 4 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 | « webrtc/base/nssidentity.h ('k') | webrtc/base/nssstreamadapter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 13 matching lines...) Expand all
24 #include "cryptohi.h" 24 #include "cryptohi.h"
25 #include "keyhi.h" 25 #include "keyhi.h"
26 #include "nss.h" 26 #include "nss.h"
27 #include "pk11pub.h" 27 #include "pk11pub.h"
28 #include "sechash.h" 28 #include "sechash.h"
29 29
30 #include "webrtc/base/logging.h" 30 #include "webrtc/base/logging.h"
31 #include "webrtc/base/helpers.h" 31 #include "webrtc/base/helpers.h"
32 #include "webrtc/base/nssstreamadapter.h" 32 #include "webrtc/base/nssstreamadapter.h"
33 #include "webrtc/base/safe_conversions.h" 33 #include "webrtc/base/safe_conversions.h"
34 #include "webrtc/base/stringutils.h"
34 35
35 namespace rtc { 36 namespace rtc {
36 37
37 // Certificate validity lifetime in seconds. 38 // Certificate validity lifetime in seconds.
38 static const int CERTIFICATE_LIFETIME = 60*60*24*30; // 30 days, arbitrarily 39 static const int CERTIFICATE_LIFETIME = 60*60*24*30; // 30 days, arbitrarily
39 // Certificate validity window in seconds. 40 // Certificate validity window in seconds.
40 // This is to compensate for slightly incorrect system clocks. 41 // This is to compensate for slightly incorrect system clocks.
41 static const int CERTIFICATE_WINDOW = -60*60*24; 42 static const int CERTIFICATE_WINDOW = -60*60*24;
42 43
43 NSSKeyPair::~NSSKeyPair() { 44 NSSKeyPair::~NSSKeyPair() {
44 if (privkey_) 45 if (privkey_)
45 SECKEY_DestroyPrivateKey(privkey_); 46 SECKEY_DestroyPrivateKey(privkey_);
46 if (pubkey_) 47 if (pubkey_)
47 SECKEY_DestroyPublicKey(pubkey_); 48 SECKEY_DestroyPublicKey(pubkey_);
48 } 49 }
49 50
50 NSSKeyPair *NSSKeyPair::Generate() { 51 NSSKeyPair* NSSKeyPair::Generate(KeyType key_type) {
51 SECKEYPrivateKey *privkey = NULL; 52 SECKEYPrivateKey* privkey = nullptr;
52 SECKEYPublicKey *pubkey = NULL; 53 SECKEYPublicKey* pubkey = nullptr;
53 PK11RSAGenParams rsaparams; 54 SSLKEAType ssl_kea_type;
54 rsaparams.keySizeInBits = 1024; 55 if (key_type == KT_RSA) {
55 rsaparams.pe = 0x010001; // 65537 -- a common RSA public exponent. 56 PK11RSAGenParams rsa_params;
57 rsa_params.keySizeInBits = 1024;
58 rsa_params.pe = 0x010001; // 65537 -- a common RSA public exponent.
56 59
57 privkey = PK11_GenerateKeyPair(NSSContext::GetSlot(), 60 privkey = PK11_GenerateKeyPair(
58 CKM_RSA_PKCS_KEY_PAIR_GEN, 61 NSSContext::GetSlot(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsa_params, &pubkey,
59 &rsaparams, &pubkey, PR_FALSE /*permanent*/, 62 PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr);
60 PR_FALSE /*sensitive*/, NULL); 63
61 if (!privkey) { 64 ssl_kea_type = ssl_kea_rsa;
62 LOG(LS_ERROR) << "Couldn't generate key pair"; 65 } else if (key_type == KT_ECDSA) {
63 return NULL; 66 unsigned char param_buf[12]; // OIDs are small
67 SECItem ecdsa_params = {siBuffer, param_buf, sizeof(param_buf)};
68 SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
69 if (!oid_data || oid_data->oid.len > sizeof(param_buf) - 2) {
70 LOG(LS_ERROR) << "oid_data incorrect: " << oid_data->oid.len;
71 return nullptr;
72 }
73 ecdsa_params.data[0] = SEC_ASN1_OBJECT_ID;
74 ecdsa_params.data[1] = oid_data->oid.len;
75 memcpy(ecdsa_params.data + 2, oid_data->oid.data, oid_data->oid.len);
76 ecdsa_params.len = oid_data->oid.len + 2;
77
78 privkey = PK11_GenerateKeyPair(
79 NSSContext::GetSlot(), CKM_EC_KEY_PAIR_GEN, &ecdsa_params, &pubkey,
80 PR_FALSE /*permanent*/, PR_FALSE /*sensitive*/, nullptr);
81
82 ssl_kea_type = ssl_kea_ecdh;
83 } else {
84 LOG(LS_ERROR) << "Key type requested not understood";
85 return nullptr;
64 } 86 }
65 87
66 return new NSSKeyPair(privkey, pubkey); 88 if (!privkey) {
89 LOG(LS_ERROR) << "Couldn't generate key pair: " << PORT_GetError();
90 return nullptr;
91 }
92
93 return new NSSKeyPair(privkey, pubkey, ssl_kea_type);
67 } 94 }
68 95
69 // Just make a copy. 96 // Just make a copy.
70 NSSKeyPair *NSSKeyPair::GetReference() { 97 NSSKeyPair* NSSKeyPair::GetReference() {
71 SECKEYPrivateKey *privkey = SECKEY_CopyPrivateKey(privkey_); 98 SECKEYPrivateKey* privkey = SECKEY_CopyPrivateKey(privkey_);
72 if (!privkey) 99 if (!privkey)
73 return NULL; 100 return nullptr;
74 101
75 SECKEYPublicKey *pubkey = SECKEY_CopyPublicKey(pubkey_); 102 SECKEYPublicKey* pubkey = SECKEY_CopyPublicKey(pubkey_);
76 if (!pubkey) { 103 if (!pubkey) {
77 SECKEY_DestroyPrivateKey(privkey); 104 SECKEY_DestroyPrivateKey(privkey);
78 return NULL; 105 return nullptr;
79 } 106 }
80 107
81 return new NSSKeyPair(privkey, pubkey); 108 return new NSSKeyPair(privkey, pubkey, ssl_kea_type_);
82 } 109 }
83 110
84 NSSCertificate::NSSCertificate(CERTCertificate* cert) 111 NSSCertificate::NSSCertificate(CERTCertificate* cert)
85 : certificate_(CERT_DupCertificate(cert)) { 112 : certificate_(CERT_DupCertificate(cert)) {
86 ASSERT(certificate_ != NULL); 113 ASSERT(certificate_ != nullptr);
87 } 114 }
88 115
89 static void DeleteCert(SSLCertificate* cert) { 116 static void DeleteCert(SSLCertificate* cert) {
90 delete cert; 117 delete cert;
91 } 118 }
92 119
93 NSSCertificate::NSSCertificate(CERTCertList* cert_list) { 120 NSSCertificate::NSSCertificate(CERTCertList* cert_list) {
94 // Copy the first cert into certificate_. 121 // Copy the first cert into certificate_.
95 CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 122 CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
96 certificate_ = CERT_DupCertificate(node->cert); 123 certificate_ = CERT_DupCertificate(node->cert);
97 124
98 // Put any remaining certificates into the chain. 125 // Put any remaining certificates into the chain.
99 node = CERT_LIST_NEXT(node); 126 node = CERT_LIST_NEXT(node);
100 std::vector<SSLCertificate*> certs; 127 std::vector<SSLCertificate*> certs;
101 for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { 128 for (; !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) {
102 certs.push_back(new NSSCertificate(node->cert)); 129 certs.push_back(new NSSCertificate(node->cert));
103 } 130 }
104 131
105 if (!certs.empty()) 132 if (!certs.empty())
106 chain_.reset(new SSLCertChain(certs)); 133 chain_.reset(new SSLCertChain(certs));
107 134
108 // The SSLCertChain constructor copies its input, so now we have to delete 135 // The SSLCertChain constructor copies its input, so now we have to delete
109 // the originals. 136 // the originals.
110 std::for_each(certs.begin(), certs.end(), DeleteCert); 137 std::for_each(certs.begin(), certs.end(), DeleteCert);
111 } 138 }
112 139
113 NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain) 140 NSSCertificate::NSSCertificate(CERTCertificate* cert, SSLCertChain* chain)
114 : certificate_(CERT_DupCertificate(cert)) { 141 : certificate_(CERT_DupCertificate(cert)) {
115 ASSERT(certificate_ != NULL); 142 ASSERT(certificate_ != nullptr);
116 if (chain) 143 if (chain)
117 chain_.reset(chain->Copy()); 144 chain_.reset(chain->Copy());
118 } 145 }
119 146
120 NSSCertificate::~NSSCertificate() { 147 NSSCertificate::~NSSCertificate() {
121 if (certificate_) 148 if (certificate_)
122 CERT_DestroyCertificate(certificate_); 149 CERT_DestroyCertificate(certificate_);
123 } 150 }
124 151
125 NSSCertificate *NSSCertificate::FromPEMString(const std::string &pem_string) { 152 NSSCertificate* NSSCertificate::FromPEMString(const std::string& pem_string) {
126 std::string der; 153 std::string der;
127 if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) 154 if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der))
128 return NULL; 155 return nullptr;
129 156
130 SECItem der_cert; 157 SECItem der_cert;
131 der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>( 158 der_cert.data = reinterpret_cast<unsigned char *>(const_cast<char *>(
132 der.data())); 159 der.data()));
133 der_cert.len = checked_cast<unsigned int>(der.size()); 160 der_cert.len = checked_cast<unsigned int>(der.size());
134 CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 161 CERTCertificate* cert = CERT_NewTempCertificate(
135 &der_cert, NULL, PR_FALSE, PR_TRUE); 162 CERT_GetDefaultCertDB(), &der_cert, nullptr, PR_FALSE, PR_TRUE);
136 163
137 if (!cert) 164 if (!cert)
138 return NULL; 165 return nullptr;
139 166
140 NSSCertificate* ret = new NSSCertificate(cert); 167 NSSCertificate* ret = new NSSCertificate(cert);
141 CERT_DestroyCertificate(cert); 168 CERT_DestroyCertificate(cert);
142 return ret; 169 return ret;
143 } 170 }
144 171
145 NSSCertificate *NSSCertificate::GetReference() const { 172 NSSCertificate* NSSCertificate::GetReference() const {
146 return new NSSCertificate(certificate_, chain_.get()); 173 return new NSSCertificate(certificate_, chain_.get());
147 } 174 }
148 175
149 std::string NSSCertificate::ToPEMString() const { 176 std::string NSSCertificate::ToPEMString() const {
150 return SSLIdentity::DerToPem(kPemTypeCertificate, 177 return SSLIdentity::DerToPem(kPemTypeCertificate,
151 certificate_->derCert.data, 178 certificate_->derCert.data,
152 certificate_->derCert.len); 179 certificate_->derCert.len);
153 } 180 }
154 181
155 void NSSCertificate::ToDER(Buffer* der_buffer) const { 182 void NSSCertificate::ToDER(Buffer* der_buffer) const {
(...skipping 17 matching lines...) Expand all
173 return false; 200 return false;
174 201
175 // Extract the parent's public key, or fail if the key could not be read 202 // Extract the parent's public key, or fail if the key could not be read
176 // (e.g. certificate is corrupted). 203 // (e.g. certificate is corrupted).
177 SECKEYPublicKey* parent_key = CERT_ExtractPublicKey(parent); 204 SECKEYPublicKey* parent_key = CERT_ExtractPublicKey(parent);
178 if (!parent_key) 205 if (!parent_key)
179 return false; 206 return false;
180 207
181 // Check that the parent's privkey was actually used to generate the child's 208 // Check that the parent's privkey was actually used to generate the child's
182 // signature. 209 // signature.
183 SECStatus verified = CERT_VerifySignedDataWithPublicKey( 210 SECStatus verified = CERT_VerifySignedDataWithPublicKey(&child->signatureWrap,
184 &child->signatureWrap, parent_key, NULL); 211 parent_key, nullptr);
185 SECKEY_DestroyPublicKey(parent_key); 212 SECKEY_DestroyPublicKey(parent_key);
186 return verified == SECSuccess; 213 return verified == SECSuccess;
187 } 214 }
188 215
189 bool NSSCertificate::IsValidChain(const CERTCertList* cert_list) { 216 bool NSSCertificate::IsValidChain(const CERTCertList* cert_list) {
190 CERTCertListNode* child = CERT_LIST_HEAD(cert_list); 217 CERTCertListNode* child = CERT_LIST_HEAD(cert_list);
191 for (CERTCertListNode* parent = CERT_LIST_NEXT(child); 218 for (CERTCertListNode* parent = CERT_LIST_NEXT(child);
192 !CERT_LIST_END(parent, cert_list); 219 !CERT_LIST_END(parent, cert_list);
193 child = parent, parent = CERT_LIST_NEXT(parent)) { 220 child = parent, parent = CERT_LIST_NEXT(parent)) {
194 if (!Certifies(parent->cert, child->cert)) 221 if (!Certifies(parent->cert, child->cert))
195 return false; 222 return false;
196 } 223 }
197 return true; 224 return true;
198 } 225 }
199 226
200 bool NSSCertificate::GetDigestLength(const std::string& algorithm, 227 bool NSSCertificate::GetDigestLength(const std::string& algorithm,
201 size_t* length) { 228 size_t* length) {
202 const SECHashObject *ho; 229 const SECHashObject* ho = nullptr;
203 230
204 if (!GetDigestObject(algorithm, &ho)) 231 if (!GetDigestObject(algorithm, &ho))
205 return false; 232 return false;
206 233
207 *length = ho->length; 234 *length = ho->length;
208 235
209 return true; 236 return true;
210 } 237 }
211 238
212 bool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const { 239 bool NSSCertificate::GetSignatureDigestAlgorithm(std::string* algorithm) const {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 algorithm->clear(); 281 algorithm->clear();
255 return false; 282 return false;
256 } 283 }
257 return true; 284 return true;
258 } 285 }
259 286
260 bool NSSCertificate::ComputeDigest(const std::string& algorithm, 287 bool NSSCertificate::ComputeDigest(const std::string& algorithm,
261 unsigned char* digest, 288 unsigned char* digest,
262 size_t size, 289 size_t size,
263 size_t* length) const { 290 size_t* length) const {
264 const SECHashObject *ho; 291 const SECHashObject* ho = nullptr;
265 292
266 if (!GetDigestObject(algorithm, &ho)) 293 if (!GetDigestObject(algorithm, &ho))
267 return false; 294 return false;
268 295
269 if (size < ho->length) // Sanity check for fit 296 if (size < ho->length) // Sanity check for fit
270 return false; 297 return false;
271 298
272 SECStatus rv = HASH_HashBuf(ho->type, digest, 299 SECStatus rv = HASH_HashBuf(ho->type, digest,
273 certificate_->derCert.data, 300 certificate_->derCert.data,
274 certificate_->derCert.len); 301 certificate_->derCert.len);
275 if (rv != SECSuccess) 302 if (rv != SECSuccess)
276 return false; 303 return false;
277 304
278 *length = ho->length; 305 *length = ho->length;
279 306
280 return true; 307 return true;
281 } 308 }
282 309
283 bool NSSCertificate::GetChain(SSLCertChain** chain) const { 310 bool NSSCertificate::GetChain(SSLCertChain** chain) const {
284 if (!chain_) 311 if (!chain_)
285 return false; 312 return false;
286 313
287 *chain = chain_->Copy(); 314 *chain = chain_->Copy();
288 return true; 315 return true;
289 } 316 }
290 317
291 bool NSSCertificate::Equals(const NSSCertificate *tocompare) const { 318 bool NSSCertificate::Equals(const NSSCertificate* tocompare) const {
292 if (!certificate_->derCert.len) 319 if (!certificate_->derCert.len)
293 return false; 320 return false;
294 if (!tocompare->certificate_->derCert.len) 321 if (!tocompare->certificate_->derCert.len)
295 return false; 322 return false;
296 323
297 if (certificate_->derCert.len != tocompare->certificate_->derCert.len) 324 if (certificate_->derCert.len != tocompare->certificate_->derCert.len)
298 return false; 325 return false;
299 326
300 return memcmp(certificate_->derCert.data, 327 return memcmp(certificate_->derCert.data,
301 tocompare->certificate_->derCert.data, 328 tocompare->certificate_->derCert.data,
302 certificate_->derCert.len) == 0; 329 certificate_->derCert.len) == 0;
303 } 330 }
304 331
305 332 bool NSSCertificate::GetDigestObject(const std::string& algorithm,
306 bool NSSCertificate::GetDigestObject(const std::string &algorithm, 333 const SECHashObject** hop) {
307 const SECHashObject **hop) { 334 const SECHashObject* ho;
308 const SECHashObject *ho;
309 HASH_HashType hash_type; 335 HASH_HashType hash_type;
310 336
311 if (algorithm == DIGEST_SHA_1) { 337 if (algorithm == DIGEST_SHA_1) {
312 hash_type = HASH_AlgSHA1; 338 hash_type = HASH_AlgSHA1;
313 // HASH_AlgSHA224 is not supported in the chromium linux build system. 339 // HASH_AlgSHA224 is not supported in the chromium linux build system.
314 #if 0 340 #if 0
315 } else if (algorithm == DIGEST_SHA_224) { 341 } else if (algorithm == DIGEST_SHA_224) {
316 hash_type = HASH_AlgSHA224; 342 hash_type = HASH_AlgSHA224;
317 #endif 343 #endif
318 } else if (algorithm == DIGEST_SHA_256) { 344 } else if (algorithm == DIGEST_SHA_256) {
(...skipping 13 matching lines...) Expand all
332 358
333 return true; 359 return true;
334 } 360 }
335 361
336 NSSIdentity::NSSIdentity(NSSKeyPair* keypair, NSSCertificate* cert) 362 NSSIdentity::NSSIdentity(NSSKeyPair* keypair, NSSCertificate* cert)
337 : keypair_(keypair), certificate_(cert) { 363 : keypair_(keypair), certificate_(cert) {
338 } 364 }
339 365
340 NSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params) { 366 NSSIdentity* NSSIdentity::GenerateInternal(const SSLIdentityParams& params) {
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(params.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 SECOidTag sec_oid;
409 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, NULL); 435 if (params.key_type == KT_RSA) {
410 if (rv != SECSuccess) 436 sec_oid = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
437 } else if (params.key_type == KT_ECDSA) {
438 sec_oid = SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
439 } else {
440 // We should not arrive here since NSSKeyPair::Generate would have failed.
441 // Play it safe in order to accomodate code changes.
442 LOG(LS_ERROR) << "Key type requested not understood";
411 goto fail; 443 goto fail;
444 }
445
446 rv = SECOID_SetAlgorithmID(arena, &certificate->signature, sec_oid, nullptr);
447 if (rv != SECSuccess) {
448 LOG(LS_ERROR) << "Couldn't set hashing algorithm";
449 goto fail;
450 }
412 451
413 // Set version to X509v3. 452 // Set version to X509v3.
414 *(certificate->version.data) = 2; 453 *(certificate->version.data) = 2;
415 certificate->version.len = 1; 454 certificate->version.len = 1;
416 455
417 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate, 456 if (!SEC_ASN1EncodeItem(arena, &inner_der, certificate,
418 SEC_ASN1_GET(CERT_CertificateTemplate))) 457 SEC_ASN1_GET(CERT_CertificateTemplate))) {
458 LOG(LS_ERROR) << "Couldn't encode certificate";
419 goto fail; 459 goto fail;
460 }
420 461
421 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len, 462 rv = SEC_DerSignData(arena, &signed_cert, inner_der.data, inner_der.len,
422 keypair->privkey(), 463 keypair->privkey(), sec_oid);
423 SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION);
424 if (rv != SECSuccess) { 464 if (rv != SECSuccess) {
425 LOG(LS_ERROR) << "Couldn't sign certificate"; 465 LOG(LS_ERROR) << "Couldn't sign certificate";
426 goto fail; 466 goto fail;
427 } 467 }
428 certificate->derCert = signed_cert; 468 certificate->derCert = signed_cert;
429 469
430 identity = new NSSIdentity(keypair, new NSSCertificate(certificate)); 470 identity = new NSSIdentity(keypair, new NSSCertificate(certificate));
431 471
432 goto done; 472 goto done;
433 473
434 fail: 474 fail:
435 delete keypair; 475 delete keypair;
436 476
437 done: 477 done:
438 if (certificate) CERT_DestroyCertificate(certificate); 478 if (certificate) CERT_DestroyCertificate(certificate);
439 if (subject_name) CERT_DestroyName(subject_name); 479 if (subject_name) CERT_DestroyName(subject_name);
440 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki); 480 if (spki) SECKEY_DestroySubjectPublicKeyInfo(spki);
441 if (certreq) CERT_DestroyCertificateRequest(certreq); 481 if (certreq) CERT_DestroyCertificateRequest(certreq);
442 if (validity) CERT_DestroyValidity(validity); 482 if (validity) CERT_DestroyValidity(validity);
443 return identity; 483 return identity;
444 } 484 }
445 485
446 NSSIdentity* NSSIdentity::Generate(const std::string &common_name) { 486 NSSIdentity* NSSIdentity::Generate(const std::string& common_name,
487 KeyType key_type) {
447 SSLIdentityParams params; 488 SSLIdentityParams params;
448 params.common_name = common_name; 489 params.common_name = common_name;
449 params.not_before = CERTIFICATE_WINDOW; 490 params.not_before = CERTIFICATE_WINDOW;
450 params.not_after = CERTIFICATE_LIFETIME; 491 params.not_after = CERTIFICATE_LIFETIME;
492 params.key_type = key_type;
451 return GenerateInternal(params); 493 return GenerateInternal(params);
452 } 494 }
453 495
454 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params) { 496 NSSIdentity* NSSIdentity::GenerateForTest(const SSLIdentityParams& params) {
455 return GenerateInternal(params); 497 return GenerateInternal(params);
456 } 498 }
457 499
458 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key, 500 SSLIdentity* NSSIdentity::FromPEMStrings(const std::string& private_key,
459 const std::string& certificate) { 501 const std::string& certificate) {
460 std::string private_key_der; 502 std::string private_key_der;
461 if (!SSLIdentity::PemToDer( 503 if (!SSLIdentity::PemToDer(
462 kPemTypeRsaPrivateKey, private_key, &private_key_der)) 504 kPemTypeRsaPrivateKey, private_key, &private_key_der))
463 return NULL; 505 return nullptr;
464 506
465 SECItem private_key_item; 507 SECItem private_key_item;
466 private_key_item.data = reinterpret_cast<unsigned char *>( 508 private_key_item.data = reinterpret_cast<unsigned char *>(
467 const_cast<char *>(private_key_der.c_str())); 509 const_cast<char *>(private_key_der.c_str()));
468 private_key_item.len = checked_cast<unsigned int>(private_key_der.size()); 510 private_key_item.len = checked_cast<unsigned int>(private_key_der.size());
469 511
470 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | 512 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT |
471 KU_DIGITAL_SIGNATURE; 513 KU_DIGITAL_SIGNATURE;
472 514
473 SECKEYPrivateKey* privkey = NULL; 515 SECKEYPrivateKey* privkey = nullptr;
474 SECStatus rv = 516 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
475 PK11_ImportDERPrivateKeyInfoAndReturnKey(NSSContext::GetSlot(), 517 NSSContext::GetSlot(), &private_key_item, nullptr, nullptr, PR_FALSE,
476 &private_key_item, 518 PR_FALSE, key_usage, &privkey, nullptr);
477 NULL, NULL, PR_FALSE, PR_FALSE,
478 key_usage, &privkey, NULL);
479 if (rv != SECSuccess) { 519 if (rv != SECSuccess) {
480 LOG(LS_ERROR) << "Couldn't import private key"; 520 LOG(LS_ERROR) << "Couldn't import private key";
481 return NULL; 521 return nullptr;
482 } 522 }
483 523
484 SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(privkey); 524 SECKEYPublicKey* pubkey = SECKEY_ConvertToPublicKey(privkey);
485 if (rv != SECSuccess) { 525 if (rv != SECSuccess) {
486 SECKEY_DestroyPrivateKey(privkey); 526 SECKEY_DestroyPrivateKey(privkey);
487 LOG(LS_ERROR) << "Couldn't convert private key to public key"; 527 LOG(LS_ERROR) << "Couldn't convert private key to public key";
488 return NULL; 528 return nullptr;
529 }
530
531 SSLKEAType ssl_kea_type;
532 if (rtc::starts_with(private_key.c_str(),
533 "-----BEGIN RSA PRIVATE KEY-----")) {
534 ssl_kea_type = ssl_kea_rsa;
535 } else {
536 // We might want to check more key types here. But since we're moving to
537 // Open/BoringSSL, don't bother. Besides, this will likely be correct for
538 // any future key type, causing a test to do more harm than good.
539 ssl_kea_type = ssl_kea_ecdh;
489 } 540 }
490 541
491 // Assign to a scoped_ptr so we don't leak on error. 542 // Assign to a scoped_ptr so we don't leak on error.
492 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey)); 543 scoped_ptr<NSSKeyPair> keypair(new NSSKeyPair(privkey, pubkey, ssl_kea_type));
493 544
494 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate)); 545 scoped_ptr<NSSCertificate> cert(NSSCertificate::FromPEMString(certificate));
495 if (!cert) { 546 if (!cert) {
496 LOG(LS_ERROR) << "Couldn't parse certificate"; 547 LOG(LS_ERROR) << "Couldn't parse certificate";
497 return NULL; 548 return nullptr;
498 } 549 }
499 550
500 // TODO(ekr@rtfm.com): Check the public key against the certificate. 551 // TODO(ekr@rtfm.com): Check the public key against the certificate.
501
502 return new NSSIdentity(keypair.release(), cert.release()); 552 return new NSSIdentity(keypair.release(), cert.release());
503 } 553 }
504 554
505 NSSIdentity::~NSSIdentity() { 555 NSSIdentity::~NSSIdentity() {
506 LOG(LS_INFO) << "Destroying NSS identity"; 556 LOG(LS_INFO) << "Destroying NSS identity";
507 } 557 }
508 558
509 NSSIdentity *NSSIdentity::GetReference() const { 559 NSSIdentity* NSSIdentity::GetReference() const {
510 NSSKeyPair *keypair = keypair_->GetReference(); 560 NSSKeyPair* keypair = keypair_->GetReference();
511 if (!keypair) 561 if (!keypair)
512 return NULL; 562 return nullptr;
513 563
514 NSSCertificate *certificate = certificate_->GetReference(); 564 NSSCertificate* certificate = certificate_->GetReference();
515 if (!certificate) { 565 if (!certificate) {
516 delete keypair; 566 delete keypair;
517 return NULL; 567 return nullptr;
518 } 568 }
519 569
520 return new NSSIdentity(keypair, certificate); 570 return new NSSIdentity(keypair, certificate);
521 } 571 }
522 572
523 573
524 NSSCertificate &NSSIdentity::certificate() const { 574 NSSCertificate &NSSIdentity::certificate() const {
525 return *certificate_; 575 return *certificate_;
526 } 576 }
527 577
528 578
529 } // rtc namespace 579 } // rtc namespace
530 580
531 #endif // HAVE_NSS_SSL_H 581 #endif // HAVE_NSS_SSL_H
532
OLDNEW
« no previous file with comments | « webrtc/base/nssidentity.h ('k') | webrtc/base/nssstreamadapter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698