Reland: Use unique_ptr and ArrayView in SSLFingerprint

Bug: webrtc:9860
Change-Id: I550528556aa27050015de29d9d7d99cd9df59ce5
Reviewed-on: https://webrtc-review.googlesource.com/c/105520
Reviewed-by: Benjamin Wright <benwright@webrtc.org>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25149}
diff --git a/p2p/base/dtlstransport_unittest.cc b/p2p/base/dtlstransport_unittest.cc
index 8dfbf61..2ccb64c 100644
--- a/p2p/base/dtlstransport_unittest.cc
+++ b/p2p/base/dtlstransport_unittest.cc
@@ -47,8 +47,8 @@
     DtlsTransport* transport,
     const rtc::scoped_refptr<rtc::RTCCertificate>& cert,
     bool modify_digest = false) {
-  rtc::SSLFingerprint* fingerprint =
-      rtc::SSLFingerprint::CreateFromCertificate(cert);
+  std::unique_ptr<rtc::SSLFingerprint> fingerprint =
+      rtc::SSLFingerprint::CreateFromCertificate(*cert);
   if (modify_digest) {
     ++fingerprint->digest[0];
   }
@@ -57,7 +57,6 @@
       fingerprint->algorithm,
       reinterpret_cast<const uint8_t*>(fingerprint->digest.data()),
       fingerprint->digest.size()));
