blob: b40810955ef191ea2444bc6b6d163e156090079a [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/sslfingerprint.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000012
13#include <ctype.h>
14#include <string>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "rtc_base/logging.h"
17#include "rtc_base/messagedigest.h"
18#include "rtc_base/stringencode.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000019
20namespace rtc {
21
Steve Antoncc21e612018-10-10 20:00:19 -070022std::unique_ptr<SSLFingerprint> SSLFingerprint::Create(
23 const std::string& algorithm,
24 const rtc::SSLIdentity& identity) {
25 return Create(algorithm, identity.certificate());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000026}
27
Steve Antoncc21e612018-10-10 20:00:19 -070028std::unique_ptr<SSLFingerprint> SSLFingerprint::Create(
29 const std::string& algorithm,
30 const rtc::SSLCertificate& cert) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020031 uint8_t digest_val[64];
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032 size_t digest_len;
Steve Antoncc21e612018-10-10 20:00:19 -070033 bool ret = cert.ComputeDigest(algorithm, digest_val, sizeof(digest_val),
34 &digest_len);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000035 if (!ret) {
deadbeef37f5ecf2017-02-27 14:06:41 -080036 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000037 }
Steve Antoncc21e612018-10-10 20:00:19 -070038 return absl::make_unique<SSLFingerprint>(
39 algorithm, ArrayView<const uint8_t>(digest_val, digest_len));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000040}
41
42SSLFingerprint* SSLFingerprint::CreateFromRfc4572(
Yves Gerey665174f2018-06-19 15:03:05 +020043 const std::string& algorithm,
44 const std::string& fingerprint) {
Steve Antoncc21e612018-10-10 20:00:19 -070045 return CreateUniqueFromRfc4572(algorithm, fingerprint).release();
46}
47
48std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateUniqueFromRfc4572(
49 const std::string& algorithm,
50 const std::string& fingerprint) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000051 if (algorithm.empty() || !rtc::IsFips180DigestAlgorithm(algorithm))
deadbeef37f5ecf2017-02-27 14:06:41 -080052 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000053
54 if (fingerprint.empty())
deadbeef37f5ecf2017-02-27 14:06:41 -080055 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000056
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000057 char value[rtc::MessageDigest::kMaxSize];
Steve Antoncc21e612018-10-10 20:00:19 -070058 size_t value_len = rtc::hex_decode_with_delimiter(
Yves Gerey665174f2018-06-19 15:03:05 +020059 value, sizeof(value), fingerprint.c_str(), fingerprint.length(), ':');
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000060 if (!value_len)
deadbeef37f5ecf2017-02-27 14:06:41 -080061 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062
Steve Antoncc21e612018-10-10 20:00:19 -070063 return absl::make_unique<SSLFingerprint>(
64 algorithm,
65 ArrayView<const uint8_t>(reinterpret_cast<uint8_t*>(value), value_len));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000066}
67
Steve Antoncc21e612018-10-10 20:00:19 -070068std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateFromCertificate(
69 const RTCCertificate& cert) {
deadbeef8662f942017-01-20 21:20:51 -080070 std::string digest_alg;
Steve Antoncc21e612018-10-10 20:00:19 -070071 if (!cert.ssl_certificate().GetSignatureDigestAlgorithm(&digest_alg)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010072 RTC_LOG(LS_ERROR)
73 << "Failed to retrieve the certificate's digest algorithm";
deadbeef8662f942017-01-20 21:20:51 -080074 return nullptr;
75 }
76
Steve Antoncc21e612018-10-10 20:00:19 -070077 std::unique_ptr<SSLFingerprint> fingerprint =
78 Create(digest_alg, *cert.identity());
deadbeef8662f942017-01-20 21:20:51 -080079 if (!fingerprint) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010080 RTC_LOG(LS_ERROR) << "Failed to create identity fingerprint, alg="
81 << digest_alg;
deadbeef8662f942017-01-20 21:20:51 -080082 }
83 return fingerprint;
84}
85
Peter Boström0c4e06b2015-10-07 12:23:21 +020086SSLFingerprint::SSLFingerprint(const std::string& algorithm,
Steve Antoncc21e612018-10-10 20:00:19 -070087 ArrayView<const uint8_t> digest_view)
88 : algorithm(algorithm), digest(digest_view.data(), digest_view.size()) {}
89
90SSLFingerprint::SSLFingerprint(const std::string& algorithm,
Peter Boström0c4e06b2015-10-07 12:23:21 +020091 const uint8_t* digest_in,
92 size_t digest_len)
Steve Antoncc21e612018-10-10 20:00:19 -070093 : SSLFingerprint(algorithm,
94 ArrayView<const uint8_t>(digest_in, digest_len)) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000095
96SSLFingerprint::SSLFingerprint(const SSLFingerprint& from)
97 : algorithm(from.algorithm), digest(from.digest) {}
98
99bool SSLFingerprint::operator==(const SSLFingerprint& other) const {
Yves Gerey665174f2018-06-19 15:03:05 +0200100 return algorithm == other.algorithm && digest == other.digest;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000101}
102
103std::string SSLFingerprint::GetRfc4572Fingerprint() const {
104 std::string fingerprint =
Karl Wiberg94784372015-04-20 14:03:07 +0200105 rtc::hex_encode_with_delimiter(digest.data<char>(), digest.size(), ':');
Yves Gerey665174f2018-06-19 15:03:05 +0200106 std::transform(fingerprint.begin(), fingerprint.end(), fingerprint.begin(),
107 ::toupper);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000108 return fingerprint;
109}
110
mikescarlette7748672016-04-29 20:20:54 -0700111std::string SSLFingerprint::ToString() const {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000112 std::string fp_str = algorithm;
113 fp_str.append(" ");
114 fp_str.append(GetRfc4572Fingerprint());
115 return fp_str;
116}
117
118} // namespace rtc