/*
 *
 *    Copyright (c) 2026 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      FuzzTest harness for the AEAD and KDF primitives that sit underneath
 *      every encrypted Matter session: CASE and PASE derive keys with
 *      HKDF-SHA256, and every secured message is AES-CCM.
 *
 *      Each parameter has its own typed domain, seeded from this directory's
 *      AES-CCM and HKDF test vectors, so the checks are functional invariants
 *      rather than only "does not crash":
 *
 *        - AES-CCM round-trip: decrypt(encrypt(pt)) recovers pt.
 *        - AES-CCM authenticity: a tampered tag or ciphertext must not decrypt.
 *        - HKDF determinism: identical inputs produce identical output.
 *
 *      Seeds are attached to the individual domains rather than to the
 *      FUZZ_TEST registration, because only domain-level seeds are injected
 *      when the suite runs under the libFuzzer compatibility engine.
 */

#include <array>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <vector>

#include <fuzztest/fuzztest_core.h>
#include <gtest/gtest.h>

#include <crypto/CHIPCryptoPAL.h>
#include <crypto/DefaultSessionKeystore.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>

#if CHIP_CRYPTO_PSA
#include <psa/crypto.h>
#endif

#include "AES_CCM_128_test_vectors.h"
#include "DerSigConversion_test_vectors.h"
#include "HKDF_SHA256_test_vectors.h"

namespace {

using namespace chip;
using namespace chip::Crypto;
using namespace fuzztest;

using KeyArray = std::array<uint8_t, kAES_CCM128_Key_Length>;
using Bytes    = std::vector<uint8_t>;

// The test vectors carry nonces of 8 and 12 bytes; Matter itself mandates 13.
// Allow a little headroom either side so nonce-length handling is exercised.
constexpr size_t kMaxNonceLen = kAES_CCM128_Nonce_Length + 3;
constexpr size_t kMaxAadLen   = 1024;
constexpr size_t kMaxTextLen  = 2048;

void EnsureInitialized()
{
    static const bool sInitialized = [] {
        VerifyOrDie(Platform::MemoryInit() == CHIP_NO_ERROR);
#if CHIP_CRYPTO_PSA
        // The PSA backend rejects every key operation until the driver is
        // initialized, which would otherwise turn each property below into a
        // vacuous pass.
        VerifyOrDie(psa_crypto_init() == PSA_SUCCESS);
#endif
        return true;
    }();
    (void) sInitialized;
}

Bytes ToBytes(const uint8_t * data, size_t len)
{
    return (data == nullptr) ? Bytes{} : Bytes(data, data + len);
}

// Pull one field out of every AES-CCM test vector to use as domain seeds.
template <typename Selector>
std::vector<Bytes> CcmSeeds(Selector select, size_t maxLen)
{
    std::vector<Bytes> seeds;
    for (const auto * vector : ccm_128_test_vectors)
    {
        Bytes value = select(vector);
        if (value.size() <= maxLen)
        {
            seeds.push_back(std::move(value));
        }
    }
    return seeds;
}

std::vector<KeyArray> CcmKeySeeds()
{
    std::vector<KeyArray> seeds;
    for (const auto * vector : ccm_128_test_vectors)
    {
        if (vector->key_len != kAES_CCM128_Key_Length)
        {
            continue;
        }
        KeyArray key{};
        memcpy(key.data(), vector->key, key.size());
        seeds.push_back(key);
    }
    return seeds;
}

auto AnyKey()
{
    return Arbitrary<KeyArray>().WithSeeds(CcmKeySeeds());
}

auto AnyNonce()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(kMaxNonceLen)
        .WithSeeds(CcmSeeds([](const ccm_128_test_vector * v) { return ToBytes(v->nonce, v->nonce_len); }, kMaxNonceLen));
}

auto AnyAad()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(kMaxAadLen)
        .WithSeeds(CcmSeeds([](const ccm_128_test_vector * v) { return ToBytes(v->aad, v->aad_len); }, kMaxAadLen));
}

auto AnyPlaintext()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(kMaxTextLen)
        .WithSeeds(CcmSeeds([](const ccm_128_test_vector * v) { return ToBytes(v->pt, v->pt_len); }, kMaxTextLen));
}

auto AnyCiphertext()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(kMaxTextLen)
        .WithSeeds(CcmSeeds([](const ccm_128_test_vector * v) { return ToBytes(v->ct, v->ct_len); }, kMaxTextLen));
}

auto AnyTag()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(kAES_CCM128_Tag_Length)
        .WithSeeds(CcmSeeds([](const ccm_128_test_vector * v) { return ToBytes(v->tag, v->tag_len); }, kAES_CCM128_Tag_Length));
}

