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

Side by Side Diff: rtc_base/opensslidentity.cc

Issue 3010363002: Implement GetChain for OpenSSLCertificate.
Patch Set: Adding unit tests and clean up. Created 3 years, 2 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 | « rtc_base/opensslidentity.h ('k') | rtc_base/opensslidentity_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
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 "rtc_base/opensslidentity.h" 11 #include "rtc_base/opensslidentity.h"
12 12
13 #include <algorithm>
13 #include <memory> 14 #include <memory>
15 #include <vector>
14 16
15 // Must be included first before openssl headers. 17 // Must be included first before openssl headers.
16 #include "rtc_base/win32.h" // NOLINT 18 #include "rtc_base/win32.h" // NOLINT
17 19
18 #include <openssl/bio.h> 20 #include <openssl/bio.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> 23 #include <openssl/bn.h>
22 #include <openssl/rsa.h> 24 #include <openssl/rsa.h>
23 #include <openssl/crypto.h> 25 #include <openssl/crypto.h>
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 } 273 }
272 X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0); 274 X509_print_ex(temp_memory_bio, x509, XN_FLAG_SEP_CPLUS_SPC, 0);
273 BIO_write(temp_memory_bio, "\0", 1); 275 BIO_write(temp_memory_bio, "\0", 1);
274 char* buffer; 276 char* buffer;
275 BIO_get_mem_data(temp_memory_bio, &buffer); 277 BIO_get_mem_data(temp_memory_bio, &buffer);
276 LOG(LS_VERBOSE) << buffer; 278 LOG(LS_VERBOSE) << buffer;
277 BIO_free(temp_memory_bio); 279 BIO_free(temp_memory_bio);
278 } 280 }
279 #endif 281 #endif
280 282
283 OpenSSLCertificate::OpenSSLCertificate(X509* x509) : x509_(x509) {
284 AddReference(x509_);
285 }
286
287 OpenSSLCertificate::OpenSSLCertificate(STACK_OF(X509) * chain) {
288 x509_ = sk_X509_value(chain, 0);
289 AddReference(x509_);
290 for (size_t i = 1; i < sk_X509_num(chain); ++i) {
291 X509* x509 = sk_X509_value(chain, i);
292 cert_chain_.push_back(new OpenSSLCertificate(x509));
293 }
294 }
295
281 OpenSSLCertificate* OpenSSLCertificate::Generate( 296 OpenSSLCertificate* OpenSSLCertificate::Generate(
282 OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) { 297 OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) {
283 SSLIdentityParams actual_params(params); 298 SSLIdentityParams actual_params(params);
284 if (actual_params.common_name.empty()) { 299 if (actual_params.common_name.empty()) {
285 // Use a random string, arbitrarily 8chars long. 300 // Use a random string, arbitrarily 8chars long.
286 actual_params.common_name = CreateRandomString(8); 301 actual_params.common_name = CreateRandomString(8);
287 } 302 }
288 X509* x509 = MakeCertificate(key_pair->pkey(), actual_params); 303 X509* x509 = MakeCertificate(key_pair->pkey(), actual_params);
289 if (!x509) { 304 if (!x509) {
290 LogSSLErrors("Generating certificate"); 305 LogSSLErrors("Generating certificate");
291 return nullptr; 306 return nullptr;
292 } 307 }
293 #if !defined(NDEBUG) 308 #if !defined(NDEBUG)
294 PrintCert(x509); 309 PrintCert(x509);
295 #endif 310 #endif
296 OpenSSLCertificate* ret = new OpenSSLCertificate(x509); 311 OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
297 X509_free(x509); 312 X509_free(x509);
298 return ret; 313 return ret;
299 } 314 }
300 315
301 OpenSSLCertificate* OpenSSLCertificate::FromPEMString( 316 OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
302 const std::string& pem_string) { 317 const std::string& pem_string) {
303 BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1); 318 BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1);
304 if (!bio) 319 if (!bio)
305 return nullptr; 320 return nullptr;
306 BIO_set_mem_eof_return(bio, 0); 321 BIO_set_mem_eof_return(bio, 0);
307 X509* x509 = 322 X509* x509 =
308 PEM_read_bio_X509(bio, nullptr, nullptr, const_cast<char*>("\0")); 323 PEM_read_bio_X509(bio, nullptr, nullptr, const_cast<char*>("\0"));
324 STACK_OF(X509)* x509s = sk_X509_new_null();
325 while (x509 != nullptr) {
326 sk_X509_push(x509s, x509);
327 x509 = PEM_read_bio_X509(bio, nullptr, nullptr, const_cast<char*>("\0"));
328 }
309 BIO_free(bio); // Frees the BIO, but not the pointed-to string. 329 BIO_free(bio); // Frees the BIO, but not the pointed-to string.
310 330
311 if (!x509) 331 if (sk_X509_num(x509s) == 0)
312 return nullptr; 332 return nullptr;
313 333
314 OpenSSLCertificate* ret = new OpenSSLCertificate(x509); 334 OpenSSLCertificate* ret = new OpenSSLCertificate(x509s);
315 X509_free(x509); 335 sk_X509_pop_free(x509s, X509_free);
316 return ret; 336 return ret;
317 } 337 }
318 338
319 // NOTE: This implementation only functions correctly after InitializeSSL 339 // NOTE: This implementation only functions correctly after InitializeSSL
320 // and before CleanupSSL. 340 // and before CleanupSSL.
321 bool OpenSSLCertificate::GetSignatureDigestAlgorithm( 341 bool OpenSSLCertificate::GetSignatureDigestAlgorithm(
322 std::string* algorithm) const { 342 std::string* algorithm) const {
323 int nid = OBJ_obj2nid(x509_->sig_alg->algorithm); 343 int nid = OBJ_obj2nid(x509_->sig_alg->algorithm);
324 switch (nid) { 344 switch (nid) {
325 case NID_md5WithRSA: 345 case NID_md5WithRSA:
(...skipping 29 matching lines...) Expand all
355 // Unknown algorithm. There are several unhandled options that are less 375 // Unknown algorithm. There are several unhandled options that are less
356 // common and more complex. 376 // common and more complex.
357 LOG(LS_ERROR) << "Unknown signature algorithm NID: " << nid; 377 LOG(LS_ERROR) << "Unknown signature algorithm NID: " << nid;
358 algorithm->clear(); 378 algorithm->clear();
359 return false; 379 return false;
360 } 380 }
361 return true; 381 return true;
362 } 382 }
363 383
364 std::unique_ptr<SSLCertChain> OpenSSLCertificate::GetChain() const { 384 std::unique_ptr<SSLCertChain> OpenSSLCertificate::GetChain() const {
365 // Chains are not yet supported when using OpenSSL. 385 if (cert_chain_.empty()) {
366 // OpenSSLStreamAdapter::SSLVerifyCallback currently requires the remote 386 return nullptr;
367 // certificate to be self-signed. 387 }
368 return nullptr; 388 std::unique_ptr<SSLCertChain> chain(new SSLCertChain(cert_chain_));
389 return chain;
369 } 390 }
370 391
371 bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm, 392 bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm,
372 unsigned char* digest, 393 unsigned char* digest,
373 size_t size, 394 size_t size,
374 size_t* length) const { 395 size_t* length) const {
375 return ComputeDigest(x509_, algorithm, digest, size, length); 396 return ComputeDigest(x509_, algorithm, digest, size, length);
376 } 397 }
377 398
378 bool OpenSSLCertificate::ComputeDigest(const X509* x509, 399 bool OpenSSLCertificate::ComputeDigest(const X509* x509,
(...skipping 12 matching lines...) Expand all
391 412
392 X509_digest(x509, md, digest, &n); 413 X509_digest(x509, md, digest, &n);
393 414
394 *length = n; 415 *length = n;
395 416
396 return true; 417 return true;
397 } 418 }
398 419
399 OpenSSLCertificate::~OpenSSLCertificate() { 420 OpenSSLCertificate::~OpenSSLCertificate() {
400 X509_free(x509_); 421 X509_free(x509_);
422 for (SSLCertificate* cert : cert_chain_) {
423 delete cert;
424 }
425 }
426
427 X509* OpenSSLCertificate::GetX509Reference() const {
428 if (x509_ != nullptr) {
429 AddReference(x509_);
430 }
431 return x509_;
401 } 432 }
402 433
403 OpenSSLCertificate* OpenSSLCertificate::GetReference() const { 434 OpenSSLCertificate* OpenSSLCertificate::GetReference() const {
404 return new OpenSSLCertificate(x509_); 435 STACK_OF(X509)* stack_x509 = sk_X509_new_null();
436 sk_X509_push(stack_x509, x509_);
437 for (auto cert_it = cert_chain_.begin(); cert_it != cert_chain_.end();
438 ++cert_it) {
439 OpenSSLCertificate* cert = reinterpret_cast<OpenSSLCertificate*>(*cert_it);
440 sk_X509_push(stack_x509, cert->x509());
441 }
442 return new OpenSSLCertificate(stack_x509);
405 } 443 }
406 444
407 std::string OpenSSLCertificate::ToPEMString() const { 445 std::string OpenSSLCertificate::ToPEMString() const {
408 BIO* bio = BIO_new(BIO_s_mem()); 446 BIO* bio = BIO_new(BIO_s_mem());
409 if (!bio) { 447 if (!bio) {
410 FATAL() << "unreachable code"; 448 FATAL() << "unreachable code";
411 } 449 }
412 if (!PEM_write_bio_X509(bio, x509_)) { 450 if (!PEM_write_bio_X509(bio, x509_)) {
413 BIO_free(bio); 451 BIO_free(bio);
414 FATAL() << "unreachable code"; 452 FATAL() << "unreachable code";
415 } 453 }
416 BIO_write(bio, "\0", 1); 454 BIO_write(bio, "\0", 1);
417 char* buffer; 455 char* buffer;
418 BIO_get_mem_data(bio, &buffer); 456 BIO_get_mem_data(bio, &buffer);
419 std::string ret(buffer); 457 std::string ret(buffer);
420 BIO_free(bio); 458 BIO_free(bio);
459 for (size_t i = 0; i < cert_chain_.size(); ++i) {
460 OpenSSLCertificate* cert =
461 reinterpret_cast<OpenSSLCertificate*>(cert_chain_[i]);
462 ret += cert->ToPEMString();
463 }
421 return ret; 464 return ret;
422 } 465 }
423 466
424 void OpenSSLCertificate::ToDER(Buffer* der_buffer) const { 467 void OpenSSLCertificate::ToDER(Buffer* der_buffer) const {
425 // In case of failure, make sure to leave the buffer empty. 468 // In case of failure, make sure to leave the buffer empty.
426 der_buffer->SetSize(0); 469 der_buffer->SetSize(0);
427 470
428 // Calculates the DER representation of the certificate, from scratch. 471 // Calculates the DER representation of the certificate, from scratch.
429 BIO* bio = BIO_new(BIO_s_mem()); 472 BIO* bio = BIO_new(BIO_s_mem());
430 if (!bio) { 473 if (!bio) {
431 FATAL() << "unreachable code"; 474 FATAL() << "unreachable code";
432 } 475 }
433 if (!i2d_X509_bio(bio, x509_)) { 476 if (!i2d_X509_bio(bio, x509_)) {
434 BIO_free(bio); 477 BIO_free(bio);
435 FATAL() << "unreachable code"; 478 FATAL() << "unreachable code";
436 } 479 }
437 char* data; 480 char* data;
438 size_t length = BIO_get_mem_data(bio, &data); 481 size_t length = BIO_get_mem_data(bio, &data);
439 der_buffer->SetData(data, length); 482 der_buffer->SetData(data, length);
440 BIO_free(bio); 483 BIO_free(bio);
441 } 484 }
442 485
443 void OpenSSLCertificate::AddReference() const { 486 void OpenSSLCertificate::AddReference(X509* x509) const {
444 RTC_DCHECK(x509_ != nullptr); 487 RTC_DCHECK(x509 != nullptr);
445 #if defined(OPENSSL_IS_BORINGSSL) 488 #if defined(OPENSSL_IS_BORINGSSL)
446 X509_up_ref(x509_); 489 X509_up_ref(x509);
447 #else 490 #else
448 CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509); 491 CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
449 #endif 492 #endif
450 } 493 }
451 494
452 bool OpenSSLCertificate::operator==(const OpenSSLCertificate& other) const { 495 bool OpenSSLCertificate::operator==(const OpenSSLCertificate& other) const {
496 if (this->cert_chain_.size() != other.cert_chain_.size()) {
497 return false;
498 }
499 for (size_t i = 0; i < cert_chain_.size(); ++i) {
500 OpenSSLCertificate* cert =
501 reinterpret_cast<OpenSSLCertificate*>(cert_chain_[i]);
502 OpenSSLCertificate* other_cert =
503 reinterpret_cast<OpenSSLCertificate*>(other.cert_chain_[i]);
504 if (*cert != *other_cert) {
505 return false;
506 }
507 }
453 return X509_cmp(this->x509_, other.x509_) == 0; 508 return X509_cmp(this->x509_, other.x509_) == 0;
454 } 509 }
455 510
456 bool OpenSSLCertificate::operator!=(const OpenSSLCertificate& other) const { 511 bool OpenSSLCertificate::operator!=(const OpenSSLCertificate& other) const {
457 return !(*this == other); 512 return !(*this == other);
458 } 513 }
459 514
460 // Documented in sslidentity.h. 515 // Documented in sslidentity.h.
461 int64_t OpenSSLCertificate::CertificateExpirationTime() const { 516 int64_t OpenSSLCertificate::CertificateExpirationTime() const {
462 ASN1_TIME* expire_time = X509_get_notAfter(x509_); 517 ASN1_TIME* expire_time = X509_get_notAfter(x509_);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 certificate_->GetReference()); 601 certificate_->GetReference());
547 } 602 }
548 603
549 bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) { 604 bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
550 // 1 is the documented success return code. 605 // 1 is the documented success return code.
551 if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 || 606 if (SSL_CTX_use_certificate(ctx, certificate_->x509()) != 1 ||
552 SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) { 607 SSL_CTX_use_PrivateKey(ctx, key_pair_->pkey()) != 1) {
553 LogSSLErrors("Configuring key and certificate"); 608 LogSSLErrors("Configuring key and certificate");
554 return false; 609 return false;
555 } 610 }
611 // If Chains are available, use it.
612 std::unique_ptr<SSLCertChain> cert_chain = certificate_->GetChain();
613 for (size_t i = 0; cert_chain != nullptr && i < cert_chain->GetSize(); ++i) {
614 const OpenSSLCertificate* cert =
615 reinterpret_cast<const OpenSSLCertificate*>(&cert_chain->Get(i));
616 if (!SSL_CTX_add_extra_chain_cert(ctx, cert->GetX509Reference())) {
617 LogSSLErrors("Configuring intermediate certificate");
618 return false;
619 }
620 }
556 return true; 621 return true;
557 } 622 }
558 623
559 std::string OpenSSLIdentity::PrivateKeyToPEMString() const { 624 std::string OpenSSLIdentity::PrivateKeyToPEMString() const {
560 return key_pair_->PrivateKeyToPEMString(); 625 return key_pair_->PrivateKeyToPEMString();
561 } 626 }
562 627
563 std::string OpenSSLIdentity::PublicKeyToPEMString() const { 628 std::string OpenSSLIdentity::PublicKeyToPEMString() const {
564 return key_pair_->PublicKeyToPEMString(); 629 return key_pair_->PublicKeyToPEMString();
565 } 630 }
566 631
567 bool OpenSSLIdentity::operator==(const OpenSSLIdentity& other) const { 632 bool OpenSSLIdentity::operator==(const OpenSSLIdentity& other) const {
568 return *this->key_pair_ == *other.key_pair_ && 633 return *this->key_pair_ == *other.key_pair_ &&
569 *this->certificate_ == *other.certificate_; 634 *this->certificate_ == *other.certificate_;
570 } 635 }
571 636
572 bool OpenSSLIdentity::operator!=(const OpenSSLIdentity& other) const { 637 bool OpenSSLIdentity::operator!=(const OpenSSLIdentity& other) const {
573 return !(*this == other); 638 return !(*this == other);
574 } 639 }
575 640
576 } // namespace rtc 641 } // namespace rtc
OLDNEW
« no previous file with comments | « rtc_base/opensslidentity.h ('k') | rtc_base/opensslidentity_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698