| /* |
| * Copyright 2012 The WebRTC Project Authors. All rights reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "rtc_base/ssl_fingerprint.h" |
| |
| #include <ctype.h> |
| |
| #include <cstdint> |
| #include <memory> |
| #include <string> |
| |
| #include "absl/algorithm/container.h" |
| #include "absl/strings/string_view.h" |
| #include "api/array_view.h" |
| #include "rtc_base/logging.h" |
| #include "rtc_base/message_digest.h" |
| #include "rtc_base/rtc_certificate.h" |
| #include "rtc_base/ssl_certificate.h" |
| #include "rtc_base/ssl_identity.h" |
| #include "rtc_base/string_encode.h" |
| |
| namespace rtc { |
| |
| SSLFingerprint* SSLFingerprint::Create(absl::string_view algorithm, |
| const rtc::SSLIdentity* identity) { |
| return CreateUnique(algorithm, *identity).release(); |
| } |
| |
| std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateUnique( |
| absl::string_view algorithm, |
| const rtc::SSLIdentity& identity) { |
| return Create(algorithm, identity.certificate()); |
| } |
| |
| std::unique_ptr<SSLFingerprint> SSLFingerprint::Create( |
| absl::string_view algorithm, |
| const rtc::SSLCertificate& cert) { |
| uint8_t digest_val[64]; |
| size_t digest_len; |
| bool ret = cert.ComputeDigest(algorithm, digest_val, sizeof(digest_val), |
| &digest_len); |
| if (!ret) { |
| return nullptr; |
| } |
| return std::make_unique<SSLFingerprint>( |
| algorithm, ArrayView<const uint8_t>(digest_val, digest_len)); |
| } |
| |
| SSLFingerprint* SSLFingerprint::CreateFromRfc4572( |
| absl::string_view algorithm, |
| absl::string_view fingerprint) { |
| return CreateUniqueFromRfc4572(algorithm, fingerprint).release(); |
| } |
| |
| std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateUniqueFromRfc4572( |
| absl::string_view algorithm, |
| absl::string_view fingerprint) { |
| if (algorithm.empty() || !rtc::IsFips180DigestAlgorithm(algorithm)) |
| return nullptr; |
| |
| if (fingerprint.empty()) |
| return nullptr; |
| |
| char value[rtc::MessageDigest::kMaxSize]; |
| size_t value_len = |
| rtc::hex_decode_with_delimiter(ArrayView<char>(value), fingerprint, ':'); |
| if (!value_len) |
| return nullptr; |
| |
| return std::make_unique<SSLFingerprint>( |
| algorithm, |
| ArrayView<const uint8_t>(reinterpret_cast<uint8_t*>(value), value_len)); |
| } |
| |
| std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateFromCertificate( |
| const RTCCertificate& cert) { |
| std::string digest_alg; |
| if (!cert.GetSSLCertificate().GetSignatureDigestAlgorithm(&digest_alg)) { |
| RTC_LOG(LS_ERROR) |
| << "Failed to retrieve the certificate's digest algorithm"; |
| return nullptr; |
| } |
| |
| std::unique_ptr<SSLFingerprint> fingerprint = |
| CreateUnique(digest_alg, *cert.identity()); |
| if (!fingerprint) { |
| RTC_LOG(LS_ERROR) << "Failed to create identity fingerprint, alg=" |
| << digest_alg; |
| } |
| return fingerprint; |
| } |
| |
| SSLFingerprint::SSLFingerprint(absl::string_view algorithm, |
| ArrayView<const uint8_t> digest_view) |
| : algorithm(algorithm), digest(digest_view.data(), digest_view.size()) {} |
| |
| SSLFingerprint::SSLFingerprint(absl::string_view algorithm, |
| const uint8_t* digest_in, |
| size_t digest_len) |
| : SSLFingerprint(algorithm, MakeArrayView(digest_in, digest_len)) {} |
| |
| bool SSLFingerprint::operator==(const SSLFingerprint& other) const { |
| return algorithm == other.algorithm && digest == other.digest; |
| } |
| |
| std::string SSLFingerprint::GetRfc4572Fingerprint() const { |
| std::string fingerprint = rtc::hex_encode_with_delimiter( |
| absl::string_view(digest.data<char>(), digest.size()), ':'); |
| absl::c_transform(fingerprint, fingerprint.begin(), ::toupper); |
| return fingerprint; |
| } |
| |
| std::string SSLFingerprint::ToString() const { |
| std::string fp_str = algorithm; |
| fp_str.append(" "); |
| fp_str.append(GetRfc4572Fingerprint()); |
| return fp_str; |
| } |
| |
| } // namespace rtc |