// AES-CCM permits these MIC/tag lengths.
auto AnyTagLen()
{
    return ElementOf<size_t>({ 4, 6, 8, 10, 12, 14, 16 });
}

bool MakeKey(const KeyArray & raw, DefaultSessionKeystore & keystore, Aes128KeyHandle & out)
{
    Symmetric128BitsKeyByteArray material;
    memcpy(material, raw.data(), raw.size());
    return keystore.CreateKey(material, out) == CHIP_NO_ERROR;
}

// Drive the decryptor with fully fuzzer-controlled inputs. The authenticity
// check is expected to reject them; the contract under test is that it does so
// without reading or writing out of bounds.
void AesCcmDecryptNoCrash(const KeyArray & key, const Bytes & nonce, const Bytes & aad, const Bytes & ciphertext,
                          const Bytes & tagBytes, size_t tagLen)
{
    EnsureInitialized();

    DefaultSessionKeystore keystore;
    Aes128KeyHandle handle;
    if (!MakeKey(key, keystore, handle))
    {
        return;
    }

    Bytes tag(tagLen, 0);
    for (size_t i = 0; i < tagLen && i < tagBytes.size(); ++i)
    {
        tag[i] = tagBytes[i];
    }

    Bytes plaintext(ciphertext.size());
    RETURN_SAFELY_IGNORED AES_CCM_decrypt(ciphertext.data(), ciphertext.size(), aad.data(), aad.size(), tag.data(), tagLen, handle,
                                          nonce.data(), nonce.size(), plaintext.data());
    keystore.DestroyKey(handle);
}

FUZZ_TEST(CryptoPrimitives, AesCcmDecryptNoCrash)
    .WithDomains(AnyKey(), AnyNonce(), AnyAad(), AnyCiphertext(), AnyTag(), AnyTagLen());

// Round-trip plus authenticity: an honest decrypt must recover the plaintext,
// and any single-bit change to the tag or the ciphertext must be rejected.
void AesCcmRoundtrip(const KeyArray & key, const Bytes & nonce, const Bytes & aad, const Bytes & plaintext, size_t tagLen)
{
    EnsureInitialized();

    DefaultSessionKeystore keystore;
    Aes128KeyHandle handle;
    if (!MakeKey(key, keystore, handle))
    {
        return;
    }

    Bytes ciphertext(plaintext.size());
    Bytes tag(tagLen);
    CHIP_ERROR encryptError = AES_CCM_encrypt(plaintext.data(), plaintext.size(), aad.data(), aad.size(), handle, nonce.data(),
                                              nonce.size(), ciphertext.data(), tag.data(), tagLen);
    if (encryptError != CHIP_NO_ERROR)
    {
        keystore.DestroyKey(handle);
        return;
    }

    Bytes recovered(plaintext.size());
    ASSERT_EQ(AES_CCM_decrypt(ciphertext.data(), ciphertext.size(), aad.data(), aad.size(), tag.data(), tagLen, handle,
                              nonce.data(), nonce.size(), recovered.data()),
              CHIP_NO_ERROR);
    ASSERT_EQ(recovered, plaintext);

    Bytes sink(plaintext.size());

    Bytes tamperedTag = tag;
    tamperedTag[0] ^= 0x01;
    ASSERT_NE(AES_CCM_decrypt(ciphertext.data(), ciphertext.size(), aad.data(), aad.size(), tamperedTag.data(), tagLen, handle,
                              nonce.data(), nonce.size(), sink.data()),
              CHIP_NO_ERROR);

    if (!ciphertext.empty())
    {
        Bytes tamperedCiphertext = ciphertext;
        tamperedCiphertext[0] ^= 0x01;
        ASSERT_NE(AES_CCM_decrypt(tamperedCiphertext.data(), tamperedCiphertext.size(), aad.data(), aad.size(), tag.data(), tagLen,
                                  handle, nonce.data(), nonce.size(), sink.data()),
                  CHIP_NO_ERROR);
    }

    keystore.DestroyKey(handle);
}

FUZZ_TEST(CryptoPrimitives, AesCcmRoundtrip).WithDomains(AnyKey(), AnyNonce(), AnyAad(), AnyPlaintext(), AnyTagLen());

// AES-CTR carries no authentication tag: it is the keystream XOR used to
// obfuscate the privacy header of a group message, and on receive it runs over
// the datagram before the AES-CCM tag is checked.
void AesCtrCryptNoCrash(const KeyArray & key, const Bytes & nonce, const Bytes & input)
{
    EnsureInitialized();

    DefaultSessionKeystore keystore;
    Aes128KeyHandle handle;
    if (!MakeKey(key, keystore, handle))
    {
        return;
    }

    Bytes output(input.size());
    RETURN_SAFELY_IGNORED AES_CTR_crypt(input.data(), input.size(), handle, nonce.data(), nonce.size(), output.data());
    keystore.DestroyKey(handle);
}

