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}
This commit is contained in:
@ -47,8 +47,8 @@ void SetRemoteFingerprintFromCert(
|
||||
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 @@ void SetRemoteFingerprintFromCert(
|
||||
fingerprint->algorithm,
|
||||
reinterpret_cast<const uint8_t*>(fingerprint->digest.data()),
|
||||
fingerprint->digest.size()));
|
||||
delete fingerprint;
|
||||
}
|
||||
|
||||
class DtlsTestClient : public sigslot::has_slots<> {
|
||||
|
@ -33,7 +33,7 @@ class FakeDtlsTransport : public DtlsTransportInternal {
|
||||
: 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 @@ class FakeDtlsTransport : public DtlsTransportInternal {
|
||||
: 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 @@ class FakeDtlsTransport : public DtlsTransportInternal {
|
||||
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 {
|
||||
|
@ -120,8 +120,8 @@ bool TransportDescriptionFactory::SetSecurityInfo(TransportDescription* desc,
|
||||
// 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;
|
||||
}
|
||||
|
@ -316,8 +316,9 @@ webrtc::RTCError JsepTransport::VerifyCertificateFingerprint(
|
||||
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 @@ webrtc::RTCError JsepTransport::NegotiateAndSetDtlsParameters(
|
||||
"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
|
||||
|
@ -126,7 +126,7 @@ class JsepTransport2Test : public testing::Test, public sigslot::has_slots<> {
|
||||
|
||||
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 @@ TEST_P(JsepTransport2WithRtcpMux, VerifyCertificateFingerprint) {
|
||||
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_
|
||||
|
@ -170,7 +170,7 @@ class JsepTransportControllerTest : public JsepTransportController::Observer,
|
||||
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>(),
|
||||
|
@ -703,8 +703,8 @@ TEST_P(PeerConnectionCryptoTest, SessionErrorIfFingerprintInvalid) {
|
||||
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;
|
||||
|
@ -146,7 +146,7 @@ std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
|
||||
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());
|
||||
}
|
||||
|
@ -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 ParseIceOptions(const std::string& line,
|
||||
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 @@ bool ParseSessionDescription(const std::string& message,
|
||||
"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 @@ bool ParseGroupAttribute(const std::string& line,
|
||||
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 @@ static bool ParseFingerprintAttribute(const std::string& line,
|
||||
::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 @@ bool ParseContent(const std::string& message,
|
||||
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;
|
||||
|
@ -1503,8 +1503,7 @@ class WebRtcSdpTest : public testing::Test {
|
||||
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,
|
||||
|
@ -54,8 +54,8 @@ std::unique_ptr<SSLCertificateStats> SSLCertificate::GetStats() const {
|
||||
// |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();
|
||||
|
@ -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;
|
||||
@ -78,12 +88,14 @@ SSLFingerprint* SSLFingerprint::CreateFromCertificate(
|
||||
return fingerprint;
|
||||
}
|
||||
|
||||
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) {}
|
||||
|
@ -22,19 +22,34 @@ namespace rtc {
|
||||
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);
|
||||
|
@ -180,7 +180,7 @@ IdentityAndInfo CreateFakeIdentityAndInfoFromDers(
|
||||
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());
|
||||
}
|
||||
|
Reference in New Issue
Block a user