|  | /* | 
|  | *  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 <cctype> | 
|  | #include <cstddef> | 
|  | #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/buffer.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 webrtc { | 
|  |  | 
|  | SSLFingerprint* SSLFingerprint::Create(absl::string_view algorithm, | 
|  | const SSLIdentity* identity) { | 
|  | return CreateUnique(algorithm, *identity).release(); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateUnique( | 
|  | absl::string_view algorithm, | 
|  | const SSLIdentity& identity) { | 
|  | return Create(algorithm, identity.certificate()); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<SSLFingerprint> SSLFingerprint::Create( | 
|  | absl::string_view algorithm, | 
|  | const SSLCertificate& cert) { | 
|  | Buffer digest(0, MessageDigest::kMaxSize); | 
|  | bool ret = cert.ComputeDigest(algorithm, digest); | 
|  | if (!ret) { | 
|  | return nullptr; | 
|  | } | 
|  | return std::make_unique<SSLFingerprint>(algorithm, digest); | 
|  | } | 
|  |  | 
|  | 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() || !IsFips180DigestAlgorithm(algorithm)) | 
|  | return nullptr; | 
|  |  | 
|  | if (fingerprint.empty()) | 
|  | return nullptr; | 
|  |  | 
|  | char value[MessageDigest::kMaxSize]; | 
|  | size_t value_len = | 
|  | 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 = 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 webrtc |