FUZZ_TEST(CryptoPrimitives, AesCtrCryptNoCrash).WithDomains(AnyKey(), AnyNonce(), AnyCiphertext());

// CTR mode is its own inverse, so applying it twice must return the input.
void AesCtrRoundtrip(const KeyArray & key, const Bytes & nonce, const Bytes & plaintext)
{
    EnsureInitialized();

    DefaultSessionKeystore keystore;
    Aes128KeyHandle handle;
    if (!MakeKey(key, keystore, handle))
    {
        return;
    }

    Bytes ciphertext(plaintext.size());
    if (AES_CTR_crypt(plaintext.data(), plaintext.size(), handle, nonce.data(), nonce.size(), ciphertext.data()) == CHIP_NO_ERROR)
    {
        Bytes recovered(plaintext.size());
        ASSERT_EQ(AES_CTR_crypt(ciphertext.data(), ciphertext.size(), handle, nonce.data(), nonce.size(), recovered.data()),
                  CHIP_NO_ERROR);
        ASSERT_EQ(recovered, plaintext);
    }
    keystore.DestroyKey(handle);
}

FUZZ_TEST(CryptoPrimitives, AesCtrRoundtrip).WithDomains(AnyKey(), AnyNonce(), AnyPlaintext());

// Epoch keys and compressed fabric ids from the group key derivation vectors in
// TestChipCryptoPAL.cpp.
const uint8_t kEpochKey1[] = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf };
const uint8_t kEpochKey2[] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf };
const uint8_t kEpochKey3[] = { 0x23, 0x5b, 0xf7, 0xe6, 0x28, 0x23, 0xd3, 0x58, 0xdc, 0xa4, 0xba, 0x50, 0xb1, 0x53, 0x5f, 0x4b };
const uint8_t kCompressedFabricId1[] = { 0x29, 0x06, 0xc9, 0x08, 0xd1, 0x15, 0xd3, 0x62 };
const uint8_t kCompressedFabricId2[] = { 0x87, 0xe1, 0xb0, 0x04, 0xe2, 0x35, 0xa1, 0x30 };

auto AnyEpochKey()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES * 2)
        .WithSeeds({ Bytes(std::begin(kEpochKey1), std::end(kEpochKey1)), Bytes(std::begin(kEpochKey2), std::end(kEpochKey2)),
                     Bytes(std::begin(kEpochKey3), std::end(kEpochKey3)) });
}

auto AnyCompressedFabricId()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(kCompressedFabricIdentifierSize * 2)
        .WithSeeds({ Bytes(std::begin(kCompressedFabricId1), std::end(kCompressedFabricId1)),
                     Bytes(std::begin(kCompressedFabricId2), std::end(kCompressedFabricId2)) });
}

// The group key schedule: an epoch key plus the compressed fabric id yield the
// encryption key, the privacy key and the session id used for group messaging.
void GroupKeyDerivation(const Bytes & epochKey, const Bytes & compressedFabricId)
{
    EnsureInitialized();

    const ByteSpan epochKeySpan(epochKey.data(), epochKey.size());
    const ByteSpan fabricIdSpan(compressedFabricId.data(), compressedFabricId.size());

    uint8_t operationalKeyBuf[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0 };
    MutableByteSpan operationalKey(operationalKeyBuf);
    if (DeriveGroupOperationalKey(epochKeySpan, fabricIdSpan, operationalKey) == CHIP_NO_ERROR)
    {
        // The session id is derived from the operational key, so it is only
        // meaningful once that derivation has succeeded.
        uint16_t sessionId = 0;
        RETURN_SAFELY_IGNORED DeriveGroupSessionId(ByteSpan(operationalKey.data(), operationalKey.size()), sessionId);
    }

    // Fed the raw fuzzer bytes rather than the derived operational key that
    // production uses, so that the length-rejection path is exercised too.
    uint8_t privacyKeyBuf[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0 };
    MutableByteSpan privacyKey(privacyKeyBuf);
    RETURN_SAFELY_IGNORED DeriveGroupPrivacyKey(epochKeySpan, privacyKey);

    GroupOperationalCredentials credentials;
    RETURN_SAFELY_IGNORED DeriveGroupOperationalCredentials(epochKeySpan, fabricIdSpan, credentials);
}

