#include <cstddef>
#include <cstdint>
#include <cstring>
#include <filesystem>
#include <initializer_list>
#include <iostream>
#include <string>
#include <string_view>
#include <system_error>
#include <tuple>
#include <vector>

#include <pw_fuzzer/fuzztest.h>
#include <pw_unit_test/framework.h>

#include "credentials/CHIPCert.h"
#include "credentials/CHIPCertificateSet.h"
#include "credentials/attestation_verifier/TestPAAStore.h"
#include "credentials/tests/CHIPAttCert_test_vectors.h"
#include "crypto/CHIPCryptoPAL.h"

namespace {

using namespace chip;
using namespace chip::Credentials;
using namespace fuzztest;

// Small C++17 helpers — abseil is not propagated through pw_fuzzer's public include path,
// so we rely on standard library primitives instead of absl::EndsWith / absl::StrContains.
constexpr bool EndsWithSv(std::string_view text, std::string_view suffix)
{
    return text.size() >= suffix.size() && text.compare(text.size() - suffix.size(), suffix.size(), suffix) == 0;
}
constexpr bool ContainsSv(std::string_view text, std::string_view needle)
{
    return text.find(needle) != std::string_view::npos;
}

/*-----------------------------------  Helper Functions: Seed Providers   -----------------------------------*/
/******************************************************************************************************************* */

const std::string OpCertsDir = "credentials/test/operational-certificates-error-cases/";

// Lower bounds for the in-tree seed corpus (currently 172 .chip / 100 .der error-case vectors).
// Set well below the real counts so ordinary corpus churn does not fail the build, but a broken
// path or filter (0 / a handful of files) does. Enforced by SeedCorpusIsPresent below.
constexpr size_t kMinChipSeeds = 50;
constexpr size_t kMinDerSeeds  = 20;

auto isChipFile     = [](std::string_view name) { return EndsWithSv(name, ".chip"); };
auto isDerFile      = [](std::string_view name) { return EndsWithSv(name, ".der"); };
auto isChipRCACFile = [](std::string_view name) { return ContainsSv(name, "RCAC") && EndsWithSv(name, ".chip"); };
auto isChipNOCFile  = [](std::string_view name) {
    return ContainsSv(name, "NOC") && ContainsSv(name, "Cert") && EndsWithSv(name, ".chip");
};

// Lambda that reads certificates from a directory and returns them as a vector of strings, to be used as seeds
auto seedProvider = [](auto filterFunction) -> std::vector<std::string> {
    std::vector<std::string> seeds;

    // The seed directory ships in the source tree but is absent in the OSS-Fuzz runner, which
    // runs fuzzers from a temporary directory without the build tree (check_build does so
    // deliberately, to reject $OUT-relative dependencies). Skip file-based seeding instead of
    // aborting when the directory is missing. This ReadFilesFromDirectory path therefore supplies
    // seeds only for LOCAL runs (where the CWD contains the tree). On OSS-Fuzz the same directory
    // reaches the fuzzer through a separate, location-independent channel: the project's oss-fuzz
    // build.sh (projects/connectedhomeip/build.sh) zips it into a per-target
    // <target>_seed_corpus.zip that libFuzzer loads as its initial corpus. The two are independent
    // -- do not assume this call contributes seeds on the platform.
    // Non-throwing overload: a permission/I/O error must not abort the harness (the build
    // disables exceptions), which would defeat the purpose of tolerating a missing directory.
    std::error_code ec;
    if (!std::filesystem::is_directory(OpCertsDir, ec))
    {
        std::cout << "Seed directory '" << OpCertsDir << "' not found or inaccessible; continuing without file seeds" << std::endl;
        return seeds;
    }

    // fuzztest::ReadFilesFromDirectory returns a vector of tuples, each tuple contains a file
    // We need to unpack the tuples and then extract file content into a vector of strings.
    std::vector<std::tuple<std::string>> tupleVector = ReadFilesFromDirectory(OpCertsDir, filterFunction);

    if (tupleVector.size() == 0)
    {
        std::cout << "No Matching Seed files found in the chosen directory" << std::endl;
    }
    // DEBUG TIP: print tupleVector.size() here to check that we have the correct number of files as seeds.
    for (auto & [fileContents] : tupleVector)
    {
        seeds.push_back(fileContents);
    }
    return seeds;
};

void ChipCertFuzzer(const std::string & fuzzChipCerts)
{
    ByteSpan span(reinterpret_cast<const uint8_t *>(fuzzChipCerts.data()), fuzzChipCerts.size());

    {
        NodeId nodeId;
        FabricId fabricId;
        RETURN_SAFELY_IGNORED ExtractFabricIdFromCert(span, &fabricId);
        RETURN_SAFELY_IGNORED ExtractNodeIdFabricIdFromOpCert(span, &nodeId, &fabricId);
    }

    {
        CATValues cats;
        RETURN_SAFELY_IGNORED ExtractCATsFromOpCert(span, cats);
    }
}
FUZZ_TEST(FuzzChipCert, ChipCertFuzzer).WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipFile)));

