// Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include #include #include #include #include "base/notreached.h" #include "base/time/time.h" #include "components/cast_certificate/cast_cert_reader.h" #include "components/cast_channel/cast_auth_util_fuzzer_shared.h" #include "components/cast_channel/fuzz_proto/fuzzer_inputs.pb.h" // Generated by the "cast_auth_util_fuzzer_certs" data_headers target. #include "components/test/data/cast_certificate/certificates/chromecast_gen1_data.h" #include "testing/libfuzzer/proto/lpm_interface.h" #include "third_party/openscreen/src/cast/common/public/parsed_certificate.h" #include "third_party/openscreen/src/cast/common/public/trust_store.h" #include "third_party/openscreen/src/cast/sender/channel/cast_auth_util.h" namespace cast_channel { namespace fuzz { namespace { using ::cast::channel::CastMessage; using ::openscreen::cast::TrustStore; const uint8_t kCertData[] = { // Generated by //net/data/ssl/certificates:generate_fuzzer_cert_includes #include "net/data/ssl/certificates/wildcard.inc" }; static std::vector* InitializeCertsOnce() { static std::vector certs = cast_certificate::ReadCertificateChainFromString( openscreen::cast::kChromecastGen1); CHECK(certs.size() >= 1) << "We should always have at least one certificate."; return &certs; } static TrustStore* InitializeCastTrustStoreOnce() { static TrustStore* cast_trust_store = openscreen::cast::CastTrustStore::Create().release(); return cast_trust_store; } static TrustStore* InitializeCastCRLTrustStoreOnce() { static TrustStore* crl_trust_store = openscreen::cast::CastCRLTrustStore::Create().release(); return crl_trust_store; } time_t GenerateCertTime(TimeBoundCase c, int direction) { base::Time t; switch (c) { case TimeBoundCase::VALID: // Create bound that include the current date. t = base::Time::Now() + base::Days(direction); break; case TimeBoundCase::INVALID: // Create a bound that excludes the current date. t = base::Time::Now() + base::Days(-direction); break; case TimeBoundCase::OOB: // Create a bound so far in the past/future it's not valid. t = base::Time::Now() + base::Days(direction * 10000); break; case TimeBoundCase::MISSING: // Remove any existing bound. t = base::Time(); break; default: NOTREACHED(); } return t.ToTimeT(); } DEFINE_PROTO_FUZZER(CastAuthUtilInputs& input_union) { std::vector* certs = InitializeCertsOnce(); TrustStore* cast_trust_store = InitializeCastTrustStoreOnce(); TrustStore* crl_trust_store = InitializeCastCRLTrustStoreOnce(); if (input_union.input_case() != CastAuthUtilInputs::kAuthenticateChallengeReplyInput) { return; } CastAuthUtilInputs::AuthenticateChallengeReplyInput& input = *input_union.mutable_authenticate_challenge_reply_input(); SetupAuthenticateChallengeReplyInput(*certs, &input); // Build a well-formed cert with start and expiry times relative to the // current time. The actual cert doesn't matter for testing purposes // because validation failures are ignored. std::vector cert_data{std::begin(kCertData), std::end(kCertData)}; std::unique_ptr peer_cert = std::move( openscreen::cast::ParsedCertificate::ParseFromDER(cert_data).value()); time_t not_before_time = GenerateCertTime(input.start_case(), -1); time_t not_after_time = GenerateCertTime(input.expiry_case(), 1); peer_cert->SetNotBeforeTimeForTesting(not_before_time); peer_cert->SetNotAfterTimeForTesting(not_after_time); auto context = openscreen::cast::AuthContext::CreateForTest(input.nonce()); openscreen::cast::AuthenticateChallengeReply(input.cast_message(), *peer_cert, context, cast_trust_store, crl_trust_store); } } // namespace } // namespace fuzz } // namespace cast_channel