blob: d1fd57fca58a8e8e0433fac50685f95fbc4be29b [file] [log] [blame]
Benjamin Wrightd6f86e82018-05-08 20:12:251/*
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
Steve Anton10542f22019-01-11 17:11:0011#include "rtc_base/ssl_certificate.h"
Benjamin Wrightd6f86e82018-05-08 20:12:2512
Mirko Bonadei317a1f02019-09-17 15:06:1813#include <memory>
Benjamin Wrightd6f86e82018-05-08 20:12:2514#include <string>
15#include <utility>
16
Steve Anton2acd1632019-03-25 20:48:3017#include "absl/algorithm/container.h"
Ali Tofigh7fa90572022-03-17 14:47:4918#include "absl/strings/string_view.h"
Yves Gerey988cc082018-10-23 10:03:0119#include "rtc_base/checks.h"
Taylor Brandstetter165c6182020-12-11 00:23:0320#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
Steve Anton10542f22019-01-11 17:11:0026#include "rtc_base/ssl_fingerprint.h"
Yves Gerey988cc082018-10-23 10:03:0127#include "rtc_base/third_party/base64/base64.h"
Benjamin Wrightd6f86e82018-05-08 20:12:2528
29namespace rtc {
30
31//////////////////////////////////////////////////////////////////////
32// SSLCertificateStats
33//////////////////////////////////////////////////////////////////////
34
35SSLCertificateStats::SSLCertificateStats(
36 std::string&& fingerprint,
37 std::string&& fingerprint_algorithm,
38 std::string&& base64_certificate,
Steve Antonf25303e2018-10-16 22:23:3139 std::unique_ptr<SSLCertificateStats> issuer)
Benjamin Wrightd6f86e82018-05-08 20:12:2540 : fingerprint(std::move(fingerprint)),
41 fingerprint_algorithm(std::move(fingerprint_algorithm)),
42 base64_certificate(std::move(base64_certificate)),
43 issuer(std::move(issuer)) {}
44
45SSLCertificateStats::~SSLCertificateStats() {}
46
Henrik Boström69d23c92022-09-26 12:13:1747std::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
Benjamin Wrightd6f86e82018-05-08 20:12:2553//////////////////////////////////////////////////////////////////////
54// SSLCertificate
55//////////////////////////////////////////////////////////////////////
56
57std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats() const {
58 // TODO(bemasc): Move this computation to a helper class that caches these
Artem Titovcfea2182021-08-09 23:22:3159 // values to reduce CPU use in `StatsCollector::GetStats`. This will require
60 // adding a fast `SSLCertificate::Equals` to detect certificate changes.
Benjamin Wrightd6f86e82018-05-08 20:12:2561 std::string digest_algorithm;
62 if (!GetSignatureDigestAlgorithm(&digest_algorithm))
63 return nullptr;
64
Artem Titovcfea2182021-08-09 23:22:3165 // `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
Benjamin Wrightd6f86e82018-05-08 20:12:2568 // with MD5- and SHA-224-signed certificates when linked to libNSS.
Steve Anton4905edb2018-10-16 02:27:4469 std::unique_ptr<SSLFingerprint> ssl_fingerprint =
70 SSLFingerprint::Create(digest_algorithm, *this);
Benjamin Wrightd6f86e82018-05-08 20:12:2571 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
Mirko Bonadei317a1f02019-09-17 15:06:1880 return std::make_unique<SSLCertificateStats>(std::move(fingerprint),
81 std::move(digest_algorithm),
82 std::move(der_base64), nullptr);
Benjamin Wrightd6f86e82018-05-08 20:12:2583}
84
Benjamin Wrightd6f86e82018-05-08 20:12:2585//////////////////////////////////////////////////////////////////////
86// SSLCertChain
87//////////////////////////////////////////////////////////////////////
88
Steve Antonf25303e2018-10-16 22:23:3189SSLCertChain::SSLCertChain(std::unique_ptr<SSLCertificate> single_cert) {
90 certs_.push_back(std::move(single_cert));
91}
92
Benjamin Wrightd6f86e82018-05-08 20:12:2593SSLCertChain::SSLCertChain(std::vector<std::unique_ptr<SSLCertificate>> certs)
94 : certs_(std::move(certs)) {}
95
Benjamin Wrightd6f86e82018-05-08 20:12:2596SSLCertChain::SSLCertChain(SSLCertChain&& rhs) = default;
97
98SSLCertChain& SSLCertChain::operator=(SSLCertChain&&) = default;
99
Steve Antonf25303e2018-10-16 22:23:31100SSLCertChain::~SSLCertChain() = default;
Benjamin Wrightd6f86e82018-05-08 20:12:25101
Steve Antonf25303e2018-10-16 22:23:31102std::unique_ptr<SSLCertChain> SSLCertChain::Clone() const {
Benjamin Wrightd6f86e82018-05-08 20:12:25103 std::vector<std::unique_ptr<SSLCertificate>> new_certs(certs_.size());
Steve Anton2acd1632019-03-25 20:48:30104 absl::c_transform(
105 certs_, new_certs.begin(),
Steve Antonf25303e2018-10-16 22:23:31106 [](const std::unique_ptr<SSLCertificate>& cert)
107 -> std::unique_ptr<SSLCertificate> { return cert->Clone(); });
Mirko Bonadei317a1f02019-09-17 15:06:18108 return std::make_unique<SSLCertChain>(std::move(new_certs));
Benjamin Wrightd6f86e82018-05-08 20:12:25109}
110
111std::unique_ptr<SSLCertificateStats> SSLCertChain::GetStats() const {
112 // We have a linked list of certificates, starting with the first element of
Artem Titov96e3b992021-07-26 14:03:14113 // `certs_` and ending with the last element of `certs_`. The "issuer" of a
Benjamin Wrightd6f86e82018-05-08 20:12:25114 // 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;
Artem Titov96e3b992021-07-26 14:03:14117 // The loop runs in reverse so that the `issuer` is known before the
118 // certificate issued by `issuer`.
Benjamin Wrightd6f86e82018-05-08 20:12:25119 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
Steve Antonf25303e2018-10-16 22:23:31130std::unique_ptr<SSLCertificate> SSLCertificate::FromPEMString(
Ali Tofigh7fa90572022-03-17 14:47:49131 absl::string_view pem_string) {
Taylor Brandstetter165c6182020-12-11 00:23:03132#ifdef OPENSSL_IS_BORINGSSL
133 return BoringSSLCertificate::FromPEMString(pem_string);
134#else
Benjamin Wrightd6f86e82018-05-08 20:12:25135 return OpenSSLCertificate::FromPEMString(pem_string);
Taylor Brandstetter165c6182020-12-11 00:23:03136#endif
Benjamin Wrightd6f86e82018-05-08 20:12:25137}
138
139} // namespace rtc