/*-----------------------------------  Chip Cert FuzzTests  -----------------------------------*/
/******************************************************************************************************************* */

// The Property function for DecodeChipCertFuzzer, The FUZZ_TEST Macro will call this function.
void DecodeChipCertFuzzer(const std::string & fuzzChipCerts, BitFlags<CertDecodeFlags> aDecodeFlag)
{
    // TODO: #34352 To Move this to a Fixture once Errors related to FuzzTest Fixtures are resolved
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        ByteSpan span(reinterpret_cast<const uint8_t *>(fuzzChipCerts.data()), fuzzChipCerts.size());

        ChipCertificateData certData;
        RETURN_SAFELY_IGNORED DecodeChipCert(span, certData, aDecodeFlag);
    }
    chip::Platform::MemoryShutdown();
}

// This function allows us to fuzz using one of three CertDecodeFlags flags; by using FuzzTests's `ElementOf` API, we define an
// input domain by explicitly enumerating the set of values in it More Info:
// https://github.com/google/fuzztest/blob/main/doc/domains-reference.md#elementof-domains-element-of
auto AnyCertDecodeFlag()
{
    constexpr BitFlags<CertDecodeFlags> NullDecodeFlag;
    constexpr BitFlags<CertDecodeFlags> GenTBSHashFlag(CertDecodeFlags::kGenerateTBSHash);
    constexpr BitFlags<CertDecodeFlags> TrustAnchorFlag(CertDecodeFlags::kIsTrustAnchor);

    return ElementOf<CertDecodeFlags>({ NullDecodeFlag, GenTBSHashFlag, TrustAnchorFlag });
}

FUZZ_TEST(FuzzChipCert, DecodeChipCertFuzzer)
    .WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipFile)), AnyCertDecodeFlag());

/*************************************** */

void ConvertChipCertToX509CertFuzz(const std::string & fuzzChipCerts)
{
    ByteSpan span(reinterpret_cast<const uint8_t *>(fuzzChipCerts.data()), fuzzChipCerts.size());

    uint8_t outCertBuf[kMaxDERCertLength];
    MutableByteSpan outCert(outCertBuf);
    RETURN_SAFELY_IGNORED ConvertChipCertToX509Cert(span, outCert);
}
FUZZ_TEST(FuzzChipCert, ConvertChipCertToX509CertFuzz).WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipFile)));

/******************************************************************************** */
/******************************************************************************** */

void ValidateChipRCACFuzz(const std::string & fuzzRcacCerts)
{
    // TODO: #35369 Move this to a Fixture once Errors related to FuzzTest Fixtures are resolved
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        ByteSpan span(reinterpret_cast<const uint8_t *>(fuzzRcacCerts.data()), fuzzRcacCerts.size());
        RETURN_SAFELY_IGNORED ValidateChipRCAC(span);
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, ValidateChipRCACFuzz).WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipRCACFile)));

/*-----------------------------------  DER Cert FuzzTests  -----------------------------------*/
/******************************************************************************** */

void ConvertX509CertToChipCertFuzz(const std::string & fuzzDerCerts)
{
    ByteSpan span(reinterpret_cast<const uint8_t *>(fuzzDerCerts.data()), fuzzDerCerts.size());

    uint8_t outCertBuf[kMaxDERCertLength];
    MutableByteSpan outCert(outCertBuf);

    RETURN_SAFELY_IGNORED ConvertX509CertToChipCert(span, outCert);
}
FUZZ_TEST(FuzzChipCert, ConvertX509CertToChipCertFuzz).WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isDerFile)));

/******************************************************************************** */
/******************************************************************************** */

void ExtractSubjectDNFromX509CertFuzz(const std::string & fuzzDerCerts)
{
    ByteSpan span(reinterpret_cast<const uint8_t *>(fuzzDerCerts.data()), fuzzDerCerts.size());
    ChipDN subjectDN;
    RETURN_SAFELY_IGNORED ExtractSubjectDNFromX509Cert(span, subjectDN);
}
FUZZ_TEST(FuzzChipCert, ExtractSubjectDNFromX509CertFuzz).WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isDerFile)));

/*-----------------------------------  Frankencert-style Signature FuzzTest  -----------------------------------*/
/******************************************************************************************************************* */
//
// The Frankencert idea (Brubaker et al., S&P 2014) is to compose well-formed cert pieces from real corpora
// in recombined ways. We approximate it by giving the fuzzer independent string inputs, each seeded
// from a role-specific corpus, so mismatched issuer/subject and wrong-role pairings are on the table without a
// structure-aware mutator.
//
// NOTE: the operational-cert *chain*-validation harness that used to live here (LoadAndValidateChainFuzz,
// driving ChipCertificateSet::LoadCert/ValidateCert) was removed as redundant: FuzzCASE.HandleSigma3b already
// fuzzes that exact path via FabricTable::VerifyCredentials, seeded with a coherent Root01:ICA01:Node01_01
// identity, and reaches GetCertType/FindValidCert/ValidateCert far deeper than the byte-blob harness (which
// bounced off GetCertType). The (subject, signer) signature harness below is kept because it is the ONLY
// harness that reaches ChipCertificateSet::VerifyCertSignature's ECDSA path — HandleSigma3b never does.

