| Index: rtc_base/opensslidentity.cc
|
| diff --git a/rtc_base/opensslidentity.cc b/rtc_base/opensslidentity.cc
|
| index 075a1b5485a80c745ee84b4991af0b86017df4f0..b22b0a5ca5485ca3046dd665d2c6795d57f4b445 100644
|
| --- a/rtc_base/opensslidentity.cc
|
| +++ b/rtc_base/opensslidentity.cc
|
| @@ -10,7 +10,9 @@
|
|
|
| #include "rtc_base/opensslidentity.h"
|
|
|
| +#include <algorithm>
|
| #include <memory>
|
| +#include <vector>
|
|
|
| // Must be included first before openssl headers.
|
| #include "rtc_base/win32.h" // NOLINT
|
| @@ -278,6 +280,19 @@ static void PrintCert(X509* x509) {
|
| }
|
| #endif
|
|
|
| +OpenSSLCertificate::OpenSSLCertificate(X509* x509) : x509_(x509) {
|
| + AddReference(x509_);
|
| +}
|
| +
|
| +OpenSSLCertificate::OpenSSLCertificate(STACK_OF(X509) * chain) {
|
| + x509_ = sk_X509_value(chain, 0);
|
| + AddReference(x509_);
|
| + for (size_t i = 1; i < sk_X509_num(chain); ++i) {
|
| + X509* x509 = sk_X509_value(chain, i);
|
| + cert_chain_.push_back(new OpenSSLCertificate(x509));
|
| + }
|
| +}
|
| +
|
| OpenSSLCertificate* OpenSSLCertificate::Generate(
|
| OpenSSLKeyPair* key_pair, const SSLIdentityParams& params) {
|
| SSLIdentityParams actual_params(params);
|
| @@ -306,13 +321,18 @@ OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
|
| BIO_set_mem_eof_return(bio, 0);
|
| X509* x509 =
|
| PEM_read_bio_X509(bio, nullptr, nullptr, const_cast<char*>("\0"));
|
| + STACK_OF(X509)* x509s = sk_X509_new_null();
|
| + while (x509 != nullptr) {
|
| + sk_X509_push(x509s, x509);
|
| + x509 = PEM_read_bio_X509(bio, nullptr, nullptr, const_cast<char*>("\0"));
|
| + }
|
| BIO_free(bio); // Frees the BIO, but not the pointed-to string.
|
|
|
| - if (!x509)
|
| + if (sk_X509_num(x509s) == 0)
|
| return nullptr;
|
|
|
| - OpenSSLCertificate* ret = new OpenSSLCertificate(x509);
|
| - X509_free(x509);
|
| + OpenSSLCertificate* ret = new OpenSSLCertificate(x509s);
|
| + sk_X509_pop_free(x509s, X509_free);
|
| return ret;
|
| }
|
|
|
| @@ -362,10 +382,11 @@ bool OpenSSLCertificate::GetSignatureDigestAlgorithm(
|
| }
|
|
|
| std::unique_ptr<SSLCertChain> OpenSSLCertificate::GetChain() const {
|
| - // Chains are not yet supported when using OpenSSL.
|
| - // OpenSSLStreamAdapter::SSLVerifyCallback currently requires the remote
|
| - // certificate to be self-signed.
|
| - return nullptr;
|
| + if (cert_chain_.empty()) {
|
| + return nullptr;
|
| + }
|
| + std::unique_ptr<SSLCertChain> chain(new SSLCertChain(cert_chain_));
|
| + return chain;
|
| }
|
|
|
| bool OpenSSLCertificate::ComputeDigest(const std::string& algorithm,
|
| @@ -398,10 +419,27 @@ bool OpenSSLCertificate::ComputeDigest(const X509* x509,
|
|
|
| OpenSSLCertificate::~OpenSSLCertificate() {
|
| X509_free(x509_);
|
| + for (SSLCertificate* cert : cert_chain_) {
|
| + delete cert;
|
| + }
|
| +}
|
| +
|
| +X509* OpenSSLCertificate::GetX509Reference() const {
|
| + if (x509_ != nullptr) {
|
| + AddReference(x509_);
|
| + }
|
| + return x509_;
|
| }
|
|
|
| OpenSSLCertificate* OpenSSLCertificate::GetReference() const {
|
| - return new OpenSSLCertificate(x509_);
|
| + STACK_OF(X509)* stack_x509 = sk_X509_new_null();
|
| + sk_X509_push(stack_x509, x509_);
|
| + for (auto cert_it = cert_chain_.begin(); cert_it != cert_chain_.end();
|
| + ++cert_it) {
|
| + OpenSSLCertificate* cert = reinterpret_cast<OpenSSLCertificate*>(*cert_it);
|
| + sk_X509_push(stack_x509, cert->x509());
|
| + }
|
| + return new OpenSSLCertificate(stack_x509);
|
| }
|
|
|
| std::string OpenSSLCertificate::ToPEMString() const {
|
| @@ -418,6 +456,11 @@ std::string OpenSSLCertificate::ToPEMString() const {
|
| BIO_get_mem_data(bio, &buffer);
|
| std::string ret(buffer);
|
| BIO_free(bio);
|
| + for (size_t i = 0; i < cert_chain_.size(); ++i) {
|
| + OpenSSLCertificate* cert =
|
| + reinterpret_cast<OpenSSLCertificate*>(cert_chain_[i]);
|
| + ret += cert->ToPEMString();
|
| + }
|
| return ret;
|
| }
|
|
|
| @@ -440,16 +483,28 @@ void OpenSSLCertificate::ToDER(Buffer* der_buffer) const {
|
| BIO_free(bio);
|
| }
|
|
|
| -void OpenSSLCertificate::AddReference() const {
|
| - RTC_DCHECK(x509_ != nullptr);
|
| +void OpenSSLCertificate::AddReference(X509* x509) const {
|
| + RTC_DCHECK(x509 != nullptr);
|
| #if defined(OPENSSL_IS_BORINGSSL)
|
| - X509_up_ref(x509_);
|
| + X509_up_ref(x509);
|
| #else
|
| - CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509);
|
| + CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
|
| #endif
|
| }
|
|
|
| bool OpenSSLCertificate::operator==(const OpenSSLCertificate& other) const {
|
| + if (this->cert_chain_.size() != other.cert_chain_.size()) {
|
| + return false;
|
| + }
|
| + for (size_t i = 0; i < cert_chain_.size(); ++i) {
|
| + OpenSSLCertificate* cert =
|
| + reinterpret_cast<OpenSSLCertificate*>(cert_chain_[i]);
|
| + OpenSSLCertificate* other_cert =
|
| + reinterpret_cast<OpenSSLCertificate*>(other.cert_chain_[i]);
|
| + if (*cert != *other_cert) {
|
| + return false;
|
| + }
|
| + }
|
| return X509_cmp(this->x509_, other.x509_) == 0;
|
| }
|
|
|
| @@ -553,6 +608,16 @@ bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
|
| LogSSLErrors("Configuring key and certificate");
|
| return false;
|
| }
|
| + // If Chains are available, use it.
|
| + std::unique_ptr<SSLCertChain> cert_chain = certificate_->GetChain();
|
| + for (size_t i = 0; cert_chain != nullptr && i < cert_chain->GetSize(); ++i) {
|
| + const OpenSSLCertificate* cert =
|
| + reinterpret_cast<const OpenSSLCertificate*>(&cert_chain->Get(i));
|
| + if (!SSL_CTX_add_extra_chain_cert(ctx, cert->GetX509Reference())) {
|
| + LogSSLErrors("Configuring intermediate certificate");
|
| + return false;
|
| + }
|
| + }
|
| return true;
|
| }
|
|
|
|
|