| /* | 
 |  *  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 |