/******************************************************************************** */

// Pair an independently-chosen (subject, signer) and run VerifyCertSignature. The seeds are role-agnostic
// so that every cross-pairing is exercised — a NOC signed by another NOC, an RCAC subject with an
// ICAC signer, etc. Bugs here would manifest as wrong-cert-accepted or as a crash inside the ECDSA path.
void VerifyCertSignatureFuzz(const std::string & subjectBytes, const std::string & signerBytes)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        BitFlags<CertDecodeFlags> generateHash(CertDecodeFlags::kGenerateTBSHash);

        ByteSpan subjectSpan(reinterpret_cast<const uint8_t *>(subjectBytes.data()), subjectBytes.size());
        ByteSpan signerSpan(reinterpret_cast<const uint8_t *>(signerBytes.data()), signerBytes.size());

        ChipCertificateData subject;
        ChipCertificateData signer;

        if (DecodeChipCert(subjectSpan, subject, generateHash) == CHIP_NO_ERROR &&
            DecodeChipCert(signerSpan, signer, generateHash) == CHIP_NO_ERROR)
        {
            RETURN_SAFELY_IGNORED VerifyCertSignature(subject, signer);
        }
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, VerifyCertSignatureFuzz)
    .WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipFile)),
                 Arbitrary<std::string>().WithSeeds(seedProvider(isChipFile)));

/*-----------------------------------  Gap-Filling: paths previously libFuzzer-only  ----------------------------------*/
/******************************************************************************************************************* */
//
// The harnesses below port API surfaces that existed as standalone libFuzzer harnesses
// (FuzzChipCertValidation.cpp, FuzzCertificateSet.cpp, FuzzOpCertExtractors.cpp) into pw_fuzzer
// FUZZ_TESTs so they are visible to the FuzzTest coverage workflow
// (scripts/tests/run_fuzztest_coverage.py) and benefit from seeded mutation.

void ValidateChipNetworkIdentityFuzz(const std::string & bytes)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        ByteSpan span(reinterpret_cast<const uint8_t *>(bytes.data()), bytes.size());

        // 1-arg form: validate only.
        RETURN_SAFELY_IGNORED ValidateChipNetworkIdentity(span);

        // 2-arg form: also returns the network identifier (SKID-shaped output).
        uint8_t keyIdBuf[kKeyIdentifierLength];
        MutableCertificateKeyId keyId(keyIdBuf);
        RETURN_SAFELY_IGNORED ValidateChipNetworkIdentity(span, keyId);
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, ValidateChipNetworkIdentityFuzz).WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipFile)));

/******************************************************************************** */
// DecodeChipDN takes a TLVReader, not a ByteSpan. Construct the reader inline.
void DecodeChipDNFuzz(const std::string & bytes)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        TLV::TLVReader reader;
        reader.Init(reinterpret_cast<const uint8_t *>(bytes.data()), bytes.size());
        if (reader.Next() == CHIP_NO_ERROR)
        {
            ChipDN dn;
            RETURN_SAFELY_IGNORED dn.DecodeFromTLV(reader);
        }
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, DecodeChipDNFuzz).WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipFile)));

/******************************************************************************** */
// Cross-cert helper that derives compressed fabric id from (rcac, noc). Two independent inputs
// so the fuzzer can pair mismatched roles — the function is one of the few that reads from two
// certificates simultaneously, and the compressed-fabric derivation involves an HKDF over the
// rcac public key plus the noc fabric id.
void OpCertCrossExtractorFuzz(const std::string & rcacBytes, const std::string & nocBytes)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        ByteSpan rcac(reinterpret_cast<const uint8_t *>(rcacBytes.data()), rcacBytes.size());
        ByteSpan noc(reinterpret_cast<const uint8_t *>(nocBytes.data()), nocBytes.size());

        // NB: current header param order is (rcac, noc, compressedFabricId, fabricId, nodeId).
        CompressedFabricId compressedFabricId = 0;
        NodeId nodeId                         = 0;
        FabricId fabricId                     = 0;
        RETURN_SAFELY_IGNORED
        ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(rcac, noc, compressedFabricId, fabricId, nodeId);

        // Also exercise the rcac-only public-key extraction.
        P256PublicKeySpan rcacPublicKey;
        RETURN_SAFELY_IGNORED ExtractPublicKeyFromChipCert(rcac, rcacPublicKey);
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, OpCertCrossExtractorFuzz)
    .WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipRCACFile)),
                 Arbitrary<std::string>().WithSeeds(seedProvider(isChipNOCFile)));