FUZZ_TEST(CryptoPrimitives, GroupKeyDerivation).WithDomains(AnyEpochKey(), AnyCompressedFabricId());

// The combined credentials call must agree with running the same schedule by
// hand. Note the chaining: the privacy key is derived from the *operational*
// key, not from the epoch key -- DeriveGroupPrivacyKey names its parameter
// encryption_key, and both keys are 16 bytes, so feeding it the epoch key is
// accepted and silently yields a different key.
void GroupKeyDerivationAgrees(const Bytes & epochKey, const Bytes & compressedFabricId)
{
    EnsureInitialized();

    const ByteSpan epochKeySpan(epochKey.data(), epochKey.size());
    const ByteSpan fabricIdSpan(compressedFabricId.data(), compressedFabricId.size());

    GroupOperationalCredentials credentials;
    if (DeriveGroupOperationalCredentials(epochKeySpan, fabricIdSpan, credentials) != CHIP_NO_ERROR)
    {
        return;
    }

    uint8_t operationalKeyBuf[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0 };
    MutableByteSpan operationalKey(operationalKeyBuf);
    ASSERT_EQ(DeriveGroupOperationalKey(epochKeySpan, fabricIdSpan, operationalKey), CHIP_NO_ERROR);
    ASSERT_EQ(memcmp(credentials.encryption_key, operationalKey.data(), operationalKey.size()), 0);

    uint8_t privacyKeyBuf[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES] = { 0 };
    MutableByteSpan privacyKey(privacyKeyBuf);
    ASSERT_EQ(DeriveGroupPrivacyKey(ByteSpan(operationalKey.data(), operationalKey.size()), privacyKey), CHIP_NO_ERROR);
    ASSERT_EQ(memcmp(credentials.privacy_key, privacyKey.data(), privacyKey.size()), 0);

    uint16_t sessionId = 0;
    ASSERT_EQ(DeriveGroupSessionId(ByteSpan(operationalKey.data(), operationalKey.size()), sessionId), CHIP_NO_ERROR);
    ASSERT_EQ(sessionId, credentials.hash);
}

FUZZ_TEST(CryptoPrimitives, GroupKeyDerivationAgrees).WithDomains(AnyEpochKey(), AnyCompressedFabricId());

// ECDSA signatures cross this boundary in both directions: raw fixed-width r||s
// on the Matter wire, X9.62 DER inside certificates.
std::vector<Bytes> DerSigSeeds(bool wantDer)
{
    std::vector<Bytes> seeds;
    for (const auto & vector : kDerSigConvTestVectors)
    {
        seeds.push_back(wantDer ? ToBytes(vector.der_version, vector.der_version_length)
                                : ToBytes(vector.raw_version, vector.raw_version_length));
    }
    return seeds;
}

// The vectors use 32- and 64-byte field elements, so the buffers here are sized
// past P-256's kMax_ECDSA_Signature_Length rather than from it. Fuzzing the
// width a little beyond the largest vector exercises the length validation.
constexpr size_t kMaxFeLen     = 80;
constexpr size_t kMaxRawSigLen = 2 * kMaxFeLen;
constexpr size_t kMaxDerSigLen = kMaxRawSigLen + kMax_ECDSA_X9Dot62_Asn1_Overhead;

auto AnyFeLength()
{
    return InRange<size_t>(0, kMaxFeLen);
}

void EcdsaSignatureRawToDer(size_t feLengthBytes, const Bytes & rawSig)
{
    EnsureInitialized();

    uint8_t derBuf[kMaxDerSigLen];
    MutableByteSpan derSig(derBuf);
    RETURN_SAFELY_IGNORED EcdsaRawSignatureToAsn1(feLengthBytes, ByteSpan(rawSig.data(), rawSig.size()), derSig);
}

FUZZ_TEST(CryptoPrimitives, EcdsaSignatureRawToDer)
    .WithDomains(AnyFeLength(), Arbitrary<Bytes>().WithMaxSize(kMaxRawSigLen).WithSeeds(DerSigSeeds(false)));

void EcdsaSignatureDerToRaw(size_t feLengthBytes, const Bytes & derSig)
{
    EnsureInitialized();

    uint8_t rawBuf[kMaxRawSigLen];
    MutableByteSpan rawSig(rawBuf);
    RETURN_SAFELY_IGNORED EcdsaAsn1SignatureToRaw(feLengthBytes, ByteSpan(derSig.data(), derSig.size()), rawSig);
}

FUZZ_TEST(CryptoPrimitives, EcdsaSignatureDerToRaw)
    .WithDomains(AnyFeLength(), Arbitrary<Bytes>().WithMaxSize(kMaxDerSigLen).WithSeeds(DerSigSeeds(true)));

