blob: 53af0f5854e3d6c50c6792ce8a9d47d5c4c7a054 [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
11#include "rtc_base/sslcertificate.h"
12
Yves Gerey2e00abc2018-10-05 15:39:24 +020013#include <algorithm> // for transform
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070014#include <string>
15#include <utility>
16
Yves Gerey2e00abc2018-10-05 15:39:24 +020017#include "absl/memory/memory.h" // for WrapUnique, make_unique
18#include "rtc_base/checks.h" // for FatalLogCall, RTC_DC...
19#include "rtc_base/opensslcertificate.h" // for OpenSSLCertificate
20#include "rtc_base/sslfingerprint.h" // for SSLFingerprint
21#include "rtc_base/third_party/base64/base64.h" // for Base64
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070022
23namespace rtc {
24
25//////////////////////////////////////////////////////////////////////
26// SSLCertificateStats
27//////////////////////////////////////////////////////////////////////
28
29SSLCertificateStats::SSLCertificateStats(
30 std::string&& fingerprint,
31 std::string&& fingerprint_algorithm,
32 std::string&& base64_certificate,
Niklas Enbom82c71af2018-10-15 16:22:55 +000033 std::unique_ptr<SSLCertificateStats>&& issuer)
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070034 : fingerprint(std::move(fingerprint)),
35 fingerprint_algorithm(std::move(fingerprint_algorithm)),
36 base64_certificate(std::move(base64_certificate)),
37 issuer(std::move(issuer)) {}
38
39SSLCertificateStats::~SSLCertificateStats() {}
40
41//////////////////////////////////////////////////////////////////////
42// SSLCertificate
43//////////////////////////////////////////////////////////////////////
44
45std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats() const {
46 // TODO(bemasc): Move this computation to a helper class that caches these
47 // values to reduce CPU use in |StatsCollector::GetStats|. This will require
48 // adding a fast |SSLCertificate::Equals| to detect certificate changes.
49 std::string digest_algorithm;
50 if (!GetSignatureDigestAlgorithm(&digest_algorithm))
51 return nullptr;
52
53 // |SSLFingerprint::Create| can fail if the algorithm returned by
54 // |SSLCertificate::GetSignatureDigestAlgorithm| is not supported by the
55 // implementation of |SSLCertificate::ComputeDigest|. This currently happens
56 // with MD5- and SHA-224-signed certificates when linked to libNSS.
Steve Anton4905edb2018-10-15 19:27:44 -070057 std::unique_ptr<SSLFingerprint> ssl_fingerprint =
58 SSLFingerprint::Create(digest_algorithm, *this);
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070059 if (!ssl_fingerprint)
60 return nullptr;
61 std::string fingerprint = ssl_fingerprint->GetRfc4572Fingerprint();
62
63 Buffer der_buffer;
64 ToDER(&der_buffer);
65 std::string der_base64;
66 Base64::EncodeFromArray(der_buffer.data(), der_buffer.size(), &der_base64);
67
Karl Wiberg918f50c2018-07-05 11:40:33 +020068 return absl::make_unique<SSLCertificateStats>(std::move(fingerprint),
69 std::move(digest_algorithm),
70 std::move(der_base64), nullptr);
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070071}
72
Niklas Enbom82c71af2018-10-15 16:22:55 +000073std::unique_ptr<SSLCertificate> SSLCertificate::GetUniqueReference() const {
74 return absl::WrapUnique(GetReference());
75}
76
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070077//////////////////////////////////////////////////////////////////////
78// SSLCertChain
79//////////////////////////////////////////////////////////////////////
80
81SSLCertChain::SSLCertChain(std::vector<std::unique_ptr<SSLCertificate>> certs)
82 : certs_(std::move(certs)) {}
83
Niklas Enbom82c71af2018-10-15 16:22:55 +000084SSLCertChain::SSLCertChain(const std::vector<SSLCertificate*>& certs) {
85 RTC_DCHECK(!certs.empty());
86 certs_.resize(certs.size());
87 std::transform(
88 certs.begin(), certs.end(), certs_.begin(),
89 [](const SSLCertificate* cert) -> std::unique_ptr<SSLCertificate> {
90 return cert->GetUniqueReference();
91 });
92}
93
94SSLCertChain::SSLCertChain(const SSLCertificate* cert) {
95 certs_.push_back(cert->GetUniqueReference());
96}
97
Benjamin Wrightd6f86e82018-05-08 13:12:25 -070098SSLCertChain::SSLCertChain(SSLCertChain&& rhs) = default;
99
100SSLCertChain& SSLCertChain::operator=(SSLCertChain&&) = default;
101
Niklas Enbom82c71af2018-10-15 16:22:55 +0000102SSLCertChain::~SSLCertChain() {}
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700103
Niklas Enbom82c71af2018-10-15 16:22:55 +0000104SSLCertChain* SSLCertChain::Copy() const {
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700105 std::vector<std::unique_ptr<SSLCertificate>> new_certs(certs_.size());
Niklas Enbom82c71af2018-10-15 16:22:55 +0000106 std::transform(certs_.begin(), certs_.end(), new_certs.begin(),
107 [](const std::unique_ptr<SSLCertificate>& cert)
108 -> std::unique_ptr<SSLCertificate> {
109 return cert->GetUniqueReference();
110 });
111 return new SSLCertChain(std::move(new_certs));
112}
113
114std::unique_ptr<SSLCertChain> SSLCertChain::UniqueCopy() const {
115 return absl::WrapUnique(Copy());
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700116}
117
118std::unique_ptr<SSLCertificateStats> SSLCertChain::GetStats() const {
119 // We have a linked list of certificates, starting with the first element of
120 // |certs_| and ending with the last element of |certs_|. The "issuer" of a
121 // certificate is the next certificate in the chain. Stats are produced for
122 // each certificate in the list. Here, the "issuer" is the issuer's stats.
123 std::unique_ptr<SSLCertificateStats> issuer;
124 // The loop runs in reverse so that the |issuer| is known before the
125 // certificate issued by |issuer|.
126 for (ptrdiff_t i = certs_.size() - 1; i >= 0; --i) {
127 std::unique_ptr<SSLCertificateStats> new_stats = certs_[i]->GetStats();
128 if (new_stats) {
129 new_stats->issuer = std::move(issuer);
130 }
131 issuer = std::move(new_stats);
132 }
133 return issuer;
134}
135
136// static
Niklas Enbom82c71af2018-10-15 16:22:55 +0000137SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) {
Benjamin Wrightd6f86e82018-05-08 13:12:25 -0700138 return OpenSSLCertificate::FromPEMString(pem_string);
139}
140
141} // namespace rtc