/******************************************************************************** */
// Consolidated chip-cert extractors that the previous PW file did not exercise. These are all
// reachable from FabricTable's AddNewFabric path on every NOC the fabric admin writes.
void OpCertChipExtractorsFuzz(const std::string & bytes)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        ByteSpan span(reinterpret_cast<const uint8_t *>(bytes.data()), bytes.size());

        {
            ChipDN dn;
            RETURN_SAFELY_IGNORED ExtractSubjectDNFromChipCert(span, dn);
        }
        {
            P256PublicKeySpan key;
            RETURN_SAFELY_IGNORED ExtractPublicKeyFromChipCert(span, key);
        }
        {
            CertificateKeyId skid;
            RETURN_SAFELY_IGNORED ExtractSKIDFromChipCert(span, skid);
        }
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, OpCertChipExtractorsFuzz).WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipFile)));

/******************************************************************************** */
// LoadCert via the TLVReader overload — distinct code path from the ByteSpan overload in
// LoadAndValidateChainFuzz. Reader-driven loading is what FabricTable + VendorIdVerificationClient
// use in the live commissioning path.
void LoadCertViaReaderFuzz(const std::string & bytes, uint8_t rawFlagByte)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        BitFlags<CertDecodeFlags> flags;
        flags.SetRaw(rawFlagByte);

        ByteSpan span(reinterpret_cast<const uint8_t *>(bytes.data()), bytes.size());

        ChipCertificateSet certSet;
        if (certSet.Init(/* maxCertsArraySize */ 4) == CHIP_NO_ERROR)
        {
            TLV::TLVReader reader;
            reader.Init(span.data(), span.size());
            if (reader.Next() == CHIP_NO_ERROR)
            {
                RETURN_SAFELY_IGNORED certSet.LoadCert(reader, flags, span);
            }
            certSet.Release();
        }
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, LoadCertViaReaderFuzz)
    .WithDomains(Arbitrary<std::string>().WithSeeds(seedProvider(isChipFile)), Arbitrary<uint8_t>());

/*-----------------------------------  Attestation chain (PAA -> PAI -> DAC)  ----------------------------------*/
/******************************************************************************************************************* */
//
// Attestation is the commissioner's first cryptographic gate. Every commissioned device hands the
// commissioner a DAC, a PAI, and (via DCL or hardcoded trust store) a PAA root. The commissioner
// must walk PAA -> PAI -> DAC and reject anything that doesn't validate. That walk is implemented
// in Crypto::ValidateCertificateChain — a totally distinct code path from ChipCertificateSet's
// TLV-chip-cert chain (which is for *operational* certs, not attestation).
//
// We seed each role with real DER-encoded test vectors from CHIPAttCert_test_vectors.h, so the
// fuzzer starts from inputs that decode cleanly and spends its budget exploring mutation rather
// than guessing valid DER. We also seed with PAA variants (ValInFuture, ValInPast, NoVID) to
// exercise the validity-window and VID-bound paths.

namespace AttestationSeeds {

inline std::vector<std::string> SeedSpansToVectorOfStrings(std::initializer_list<chip::ByteSpan> spans)
{
    std::vector<std::string> out;
    out.reserve(spans.size());
    for (const chip::ByteSpan & span : spans)
    {
        out.emplace_back(reinterpret_cast<const char *>(span.data()), span.size());
    }
    return out;
}

inline std::vector<std::string> PAASeeds()
{
    // The FIRST seed of each role domain (PAA/PAI/DAC) must form a coherent, currently-valid
    // chain so the pristine seed tuple passes Crypto::ValidateCertificateChain and exercises the
    // deep validation logic; without this the fuzzer bounces off the DER/chain gate.
    // Canonical valid chain: PAA_FFF1 -> PAI_FFF1_8000 -> DAC_FFF1_8000_0000
    // (see TestChipCryptoPAL.cpp ValidateCertificateChain success vectors).
    // sTestCert_PAA_FFF1_Cert lives in TestPAAStore.h (still chip::TestCerts), not
    // CHIPAttCert_test_vectors.h; it is linked via cert_test_vectors -> :test_paa_store.
    return SeedSpansToVectorOfStrings({
        chip::TestCerts::sTestCert_PAA_FFF1_Cert, // valid root, signs PAI_FFF1_8000
        chip::TestCerts::sTestCert_PAA_FFF2_ValInFuture_Cert,
        chip::TestCerts::sTestCert_PAA_FFF2_ValInPast_Cert,
        chip::TestCerts::sTestCert_PAA_NoVID_ToResignPAIs_Cert,
    });
}

inline std::vector<std::string> PAISeeds()
{
    return SeedSpansToVectorOfStrings({
        chip::TestCerts::sTestCert_PAI_FFF1_8000_Cert, // valid, issued by PAA_FFF1, signs DAC_FFF1_8000_0000
        chip::TestCerts::sTestCert_DAC_FFF1_8000_0000_2CDPs_Issuer_PAI_FFF2_8004_Cert,
    });
}

inline std::vector<std::string> DACSeeds()
{
    return SeedSpansToVectorOfStrings({
        chip::TestCerts::sTestCert_DAC_FFF1_8000_0000_Cert,
        chip::TestCerts::sTestCert_DAC_FFF1_8000_0001_Cert,
        chip::TestCerts::sTestCert_DAC_FFF1_8000_0002_Cert,
        chip::TestCerts::sTestCert_DAC_FFF1_8000_0000_2CDPs_Cert,
        chip::TestCerts::sTestCert_DAC_FFF1_8000_0000_CDP_Cert,
        chip::TestCerts::sTestCert_DAC_FFF1_8000_0000_CDP_Long_Cert,
        chip::TestCerts::sTestCert_DAC_FFF1_8000_0000_CDP_Wrong_Prefix_Cert,
    });
}

inline std::vector<std::string> AttestationDERSeeds()
{
    // Mixed DER corpus across the three roles, for seeding harnesses that don't need role distinction.
    std::vector<std::string> all = PAASeeds();
    auto pai                     = PAISeeds();
    auto dac                     = DACSeeds();
    all.insert(all.end(), pai.begin(), pai.end());
    all.insert(all.end(), dac.begin(), dac.end());
    return all;
}

} // namespace AttestationSeeds

