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

Side by Side Diff: webrtc/rtc_base/opensslidentity.cc

Issue 3010363002: Implement GetChain for OpenSSLCertificate.
Patch Set: Created 3 years, 3 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/rtc_base/opensslidentity.h ('k') | webrtc/rtc_base/opensslstreamadapter.cc » ('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 2004 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2004 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
11 #include "webrtc/rtc_base/opensslidentity.h" 11 #include "webrtc/rtc_base/opensslidentity.h"
12 12
13 #include <memory> 13 #include <memory>
14 14
15 // Must be included first before openssl headers. 15 // Must be included first before openssl headers.
16 #include "webrtc/rtc_base/win32.h" // NOLINT 16 #include "webrtc/rtc_base/win32.h" // NOLINT
17 17
18 #include <openssl/bio.h> 18 #include <openssl/bio.h>
19 #include <openssl/bn.h>
20 #include <openssl/crypto.h>
19 #include <openssl/err.h> 21 #include <openssl/err.h>
20 #include <openssl/pem.h> 22 #include <openssl/pem.h>
21 #include <openssl/bn.h>
22 #include <openssl/rsa.h> 23 #include <openssl/rsa.h>
23 #include <openssl/crypto.h>
24 24
25 #include "webrtc/rtc_base/checks.h" 25 #include "webrtc/rtc_base/checks.h"
26 #include "webrtc/rtc_base/helpers.h" 26 #include "webrtc/rtc_base/helpers.h"
27 #include "webrtc/rtc_base/logging.h" 27 #include "webrtc/rtc_base/logging.h"
28 #include "webrtc/rtc_base/openssl.h" 28 #include "webrtc/rtc_base/openssl.h"
29 #include "webrtc/rtc_base/openssldigest.h" 29 #include "webrtc/rtc_base/openssldigest.h"
30 30
31 namespace rtc { 31 namespace rtc {
32 32
33 // We could have exposed a myriad of parameters for the crypto stuff, 33 // We could have exposed a myriad of parameters for the crypto stuff,
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 goto error; 136 goto error;
137 137
138 if (!X509_sign(x509, pkey, EVP_sha256())) 138 if (!X509_sign(x509, pkey, EVP_sha256()))
139 goto error; 139 goto error;
140 140
141 BN_free(serial_number); 141 BN_free(serial_number);
142 X509_NAME_free(name); 142 X509_NAME_free(name);
143 LOG(LS_INFO) << "Returning certificate"; 143 LOG(LS_INFO) << "Returning certificate";
144 return x509; 144 return x509;
145 145
146 error: 146 error:
147 BN_free(serial_number); 147 BN_free(serial_number);
148 X509_NAME_free(name); 148 X509_NAME_free(name);
149 X509_free(x509); 149 X509_free(x509);
150 return nullptr; 150 return nullptr;
151 } 151 }
152 152
153 // This dumps the SSL error stack to the log. 153 // This dumps the SSL error stack to the log.
154 static void LogSSLErrors(const std::string& prefix) { 154 static void LogSSLErrors(const std::string& prefix) {
155 char error_buf[200]; 155 char error_buf[200];
156 unsigned long err; 156 unsigned long err;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 #endif 210 #endif
211 } 211 }
212 212
213 std::string OpenSSLKeyPair::PrivateKeyToPEMString() const { 213 std::string OpenSSLKeyPair::PrivateKeyToPEMString() const {
214 BIO* temp_memory_bio = BIO_new(BIO_s_mem()); 214 BIO* temp_memory_bio = BIO_new(BIO_s_mem());
215 if (!temp_memory_bio) { 215 if (!temp_memory_bio) {
216 LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; 216 LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
217 RTC_NOTREACHED(); 217 RTC_NOTREACHED();
218 return ""; 218 return "";
219 } 219 }
220 if (!PEM_write_bio_PrivateKey( 220 if (!PEM_write_bio_PrivateKey(temp_memory_bio, pkey_, nullptr, nullptr, 0,
221 temp_memory_bio, pkey_, nullptr, nullptr, 0, nullptr, nullptr)) { 221 nullptr, nullptr)) {
222 LOG_F(LS_ERROR) << "Failed to write private key"; 222 LOG_F(LS_ERROR) << "Failed to write private key";
223 BIO_free(temp_memory_bio); 223 BIO_free(temp_memory_bio);
224 RTC_NOTREACHED(); 224 RTC_NOTREACHED();
225 return ""; 225 return "";
226 } 226 }
227 BIO_write(temp_memory_bio, "\0", 1); 227 BIO_write(temp_memory_bio, "\0", 1);
228 char* buffer; 228 char* buffer;
229 BIO_get_mem_data(temp_memory_bio, &buffer); 229 BIO_get_mem_data(temp_memory_bio, &buffer);
230 std::string priv_key_str = buffer; 230 std::string priv_key_str = buffer;
231 BIO_free(temp_memory_bio); 231 BIO_free(temp_memory_bio);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 } 271 }
272 X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0); 272 X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0);
273 BIO_write(temp_memory_bio, "\0", 1); 273 BIO_write(temp_memory_bio, "\0", 1);
274 char* buffer; 274 char* buffer;
275 BIO_get_mem_data(temp_memory_bio, &buffer); 275 BIO_get_mem_data(temp_memory_bio, &buffer);
276 LOG(LS_VERBOSE) << buffer; 276 LOG(LS_VERBOSE) << buffer;
277 BIO_free(temp_memory_bio); 277 BIO_free(temp_memory_bio);
278 } 278 }
279 #endif 279 #endif
280 280
281 OpenSSLCertificate::OpenSSLCertificate(X509* x509) : x509_(x509) {
282 AddReference(x509_);
283 }
284
285 OpenSSLCertificate::OpenSSLCertificate(STACK_OF(X509) * chain) {
286 x509_ = sk_X509_value(chain, 0);
287 LOG(LS_INFO) << "leaf_cert:" << x509_->name;
Taylor Brandstetter 2017/09/26 00:57:26 Are these logs statements intended to be in the fi
pthatcher1 2017/09/26 20:55:07 Even at verbose level I'm not sure they are worth
288 AddReference(x509_);
289 for (size_t i = 1; i < sk_X509_num(chain); ++i) {
Taylor Brandstetter 2017/09/26 00:57:26 May be a dumb question, but is there a reason for
290 X509* x509 = sk_X509_value(chain, i);
291 AddReference(x509);
292 LOG(LS_INFO) << "parent certificate name:" << x509->name;
293 cert_chain_.push_back(new OpenSSLCertificate(x509));
pthatcher1 2017/09/26 20:55:07 Passing in the x509 here cause the constructor to
294 }
295 }
296
281 OpenSSLCertificate* OpenSSLCertificate::Generate( 297 OpenSSLCertificate* OpenSSLCertificate::Generate(
282 OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) { 298 OpenSSLKeyPair* key_pair,
299 const SSLIdentityParams& params) {
283 SSLIdentityParams actual_params(params); 300 SSLIdentityParams actual_params(params);
284 if (actual_params.common_name.empty()) { 301 if (actual_params.common_name.empty()) {
285 // Use a random string, arbitrarily 8chars long. 302 // Use a random string, arbitrarily 8chars long.
286 actual_params.common_name = CreateRandomString(8); 303 actual_params.common_name = CreateRandomString(8);
287 } 304 }
288 X509* x509 = MakeCertificate(key_pair->pkey(), actual_params); 305 X509* x509 = MakeCertificate(key_pair->pkey(), actual_params);
289 if (!x509) { 306 if (!x509) {
290 LogSSLErrors("Generating certificate"); 307 LogSSLErrors("Generating certificate");
291 return nullptr; 308 return nullptr;
292 } 309 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 // Unknown algorithm. There are several unhandled options that are less 372 // Unknown algorithm. There are several unhandled options that are less
356 // common and more complex. 373 // common and more complex.
357 LOG(LS_ERROR) << "Unknown signature algorithm NID: " << nid; 374 LOG(LS_ERROR) << "Unknown signature algorithm NID: " << nid;
358 algorithm->clear(); 375 algorithm->clear();
359 return false; 376 return false;
360 } 377 }
361 return true; 378 return true;
362 } 379 }
363 380
364 std::unique_ptr<SSLCertChain> OpenSSLCertificate::GetChain() const { 381 std::unique_ptr<SSLCertChain> OpenSSLCertificate::GetChain() const {
365 // Chains are not yet supported when using OpenSSL. 382 if (cert_chain_.empty()) {
366 // OpenSSLStreamAdapter::SSLVerifyCallback currently requires the remote 383 return nullptr;
367 // certificate to be self-signed. 384 }
368 return nullptr; 385 std::vector<SSLCertificate*> new_certs(cert_chain_.size());
386 std::transform(cert_chain_.begin(), cert_chain_.end(), new_certs.begin(),
387 [](OpenSSLCertificate* cert) -> SSLCertificate* {
388 return cert->GetReference();
389 });
390 std::unique_ptr<SSLCertChain> chain(new SSLCertChain(new_certs));
391 std::for_each(new_certs.begin(), new_certs.end(),
392 [](SSLCertificate* cert) { delete cert; });
pthatcher1 2017/09/26 20:55:07 I find this confusing. We create a copy of the ve
393 return chain;
369 } 394 }
370 395
371 bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm, 396 bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm,
372 unsigned char* digest, 397 unsigned char* digest,
373 size_t size, 398 size_t size,
374 size_t* length) const { 399 size_t* length) const {
375 return ComputeDigest(x509_, algorithm, digest, size, length); 400 return ComputeDigest(x509_, algorithm, digest, size, length);
376 } 401 }
377 402
378 bool OpenSSLCertificate::ComputeDigest(const X509* x509, 403 bool OpenSSLCertificate::ComputeDigest(const X509* x509,
(...skipping 15 matching lines...) Expand all
394 *length = n; 419 *length = n;
395 420
396 return true; 421 return true;
397 } 422 }
398 423
399 OpenSSLCertificate::~OpenSSLCertificate() { 424 OpenSSLCertificate::~OpenSSLCertificate() {
400 X509_free(x509_); 425 X509_free(x509_);
401 } 426 }
402 427
403 OpenSSLCertificate* OpenSSLCertificate::GetReference() const { 428 OpenSSLCertificate* OpenSSLCertificate::GetReference() const {
404 return new OpenSSLCertificate(x509_); 429 if (cert_chain_.empty()) {
430 return new OpenSSLCertificate(x509_);
431 }
432 STACK_OF(X509)* stack_x509 = sk_X509_new_null();
433 sk_X509_push(stack_x509, x509_);
434 LOG(LS_INFO) << "Push cert to stack:" << x509_->name;
Taylor Brandstetter 2017/09/26 00:57:26 Same question about log messages. Should be verbos
435 for (auto cert_it = cert_chain_.begin(); cert_it != cert_chain_.end();
436 ++cert_it) {
437 LOG(LS_INFO) << "Push cert to stack:" << (*cert_it)->x509()->name;
438 sk_X509_push(stack_x509, (*cert_it)->x509());
439 }
440 return new OpenSSLCertificate(stack_x509);
405 } 441 }
406 442
407 std::string OpenSSLCertificate::ToPEMString() const { 443 std::string OpenSSLCertificate::ToPEMString() const {
408 BIO* bio = BIO_new(BIO_s_mem()); 444 BIO* bio = BIO_new(BIO_s_mem());
409 if (!bio) { 445 if (!bio) {
410 FATAL() << "unreachable code"; 446 FATAL() << "unreachable code";
411 } 447 }
412 if (!PEM_write_bio_X509(bio, x509_)) { 448 if (!PEM_write_bio_X509(bio, x509_)) {
413 BIO_free(bio); 449 BIO_free(bio);
414 FATAL() << "unreachable code"; 450 FATAL() << "unreachable code";
(...skipping 18 matching lines...) Expand all
433 if (!i2d_X509_bio(bio, x509_)) { 469 if (!i2d_X509_bio(bio, x509_)) {
434 BIO_free(bio); 470 BIO_free(bio);
435 FATAL() << "unreachable code"; 471 FATAL() << "unreachable code";
436 } 472 }
437 char* data; 473 char* data;
438 size_t length = BIO_get_mem_data(bio, &data); 474 size_t length = BIO_get_mem_data(bio, &data);
439 der_buffer->SetData(data, length); 475 der_buffer->SetData(data, length);
440 BIO_free(bio); 476 BIO_free(bio);
441 } 477 }
442 478
443 void OpenSSLCertificate::AddReference() const { 479 void OpenSSLCertificate::AddReference(X509* x509) const {
444 RTC_DCHECK(x509_ != nullptr); 480 RTC_DCHECK(x509 != nullptr);
445 #if defined(OPENSSL_IS_BORINGSSL) 481 #if defined(OPENSSL_IS_BORINGSSL)
446 X509_up_ref(x509_); 482 X509_up_ref(x509);
447 #else 483 #else
448 CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509); 484 CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
449 #endif 485 #endif
450 } 486 }
451 487
452 bool OpenSSLCertificate::operator==(const OpenSSLCertificate& other) const { 488 bool OpenSSLCertificate::operator==(const OpenSSLCertificate& other) const {
453 return X509_cmp(this->x509_, other.x509_) == 0; 489 return X509_cmp(this->x509_, other.x509_) == 0;
454 } 490 }
455 491
456 bool OpenSSLCertificate::operator!=(const OpenSSLCertificate& other) const { 492 bool OpenSSLCertificate::operator!=(const OpenSSLCertificate& other) const {
457 return !(*this == other); 493 return !(*this == other);
458 } 494 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 if (params.not_before > params.not_after) 545 if (params.not_before > params.not_after)
510 return nullptr; 546 return nullptr;
511 return GenerateInternal(params); 547 return GenerateInternal(params);
512 } 548 }
513 549
514 OpenSSLIdentity* OpenSSLIdentity::GenerateForTest( 550 OpenSSLIdentity* OpenSSLIdentity::GenerateForTest(
515 const SSLIdentityParams& params) { 551 const SSLIdentityParams& params) {
516 return GenerateInternal(params); 552 return GenerateInternal(params);
517 } 553 }
518 554
519 SSLIdentity* OpenSSLIdentity::FromPEMStrings( 555 SSLIdentity* OpenSSLIdentity::FromPEMStrings(const std::string& private_key,
520 const std::string& private_key, 556 const std::string& certificate) {
521 const std::string& certificate) {
522 std::unique_ptr<OpenSSLCertificate> cert( 557 std::unique_ptr<OpenSSLCertificate> cert(
523 OpenSSLCertificate::FromPEMString(certificate)); 558 OpenSSLCertificate::FromPEMString(certificate));
524 if (!cert) { 559 if (!cert) {
525 LOG(LS_ERROR) << "Failed to create OpenSSLCertificate from PEM string."; 560 LOG(LS_ERROR) << "Failed to create OpenSSLCertificate from PEM string.";
526 return nullptr; 561 return nullptr;
527 } 562 }
528 563
529 OpenSSLKeyPair* key_pair = 564 OpenSSLKeyPair* key_pair =
530 OpenSSLKeyPair::FromPrivateKeyPEMString(private_key); 565 OpenSSLKeyPair::FromPrivateKeyPEMString(private_key);
531 if (!key_pair) { 566 if (!key_pair) {
532 LOG(LS_ERROR) << "Failed to create key pair from PEM string."; 567 LOG(LS_ERROR) << "Failed to create key pair from PEM string.";
533 return nullptr; 568 return nullptr;
534 } 569 }
535 570
536 return new OpenSSLIdentity(key_pair, 571 return new OpenSSLIdentity(key_pair, cert.release());
537 cert.release());
538 } 572 }
539 573
540 const OpenSSLCertificate& OpenSSLIdentity::certificate() const { 574 const OpenSSLCertificate& OpenSSLIdentity::certificate() const {
541 return *certificate_; 575 return *certificate_;
542 } 576 }
543 577
544 OpenSSLIdentity* OpenSSLIdentity::GetReference() const { 578 OpenSSLIdentity* OpenSSLIdentity::GetReference() const {
545 return new OpenSSLIdentity(key_pair_->GetReference(), 579 return new OpenSSLIdentity(key_pair_->GetReference(),
546 certificate_->GetReference()); 580 certificate_->GetReference());
547 } 581 }
548 582
549 bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) { 583 bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
550 // 1 is the documented success return code. 584 // 1 is the documented success return code.
551 if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 || 585 if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 ||
552 SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) { 586 SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) {
553 LogSSLErrors("Configuring key and certificate"); 587 LogSSLErrors("Configuring key and certificate");
554 return false; 588 return false;
555 } 589 }
556 return true; 590 return true;
557 } 591 }
558 592
559 std::string OpenSSLIdentity::PrivateKeyToPEMString() const { 593 std::string OpenSSLIdentity::PrivateKeyToPEMString() const {
560 return key_pair_->PrivateKeyToPEMString(); 594 return key_pair_->PrivateKeyToPEMString();
561 } 595 }
562 596
563 std::string OpenSSLIdentity::PublicKeyToPEMString() const { 597 std::string OpenSSLIdentity::PublicKeyToPEMString() const {
564 return key_pair_->PublicKeyToPEMString(); 598 return key_pair_->PublicKeyToPEMString();
565 } 599 }
566 600
567 bool OpenSSLIdentity::operator==(const OpenSSLIdentity& other) const { 601 bool OpenSSLIdentity::operator==(const OpenSSLIdentity& other) const {
568 return *this->key_pair_ == *other.key_pair_ && 602 return *this->key_pair_ == *other.key_pair_ &&
569 *this->certificate_ == *other.certificate_; 603 *this->certificate_ == *other.certificate_;
570 } 604 }
571 605
572 bool OpenSSLIdentity::operator!=(const OpenSSLIdentity& other) const { 606 bool OpenSSLIdentity::operator!=(const OpenSSLIdentity& other) const {
573 return !(*this == other); 607 return !(*this == other);
574 } 608 }
575 609
576 } // namespace rtc 610 } // namespace rtc
OLDNEW
« no previous file with comments | « webrtc/rtc_base/opensslidentity.h ('k') | webrtc/rtc_base/opensslstreamadapter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698