blob: fcbd10256f40fcee6e80f38eea7471356541a1e7 [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
13#include <ctime>
14#include <string>
15#include <utility>
16
17#include "rtc_base/base64.h"
18#include "rtc_base/checks.h"
19#include "rtc_base/logging.h"
20#include "rtc_base/opensslcertificate.h"
21#include "rtc_base/ptr_util.h"
22#include "rtc_base/sslfingerprint.h"
23
24namespace rtc {
25
26//////////////////////////////////////////////////////////////////////
27// SSLCertificateStats
28//////////////////////////////////////////////////////////////////////
29
30SSLCertificateStats::SSLCertificateStats(
31 std::string&& fingerprint,
32 std::string&& fingerprint_algorithm,
33 std::string&& base64_certificate,
34 std::unique_ptr<SSLCertificateStats>&& issuer)
35 : fingerprint(std::move(fingerprint)),
36 fingerprint_algorithm(std::move(fingerprint_algorithm)),
37 base64_certificate(std::move(base64_certificate)),
38 issuer(std::move(issuer)) {}
39
40SSLCertificateStats::~SSLCertificateStats() {}
41
42//////////////////////////////////////////////////////////////////////
43// SSLCertificate
44//////////////////////////////////////////////////////////////////////
45
46std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats() const {
47 // TODO(bemasc): Move this computation to a helper class that caches these
48 // values to reduce CPU use in |StatsCollector::GetStats|. This will require
49 // adding a fast |SSLCertificate::Equals| to detect certificate changes.
50 std::string digest_algorithm;
51 if (!GetSignatureDigestAlgorithm(&digest_algorithm))
52 return nullptr;
53
54 // |SSLFingerprint::Create| can fail if the algorithm returned by
55 // |SSLCertificate::GetSignatureDigestAlgorithm| is not supported by the
56 // implementation of |SSLCertificate::ComputeDigest|. This currently happens
57 // with MD5- and SHA-224-signed certificates when linked to libNSS.
58 std::unique_ptr<SSLFingerprint> ssl_fingerprint(
59 SSLFingerprint::Create(digest_algorithm, this));
60 if (!ssl_fingerprint)
61 return nullptr;
62 std::string fingerprint = ssl_fingerprint->GetRfc4572Fingerprint();
63
64 Buffer der_buffer;
65 ToDER(&der_buffer);
66 std::string der_base64;
67 Base64::EncodeFromArray(der_buffer.data(), der_buffer.size(), &der_base64);
68
69 return rtc::MakeUnique<SSLCertificateStats>(std::move(fingerprint),
70 std::move(digest_algorithm),
71 std::move(der_base64), nullptr);
72}
73
74std::unique_ptr<SSLCertificate> SSLCertificate::GetUniqueReference() const {
75 return WrapUnique(GetReference());
76}
77
78//////////////////////////////////////////////////////////////////////
79// SSLCertChain
80//////////////////////////////////////////////////////////////////////
81
82SSLCertChain::SSLCertChain(std::vector<std::unique_ptr<SSLCertificate>> certs)
83 : certs_(std::move(certs)) {}
84
85SSLCertChain::SSLCertChain(const std::vector<SSLCertificate*>& certs) {
86 RTC_DCHECK(!certs.empty());
87 certs_.resize(certs.size());
88 std::transform(
89 certs.begin(), certs.end(), certs_.begin(),
90 [](const SSLCertificate* cert) -> std::unique_ptr<SSLCertificate> {
91 return cert->GetUniqueReference();
92 });
93}
94
95SSLCertChain::SSLCertChain(const SSLCertificate* cert) {
96 certs_.push_back(cert->GetUniqueReference());
97}
98
99SSLCertChain::SSLCertChain(SSLCertChain&& rhs) = default;
100
101SSLCertChain& SSLCertChain::operator=(SSLCertChain&&) = default;
102
103SSLCertChain::~SSLCertChain() {}
104
105SSLCertChain* SSLCertChain::Copy() const {
106 std::vector<std::unique_ptr<SSLCertificate>> new_certs(certs_.size());
107 std::transform(certs_.begin(), certs_.end(), new_certs.begin(),
108 [](const std::unique_ptr<SSLCertificate>& cert)
109 -> std::unique_ptr<SSLCertificate> {
110 return cert->GetUniqueReference();
111 });
112 return new SSLCertChain(std::move(new_certs));
113}
114
115std::unique_ptr<SSLCertChain> SSLCertChain::UniqueCopy() const {
116 return WrapUnique(Copy());
117}
118
119std::unique_ptr<SSLCertificateStats> SSLCertChain::GetStats() const {
120 // We have a linked list of certificates, starting with the first element of
121 // |certs_| and ending with the last element of |certs_|. The "issuer" of a
122 // certificate is the next certificate in the chain. Stats are produced for
123 // each certificate in the list. Here, the "issuer" is the issuer's stats.
124 std::unique_ptr<SSLCertificateStats> issuer;
125 // The loop runs in reverse so that the |issuer| is known before the
126 // certificate issued by |issuer|.
127 for (ptrdiff_t i = certs_.size() - 1; i >= 0; --i) {
128 std::unique_ptr<SSLCertificateStats> new_stats = certs_[i]->GetStats();
129 if (new_stats) {
130 new_stats->issuer = std::move(issuer);
131 }
132 issuer = std::move(new_stats);
133 }
134 return issuer;
135}
136
137// static
138SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) {
139 return OpenSSLCertificate::FromPEMString(pem_string);
140}
141
142} // namespace rtc