/******************************************************************************** */
// Real attestation chain walker. Calls into Crypto::ValidateCertificateChain which is what the
// DefaultDACVerifier::VerifyAttestationInformation pipeline uses.
void AttestationChainValidationFuzz(const std::string & rootDer, const std::string & caDer, const std::string & leafDer)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        Crypto::CertificateChainValidationResult result = Crypto::CertificateChainValidationResult::kSuccess;
        RETURN_SAFELY_IGNORED Crypto::ValidateCertificateChain(
            reinterpret_cast<const uint8_t *>(rootDer.data()), rootDer.size(), reinterpret_cast<const uint8_t *>(caDer.data()),
            caDer.size(), reinterpret_cast<const uint8_t *>(leafDer.data()), leafDer.size(), result);
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, AttestationChainValidationFuzz)
    .WithDomains(Arbitrary<std::string>().WithSeeds(AttestationSeeds::PAASeeds()),
                 Arbitrary<std::string>().WithSeeds(AttestationSeeds::PAISeeds()),
                 Arbitrary<std::string>().WithSeeds(AttestationSeeds::DACSeeds()));

/******************************************************************************** */
// Format-only validator: enforces basicConstraints/keyUsage/EKU constraints per role.
// Each role has different rules — PAA must be self-signed CA, PAI must be CA with pathLen=0,
// DAC must not be CA. Wrong-role inputs and malformed extensions are the primary find class here.
void VerifyAttestationCertFormatFuzz(const std::string & derBytes, uint8_t certTypeRaw)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        chip::ByteSpan span(reinterpret_cast<const uint8_t *>(derBytes.data()), derBytes.size());

        // Map uint8_t -> AttestationCertType, cycling through the 3 valid values.
        Crypto::AttestationCertType type;
        switch (certTypeRaw % 3)
        {
        case 0:
            type = Crypto::AttestationCertType::kPAA;
            break;
        case 1:
            type = Crypto::AttestationCertType::kPAI;
            break;
        default:
            type = Crypto::AttestationCertType::kDAC;
            break;
        }
        RETURN_SAFELY_IGNORED Crypto::VerifyAttestationCertificateFormat(span, type);
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, VerifyAttestationCertFormatFuzz)
    .WithDomains(Arbitrary<std::string>().WithSeeds(AttestationSeeds::AttestationDERSeeds()), Arbitrary<uint8_t>());

/*-----------------------------------  Better-seeded existing DER fuzzers  ------------------------------------*/
/******************************************************************************************************************* */
// Re-seed the round-trip-from-DER fuzzers with real attestation certs. The originals only had
// error-case .der files, so the fuzzer mostly bounced off the ASN.1 layer. With valid PAA/PAI/DAC
// seeds we get past DER decode and into the Matter-specific cert-shape checks.

void SeededConvertX509CertToChipCertFuzz(const std::string & derBytes)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        ByteSpan span(reinterpret_cast<const uint8_t *>(derBytes.data()), derBytes.size());
        uint8_t outCertBuf[kMaxDERCertLength];
        MutableByteSpan outCert(outCertBuf);
        RETURN_SAFELY_IGNORED ConvertX509CertToChipCert(span, outCert);
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, SeededConvertX509CertToChipCertFuzz)
    .WithDomains(Arbitrary<std::string>().WithSeeds(AttestationSeeds::AttestationDERSeeds()));

void SeededExtractSubjectDNFromX509Fuzz(const std::string & derBytes)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        ByteSpan span(reinterpret_cast<const uint8_t *>(derBytes.data()), derBytes.size());
        ChipDN subjectDN;
        RETURN_SAFELY_IGNORED ExtractSubjectDNFromX509Cert(span, subjectDN);
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, SeededExtractSubjectDNFromX509Fuzz)
    .WithDomains(Arbitrary<std::string>().WithSeeds(AttestationSeeds::AttestationDERSeeds()));

