blob: 3f12c79215bc99102ebf8a617a4d2edc3131d3f5 [file] [log] [blame]
Benjamin Wrightd6f86e82018-05-08 13:12:25 -07001/*
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 09:11:00 -080011#include "rtc_base/ssl_certificate.h"
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070012
Mirko Bonadei317a1f02019-09-17 17:06:18 +020013#include <memory>
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070014#include <string>
15#include <utility>
16
Steve Anton2acd1632019-03-25 13:48:30 -070017#include "absl/algorithm/container.h"
Yves Gerey988cc082018-10-23 12:03:01 +020018#include "rtc_base/checks.h"
Taylor Brandstetter165c6182020-12-10 16:23:03 -080019#include "rtc_base/openssl.h"
20#ifdef OPENSSL_IS_BORINGSSL
21#include "rtc_base/boringssl_identity.h"
22#else
23#include "rtc_base/openssl_identity.h"
24#endif
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/ssl_fingerprint.h"
Yves Gerey988cc082018-10-23 12:03:01 +020026#include "rtc_base/third_party/base64/base64.h"
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070027
28namespace rtc {
29
30//////////////////////////////////////////////////////////////////////
31// SSLCertificateStats
32//////////////////////////////////////////////////////////////////////
33
34SSLCertificateStats::SSLCertificateStats(
35 std::string&& fingerprint,
36 std::string&& fingerprint_algorithm,
37 std::string&& base64_certificate,
Steve Antonf25303e2018-10-16 15:23:31 -070038 std::unique_ptr<SSLCertificateStats> issuer)
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070039 : fingerprint(std::move(fingerprint)),
40 fingerprint_algorithm(std::move(fingerprint_algorithm)),
41 base64_certificate(std::move(base64_certificate)),
42 issuer(std::move(issuer)) {}
43
44SSLCertificateStats::~SSLCertificateStats() {}
45
46//////////////////////////////////////////////////////////////////////
47// SSLCertificate
48//////////////////////////////////////////////////////////////////////
49
50std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats() const {
51 // TODO(bemasc): Move this computation to a helper class that caches these
52 // values to reduce CPU use in |StatsCollector::GetStats|. This will require
53 // adding a fast |SSLCertificate::Equals| to detect certificate changes.
54 std::string digest_algorithm;
55 if (!GetSignatureDigestAlgorithm(&digest_algorithm))
56 return nullptr;
57
58 // |SSLFingerprint::Create| can fail if the algorithm returned by
59 // |SSLCertificate::GetSignatureDigestAlgorithm| is not supported by the
60 // implementation of |SSLCertificate::ComputeDigest|. This currently happens
61 // with MD5- and SHA-224-signed certificates when linked to libNSS.
Steve Anton4905edb2018-10-15 19:27:44 -070062 std::unique_ptr<SSLFingerprint> ssl_fingerprint =
63 SSLFingerprint::Create(digest_algorithm, *this);
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070064 if (!ssl_fingerprint)
65 return nullptr;
66 std::string fingerprint = ssl_fingerprint->GetRfc4572Fingerprint();
67
68 Buffer der_buffer;
69 ToDER(&der_buffer);
70 std::string der_base64;
71 Base64::EncodeFromArray(der_buffer.data(), der_buffer.size(), &der_base64);
72
Mirko Bonadei317a1f02019-09-17 17:06:18 +020073 return std::make_unique<SSLCertificateStats>(std::move(fingerprint),
74 std::move(digest_algorithm),
75 std::move(der_base64), nullptr);
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070076}
77
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070078//////////////////////////////////////////////////////////////////////
79// SSLCertChain
80//////////////////////////////////////////////////////////////////////
81
Steve Antonf25303e2018-10-16 15:23:31 -070082SSLCertChain::SSLCertChain(std::unique_ptr<SSLCertificate> single_cert) {
83 certs_.push_back(std::move(single_cert));
84}
85
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070086SSLCertChain::SSLCertChain(std::vector<std::unique_ptr<SSLCertificate>> certs)
87 : certs_(std::move(certs)) {}
88
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070089SSLCertChain::SSLCertChain(SSLCertChain&& rhs) = default;
90
91SSLCertChain& SSLCertChain::operator=(SSLCertChain&&) = default;
92
Steve Antonf25303e2018-10-16 15:23:31 -070093SSLCertChain::~SSLCertChain() = default;
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070094
Steve Antonf25303e2018-10-16 15:23:31 -070095std::unique_ptr<SSLCertChain> SSLCertChain::Clone() const {
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070096 std::vector<std::unique_ptr<SSLCertificate>> new_certs(certs_.size());
Steve Anton2acd1632019-03-25 13:48:30 -070097 absl::c_transform(
98 certs_, new_certs.begin(),
Steve Antonf25303e2018-10-16 15:23:31 -070099 [](const std::unique_ptr<SSLCertificate>& cert)
100 -> std::unique_ptr<SSLCertificate> { return cert->Clone(); });
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200101 return std::make_unique<SSLCertChain>(std::move(new_certs));
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700102}
103
104std::unique_ptr<SSLCertificateStats> SSLCertChain::GetStats() const {
105 // We have a linked list of certificates, starting with the first element of
Artem Titov96e3b992021-07-26 16:03:14 +0200106 // `certs_` and ending with the last element of `certs_`. The "issuer" of a
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700107 // certificate is the next certificate in the chain. Stats are produced for
108 // each certificate in the list. Here, the "issuer" is the issuer's stats.
109 std::unique_ptr<SSLCertificateStats> issuer;
Artem Titov96e3b992021-07-26 16:03:14 +0200110 // The loop runs in reverse so that the `issuer` is known before the
111 // certificate issued by `issuer`.
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700112 for (ptrdiff_t i = certs_.size() - 1; i >= 0; --i) {
113 std::unique_ptr<SSLCertificateStats> new_stats = certs_[i]->GetStats();
114 if (new_stats) {
115 new_stats->issuer = std::move(issuer);
116 }
117 issuer = std::move(new_stats);
118 }
119 return issuer;
120}
121
122// static
Steve Antonf25303e2018-10-16 15:23:31 -0700123std::unique_ptr<SSLCertificate> SSLCertificate::FromPEMString(
124 const std::string& pem_string) {
Taylor Brandstetter165c6182020-12-10 16:23:03 -0800125#ifdef OPENSSL_IS_BORINGSSL
126 return BoringSSLCertificate::FromPEMString(pem_string);
127#else
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700128 return OpenSSLCertificate::FromPEMString(pem_string);
Taylor Brandstetter165c6182020-12-10 16:23:03 -0800129#endif
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700130}
131
132} // namespace rtc