-  delete fingerprint;
 }
 
 class DtlsTestClient : public sigslot::has_slots<> {
diff --git a/p2p/base/fakedtlstransport.h b/p2p/base/fakedtlstransport.h
index c4f9d2c..8b0619a 100644
--- a/p2p/base/fakedtlstransport.h
+++ b/p2p/base/fakedtlstransport.h
@@ -33,7 +33,7 @@
       : ice_transport_(ice_transport),
         transport_name_(ice_transport->transport_name()),
         component_(ice_transport->component()),
-        dtls_fingerprint_("", nullptr, 0) {
+        dtls_fingerprint_("", nullptr) {
     RTC_DCHECK(ice_transport_);
     ice_transport_->SignalReadPacket.connect(
         this, &FakeDtlsTransport::OnIceTransportReadPacket);
@@ -45,7 +45,7 @@
       : owned_ice_transport_(std::move(ice)),
         transport_name_(owned_ice_transport_->transport_name()),
         component_(owned_ice_transport_->component()),
-        dtls_fingerprint_("", nullptr, 0) {
+        dtls_fingerprint_("", rtc::ArrayView<const uint8_t>()) {
     ice_transport_ = owned_ice_transport_.get();
     ice_transport_->SignalReadPacket.connect(
         this, &FakeDtlsTransport::OnIceTransportReadPacket);
@@ -133,7 +133,8 @@
   bool SetRemoteFingerprint(const std::string& alg,
                             const uint8_t* digest,
                             size_t digest_len) override {
-    dtls_fingerprint_ = rtc::SSLFingerprint(alg, digest, digest_len);
+    dtls_fingerprint_ =
+        rtc::SSLFingerprint(alg, rtc::MakeArrayView(digest, digest_len));
     return true;
   }
   bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override {
diff --git a/p2p/base/transportdescriptionfactory.cc b/p2p/base/transportdescriptionfactory.cc
index 670950d..689cd4f 100644
--- a/p2p/base/transportdescriptionfactory.cc
+++ b/p2p/base/transportdescriptionfactory.cc
@@ -120,8 +120,8 @@
   // This digest algorithm is used to produce the a=fingerprint lines in SDP.
   // RFC 4572 Section 5 requires that those lines use the same hash function as
   // the certificate's signature, which is what CreateFromCertificate does.
-  desc->identity_fingerprint.reset(
-      rtc::SSLFingerprint::CreateFromCertificate(certificate_));
+  desc->identity_fingerprint =
+      rtc::SSLFingerprint::CreateFromCertificate(*certificate_);
   if (!desc->identity_fingerprint) {
     return false;
   }
diff --git a/pc/jseptransport.cc b/pc/jseptransport.cc
index 894dce1..368b32f 100644
--- a/pc/jseptransport.cc
+++ b/pc/jseptransport.cc
@@ -316,8 +316,9 @@
     return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER,
                             "Fingerprint provided but no identity available.");
   }
-  std::unique_ptr<rtc::SSLFingerprint> fp_tmp(rtc::SSLFingerprint::Create(
-      fingerprint->algorithm, certificate->identity()));
+  std::unique_ptr<rtc::SSLFingerprint> fp_tmp =
+      rtc::SSLFingerprint::CreateUnique(fingerprint->algorithm,
+                                        *certificate->identity());
   RTC_DCHECK(fp_tmp.get() != NULL);
   if (*fp_tmp == *fingerprint) {
     return webrtc::RTCError::OK();
@@ -506,7 +507,8 @@
         "Local fingerprint supplied when caller didn't offer DTLS.");
   } else {
     // We are not doing DTLS
-    remote_fingerprint = absl::make_unique<rtc::SSLFingerprint>("", nullptr, 0);
+    remote_fingerprint = absl::make_unique<rtc::SSLFingerprint>(
+        "", rtc::ArrayView<const uint8_t>());
   }
   // Now that we have negotiated everything, push it downward.
   // Note that we cache the result so that if we have race conditions
diff --git a/pc/jseptransport_unittest.cc b/pc/jseptransport_unittest.cc
index 1b42578..748a4e0 100644
--- a/pc/jseptransport_unittest.cc
+++ b/pc/jseptransport_unittest.cc
@@ -126,7 +126,7 @@
 
     std::unique_ptr<rtc::SSLFingerprint> fingerprint;
     if (cert) {
-      fingerprint.reset(rtc::SSLFingerprint::CreateFromCertificate(cert));
+      fingerprint = rtc::SSLFingerprint::CreateFromCertificate(*cert);
     }
     jsep_description.transport_desc =
         TransportDescription(std::vector<std::string>(), ufrag, pwd,
@@ -386,8 +386,9 @@
     ASSERT_TRUE(certificate->ssl_certificate().GetSignatureDigestAlgorithm(
         &digest_algorithm));
     ASSERT_FALSE(digest_algorithm.empty());
-    std::unique_ptr<rtc::SSLFingerprint> good_fingerprint(
-        rtc::SSLFingerprint::Create(digest_algorithm, certificate->identity()));
+    std::unique_ptr<rtc::SSLFingerprint> good_fingerprint =
+        rtc::SSLFingerprint::CreateUnique(digest_algorithm,
+                                          *certificate->identity());
     ASSERT_NE(nullptr, good_fingerprint);
 
     EXPECT_TRUE(jsep_transport_
diff --git a/pc/jseptransportcontroller_unittest.cc b/pc/jseptransportcontroller_unittest.cc
index 26813e1..d36b8f3 100644
--- a/pc/jseptransportcontroller_unittest.cc
+++ b/pc/jseptransportcontroller_unittest.cc
@@ -170,7 +170,7 @@
                         rtc::scoped_refptr<rtc::RTCCertificate> cert) {
     std::unique_ptr<rtc::SSLFingerprint> fingerprint;
     if (cert) {
-      fingerprint.reset(rtc::SSLFingerprint::CreateFromCertificate(cert));
+      fingerprint = rtc::SSLFingerprint::CreateFromCertificate(*cert);
     }
 
     cricket::TransportDescription transport_desc(std::vector<std::string>(),
diff --git a/pc/peerconnection_crypto_unittest.cc b/pc/peerconnection_crypto_unittest.cc
index 71e8763..1a53d86 100644
--- a/pc/peerconnection_crypto_unittest.cc
+++ b/pc/peerconnection_crypto_unittest.cc
@@ -703,8 +703,8 @@
       invalid_answer->description()->GetTransportInfoByName(
           audio_content->name);
   ASSERT_TRUE(audio_transport_info);
-  audio_transport_info->description.identity_fingerprint.reset(
-      rtc::SSLFingerprint::CreateFromCertificate(other_certificate));
+  audio_transport_info->description.identity_fingerprint =
+      rtc::SSLFingerprint::CreateFromCertificate(*other_certificate);
 
   // Set the invalid answer and expect a fingerprint error.
   std::string error;
diff --git a/pc/rtcstatscollector_unittest.cc b/pc/rtcstatscollector_unittest.cc
index 7404d49..96ccfdf 100644
--- a/pc/rtcstatscollector_unittest.cc
+++ b/pc/rtcstatscollector_unittest.cc
@@ -146,7 +146,7 @@
   const rtc::SSLCertChain& chain = info->certificate->ssl_cert_chain();
   std::unique_ptr<rtc::SSLFingerprint> fp;
   for (size_t i = 0; i < chain.GetSize(); i++) {
-    fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain.Get(i)));
+    fp = rtc::SSLFingerprint::Create("sha-1", chain.Get(i));
     EXPECT_TRUE(fp);
     info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
   }
diff --git a/pc/webrtcsdp.cc b/pc/webrtcsdp.cc
index 67d4bbb..1260582 100644
--- a/pc/webrtcsdp.cc
+++ b/pc/webrtcsdp.cc
@@ -20,6 +20,7 @@
 #include <set>
 #include <string>
 #include <unordered_map>
+#include <utility>
 #include <vector>
 
 #include "api/mediatypes.h"
@@ -335,9 +336,10 @@
 static bool ParseExtmap(const std::string& line,
                         RtpExtension* extmap,
                         SdpParseError* error);
-static bool ParseFingerprintAttribute(const std::string& line,
-                                      rtc::SSLFingerprint** fingerprint,
-                                      SdpParseError* error);
+static bool ParseFingerprintAttribute(
+    const std::string& line,
+    std::unique_ptr<rtc::SSLFingerprint>* fingerprint,
+    SdpParseError* error);
 static bool ParseDtlsSetup(const std::string& line,
                            cricket::ConnectionRole* role,
                            SdpParseError* error);
@@ -2134,11 +2136,11 @@
             "Can't have multiple fingerprint attributes at the same level.",
             error);
       }
-      rtc::SSLFingerprint* fingerprint = NULL;
+      std::unique_ptr<rtc::SSLFingerprint> fingerprint;
       if (!ParseFingerprintAttribute(line, &fingerprint, error)) {
         return false;
       }
-      session_td->identity_fingerprint.reset(fingerprint);
+      session_td->identity_fingerprint = std::move(fingerprint);
     } else if (HasAttribute(line, kAttributeSetup)) {
       if (!ParseDtlsSetup(line, &(session_td->connection_role), error)) {
         return false;
@@ -2185,9 +2187,10 @@
   return true;
 }
 
-static bool ParseFingerprintAttribute(const std::string& line,
-                                      rtc::SSLFingerprint** fingerprint,
-                                      SdpParseError* error) {
+static bool ParseFingerprintAttribute(
+    const std::string& line,
+    std::unique_ptr<rtc::SSLFingerprint>* fingerprint,
+    SdpParseError* error) {
   if (!IsLineType(line, kLineTypeAttributes) ||
       !HasAttribute(line, kAttributeFingerprint)) {
     return ParseFailedExpectLine(line, 0, kLineTypeAttributes,
@@ -2213,7 +2216,8 @@
                  ::tolower);
 
   // The second field is the digest value. De-hexify it.
-  *fingerprint = rtc::SSLFingerprint::CreateFromRfc4572(algorithm, fields[1]);
+  *fingerprint =
+      rtc::SSLFingerprint::CreateUniqueFromRfc4572(algorithm, fields[1]);
   if (!*fingerprint) {
     return ParseFailed(line, "Failed to create fingerprint from the digest.",
                        error);
@@ -2857,12 +2861,11 @@
         return false;
       }
     } else if (HasAttribute(line, kAttributeFingerprint)) {
-      rtc::SSLFingerprint* fingerprint = NULL;
-
+      std::unique_ptr<rtc::SSLFingerprint> fingerprint;
       if (!ParseFingerprintAttribute(line, &fingerprint, error)) {
         return false;
       }
-      transport->identity_fingerprint.reset(fingerprint);
+      transport->identity_fingerprint = std::move(fingerprint);
     } else if (HasAttribute(line, kAttributeSetup)) {
       if (!ParseDtlsSetup(line, &(transport->connection_role), error)) {
         return false;
diff --git a/pc/webrtcsdp_unittest.cc b/pc/webrtcsdp_unittest.cc
index 6a95685..3111724 100644
--- a/pc/webrtcsdp_unittest.cc
+++ b/pc/webrtcsdp_unittest.cc
@@ -1503,8 +1503,7 @@
   void AddFingerprint() {
     desc_.RemoveTransportInfoByName(kAudioContentName);
     desc_.RemoveTransportInfoByName(kVideoContentName);
-    rtc::SSLFingerprint fingerprint(rtc::DIGEST_SHA_1, kIdentityDigest,
-                                    sizeof(kIdentityDigest));
+    rtc::SSLFingerprint fingerprint(rtc::DIGEST_SHA_1, kIdentityDigest);
     EXPECT_TRUE(desc_.AddTransportInfo(TransportInfo(
         kAudioContentName,
         TransportDescription(std::vector<std::string>(), kUfragVoice, kPwdVoice,
diff --git a/rtc_base/sslcertificate.cc b/rtc_base/sslcertificate.cc
index e40feec..53af0f5 100644
--- a/rtc_base/sslcertificate.cc
+++ b/rtc_base/sslcertificate.cc
@@ -54,8 +54,8 @@
   // |SSLCertificate::GetSignatureDigestAlgorithm| is not supported by the
   // implementation of |SSLCertificate::ComputeDigest|. This currently happens
   // with MD5- and SHA-224-signed certificates when linked to libNSS.
-  std::unique_ptr<SSLFingerprint> ssl_fingerprint(
-      SSLFingerprint::Create(digest_algorithm, this));
+  std::unique_ptr<SSLFingerprint> ssl_fingerprint =
+      SSLFingerprint::Create(digest_algorithm, *this);
   if (!ssl_fingerprint)
     return nullptr;
   std::string fingerprint = ssl_fingerprint->GetRfc4572Fingerprint();
diff --git a/rtc_base/sslfingerprint.cc b/rtc_base/sslfingerprint.cc
index 4f1ae8f..c62f703 100644
--- a/rtc_base/sslfingerprint.cc
+++ b/rtc_base/sslfingerprint.cc
@@ -20,57 +20,67 @@
 namespace rtc {
 
 SSLFingerprint* SSLFingerprint::Create(const std::string& algorithm,
-                                       const rtc::SSLIdentity* identity) {
-  if (!identity) {
-    return nullptr;
-  }
-
-  return Create(algorithm, &(identity->certificate()));
+                                       const rtc::SSLIdentity& identity) {
+  return CreateUnique(algorithm, identity).release();
 }
 
-SSLFingerprint* SSLFingerprint::Create(const std::string& algorithm,
-                                       const rtc::SSLCertificate* cert) {
+std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateUnique(
+    const std::string& algorithm,
+    const rtc::SSLIdentity& identity) {
+  return Create(algorithm, identity.certificate());
+}
+
+std::unique_ptr<SSLFingerprint> SSLFingerprint::Create(
+    const std::string& 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);
+  bool ret = cert.ComputeDigest(algorithm, digest_val, sizeof(digest_val),
+                                &digest_len);
   if (!ret) {
     return nullptr;
   }
-
-  return new SSLFingerprint(algorithm, digest_val, digest_len);
+  return absl::make_unique<SSLFingerprint>(
+      algorithm, ArrayView<const uint8_t>(digest_val, digest_len));
 }
 
 SSLFingerprint* SSLFingerprint::CreateFromRfc4572(
     const std::string& algorithm,
     const std::string& fingerprint) {
+  return CreateUniqueFromRfc4572(algorithm, fingerprint).release();
+}
+
+std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateUniqueFromRfc4572(
+    const std::string& algorithm,
+    const std::string& fingerprint) {
   if (algorithm.empty() || !rtc::IsFips180DigestAlgorithm(algorithm))
     return nullptr;
 
   if (fingerprint.empty())
     return nullptr;
 
-  size_t value_len;
   char value[rtc::MessageDigest::kMaxSize];
-  value_len = rtc::hex_decode_with_delimiter(
+  size_t value_len = rtc::hex_decode_with_delimiter(
       value, sizeof(value), fingerprint.c_str(), fingerprint.length(), ':');
   if (!value_len)
     return nullptr;
 
-  return new SSLFingerprint(algorithm, reinterpret_cast<uint8_t*>(value),
-                            value_len);
+  return absl::make_unique<SSLFingerprint>(
+      algorithm,
+      ArrayView<const uint8_t>(reinterpret_cast<uint8_t*>(value), value_len));
 }
 
-SSLFingerprint* SSLFingerprint::CreateFromCertificate(
-    const RTCCertificate* cert) {
+std::unique_ptr<SSLFingerprint> SSLFingerprint::CreateFromCertificate(
+    const RTCCertificate& cert) {
   std::string digest_alg;
-  if (!cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_alg)) {
+  if (!cert.ssl_certificate().GetSignatureDigestAlgorithm(&digest_alg)) {
     RTC_LOG(LS_ERROR)
         << "Failed to retrieve the certificate's digest algorithm";
     return nullptr;
   }
 
-  SSLFingerprint* fingerprint = Create(digest_alg, cert->identity());
+  std::unique_ptr<SSLFingerprint> fingerprint =
+      CreateUnique(digest_alg, *cert.identity());
   if (!fingerprint) {
     RTC_LOG(LS_ERROR) << "Failed to create identity fingerprint, alg="
                       << digest_alg;
@@ -79,11 +89,13 @@
 }
 
 SSLFingerprint::SSLFingerprint(const std::string& algorithm,
+                               ArrayView<const uint8_t> digest_view)
+    : algorithm(algorithm), digest(digest_view.data(), digest_view.size()) {}
+
+SSLFingerprint::SSLFingerprint(const std::string& algorithm,
                                const uint8_t* digest_in,
                                size_t digest_len)
-    : algorithm(algorithm) {
-  digest.SetData(digest_in, digest_len);
-}
+    : SSLFingerprint(algorithm, MakeArrayView(digest_in, digest_len)) {}
 
 SSLFingerprint::SSLFingerprint(const SSLFingerprint& from)
     : algorithm(from.algorithm), digest(from.digest) {}
diff --git a/rtc_base/sslfingerprint.h b/rtc_base/sslfingerprint.h
index b204bc7..a2d324c 100644
--- a/rtc_base/sslfingerprint.h
+++ b/rtc_base/sslfingerprint.h
@@ -22,20 +22,35 @@
 class SSLCertificate;
 
 struct SSLFingerprint {
+  // TODO(steveanton): Remove once downstream projects have moved off of this.
   static SSLFingerprint* Create(const std::string& algorithm,
-                                const rtc::SSLIdentity* identity);
+                                const rtc::SSLIdentity& identity);
+  // TODO(steveanton): Rename to Create once projects have migrated.
+  static std::unique_ptr<SSLFingerprint> CreateUnique(
+      const std::string& algorithm,
+      const rtc::SSLIdentity& identity);
 
-  static SSLFingerprint* Create(const std::string& algorithm,
-                                const rtc::SSLCertificate* cert);
+  static std::unique_ptr<SSLFingerprint> Create(
+      const std::string& algorithm,
+      const rtc::SSLCertificate& cert);
 
+  // TODO(steveanton): Remove once downstream projects have moved off of this.
   static SSLFingerprint* CreateFromRfc4572(const std::string& algorithm,
                                            const std::string& fingerprint);
+  // TODO(steveanton): Rename to CreateFromRfc4572 once projects have migrated.
+  static std::unique_ptr<SSLFingerprint> CreateUniqueFromRfc4572(
+      const std::string& algorithm,
+      const std::string& fingerprint);
 
   // Creates a fingerprint from a certificate, using the same digest algorithm
   // as the certificate's signature.
-  static SSLFingerprint* CreateFromCertificate(const RTCCertificate* cert);
+  static std::unique_ptr<SSLFingerprint> CreateFromCertificate(
+      const RTCCertificate& cert);
 
   SSLFingerprint(const std::string& algorithm,
+                 ArrayView<const uint8_t> digest_view);
+  // TODO(steveanton): Remove once downstream projects have moved off of this.
+  SSLFingerprint(const std::string& algorithm,
                  const uint8_t* digest_in,
                  size_t digest_len);
 
diff --git a/rtc_base/sslidentity_unittest.cc b/rtc_base/sslidentity_unittest.cc
index 68b5828..8183184 100644
--- a/rtc_base/sslidentity_unittest.cc
+++ b/rtc_base/sslidentity_unittest.cc
@@ -180,7 +180,7 @@
   const rtc::SSLCertChain& chain = info.identity->cert_chain();
   std::unique_ptr<rtc::SSLFingerprint> fp;
   for (size_t i = 0; i < chain.GetSize(); i++) {
-    fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain.Get(i)));
+    fp = rtc::SSLFingerprint::Create("sha-1", chain.Get(i));
     EXPECT_TRUE(fp);
     info.fingerprints.push_back(fp->GetRfc4572Fingerprint());
   }