blob: 0c3b35f784720f3db1bee451349128cf9929ebae [file] [log] [blame]
// 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::TimeDelta::FromDays(direction);
break;
case TimeBoundCase::INVALID:
// Create a bound that excludes the current date.
mtime = base::Time::Now() + base::TimeDelta::FromDays(-direction);
break;
case TimeBoundCase::OOB:
// Create a bound so far in the past/future it's not valid.
mtime = base::Time::Now() + base::TimeDelta::FromDays(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