/*-----------------------------------  Re-signing Frankencert FuzzTest  -----------------------------------*/
/******************************************************************************************************************* */
//
// Coverage-driven harness for ChipCertificateSet::ValidateCert. Every other cert harness only *reaches* the
// operational-cert validation logic via a static seed — any mutation breaks the signature/DER, so the validator
// bails before the field checks (VerifyCertSignature stays on its failure arm). This closes that gap the way real
// Frankencert testing does: hold a fixed in-harness CA (built once), let the fuzzer mutate the certificate
// *fields* (node/fabric id, serial, validity window, and the effective time the chain is validated at), then
// RE-SIGN the resulting cert with the CA key so the signature is always valid. Validation therefore proceeds past
// VerifyCertSignature into the validity-window / DN-classification / key-usage / cert-type logic on
// mutated-but-validly-signed input.
//
// No production code is stubbed or weakened: NewNodeOperationalX509Cert, ConvertX509CertToChipCert and
// ChipCertificateSet::ValidateCert are the real project functions; the CA + trust anchor mirror a production trust
// store. The CA (two P256 keygens + a self-signed root) is built once behind a function-local static, so
// per-input cost is one ECDSA sign + one DER->CHIP conversion + one validation.

struct ResignCaFixture
{
    Crypto::P256Keypair rootKeypair;
    Crypto::P256Keypair leafKeypair;
    ChipDN rootDN; // RCAC subject, reused as the NOC issuer DN
    uint8_t rcacChipBuf[kMaxCHIPCertLength];
    ByteSpan rcacChip;
    CHIP_ERROR status = CHIP_ERROR_INTERNAL;

    ResignCaFixture()
    {
        if (chip::Platform::MemoryInit() != CHIP_NO_ERROR)
            return;
        if (rootKeypair.Initialize(Crypto::ECPKeyTarget::ECDSA) != CHIP_NO_ERROR)
            return;
        if (leafKeypair.Initialize(Crypto::ECPKeyTarget::ECDSA) != CHIP_NO_ERROR)
            return;
        if (rootDN.AddAttribute_MatterRCACId(0xCAFECAFECAFECAFE) != CHIP_NO_ERROR)
            return;

        // Wide validity window (the canonical one used across the cert tests): 1990-01-01 .. 2013-02-xx epoch.
        X509CertRequestParams rootParams = { 1, 631161876, 729942000, rootDN, rootDN };
        uint8_t der[kMaxDERCertLength];
        MutableByteSpan derSpan(der);
        if (NewRootX509Cert(rootParams, rootKeypair, derSpan) != CHIP_NO_ERROR)
            return;

        MutableByteSpan chipSpan(rcacChipBuf);
        if (ConvertX509CertToChipCert(derSpan, chipSpan) != CHIP_NO_ERROR)
            return;
        rcacChip = chipSpan;
        status   = CHIP_NO_ERROR;
    }
};

const ResignCaFixture & ResignCa()
{
    static ResignCaFixture ca;
    return ca;
}

void ValidateSignedChipCertFuzz(uint64_t nodeId, uint64_t fabricId, int64_t serialNumber, uint32_t validityStart,
                                uint32_t validityEnd, uint32_t effectiveTimeSecs, const std::vector<uint32_t> & cats)
{
    const ResignCaFixture & ca = ResignCa();
    if (ca.status != CHIP_NO_ERROR)
        return;

    // NOC subject DN from the fuzzed identity, issued by our CA's root DN.
    ChipDN nocDN;
    if (nocDN.AddAttribute_MatterNodeId(nodeId) != CHIP_NO_ERROR || nocDN.AddAttribute_MatterFabricId(fabricId) != CHIP_NO_ERROR)
        return;

    // Count-amplify the CAT (CASE Authentication Tag) list — a variable-length subject-DN field that
    // fills the fixed std::array<CASEAuthTag, kMaxSubjectCATAttributeCount> in CATValues. Fuzz both the
    // count (0 .. just past the cap) and the values: over-cap counts exercise the generator's rejection
    // boundary, at-cap counts drive ExtractCATsFromOpCert's fixed-array fill on a valid multi-CAT cert.
    for (size_t i = 0; i < cats.size() && i <= kMaxSubjectCATAttributeCount + 1; ++i)
    {
        if (nocDN.AddAttribute_MatterCASEAuthTag(cats[i]) != CHIP_NO_ERROR)
            break;
    }

    X509CertRequestParams nocParams = { serialNumber, validityStart, validityEnd, nocDN, ca.rootDN };

    // Re-sign with the CA root key: the NOC signature is always valid no matter how the fields were mutated.
    // Field combinations the generator itself rejects (negative serial, malformed DN) return early as uninteresting.
    uint8_t der[kMaxDERCertLength];
    MutableByteSpan derSpan(der);
    if (NewNodeOperationalX509Cert(nocParams, ca.leafKeypair.Pubkey(), ca.rootKeypair, derSpan) != CHIP_NO_ERROR)
        return;

    uint8_t nocChipBuf[kMaxCHIPCertLength];
    MutableByteSpan nocChip(nocChipBuf);
    if (ConvertX509CertToChipCert(derSpan, nocChip) != CHIP_NO_ERROR)
        return;

    // Drive the CAT extraction fixed-array fill on the freshly-signed, CAT-bearing NOC.
    {
        CATValues extractedCats;
        RETURN_SAFELY_IGNORED ExtractCATsFromOpCert(nocChip, extractedCats);
    }

    ChipCertificateSet certSet;
    if (certSet.Init(2) != CHIP_NO_ERROR)
        return;

    BitFlags<CertDecodeFlags> anchor;
    anchor.Set(CertDecodeFlags::kIsTrustAnchor).Set(CertDecodeFlags::kGenerateTBSHash);
    BitFlags<CertDecodeFlags> genHash(CertDecodeFlags::kGenerateTBSHash);

    RETURN_SAFELY_IGNORED certSet.LoadCert(ca.rcacChip, anchor);
    if (certSet.LoadCert(nocChip, genHash) == CHIP_NO_ERROR)
    {
        ValidationContext context;
        context.Reset();
        context.SetEffectiveTime<CurrentChipEpochTime>(chip::System::Clock::Seconds32(effectiveTimeSecs));
        context.mRequiredKeyUsages.Set(KeyUsageFlags::kDigitalSignature);

        const ChipCertificateData * leaf = certSet.GetLastCert();
        RETURN_SAFELY_IGNORED certSet.ValidateCert(leaf, context);
    }

    certSet.Release();
    // Intentionally no MemoryShutdown: the CA fixture persists across iterations.
}

