• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "rtc_base/checks.h"
19 #include "rtc_base/openssl_certificate.h"
20 #include "rtc_base/ssl_fingerprint.h"
21 #include "rtc_base/third_party/base64/base64.h"
22 
23 namespace rtc {
24 
25 //////////////////////////////////////////////////////////////////////
26 // SSLCertificateStats
27 //////////////////////////////////////////////////////////////////////
28 
SSLCertificateStats(std::string && fingerprint,std::string && fingerprint_algorithm,std::string && base64_certificate,std::unique_ptr<SSLCertificateStats> issuer)29 SSLCertificateStats::SSLCertificateStats(
30     std::string&& fingerprint,
31     std::string&& fingerprint_algorithm,
32     std::string&& base64_certificate,
33     std::unique_ptr<SSLCertificateStats> issuer)
34     : fingerprint(std::move(fingerprint)),
35       fingerprint_algorithm(std::move(fingerprint_algorithm)),
36       base64_certificate(std::move(base64_certificate)),
37       issuer(std::move(issuer)) {}
38 
~SSLCertificateStats()39 SSLCertificateStats::~SSLCertificateStats() {}
40 
41 //////////////////////////////////////////////////////////////////////
42 // SSLCertificate
43 //////////////////////////////////////////////////////////////////////
44 
GetStats() const45 std::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.
57   std::unique_ptr<SSLFingerprint> ssl_fingerprint =
58       SSLFingerprint::Create(digest_algorithm, *this);
59   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 
68   return std::make_unique<SSLCertificateStats>(std::move(fingerprint),
69                                                std::move(digest_algorithm),
70                                                std::move(der_base64), nullptr);
71 }
72 
73 //////////////////////////////////////////////////////////////////////
74 // SSLCertChain
75 //////////////////////////////////////////////////////////////////////
76 
SSLCertChain(std::unique_ptr<SSLCertificate> single_cert)77 SSLCertChain::SSLCertChain(std::unique_ptr<SSLCertificate> single_cert) {
78   certs_.push_back(std::move(single_cert));
79 }
80 
SSLCertChain(std::vector<std::unique_ptr<SSLCertificate>> certs)81 SSLCertChain::SSLCertChain(std::vector<std::unique_ptr<SSLCertificate>> certs)
82     : certs_(std::move(certs)) {}
83 
84 SSLCertChain::SSLCertChain(SSLCertChain&& rhs) = default;
85 
86 SSLCertChain& SSLCertChain::operator=(SSLCertChain&&) = default;
87 
88 SSLCertChain::~SSLCertChain() = default;
89 
Clone() const90 std::unique_ptr<SSLCertChain> SSLCertChain::Clone() const {
91   std::vector<std::unique_ptr<SSLCertificate>> new_certs(certs_.size());
92   absl::c_transform(
93       certs_, new_certs.begin(),
94       [](const std::unique_ptr<SSLCertificate>& cert)
95           -> std::unique_ptr<SSLCertificate> { return cert->Clone(); });
96   return std::make_unique<SSLCertChain>(std::move(new_certs));
97 }
98 
GetStats() const99 std::unique_ptr<SSLCertificateStats> SSLCertChain::GetStats() const {
100   // We have a linked list of certificates, starting with the first element of
101   // |certs_| and ending with the last element of |certs_|. The "issuer" of a
102   // certificate is the next certificate in the chain. Stats are produced for
103   // each certificate in the list. Here, the "issuer" is the issuer's stats.
104   std::unique_ptr<SSLCertificateStats> issuer;
105   // The loop runs in reverse so that the |issuer| is known before the
106   // certificate issued by |issuer|.
107   for (ptrdiff_t i = certs_.size() - 1; i >= 0; --i) {
108     std::unique_ptr<SSLCertificateStats> new_stats = certs_[i]->GetStats();
109     if (new_stats) {
110       new_stats->issuer = std::move(issuer);
111     }
112     issuer = std::move(new_stats);
113   }
114   return issuer;
115 }
116 
117 // static
FromPEMString(const std::string & pem_string)118 std::unique_ptr<SSLCertificate> SSLCertificate::FromPEMString(
119     const std::string& pem_string) {
120   return OpenSSLCertificate::FromPEMString(pem_string);
121 }
122 
123 }  // namespace rtc
124