1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_certificate.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <memory>
14*d9f75844SAndroid Build Coastguard Worker #include <string>
15*d9f75844SAndroid Build Coastguard Worker #include <utility>
16*d9f75844SAndroid Build Coastguard Worker
17*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
18*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/openssl.h"
21*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/boringssl_identity.h"
23*d9f75844SAndroid Build Coastguard Worker #else
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/openssl_identity.h"
25*d9f75844SAndroid Build Coastguard Worker #endif
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_fingerprint.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/third_party/base64/base64.h"
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker namespace rtc {
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
32*d9f75844SAndroid Build Coastguard Worker // SSLCertificateStats
33*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
34*d9f75844SAndroid Build Coastguard Worker
SSLCertificateStats(std::string && fingerprint,std::string && fingerprint_algorithm,std::string && base64_certificate,std::unique_ptr<SSLCertificateStats> issuer)35*d9f75844SAndroid Build Coastguard Worker SSLCertificateStats::SSLCertificateStats(
36*d9f75844SAndroid Build Coastguard Worker std::string&& fingerprint,
37*d9f75844SAndroid Build Coastguard Worker std::string&& fingerprint_algorithm,
38*d9f75844SAndroid Build Coastguard Worker std::string&& base64_certificate,
39*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLCertificateStats> issuer)
40*d9f75844SAndroid Build Coastguard Worker : fingerprint(std::move(fingerprint)),
41*d9f75844SAndroid Build Coastguard Worker fingerprint_algorithm(std::move(fingerprint_algorithm)),
42*d9f75844SAndroid Build Coastguard Worker base64_certificate(std::move(base64_certificate)),
43*d9f75844SAndroid Build Coastguard Worker issuer(std::move(issuer)) {}
44*d9f75844SAndroid Build Coastguard Worker
~SSLCertificateStats()45*d9f75844SAndroid Build Coastguard Worker SSLCertificateStats::~SSLCertificateStats() {}
46*d9f75844SAndroid Build Coastguard Worker
Copy() const47*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLCertificateStats> SSLCertificateStats::Copy() const {
48*d9f75844SAndroid Build Coastguard Worker return std::make_unique<SSLCertificateStats>(
49*d9f75844SAndroid Build Coastguard Worker std::string(fingerprint), std::string(fingerprint_algorithm),
50*d9f75844SAndroid Build Coastguard Worker std::string(base64_certificate), issuer ? issuer->Copy() : nullptr);
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker
53*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
54*d9f75844SAndroid Build Coastguard Worker // SSLCertificate
55*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
56*d9f75844SAndroid Build Coastguard Worker
GetStats() const57*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats() const {
58*d9f75844SAndroid Build Coastguard Worker // TODO(bemasc): Move this computation to a helper class that caches these
59*d9f75844SAndroid Build Coastguard Worker // values to reduce CPU use in `StatsCollector::GetStats`. This will require
60*d9f75844SAndroid Build Coastguard Worker // adding a fast `SSLCertificate::Equals` to detect certificate changes.
61*d9f75844SAndroid Build Coastguard Worker std::string digest_algorithm;
62*d9f75844SAndroid Build Coastguard Worker if (!GetSignatureDigestAlgorithm(&digest_algorithm))
63*d9f75844SAndroid Build Coastguard Worker return nullptr;
64*d9f75844SAndroid Build Coastguard Worker
65*d9f75844SAndroid Build Coastguard Worker // `SSLFingerprint::Create` can fail if the algorithm returned by
66*d9f75844SAndroid Build Coastguard Worker // `SSLCertificate::GetSignatureDigestAlgorithm` is not supported by the
67*d9f75844SAndroid Build Coastguard Worker // implementation of `SSLCertificate::ComputeDigest`. This currently happens
68*d9f75844SAndroid Build Coastguard Worker // with MD5- and SHA-224-signed certificates when linked to libNSS.
69*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLFingerprint> ssl_fingerprint =
70*d9f75844SAndroid Build Coastguard Worker SSLFingerprint::Create(digest_algorithm, *this);
71*d9f75844SAndroid Build Coastguard Worker if (!ssl_fingerprint)
72*d9f75844SAndroid Build Coastguard Worker return nullptr;
73*d9f75844SAndroid Build Coastguard Worker std::string fingerprint = ssl_fingerprint->GetRfc4572Fingerprint();
74*d9f75844SAndroid Build Coastguard Worker
75*d9f75844SAndroid Build Coastguard Worker Buffer der_buffer;
76*d9f75844SAndroid Build Coastguard Worker ToDER(&der_buffer);
77*d9f75844SAndroid Build Coastguard Worker std::string der_base64;
78*d9f75844SAndroid Build Coastguard Worker Base64::EncodeFromArray(der_buffer.data(), der_buffer.size(), &der_base64);
79*d9f75844SAndroid Build Coastguard Worker
80*d9f75844SAndroid Build Coastguard Worker return std::make_unique<SSLCertificateStats>(std::move(fingerprint),
81*d9f75844SAndroid Build Coastguard Worker std::move(digest_algorithm),
82*d9f75844SAndroid Build Coastguard Worker std::move(der_base64), nullptr);
83*d9f75844SAndroid Build Coastguard Worker }
84*d9f75844SAndroid Build Coastguard Worker
85*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
86*d9f75844SAndroid Build Coastguard Worker // SSLCertChain
87*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
88*d9f75844SAndroid Build Coastguard Worker
SSLCertChain(std::unique_ptr<SSLCertificate> single_cert)89*d9f75844SAndroid Build Coastguard Worker SSLCertChain::SSLCertChain(std::unique_ptr<SSLCertificate> single_cert) {
90*d9f75844SAndroid Build Coastguard Worker certs_.push_back(std::move(single_cert));
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker
SSLCertChain(std::vector<std::unique_ptr<SSLCertificate>> certs)93*d9f75844SAndroid Build Coastguard Worker SSLCertChain::SSLCertChain(std::vector<std::unique_ptr<SSLCertificate>> certs)
94*d9f75844SAndroid Build Coastguard Worker : certs_(std::move(certs)) {}
95*d9f75844SAndroid Build Coastguard Worker
96*d9f75844SAndroid Build Coastguard Worker SSLCertChain::SSLCertChain(SSLCertChain&& rhs) = default;
97*d9f75844SAndroid Build Coastguard Worker
98*d9f75844SAndroid Build Coastguard Worker SSLCertChain& SSLCertChain::operator=(SSLCertChain&&) = default;
99*d9f75844SAndroid Build Coastguard Worker
100*d9f75844SAndroid Build Coastguard Worker SSLCertChain::~SSLCertChain() = default;
101*d9f75844SAndroid Build Coastguard Worker
Clone() const102*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLCertChain> SSLCertChain::Clone() const {
103*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<SSLCertificate>> new_certs(certs_.size());
104*d9f75844SAndroid Build Coastguard Worker absl::c_transform(
105*d9f75844SAndroid Build Coastguard Worker certs_, new_certs.begin(),
106*d9f75844SAndroid Build Coastguard Worker [](const std::unique_ptr<SSLCertificate>& cert)
107*d9f75844SAndroid Build Coastguard Worker -> std::unique_ptr<SSLCertificate> { return cert->Clone(); });
108*d9f75844SAndroid Build Coastguard Worker return std::make_unique<SSLCertChain>(std::move(new_certs));
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker
GetStats() const111*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLCertificateStats> SSLCertChain::GetStats() const {
112*d9f75844SAndroid Build Coastguard Worker // We have a linked list of certificates, starting with the first element of
113*d9f75844SAndroid Build Coastguard Worker // `certs_` and ending with the last element of `certs_`. The "issuer" of a
114*d9f75844SAndroid Build Coastguard Worker // certificate is the next certificate in the chain. Stats are produced for
115*d9f75844SAndroid Build Coastguard Worker // each certificate in the list. Here, the "issuer" is the issuer's stats.
116*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLCertificateStats> issuer;
117*d9f75844SAndroid Build Coastguard Worker // The loop runs in reverse so that the `issuer` is known before the
118*d9f75844SAndroid Build Coastguard Worker // certificate issued by `issuer`.
119*d9f75844SAndroid Build Coastguard Worker for (ptrdiff_t i = certs_.size() - 1; i >= 0; --i) {
120*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLCertificateStats> new_stats = certs_[i]->GetStats();
121*d9f75844SAndroid Build Coastguard Worker if (new_stats) {
122*d9f75844SAndroid Build Coastguard Worker new_stats->issuer = std::move(issuer);
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker issuer = std::move(new_stats);
125*d9f75844SAndroid Build Coastguard Worker }
126*d9f75844SAndroid Build Coastguard Worker return issuer;
127*d9f75844SAndroid Build Coastguard Worker }
128*d9f75844SAndroid Build Coastguard Worker
129*d9f75844SAndroid Build Coastguard Worker // static
FromPEMString(absl::string_view pem_string)130*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLCertificate> SSLCertificate::FromPEMString(
131*d9f75844SAndroid Build Coastguard Worker absl::string_view pem_string) {
132*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
133*d9f75844SAndroid Build Coastguard Worker return BoringSSLCertificate::FromPEMString(pem_string);
134*d9f75844SAndroid Build Coastguard Worker #else
135*d9f75844SAndroid Build Coastguard Worker return OpenSSLCertificate::FromPEMString(pem_string);
136*d9f75844SAndroid Build Coastguard Worker #endif
137*d9f75844SAndroid Build Coastguard Worker }
138*d9f75844SAndroid Build Coastguard Worker
139*d9f75844SAndroid Build Coastguard Worker } // namespace rtc
140