FUZZ_TEST(FuzzChipCert, ValidateSignedChipCertFuzz)
    .WithDomains(Arbitrary<uint64_t>().WithSeeds({ 0x1122334455667788ULL }), // nodeId
                 Arbitrary<uint64_t>().WithSeeds({ 0xFAB0000000000001ULL }), // fabricId
                 Arbitrary<int64_t>().WithSeeds({ 1 }),                      // serialNumber
                 Arbitrary<uint32_t>().WithSeeds({ 631161876U }),            // validityStart
                 Arbitrary<uint32_t>().WithSeeds({ 729942000U }),            // validityEnd
                 Arbitrary<uint32_t>().WithSeeds({ 680000000U }),            // effectiveTime (within validity)
                 // CATs: fuzz count + values; seed one valid CAT (id 0xABCD, version 1) to reach the CAT path
                 Arbitrary<std::vector<uint32_t>>().WithSeeds({ std::vector<uint32_t>{ 0xABCD0001U } }));

/*-----------------------------------  PW parity for un-ported libFuzzer cert helpers  -----------------------------------*/
/******************************************************************************************************************* */
// FuzzEcdsaSignatureConvert.cpp and FuzzAsn1ChipEpochTime.cpp had no FuzzTest equivalent. Both run on
// fuzzed bytes: the ECDSA signature raw<->DER conversion sits on attestation-response and
// op-cert signatures; the ASN.1<->CHIP-epoch conversion parses X.509 NotBefore/NotAfter from peer op-certs
// and DACs. Ported here so the FuzzTest coverage workflow sees them.

// Domain seeds for the raw<->DER ECDSA conversions. Arbitrary<std::string>() alone starts from
// empty/short strings that miss the >= 64-byte gate in ConvertECDSASignatureRawToDER and hand
// ConvertIntegerDERToRaw only trivial inputs, so the DER emit branches stay cold. A valid 64-byte
// raw signature and a well-formed DER ECDSA-Sig-Value cover the zero-pad / no-pad integer arms.
inline std::vector<std::string> EcdsaSignatureSeeds()
{
    std::vector<std::string> seeds;

    // 64-byte raw P-256 signature (r || s): r's leading 0x80 exercises the DER positive-integer
    // zero-pad branch, s does not (no-pad branch); the whole is also a valid 64-byte positive integer.
    std::string raw(Crypto::kP256_ECDSA_Signature_Length_Raw, '\x11');
    raw[0]                                            = static_cast<char>(0x80);
    raw[Crypto::kP256_ECDSA_Signature_Length_Raw / 2] = '\x22';
    seeds.push_back(std::move(raw));

    // Well-formed DER ECDSA-Sig-Value: SEQUENCE { INTEGER r(32B), INTEGER s(32B) }.
    std::string der;
    der.push_back('\x30');
    der.push_back('\x44');
    der.push_back('\x02');
    der.push_back('\x20');
    der.append(32, '\x33');
    der.push_back('\x02');
    der.push_back('\x20');
    der.append(32, '\x44');
    seeds.push_back(std::move(der));

    return seeds;
}

