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