1 /*
2 * Copyright 2012 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_fingerprint.h"
12
13 #include <ctype.h>
14 #include <cstdint>
15 #include <memory>
16 #include <string>
17
18 #include "absl/algorithm/container.h"
19 #include "rtc_base/logging.h"
20 #include "rtc_base/message_digest.h"
21 #include "rtc_base/rtc_certificate.h"
22 #include "rtc_base/ssl_certificate.h"
23 #include "rtc_base/ssl_identity.h"
24 #include "rtc_base/string_encode.h"
25
26 namespace rtc {
27
Create(const std::string & algorithm,const rtc::SSLIdentity * identity)28 SSLFingerprint* SSLFingerprint::Create(const std::string& algorithm,
29 const rtc::SSLIdentity* identity) {
30 return CreateUnique(algorithm, *identity).release();
31 }
32
CreateUnique(const std::string & algorithm,const rtc::SSLIdentity & identity)33 std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateUnique(
34 const std::string& algorithm,
35 const rtc::SSLIdentity& identity) {
36 return Create(algorithm, identity.certificate());
37 }
38
Create(const std::string & algorithm,const rtc::SSLCertificate & cert)39 std::unique_ptr<SSLFingerprint> SSLFingerprint::Create(
40 const std::string& algorithm,
41 const rtc::SSLCertificate& cert) {
42 uint8_t digest_val[64];
43 size_t digest_len;
44 bool ret = cert.ComputeDigest(algorithm, digest_val, sizeof(digest_val),
45 &digest_len);
46 if (!ret) {
47 return nullptr;
48 }
49 return std::make_unique<SSLFingerprint>(
50 algorithm, ArrayView<const uint8_t>(digest_val, digest_len));
51 }
52
CreateFromRfc4572(const std::string & algorithm,const std::string & fingerprint)53 SSLFingerprint* SSLFingerprint::CreateFromRfc4572(
54 const std::string& algorithm,
55 const std::string& fingerprint) {
56 return CreateUniqueFromRfc4572(algorithm, fingerprint).release();
57 }
58
CreateUniqueFromRfc4572(const std::string & algorithm,const std::string & fingerprint)59 std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateUniqueFromRfc4572(
60 const std::string& algorithm,
61 const std::string& fingerprint) {
62 if (algorithm.empty() || !rtc::IsFips180DigestAlgorithm(algorithm))
63 return nullptr;
64
65 if (fingerprint.empty())
66 return nullptr;
67
68 char value[rtc::MessageDigest::kMaxSize];
69 size_t value_len = rtc::hex_decode_with_delimiter(
70 value, sizeof(value), fingerprint.c_str(), fingerprint.length(), ':');
71 if (!value_len)
72 return nullptr;
73
74 return std::make_unique<SSLFingerprint>(
75 algorithm,
76 ArrayView<const uint8_t>(reinterpret_cast<uint8_t*>(value), value_len));
77 }
78
CreateFromCertificate(const RTCCertificate & cert)79 std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateFromCertificate(
80 const RTCCertificate& cert) {
81 std::string digest_alg;
82 if (!cert.GetSSLCertificate().GetSignatureDigestAlgorithm(&digest_alg)) {
83 RTC_LOG(LS_ERROR)
84 << "Failed to retrieve the certificate's digest algorithm";
85 return nullptr;
86 }
87
88 std::unique_ptr<SSLFingerprint> fingerprint =
89 CreateUnique(digest_alg, *cert.identity());
90 if (!fingerprint) {
91 RTC_LOG(LS_ERROR) << "Failed to create identity fingerprint, alg="
92 << digest_alg;
93 }
94 return fingerprint;
95 }
96
SSLFingerprint(const std::string & algorithm,ArrayView<const uint8_t> digest_view)97 SSLFingerprint::SSLFingerprint(const std::string& algorithm,
98 ArrayView<const uint8_t> digest_view)
99 : algorithm(algorithm), digest(digest_view.data(), digest_view.size()) {}
100
SSLFingerprint(const std::string & algorithm,const uint8_t * digest_in,size_t digest_len)101 SSLFingerprint::SSLFingerprint(const std::string& algorithm,
102 const uint8_t* digest_in,
103 size_t digest_len)
104 : SSLFingerprint(algorithm, MakeArrayView(digest_in, digest_len)) {}
105
SSLFingerprint(const SSLFingerprint & from)106 SSLFingerprint::SSLFingerprint(const SSLFingerprint& from)
107 : algorithm(from.algorithm), digest(from.digest) {}
108
operator ==(const SSLFingerprint & other) const109 bool SSLFingerprint::operator==(const SSLFingerprint& other) const {
110 return algorithm == other.algorithm && digest == other.digest;
111 }
112
GetRfc4572Fingerprint() const113 std::string SSLFingerprint::GetRfc4572Fingerprint() const {
114 std::string fingerprint =
115 rtc::hex_encode_with_delimiter(digest.data<char>(), digest.size(), ':');
116 absl::c_transform(fingerprint, fingerprint.begin(), ::toupper);
117 return fingerprint;
118 }
119
ToString() const120 std::string SSLFingerprint::ToString() const {
121 std::string fp_str = algorithm;
122 fp_str.append(" ");
123 fp_str.append(GetRfc4572Fingerprint());
124 return fp_str;
125 }
126
127 } // namespace rtc
128