// The two converters are inverses for a well-formed raw signature, so a
// successful round-trip must reproduce the input exactly.
void EcdsaSignatureConversionRoundtrip(const Bytes & rawSig)
{
    EnsureInitialized();

    // Both directions take the field-element width, which is half of r||s.
    if (rawSig.empty() || (rawSig.size() % 2) != 0)
    {
        return;
    }
    const size_t feLengthBytes = rawSig.size() / 2;

    uint8_t derBuf[kMaxDerSigLen];
    MutableByteSpan derSig(derBuf);
    if (EcdsaRawSignatureToAsn1(feLengthBytes, ByteSpan(rawSig.data(), rawSig.size()), derSig) != CHIP_NO_ERROR)
    {
        return;
    }

    uint8_t rawBuf[kMaxRawSigLen];
    MutableByteSpan recovered(rawBuf);
    ASSERT_EQ(EcdsaAsn1SignatureToRaw(feLengthBytes, ByteSpan(derSig.data(), derSig.size()), recovered), CHIP_NO_ERROR);
    ASSERT_EQ(recovered.size(), rawSig.size());
    ASSERT_EQ(memcmp(recovered.data(), rawSig.data(), rawSig.size()), 0);
}

FUZZ_TEST(CryptoPrimitives, EcdsaSignatureConversionRoundtrip)
    .WithDomains(Arbitrary<Bytes>().WithMaxSize(kMaxRawSigLen).WithSeeds(DerSigSeeds(false)));

template <typename Selector>
std::vector<Bytes> HkdfSeeds(Selector select, size_t maxLen)
{
    std::vector<Bytes> seeds;
    for (const auto & vector : hkdf_sha256_test_vectors)
    {
        Bytes value = select(vector);
        if (value.size() <= maxLen)
        {
            seeds.push_back(std::move(value));
        }
    }
    return seeds;
}

constexpr size_t kMaxHkdfInputLen = 512;

auto AnyHkdfSecret()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(kMaxHkdfInputLen)
        .WithSeeds(
            HkdfSeeds([](const hkdf_sha256_vector & v) { return ToBytes(v.initial_key_material, v.initial_key_material_length); },
                      kMaxHkdfInputLen));
}

auto AnyHkdfSalt()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(kMaxHkdfInputLen)
        .WithSeeds(HkdfSeeds([](const hkdf_sha256_vector & v) { return ToBytes(v.salt, v.salt_length); }, kMaxHkdfInputLen));
}

auto AnyHkdfInfo()
{
    return Arbitrary<Bytes>()
        .WithMaxSize(kMaxHkdfInputLen)
        .WithSeeds(HkdfSeeds([](const hkdf_sha256_vector & v) { return ToBytes(v.info, v.info_length); }, kMaxHkdfInputLen));
}

void HkdfSha256NoCrash(const Bytes & secret, const Bytes & salt, const Bytes & info, size_t outLen)
{
    EnsureInitialized();

    Bytes out(outLen);
    HKDF_sha hkdf;
    RETURN_SAFELY_IGNORED hkdf.HKDF_SHA256(secret.data(), secret.size(), salt.data(), salt.size(), info.data(), info.size(),
                                           out.data(), outLen);
}

FUZZ_TEST(CryptoPrimitives, HkdfSha256NoCrash).WithDomains(AnyHkdfSecret(), AnyHkdfSalt(), AnyHkdfInfo(), InRange<size_t>(1, 4096));

// HKDF is a pure function: the same inputs must always produce the same output.
void HkdfSha256Deterministic(const Bytes & secret, const Bytes & salt, const Bytes & info, size_t outLen)
{
    EnsureInitialized();

    HKDF_sha hkdf;
    Bytes first(outLen);
    Bytes second(outLen);
    CHIP_ERROR firstError =
        hkdf.HKDF_SHA256(secret.data(), secret.size(), salt.data(), salt.size(), info.data(), info.size(), first.data(), outLen);
    CHIP_ERROR secondError =
        hkdf.HKDF_SHA256(secret.data(), secret.size(), salt.data(), salt.size(), info.data(), info.size(), second.data(), outLen);
    ASSERT_EQ(firstError, secondError);
    if (firstError == CHIP_NO_ERROR)
    {
        ASSERT_EQ(first, second);
    }
}

FUZZ_TEST(CryptoPrimitives, HkdfSha256Deterministic)
    .WithDomains(AnyHkdfSecret(), AnyHkdfSalt(), AnyHkdfInfo(), InRange<size_t>(1, 1024));

} // namespace