// Domain seeds for the ASN.1 <-> CHIP-epoch conversions. ASN1ToChipEpochTime reads the fuzzed
// bytes as a raw ASN1UniversalTime struct (see the harness below), so a seed must be valid struct
// bytes for CalendarToChipEpochTime's success arm to run -- blind bytes almost never form a legal
// Year/Month/Day/.../Second tuple, leaving that path and the 99991231235959Z sentinel branch cold.
inline std::vector<std::string> Asn1TimeStructSeeds()
{
    auto asStructBytes = [](const chip::ASN1::ASN1UniversalTime & t) {
        return std::string(reinterpret_cast<const char *>(&t), sizeof(t));
    };

    std::vector<std::string> seeds;

    // A valid calendar time -> CalendarToChipEpochTime success arm.
    chip::ASN1::ASN1UniversalTime valid{};
    valid.Year   = 2023;
    valid.Month  = 6;
    valid.Day    = 15;
    valid.Hour   = 12;
    valid.Minute = 30;
    valid.Second = 0;
    seeds.push_back(asStructBytes(valid));

    // The X.509 'no well-defined expiration' sentinel 99991231235959Z -> kNullCertTime branch.
    chip::ASN1::ASN1UniversalTime sentinel{};
    sentinel.Year   = 9999;
    sentinel.Month  = 12;
    sentinel.Day    = 31;
    sentinel.Hour   = 23;
    sentinel.Minute = 59;
    sentinel.Second = 59;
    seeds.push_back(asStructBytes(sentinel));

    return seeds;
}

void EcdsaSignatureConvertFuzz(const std::string & bytes)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        const uint8_t * data = reinterpret_cast<const uint8_t *>(bytes.data());
        const size_t len     = bytes.size();

        // Raw -> DER
        if (len >= Crypto::kP256_ECDSA_Signature_Length_Raw)
        {
            uint8_t rawBuf[Crypto::kP256_ECDSA_Signature_Length_Raw];
            memcpy(rawBuf, data, sizeof(rawBuf));
            P256ECDSASignatureSpan rawSig(rawBuf);
            uint8_t derBuf[256];
            MutableByteSpan derOut(derBuf);
            RETURN_SAFELY_IGNORED ConvertECDSASignatureRawToDER(rawSig, derOut);
        }

        // Integer DER -> raw
        {
            ByteSpan derInt(data, len);
            uint8_t rawBuf[64];
            RETURN_SAFELY_IGNORED ConvertIntegerDERToRaw(derInt, rawBuf, sizeof(rawBuf));
        }
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, EcdsaSignatureConvertFuzz).WithDomains(Arbitrary<std::string>().WithSeeds(EcdsaSignatureSeeds()));

void Asn1ChipEpochTimeFuzz(const std::string & bytes, uint32_t epochCandidate)
{
    ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
    {
        // fuzzed bytes -> raw ASN1UniversalTime -> epoch
        chip::ASN1::ASN1UniversalTime t{};
        const size_t n = bytes.size() < sizeof(t) ? bytes.size() : sizeof(t);
        if (n > 0)
        {
            memcpy(&t, bytes.data(), n);
        }
        uint32_t epoch = 0;
        RETURN_SAFELY_IGNORED ASN1ToChipEpochTime(t, epoch);

        // fuzzed epoch -> ASN1 time (reverse direction)
        chip::ASN1::ASN1UniversalTime back{};
        RETURN_SAFELY_IGNORED ChipEpochToASN1Time(epochCandidate, back);
    }
    chip::Platform::MemoryShutdown();
}

FUZZ_TEST(FuzzChipCert, Asn1ChipEpochTimeFuzz)
    .WithDomains(Arbitrary<std::string>().WithSeeds(Asn1TimeStructSeeds()),
                 Arbitrary<uint32_t>().WithSeeds({ 0u, 680000000u, 729942000u }));

/*-----------------------------------  Seed-corpus guard  -----------------------------------*/
/******************************************************************************************************************* */
// A seedless run of a DER/TLV certificate parser bounces off the ASN.1 front door and yields
// near-zero coverage, so silently fuzzing without seeds gives false confidence. This unit test
// (runs in the FuzzTest binary's unit-test mode, i.e. CI) fails loudly if the in-tree seed
// directory exists but yields an implausibly small corpus (wrong CWD, broken filter, or a
// moved/emptied seed dir). It intentionally passes when the directory is absent: on OSS-Fuzz the
// fuzzers run from a temp CWD and seeds arrive via <target>_seed_corpus.zip (packaged by the
// oss-fuzz build.sh; see seedProvider above), so a missing dir is expected there and must not fail
// the build. Note this guard validates the LOCAL file-seed corpus only -- it does not, and cannot,
// verify OSS-Fuzz seed delivery, which is the build.sh zip's responsibility.
TEST(FuzzChipCertSeeds, SeedCorpusIsPresent)
{
    std::error_code ec;
    if (!std::filesystem::is_directory(OpCertsDir, ec))
    {
        // OSS-Fuzz path (seeds supplied out-of-tree); nothing to assert here.
        return;
    }

    EXPECT_GE(seedProvider(isChipFile).size(), kMinChipSeeds);
    EXPECT_GE(seedProvider(isDerFile).size(), kMinDerSeeds);
}

} // namespace
