| // Copyright 2020 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 <cstdlib> |
| #include <iostream> |
| #include <string> |
| #include <vector> |
| |
| #include "base/no_destructor.h" |
| #include "base/notreached.h" |
| #include "base/time/time_override.h" |
| #include "components/cast_certificate/cast_cert_reader.h" |
| #include "components/cast_certificate/cast_cert_test_helpers.h" |
| #include "components/cast_channel/cast_auth_util.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 "net/cert/x509_certificate.h" |
| #include "net/cert/x509_util.h" |
| #include "net/test/test_certificate_data.h" |
| #include "testing/libfuzzer/proto/lpm_interface.h" |
| |
| namespace cast_channel { |
| namespace fuzz { |
| namespace { |
| |
| const uint8_t kCertData[] = { |
| // Generated by //net/data/ssl/certificates:generate_fuzzer_cert_includes |
| #include "net/data/ssl/certificates/wildcard.inc" |
| }; |
| |
| base::NoDestructor<std::vector<std::string>> certs; |
| |
| static bool InitializeOnce() { |
| *certs = cast_certificate::ReadCertificateChainFromString( |
| openscreen::cast::kChromecastGen1); |
| CHECK(certs->size() >= 1) |
| << "We should always have at least one certificate."; |
| return true; |
| } |
| |
| void UpdateTime(TimeBoundCase c, const base::Time* time, int direction) { |
| auto& mtime = const_cast<base::Time&>(*time); |
| switch (c) { |
| case TimeBoundCase::VALID: |
| // Create bound that include the current date. |
| mtime = base::Time::Now() + base::Days(direction); |
| break; |
| case TimeBoundCase::INVALID: |
| // Create a bound that excludes the current date. |
| mtime = base::Time::Now() + base::Days(-direction); |
| break; |
| case TimeBoundCase::OOB: |
| // Create a bound so far in the past/future it's not valid. |
| mtime = base::Time::Now() + base::Days(direction * 10000); |
| break; |
| case TimeBoundCase::MISSING: |
| // Remove any existing bound. |
| mtime = base::Time(); |
| break; |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| DEFINE_PROTO_FUZZER(CastAuthUtilInputs& input_union) { |
| static bool init = InitializeOnce(); |
| CHECK(init); |
| |
| if (input_union.input_case() != |
| CastAuthUtilInputs::kAuthenticateChallengeReplyInput) { |
| return; |
| } |
| |
| auto& 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. |
| scoped_refptr<net::X509Certificate> peer_cert = |
| net::X509Certificate::CreateFromBytes(kCertData); |
| UpdateTime(input.start_case(), &peer_cert->valid_start(), -1); |
| UpdateTime(input.expiry_case(), &peer_cert->valid_expiry(), +1); |
| |
| AuthContext context = AuthContext::CreateForTest(input.nonce()); |
| |
| AuthenticateChallengeReply(input.cast_message(), *peer_cert, context); |
| } |
| |
| } // namespace |
| } // namespace fuzz |
| } // namespace cast_channel |