| // 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 <openssl/asn1.h> |
| #include <openssl/x509.h> |
| |
| #include <cstdlib> |
| #include <iostream> |
| #include <string> |
| #include <vector> |
| |
| #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/sender/channel/cast_auth_util.h" |
| |
| namespace cast_channel { |
| namespace fuzz { |
| namespace { |
| |
| using ::cast::channel::CastMessage; |
| |
| const uint8_t kCertData[] = { |
| // Generated by //net/data/ssl/certificates:generate_fuzzer_cert_includes |
| #include "net/data/ssl/certificates/wildcard.inc" |
| }; |
| |
| static std::vector<std::string>* InitializeCertsOnce() { |
| static std::vector<std::string> certs = |
| cast_certificate::ReadCertificateChainFromString( |
| openscreen::cast::kChromecastGen1); |
| CHECK(certs.size() >= 1) << "We should always have at least one certificate."; |
| return &certs; |
| } |
| |
| 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::TimeDelta::FromDays(direction); |
| break; |
| case TimeBoundCase::INVALID: |
| // Create a bound that excludes the current date. |
| t = base::Time::Now() + base::TimeDelta::FromDays(-direction); |
| break; |
| case TimeBoundCase::OOB: |
| // Create a bound so far in the past/future it's not valid. |
| t = base::Time::Now() + base::TimeDelta::FromDays(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<std::string>* certs = InitializeCertsOnce(); |
| |
| 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. |
| const uint8_t* in = kCertData; |
| bssl::UniquePtr<X509> peer_cert{d2i_X509(nullptr, &in, sizeof(kCertData))}; |
| time_t not_before_time = GenerateCertTime(input.start_case(), -1); |
| time_t not_after_time = GenerateCertTime(input.expiry_case(), 1); |
| ASN1_TIME_set(const_cast<ASN1_TIME*>(X509_get0_notBefore(peer_cert.get())), |
| not_before_time); |
| ASN1_TIME_set(const_cast<ASN1_TIME*>(X509_get0_notAfter(peer_cert.get())), |
| not_after_time); |
| |
| auto context = openscreen::cast::AuthContext::CreateForTest(input.nonce()); |
| |
| openscreen::cast::AuthenticateChallengeReply(input.cast_message(), |
| peer_cert.get(), context); |
| } |
| |
| } // namespace |
| } // namespace fuzz |
| } // namespace cast_channel |