blob: e1c940f5d3b1d1ff20b57f53a5267e851cbbdde9 [file] [log] [blame]
// 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