/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *
 *    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.
 */

/**
 * @brief Defines a table of fabrics that have provisioned the device.
 */

#include "FabricTable.h"

#include <lib/core/CHIPEncoding.h>
#include <lib/support/BufferWriter.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/SafeInt.h>
#include <lib/support/ScopedBuffer.h>
#include <platform/LockTracker.h>

namespace chip {
using namespace Credentials;
using namespace Crypto;

using CertChainElement = chip::Credentials::OperationalCertificateStore::CertChainElement;

namespace {

static_assert(kMinValidFabricIndex <= CHIP_CONFIG_MAX_FABRICS, "Must support some fabrics.");
static_assert(CHIP_CONFIG_MAX_FABRICS <= kMaxValidFabricIndex, "Max fabric count out of range.");

// Tags for our metadata storage.
constexpr TLV::Tag kVendorIdTag    = TLV::ContextTag(0);
constexpr TLV::Tag kFabricLabelTag = TLV::ContextTag(1);

// Tags for our index list storage.
constexpr TLV::Tag kNextAvailableFabricIndexTag = TLV::ContextTag(0);
constexpr TLV::Tag kFabricIndicesTag            = TLV::ContextTag(1);

// Tags for commit marker storage
constexpr TLV::Tag kMarkerFabricIndexTag = TLV::ContextTag(0);
constexpr TLV::Tag kMarkerIsAdditionTag  = TLV::ContextTag(1);

constexpr size_t CommitMarkerContextTLVMaxSize()
{
    // Add 2x uncommitted uint64_t to leave space for backwards/forwards
    // versioning for this critical feature that runs at boot.
    return TLV::EstimateStructOverhead(sizeof(FabricIndex), sizeof(bool), sizeof(uint64_t), sizeof(uint64_t));
}

constexpr size_t IndexInfoTLVMaxSize()
{
    // We have a single next-available index and an array of anonymous-tagged
    // fabric indices.
    //
    // The max size of the list is (1 byte control + bytes for actual value)
    // times max number of list items, plus one byte for the list terminator.
    return TLV::EstimateStructOverhead(sizeof(FabricIndex), CHIP_CONFIG_MAX_FABRICS * (1 + sizeof(FabricIndex)) + 1);
}

} // anonymous namespace

CHIP_ERROR FabricInfo::Init(const FabricInfo::InitParams & initParams)
{
    ReturnErrorOnFailure(initParams.AreValid());

    Reset();

    mNodeId                  = initParams.nodeId;
    mFabricId                = initParams.fabricId;
    mFabricIndex             = initParams.fabricIndex;
    mCompressedFabricId      = initParams.compressedFabricId;
    mRootPublicKey           = initParams.rootPublicKey;
    mVendorId                = static_cast<VendorId>(initParams.vendorId);
    mShouldAdvertiseIdentity = initParams.advertiseIdentity;

    // Deal with externally injected keys
    if (initParams.operationalKeypair != nullptr)
    {
        if (initParams.hasExternallyOwnedKeypair)
        {
            ReturnErrorOnFailure(SetExternallyOwnedOperationalKeypair(initParams.operationalKeypair));
        }
        else
        {
            ReturnErrorOnFailure(SetOperationalKeypair(initParams.operationalKeypair));
        }
    }

    return CHIP_NO_ERROR;
}

void FabricInfo::operator=(FabricInfo && other)
{
    Reset();

    mNodeId                  = other.mNodeId;
    mFabricId                = other.mFabricId;
    mFabricIndex             = other.mFabricIndex;
    mCompressedFabricId      = other.mCompressedFabricId;
    mRootPublicKey           = other.mRootPublicKey;
    mVendorId                = other.mVendorId;
    mShouldAdvertiseIdentity = other.mShouldAdvertiseIdentity;

    SetFabricLabel(other.GetFabricLabel());

    // Transfer ownership of operational keypair (if it was nullptr, it stays that way).
    mOperationalKey                         = other.mOperationalKey;
    mHasExternallyOwnedOperationalKey       = other.mHasExternallyOwnedOperationalKey;
    other.mOperationalKey                   = nullptr;
    other.mHasExternallyOwnedOperationalKey = false;

    other.Reset();
}

CHIP_ERROR FabricInfo::CommitToStorage(PersistentStorageDelegate * storage) const
{
    {
        uint8_t buf[MetadataTLVMaxSize()];
        TLV::TLVWriter writer;
        writer.Init(buf);

        TLV::TLVType outerType;
        ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType));

        ReturnErrorOnFailure(writer.Put(kVendorIdTag, mVendorId));

        ReturnErrorOnFailure(writer.PutString(kFabricLabelTag, CharSpan::fromCharString(mFabricLabel)));

        ReturnErrorOnFailure(writer.EndContainer(outerType));

        const auto metadataLength = writer.GetLengthWritten();
        VerifyOrReturnError(CanCastTo<uint16_t>(metadataLength), CHIP_ERROR_BUFFER_TOO_SMALL);
        ReturnErrorOnFailure(storage->SyncSetKeyValue(DefaultStorageKeyAllocator::FabricMetadata(mFabricIndex).KeyName(), buf,
                                                      static_cast<uint16_t>(metadataLength)));
    }

    // NOTE: Operational Key is never saved to storage here. See OperationalKeystore interface for how it is accessed

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricInfo::LoadFromStorage(PersistentStorageDelegate * storage, FabricIndex newFabricIndex, const ByteSpan & rcac,
                                       const ByteSpan & noc)
{
    mFabricIndex = newFabricIndex;

    // Regenerate operational metadata from NOC/RCAC
    {
        ReturnErrorOnFailure(ExtractNodeIdFabricIdFromOpCert(noc, &mNodeId, &mFabricId));

        P256PublicKeySpan rootPubKeySpan;
        ReturnErrorOnFailure(ExtractPublicKeyFromChipCert(rcac, rootPubKeySpan));
        mRootPublicKey = rootPubKeySpan;

        uint8_t compressedFabricIdBuf[sizeof(uint64_t)];
        MutableByteSpan compressedFabricIdSpan(compressedFabricIdBuf);
        ReturnErrorOnFailure(GenerateCompressedFabricId(mRootPublicKey, mFabricId, compressedFabricIdSpan));

        // Decode compressed fabric ID accounting for endianness, as GenerateCompressedFabricId()
        // returns a binary buffer and is agnostic of usage of the output as an integer type.
        mCompressedFabricId = Encoding::BigEndian::Get64(compressedFabricIdBuf);
    }

    // Load other storable metadata (label, vendorId, etc)
    {
        uint8_t buf[MetadataTLVMaxSize()];
        uint16_t size = sizeof(buf);
        ReturnErrorOnFailure(
            storage->SyncGetKeyValue(DefaultStorageKeyAllocator::FabricMetadata(mFabricIndex).KeyName(), buf, size));
        TLV::ContiguousBufferTLVReader reader;
        reader.Init(buf, size);

        ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
        TLV::TLVType containerType;
        ReturnErrorOnFailure(reader.EnterContainer(containerType));

        ReturnErrorOnFailure(reader.Next(kVendorIdTag));
        ReturnErrorOnFailure(reader.Get(mVendorId));

        ReturnErrorOnFailure(reader.Next(kFabricLabelTag));
        CharSpan label;
        ReturnErrorOnFailure(reader.Get(label));

        VerifyOrReturnError(label.size() <= kFabricLabelMaxLengthInBytes, CHIP_ERROR_BUFFER_TOO_SMALL);
        Platform::CopyString(mFabricLabel, label);

        ReturnErrorOnFailure(reader.ExitContainer(containerType));
        ReturnErrorOnFailure(reader.VerifyEndOfContainer());
    }

    // NOTE: Operational Key is never loaded here. See OperationalKeystore interface for how it is accessed

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricInfo::SetFabricLabel(const CharSpan & fabricLabel)
{
    Platform::CopyString(mFabricLabel, fabricLabel);

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::DeleteMetadataFromStorage(FabricIndex fabricIndex)
{
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
    VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);

    CHIP_ERROR deleteErr = mStorage->SyncDeleteKeyValue(DefaultStorageKeyAllocator::FabricMetadata(fabricIndex).KeyName());

    if (deleteErr != CHIP_NO_ERROR)
    {
        if (deleteErr == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
        {
            ChipLogError(FabricProvisioning, "Warning: metadata not found during delete of fabric 0x%x",
                         static_cast<unsigned>(fabricIndex));
        }
        else
        {
            ChipLogError(FabricProvisioning, "Error deleting metadata for fabric fabric 0x%x: %" CHIP_ERROR_FORMAT,
                         static_cast<unsigned>(fabricIndex), deleteErr.Format());
        }
    }

    return deleteErr;
}

CHIP_ERROR FabricInfo::SetOperationalKeypair(const P256Keypair * keyPair)
{
    VerifyOrReturnError(keyPair != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    P256SerializedKeypair serialized;
    ReturnErrorOnFailure(keyPair->Serialize(serialized));

    if (mHasExternallyOwnedOperationalKey)
    {
        // Drop it, so we will allocate an internally owned one.
        mOperationalKey                   = nullptr;
        mHasExternallyOwnedOperationalKey = false;
    }

    if (mOperationalKey == nullptr)
    {
        mOperationalKey = chip::Platform::New<P256Keypair>();
    }
    VerifyOrReturnError(mOperationalKey != nullptr, CHIP_ERROR_NO_MEMORY);
    return mOperationalKey->Deserialize(serialized);
}

CHIP_ERROR FabricInfo::SetExternallyOwnedOperationalKeypair(P256Keypair * keyPair)
{
    VerifyOrReturnError(keyPair != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    if (!mHasExternallyOwnedOperationalKey && mOperationalKey != nullptr)
    {
        chip::Platform::Delete(mOperationalKey);
        mOperationalKey = nullptr;
    }

    mHasExternallyOwnedOperationalKey = true;
    mOperationalKey                   = keyPair;
    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::ValidateIncomingNOCChain(const ByteSpan & noc, const ByteSpan & icac, const ByteSpan & rcac,
                                                 FabricId existingFabricId, Credentials::CertificateValidityPolicy * policy,
                                                 CompressedFabricId & outCompressedFabricId, FabricId & outFabricId,
                                                 NodeId & outNodeId, Crypto::P256PublicKey & outNocPubkey,
                                                 Crypto::P256PublicKey & outRootPubkey)
{
    Credentials::ValidationContext validContext;

    // Note that we do NOT set a time in the validation context.  This will
    // cause the certificate chain NotBefore / NotAfter time validation logic
    // to report CertificateValidityResult::kTimeUnknown.
    //
    // The default CHIPCert policy passes NotBefore / NotAfter validation for
    // this case where time is unknown.  If an override policy is passed, it
    // will be up to the passed policy to decide how to handle this.
    //
    // In the FabricTable::AddNewFabric and FabricTable::UpdateFabric calls,
    // the passed policy always passes for all questions of time validity.  The
    // rationale is that installed certificates should be valid at the time of
    // installation by definition.  If they are not and the commissionee and
    // commissioner disagree enough on current time, CASE will fail and our
    // fail-safe timer will expire.
    //
    // This then is ultimately how we validate that NotBefore / NotAfter in
    // newly installed certificates is workable.
    validContext.Reset();
    validContext.mRequiredKeyUsages.Set(KeyUsageFlags::kDigitalSignature);
    validContext.mRequiredKeyPurposes.Set(KeyPurposeFlags::kServerAuth);
    validContext.mValidityPolicy = policy;

    ChipLogProgress(FabricProvisioning, "Validating NOC chain");
    CHIP_ERROR err = FabricTable::VerifyCredentials(noc, icac, rcac, validContext, outCompressedFabricId, outFabricId, outNodeId,
                                                    outNocPubkey, &outRootPubkey);
    if (err != CHIP_NO_ERROR && err != CHIP_ERROR_WRONG_NODE_ID)
    {
        err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
    }
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(FabricProvisioning, "Failed NOC chain validation: %" CHIP_ERROR_FORMAT, err.Format());
    }
    ReturnErrorOnFailure(err);

    // Validate fabric ID match for cases like UpdateNOC.
    if (existingFabricId != kUndefinedFabricId)
    {
        VerifyOrReturnError(existingFabricId == outFabricId, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
    }

    ChipLogProgress(FabricProvisioning, "NOC chain validation successful");
    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricInfo::SignWithOpKeypair(ByteSpan message, P256ECDSASignature & outSignature) const
{
    VerifyOrReturnError(mOperationalKey != nullptr, CHIP_ERROR_KEY_NOT_FOUND);

    return mOperationalKey->ECDSA_sign_msg(message.data(), message.size(), outSignature);
}

CHIP_ERROR FabricInfo::FetchRootPubkey(Crypto::P256PublicKey & outPublicKey) const
{
    VerifyOrReturnError(IsInitialized(), CHIP_ERROR_KEY_NOT_FOUND);
    outPublicKey = mRootPublicKey;
    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::VerifyCredentials(FabricIndex fabricIndex, const ByteSpan & noc, const ByteSpan & icac,
                                          ValidationContext & context, CompressedFabricId & outCompressedFabricId,
                                          FabricId & outFabricId, NodeId & outNodeId, Crypto::P256PublicKey & outNocPubkey,
                                          Crypto::P256PublicKey * outRootPublicKey) const
{
    assertChipStackLockedByCurrentThread();
    uint8_t rootCertBuf[kMaxCHIPCertLength];
    MutableByteSpan rootCertSpan{ rootCertBuf };
    ReturnErrorOnFailure(FetchRootCert(fabricIndex, rootCertSpan));
    return VerifyCredentials(noc, icac, rootCertSpan, context, outCompressedFabricId, outFabricId, outNodeId, outNocPubkey,
                             outRootPublicKey);
}

CHIP_ERROR FabricTable::VerifyCredentials(const ByteSpan & noc, const ByteSpan & icac, const ByteSpan & rcac,
                                          ValidationContext & context, CompressedFabricId & outCompressedFabricId,
                                          FabricId & outFabricId, NodeId & outNodeId, Crypto::P256PublicKey & outNocPubkey,
                                          Crypto::P256PublicKey * outRootPublicKey)
{
    // TODO - Optimize credentials verification logic
    //        The certificate chain construction and verification is a compute and memory intensive operation.
    //        It can be optimized by not loading certificate (i.e. rcac) that's local and implicitly trusted.
    //        The FindValidCert() algorithm will need updates to achieve this refactor.
    constexpr uint8_t kMaxNumCertsInOpCreds = 3;

    ChipCertificateSet certificates;
    ReturnErrorOnFailure(certificates.Init(kMaxNumCertsInOpCreds));

    ReturnErrorOnFailure(certificates.LoadCert(rcac, BitFlags<CertDecodeFlags>(CertDecodeFlags::kIsTrustAnchor)));

    if (!icac.empty())
    {
        ReturnErrorOnFailure(certificates.LoadCert(icac, BitFlags<CertDecodeFlags>(CertDecodeFlags::kGenerateTBSHash)));
    }

    ReturnErrorOnFailure(certificates.LoadCert(noc, BitFlags<CertDecodeFlags>(CertDecodeFlags::kGenerateTBSHash)));

    const ChipDN & nocSubjectDN              = certificates.GetLastCert()[0].mSubjectDN;
    const CertificateKeyId & nocSubjectKeyId = certificates.GetLastCert()[0].mSubjectKeyId;

    const ChipCertificateData * resultCert = nullptr;
    // FindValidCert() checks the certificate set constructed by loading noc, icac and rcac.
    // It confirms that the certs link correctly (noc -> icac -> rcac), and have been correctly signed.
    ReturnErrorOnFailure(certificates.FindValidCert(nocSubjectDN, nocSubjectKeyId, context, &resultCert));

    ReturnErrorOnFailure(ExtractNodeIdFabricIdFromOpCert(certificates.GetLastCert()[0], &outNodeId, &outFabricId));

    CHIP_ERROR err;
    FabricId icacFabricId = kUndefinedFabricId;
    if (!icac.empty())
    {
        err = ExtractFabricIdFromCert(certificates.GetCertSet()[1], &icacFabricId);
        if (err == CHIP_NO_ERROR)
        {
            ReturnErrorCodeIf(icacFabricId != outFabricId, CHIP_ERROR_FABRIC_MISMATCH_ON_ICA);
        }
        // FabricId is optional field in ICAC and "not found" code is not treated as error.
        else if (err != CHIP_ERROR_NOT_FOUND)
        {
            return err;
        }
    }

    FabricId rcacFabricId = kUndefinedFabricId;
    err                   = ExtractFabricIdFromCert(certificates.GetCertSet()[0], &rcacFabricId);
    if (err == CHIP_NO_ERROR)
    {
        ReturnErrorCodeIf(rcacFabricId != outFabricId, CHIP_ERROR_WRONG_CERT_DN);
    }
    // FabricId is optional field in RCAC and "not found" code is not treated as error.
    else if (err != CHIP_ERROR_NOT_FOUND)
    {
        return err;
    }

    // Extract compressed fabric ID and root public key
    {
        uint8_t compressedFabricIdBuf[sizeof(uint64_t)];
        MutableByteSpan compressedFabricIdSpan(compressedFabricIdBuf);
        P256PublicKey rootPubkey(certificates.GetCertSet()[0].mPublicKey);

        ReturnErrorOnFailure(GenerateCompressedFabricId(rootPubkey, outFabricId, compressedFabricIdSpan));

        // Decode compressed fabric ID accounting for endianness, as GenerateCompressedFabricId()
        // returns a binary buffer and is agnostic of usage of the output as an integer type.
        outCompressedFabricId = Encoding::BigEndian::Get64(compressedFabricIdBuf);

        if (outRootPublicKey != nullptr)
        {
            *outRootPublicKey = rootPubkey;
        }
    }

    outNocPubkey = certificates.GetLastCert()->mPublicKey;

    return CHIP_NO_ERROR;
}

const FabricInfo * FabricTable::FindFabric(const Crypto::P256PublicKey & rootPubKey, FabricId fabricId) const
{
    return FindFabricCommon(rootPubKey, fabricId);
}

const FabricInfo * FabricTable::FindIdentity(const Crypto::P256PublicKey & rootPubKey, FabricId fabricId, NodeId nodeId) const
{
    return FindFabricCommon(rootPubKey, fabricId, nodeId);
}

const FabricInfo * FabricTable::FindFabricCommon(const Crypto::P256PublicKey & rootPubKey, FabricId fabricId, NodeId nodeId) const
{
    P256PublicKey candidatePubKey;

    // Try to match pending fabric first if available
    if (HasPendingFabricUpdate())
    {
        bool pubKeyAvailable = (mPendingFabric.FetchRootPubkey(candidatePubKey) == CHIP_NO_ERROR);
        auto matchingNodeId  = (nodeId == kUndefinedNodeId) ? mPendingFabric.GetNodeId() : nodeId;
        if (pubKeyAvailable && rootPubKey.Matches(candidatePubKey) && fabricId == mPendingFabric.GetFabricId() &&
            matchingNodeId == mPendingFabric.GetNodeId())
        {
            return &mPendingFabric;
        }
    }

    for (auto & fabric : mStates)
    {
        auto matchingNodeId = (nodeId == kUndefinedNodeId) ? fabric.GetNodeId() : nodeId;

        if (!fabric.IsInitialized())
        {
            continue;
        }
        if (fabric.FetchRootPubkey(candidatePubKey) != CHIP_NO_ERROR)
        {
            continue;
        }
        if (rootPubKey.Matches(candidatePubKey) && fabricId == fabric.GetFabricId() && matchingNodeId == fabric.GetNodeId())
        {
            return &fabric;
        }
    }

    return nullptr;
}

FabricInfo * FabricTable::GetMutableFabricByIndex(FabricIndex fabricIndex)
{
    // Try to match pending fabric first if available
    if (HasPendingFabricUpdate() && (mPendingFabric.GetFabricIndex() == fabricIndex))
    {
        return &mPendingFabric;
    }

    for (auto & fabric : mStates)
    {
        if (!fabric.IsInitialized())
        {
            continue;
        }

        if (fabric.GetFabricIndex() == fabricIndex)
        {
            return &fabric;
        }
    }

    return nullptr;
}

const FabricInfo * FabricTable::FindFabricWithIndex(FabricIndex fabricIndex) const
{
    if (fabricIndex == kUndefinedFabricIndex)
    {
        return nullptr;
    }

    // Try to match pending fabric first if available
    if (HasPendingFabricUpdate() && (mPendingFabric.GetFabricIndex() == fabricIndex))
    {
        return &mPendingFabric;
    }

    for (const auto & fabric : mStates)
    {
        if (!fabric.IsInitialized())
        {
            continue;
        }

        if (fabric.GetFabricIndex() == fabricIndex)
        {
            return &fabric;
        }
    }

    return nullptr;
}

const FabricInfo * FabricTable::FindFabricWithCompressedId(CompressedFabricId compressedFabricId) const
{
    // Try to match pending fabric first if available
    if (HasPendingFabricUpdate() && (mPendingFabric.GetCompressedFabricId() == compressedFabricId))
    {
        return &mPendingFabric;
    }

    for (auto & fabric : mStates)
    {
        if (!fabric.IsInitialized())
        {
            continue;
        }

        if (compressedFabricId == fabric.GetPeerId().GetCompressedFabricId())
        {
            return &fabric;
        }
    }
    return nullptr;
}

CHIP_ERROR FabricTable::FetchRootCert(FabricIndex fabricIndex, MutableByteSpan & outCert) const
{
    VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE);
    return mOpCertStore->GetCertificate(fabricIndex, CertChainElement::kRcac, outCert);
}

CHIP_ERROR FabricTable::FetchPendingNonFabricAssociatedRootCert(MutableByteSpan & outCert) const
{
    VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE);
    if (!mStateFlags.Has(StateFlags::kIsTrustedRootPending))
    {
        return CHIP_ERROR_NOT_FOUND;
    }

    if (mStateFlags.Has(StateFlags::kIsAddPending))
    {
        // The root certificate is already associated with a pending fabric, so
        // does not exist for purposes of this API.
        return CHIP_ERROR_NOT_FOUND;
    }

    return FetchRootCert(mFabricIndexWithPendingState, outCert);
}

CHIP_ERROR FabricTable::FetchICACert(FabricIndex fabricIndex, MutableByteSpan & outCert) const
{
    VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE);

    CHIP_ERROR err = mOpCertStore->GetCertificate(fabricIndex, CertChainElement::kIcac, outCert);
    if (err == CHIP_ERROR_NOT_FOUND)
    {
        if (mOpCertStore->HasCertificateForFabric(fabricIndex, CertChainElement::kNoc))
        {
            // Didn't find ICAC, but have NOC: return empty for ICAC since not present in chain, but chain exists
            outCert.reduce_size(0);
            return CHIP_NO_ERROR;
        }
    }

    // For all other cases, delegate to operational cert store for results
    return err;
}

CHIP_ERROR FabricTable::FetchNOCCert(FabricIndex fabricIndex, MutableByteSpan & outCert) const
{
    VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE);
    return mOpCertStore->GetCertificate(fabricIndex, CertChainElement::kNoc, outCert);
}

CHIP_ERROR FabricTable::FetchRootPubkey(FabricIndex fabricIndex, Crypto::P256PublicKey & outPublicKey) const
{
    const FabricInfo * fabricInfo = FindFabricWithIndex(fabricIndex);
    ReturnErrorCodeIf(fabricInfo == nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
    return fabricInfo->FetchRootPubkey(outPublicKey);
}

CHIP_ERROR FabricTable::FetchCATs(const FabricIndex fabricIndex, CATValues & cats) const
{
    uint8_t nocBuf[Credentials::kMaxCHIPCertLength];
    MutableByteSpan nocSpan{ nocBuf };
    ReturnErrorOnFailure(FetchNOCCert(fabricIndex, nocSpan));
    ReturnErrorOnFailure(ExtractCATsFromOpCert(nocSpan, cats));
    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::StoreFabricMetadata(const FabricInfo * fabricInfo) const
{
    VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrDie(fabricInfo != nullptr);

    FabricIndex fabricIndex = fabricInfo->GetFabricIndex();
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INTERNAL);

    // TODO: Refactor not to internally rely directly on storage
    ReturnErrorOnFailure(fabricInfo->CommitToStorage(mStorage));

    ChipLogProgress(FabricProvisioning, "Metadata for Fabric 0x%x persisted to storage.", static_cast<unsigned>(fabricIndex));

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::LoadFromStorage(FabricInfo * fabric, FabricIndex newFabricIndex)
{
    VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(!fabric->IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

    uint8_t nocBuf[kMaxCHIPCertLength];
    MutableByteSpan nocSpan{ nocBuf };
    uint8_t rcacBuf[kMaxCHIPCertLength];
    MutableByteSpan rcacSpan{ rcacBuf };

    CHIP_ERROR err = FetchNOCCert(newFabricIndex, nocSpan);
    if (err == CHIP_NO_ERROR)
    {
        err = FetchRootCert(newFabricIndex, rcacSpan);
    }

    // TODO(#19935): Sweep-away fabrics without RCAC/NOC by deleting everything and marking fabric gone.

    if (err == CHIP_NO_ERROR)
    {
        err = fabric->LoadFromStorage(mStorage, newFabricIndex, rcacSpan, nocSpan);
    }

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(FabricProvisioning, "Failed to load Fabric (0x%x): %" CHIP_ERROR_FORMAT, static_cast<unsigned>(newFabricIndex),
                     err.Format());
        fabric->Reset();
        return err;
    }

    ChipLogProgress(FabricProvisioning,
                    "Fabric index 0x%x was retrieved from storage. Compressed FabricId 0x" ChipLogFormatX64
                    ", FabricId 0x" ChipLogFormatX64 ", NodeId 0x" ChipLogFormatX64 ", VendorId 0x%04X",
                    static_cast<unsigned>(fabric->GetFabricIndex()), ChipLogValueX64(fabric->GetCompressedFabricId()),
                    ChipLogValueX64(fabric->GetFabricId()), ChipLogValueX64(fabric->GetNodeId()),
                    to_underlying(fabric->GetVendorId()));

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::AddNewFabricForTest(const ByteSpan & rootCert, const ByteSpan & icacCert, const ByteSpan & nocCert,
                                            const ByteSpan & opKeySpan, FabricIndex * outFabricIndex)
{
    VerifyOrReturnError(outFabricIndex != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    CHIP_ERROR err = CHIP_ERROR_INTERNAL;

    Crypto::P256Keypair injectedOpKey;
    Crypto::P256SerializedKeypair injectedOpKeysSerialized;

    Crypto::P256Keypair * opKey = nullptr;
    if (!opKeySpan.empty())
    {
        VerifyOrReturnError(opKeySpan.size() == injectedOpKeysSerialized.Capacity(), CHIP_ERROR_INVALID_ARGUMENT);

        memcpy(injectedOpKeysSerialized.Bytes(), opKeySpan.data(), opKeySpan.size());
        SuccessOrExit(err = injectedOpKeysSerialized.SetLength(opKeySpan.size()));
        SuccessOrExit(err = injectedOpKey.Deserialize(injectedOpKeysSerialized));
        opKey = &injectedOpKey;
    }

    SuccessOrExit(err = AddNewPendingTrustedRootCert(rootCert));
    SuccessOrExit(err = AddNewPendingFabricWithProvidedOpKey(nocCert, icacCert, VendorId::TestVendor1, opKey,
                                                             /*isExistingOpKeyExternallyOwned =*/false, outFabricIndex));
    SuccessOrExit(err = CommitPendingFabricData());
exit:
    if (err != CHIP_NO_ERROR)
    {
        RevertPendingFabricData();
    }
    return err;
}

/*
 * A validation policy we can pass into VerifyCredentials to extract the
 * latest NotBefore time in the certificate chain without having to load the
 * certificates into memory again, and one which will pass validation for all
 * questions of NotBefore / NotAfter validity.
 *
 * The rationale is that installed certificates should be valid at the time of
 * installation by definition.  If they are not and the commissionee and
 * commissioner disagree enough on current time, CASE will fail and our
 * fail-safe timer will expire.
 *
 * This then is ultimately how we validate that NotBefore / NotAfter in
 * newly installed certificates is workable.
 */
class NotBeforeCollector : public Credentials::CertificateValidityPolicy
{
public:
    NotBeforeCollector() : mLatestNotBefore(0) {}
    CHIP_ERROR ApplyCertificateValidityPolicy(const ChipCertificateData * cert, uint8_t depth,
                                              CertificateValidityResult result) override
    {
        if (cert->mNotBeforeTime > mLatestNotBefore.count())
        {
            mLatestNotBefore = System::Clock::Seconds32(cert->mNotBeforeTime);
        }
        return CHIP_NO_ERROR;
    }
    System::Clock::Seconds32 mLatestNotBefore;
};

CHIP_ERROR FabricTable::NotifyFabricUpdated(FabricIndex fabricIndex)
{
    FabricTable::Delegate * delegate = mDelegateListRoot;
    while (delegate)
    {
        // It is possible that delegate will remove itself from the list in the callback
        // so we grab the next delegate in the list now.
        FabricTable::Delegate * nextDelegate = delegate->next;
        delegate->OnFabricUpdated(*this, fabricIndex);
        delegate = nextDelegate;
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::NotifyFabricCommitted(FabricIndex fabricIndex)
{
    FabricTable::Delegate * delegate = mDelegateListRoot;
    while (delegate)
    {
        // It is possible that delegate will remove itself from the list in the callback
        // so we grab the next delegate in the list now.
        FabricTable::Delegate * nextDelegate = delegate->next;
        delegate->OnFabricCommitted(*this, fabricIndex);
        delegate = nextDelegate;
    }
    return CHIP_NO_ERROR;
}

CHIP_ERROR
FabricTable::AddOrUpdateInner(FabricIndex fabricIndex, bool isAddition, Crypto::P256Keypair * existingOpKey,
                              bool isExistingOpKeyExternallyOwned, uint16_t vendorId, AdvertiseIdentity advertiseIdentity)
{
    // All parameters pre-validated before we get here

    FabricInfo::InitParams newFabricInfo;
    FabricInfo * fabricEntry    = nullptr;
    FabricId fabricIdToValidate = kUndefinedFabricId;
    CharSpan fabricLabel;

    if (isAddition)
    {
        // Initialization for Adding a fabric

        // Find an available slot.
        for (auto & fabric : mStates)
        {
            if (fabric.IsInitialized())
            {
                continue;
            }
            fabricEntry = &fabric;
            break;
        }

        VerifyOrReturnError(fabricEntry != nullptr, CHIP_ERROR_NO_MEMORY);

        newFabricInfo.vendorId    = static_cast<VendorId>(vendorId);
        newFabricInfo.fabricIndex = fabricIndex;
    }
    else
    {
        // Initialization for Updating fabric: setting up a shadow fabricInfo
        const FabricInfo * existingFabric = FindFabricWithIndex(fabricIndex);
        VerifyOrReturnError(existingFabric != nullptr, CHIP_ERROR_INTERNAL);

        mPendingFabric.Reset();
        fabricEntry = &mPendingFabric;

        newFabricInfo.vendorId    = existingFabric->GetVendorId();
        newFabricInfo.fabricIndex = fabricIndex;

        fabricIdToValidate = existingFabric->GetFabricId();
        fabricLabel        = existingFabric->GetFabricLabel();
    }

    // Make sure to not modify any of our state until ValidateIncomingNOCChain passes.
    NotBeforeCollector notBeforeCollector;
    P256PublicKey nocPubKey;

    // Validate the cert chain prior to adding
    {
        Platform::ScopedMemoryBuffer<uint8_t> nocBuf;
        Platform::ScopedMemoryBuffer<uint8_t> icacBuf;
        Platform::ScopedMemoryBuffer<uint8_t> rcacBuf;

        ReturnErrorCodeIf(!nocBuf.Alloc(kMaxCHIPCertLength), CHIP_ERROR_NO_MEMORY);
        ReturnErrorCodeIf(!icacBuf.Alloc(kMaxCHIPCertLength), CHIP_ERROR_NO_MEMORY);
        ReturnErrorCodeIf(!rcacBuf.Alloc(kMaxCHIPCertLength), CHIP_ERROR_NO_MEMORY);

        MutableByteSpan nocSpan{ nocBuf.Get(), kMaxCHIPCertLength };
        MutableByteSpan icacSpan{ icacBuf.Get(), kMaxCHIPCertLength };
        MutableByteSpan rcacSpan{ rcacBuf.Get(), kMaxCHIPCertLength };

        ReturnErrorOnFailure(FetchNOCCert(fabricIndex, nocSpan));
        ReturnErrorOnFailure(FetchICACert(fabricIndex, icacSpan));
        ReturnErrorOnFailure(FetchRootCert(fabricIndex, rcacSpan));

        ReturnErrorOnFailure(ValidateIncomingNOCChain(nocSpan, icacSpan, rcacSpan, fabricIdToValidate, &notBeforeCollector,
                                                      newFabricInfo.compressedFabricId, newFabricInfo.fabricId,
                                                      newFabricInfo.nodeId, nocPubKey, newFabricInfo.rootPublicKey));
    }

    if (existingOpKey != nullptr)
    {
        // Verify that public key in NOC matches public key of the provided keypair.
        // When operational key is not injected (e.g. when mOperationalKeystore != nullptr)
        // the check is done by the keystore in `ActivateOpKeypairForFabric`.
        VerifyOrReturnError(existingOpKey->Pubkey().Matches(nocPubKey), CHIP_ERROR_INVALID_PUBLIC_KEY);

        newFabricInfo.operationalKeypair        = existingOpKey;
        newFabricInfo.hasExternallyOwnedKeypair = isExistingOpKeyExternallyOwned;
    }
    else if (mOperationalKeystore != nullptr)
    {
        // If a keystore exists, we activate the operational key now, which also validates if it was previously installed
        if (mOperationalKeystore->HasPendingOpKeypair())
        {
            ReturnErrorOnFailure(mOperationalKeystore->ActivateOpKeypairForFabric(fabricIndex, nocPubKey));
        }
        else
        {
            VerifyOrReturnError(mOperationalKeystore->HasOpKeypairForFabric(fabricIndex), CHIP_ERROR_KEY_NOT_FOUND);
        }
    }
    else
    {
        return CHIP_ERROR_INCORRECT_STATE;
    }

    newFabricInfo.advertiseIdentity = (advertiseIdentity == AdvertiseIdentity::Yes);

    // Update local copy of fabric data. For add it's a new entry, for update, it's `mPendingFabric` shadow entry.
    ReturnErrorOnFailure(fabricEntry->Init(newFabricInfo));

    // Set the label, matching add/update semantics of empty/existing.
    fabricEntry->SetFabricLabel(fabricLabel);

    if (isAddition)
    {
        ChipLogProgress(FabricProvisioning, "Added new fabric at index: 0x%x",
                        static_cast<unsigned>(fabricEntry->GetFabricIndex()));
        ChipLogProgress(FabricProvisioning, "Assigned compressed fabric ID: 0x" ChipLogFormatX64 ", node ID: 0x" ChipLogFormatX64,
                        ChipLogValueX64(fabricEntry->GetCompressedFabricId()), ChipLogValueX64(fabricEntry->GetNodeId()));
    }
    else
    {
        ChipLogProgress(FabricProvisioning, "Updated fabric at index: 0x%x, Node ID: 0x" ChipLogFormatX64,
                        static_cast<unsigned>(fabricEntry->GetFabricIndex()), ChipLogValueX64(fabricEntry->GetNodeId()));
    }

    // Failure to update pending Last Known Good Time is non-fatal.  If Last
    // Known Good Time is incorrect and this causes the commissioner's
    // certificates to appear invalid, the certificate validity policy will
    // determine what to do.  And if the validity policy considers this fatal
    // this will prevent CASE and cause the pending fabric and Last Known Good
    // Time to be reverted.
    CHIP_ERROR lkgtErr = mLastKnownGoodTime.UpdatePendingLastKnownGoodChipEpochTime(notBeforeCollector.mLatestNotBefore);
    if (lkgtErr != CHIP_NO_ERROR)
    {
        // Log but this is not sticky...
        ChipLogError(FabricProvisioning, "Failed to update pending Last Known Good Time: %" CHIP_ERROR_FORMAT, lkgtErr.Format());
    }

    // Must be the last thing before we return, as this is undone later on error handling within Delete.
    if (isAddition)
    {
        mFabricCount++;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::Delete(FabricIndex fabricIndex)
{
    VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_ARGUMENT);

    {
        FabricTable::Delegate * delegate = mDelegateListRoot;
        while (delegate)
        {
            // It is possible that delegate will remove itself from the list in FabricWillBeRemoved,
            // so we grab the next delegate in the list now.
            FabricTable::Delegate * nextDelegate = delegate->next;
            delegate->FabricWillBeRemoved(*this, fabricIndex);
            delegate = nextDelegate;
        }
    }

    FabricInfo * fabricInfo = GetMutableFabricByIndex(fabricIndex);
    if (fabricInfo == &mPendingFabric)
    {
        // Asked to Delete while pending an update: reset the pending state and
        // get back to the underlying fabric data for existing fabric.
        RevertPendingFabricData();
        fabricInfo = GetMutableFabricByIndex(fabricIndex);
    }

    bool fabricIsInitialized = fabricInfo != nullptr && fabricInfo->IsInitialized();
    CHIP_ERROR metadataErr   = DeleteMetadataFromStorage(fabricIndex); // Delete from storage regardless

    CHIP_ERROR opKeyErr = CHIP_NO_ERROR;
    if (mOperationalKeystore != nullptr)
    {
        opKeyErr = mOperationalKeystore->RemoveOpKeypairForFabric(fabricIndex);
        // Not having found data is not an error, we may just have gotten here
        // on a fail-safe expiry after `RevertPendingFabricData`.
        if (opKeyErr == CHIP_ERROR_INVALID_FABRIC_INDEX)
        {
            opKeyErr = CHIP_NO_ERROR;
        }
    }

    CHIP_ERROR opCertsErr = CHIP_NO_ERROR;
    if (mOpCertStore != nullptr)
    {
        opCertsErr = mOpCertStore->RemoveOpCertsForFabric(fabricIndex);
        // Not having found data is not an error, we may just have gotten here
        // on a fail-safe expiry after `RevertPendingFabricData`.
        if (opCertsErr == CHIP_ERROR_INVALID_FABRIC_INDEX)
        {
            opCertsErr = CHIP_NO_ERROR;
        }
    }

    if (!fabricIsInitialized)
    {
        // Make sure to return the error our API promises, not whatever storage
        // chose to return.
        return CHIP_ERROR_NOT_FOUND;
    }

    // Since fabricIsInitialized was true, fabric is not null.
    fabricInfo->Reset();

    if (!mNextAvailableFabricIndex.HasValue())
    {
        // We must have been in a situation where CHIP_CONFIG_MAX_FABRICS is 254
        // and our fabric table was full, so there was no valid next index.  We
        // have a single available index now, though; use it as
        // mNextAvailableFabricIndex.
        mNextAvailableFabricIndex.SetValue(fabricIndex);
    }
    // If StoreFabricIndexInfo fails here, that's probably OK.  When we try to
    // read things from storage later we will realize there is nothing for this
    // index.
    StoreFabricIndexInfo();

    // If we ever start moving the FabricInfo entries around in the array on
    // delete, we should update DeleteAllFabrics to handle that.
    if (mFabricCount == 0)
    {
        ChipLogError(FabricProvisioning, "Trying to delete a fabric, but the current fabric count is already 0");
    }
    else
    {
        mFabricCount--;
        ChipLogProgress(FabricProvisioning, "Fabric (0x%x) deleted.", static_cast<unsigned>(fabricIndex));
    }

    if (mDelegateListRoot != nullptr)
    {
        FabricTable::Delegate * delegate = mDelegateListRoot;
        while (delegate)
        {
            // It is possible that delegate will remove itself from the list in OnFabricRemoved,
            // so we grab the next delegate in the list now.
            FabricTable::Delegate * nextDelegate = delegate->next;
            delegate->OnFabricRemoved(*this, fabricIndex);
            delegate = nextDelegate;
        }
    }

    // Only return error after trying really hard to remove everything we could
    ReturnErrorOnFailure(metadataErr);
    ReturnErrorOnFailure(opKeyErr);
    ReturnErrorOnFailure(opCertsErr);

    return CHIP_NO_ERROR;
}

void FabricTable::DeleteAllFabrics()
{
    static_assert(kMaxValidFabricIndex <= UINT8_MAX, "Cannot create more fabrics than UINT8_MAX");

    RevertPendingFabricData();

    for (auto & fabric : *this)
    {
        Delete(fabric.GetFabricIndex());
    }
}

CHIP_ERROR FabricTable::Init(const FabricTable::InitParams & initParams)
{
    VerifyOrReturnError(initParams.storage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(initParams.opCertStore != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    mStorage             = initParams.storage;
    mOperationalKeystore = initParams.operationalKeystore;
    mOpCertStore         = initParams.opCertStore;

    ChipLogDetail(FabricProvisioning, "Initializing FabricTable from persistent storage");

    // Load the current fabrics from the storage.
    static_assert(kMaxValidFabricIndex <= UINT8_MAX, "Cannot create more fabrics than UINT8_MAX");

    mFabricCount = 0;
    for (auto & fabric : mStates)
    {
        fabric.Reset();
    }
    mNextAvailableFabricIndex.SetValue(kMinValidFabricIndex);

    // Init failure of Last Known Good Time is non-fatal.  If Last Known Good
    // Time is unknown during incoming certificate validation for CASE and
    // current time is also unknown, the certificate validity policy will see
    // this condition and can act appropriately.
    mLastKnownGoodTime.Init(mStorage);

    uint8_t buf[IndexInfoTLVMaxSize()];
    uint16_t size  = sizeof(buf);
    CHIP_ERROR err = mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::FabricIndexInfo().KeyName(), buf, size);
    if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
    {
        // No fabrics yet.  Nothing to be done here.
    }
    else
    {
        ReturnErrorOnFailure(err);
        TLV::ContiguousBufferTLVReader reader;
        reader.Init(buf, size);

        // TODO: A safer way would be to just clean-up the entire fabric table on this situation...
        err = ReadFabricInfo(reader);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(FabricProvisioning, "Error loading fabric table: %" CHIP_ERROR_FORMAT ", we are in a bad state!",
                         err.Format());
        }

        ReturnErrorOnFailure(err);
    }

    CommitMarker commitMarker;
    err = GetCommitMarker(commitMarker);
    if (err == CHIP_NO_ERROR)
    {
        // Found a commit marker! We need to possibly delete a loaded fabric
        ChipLogError(FabricProvisioning, "Found a FabricTable aborted commit for index 0x%x (isAddition: %d), removing!",
                     static_cast<unsigned>(commitMarker.fabricIndex), static_cast<int>(commitMarker.isAddition));

        mDeletedFabricIndexFromInit = commitMarker.fabricIndex;

        // Can't do better on error. We just have to hope for the best.
        (void) Delete(commitMarker.fabricIndex);
    }
    else if (err != CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
    {
        // Got an error, but somehow value is not missing altogether: inconsistent state but touch nothing.
        ChipLogError(FabricProvisioning, "Error loading Table commit marker: %" CHIP_ERROR_FORMAT ", hope for the best!",
                     err.Format());
    }

    return CHIP_NO_ERROR;
}

void FabricTable::Forget(FabricIndex fabricIndex)
{
    ChipLogProgress(FabricProvisioning, "Forgetting fabric 0x%x", static_cast<unsigned>(fabricIndex));

    auto * fabricInfo = GetMutableFabricByIndex(fabricIndex);
    VerifyOrReturn(fabricInfo != nullptr);

    RevertPendingFabricData();
    fabricInfo->Reset();
}

void FabricTable::Shutdown()
{
    VerifyOrReturn(mStorage != nullptr);
    ChipLogProgress(FabricProvisioning, "Shutting down FabricTable");

    // Remove all links to every delegate
    FabricTable::Delegate * delegate = mDelegateListRoot;
    while (delegate)
    {
        FabricTable::Delegate * temp = delegate->next;
        delegate->next               = nullptr;
        delegate                     = temp;
    }

    RevertPendingFabricData();
    for (FabricInfo & fabricInfo : mStates)
    {
        // Clear-out any FabricInfo-owned operational keys and make sure any further
        // direct lookups fail.
        fabricInfo.Reset();
    }

    mStorage = nullptr;
}

FabricIndex FabricTable::GetDeletedFabricFromCommitMarker()
{
    FabricIndex retVal = mDeletedFabricIndexFromInit;

    // Reset for next read
    mDeletedFabricIndexFromInit = kUndefinedFabricIndex;

    return retVal;
}

CHIP_ERROR FabricTable::AddFabricDelegate(FabricTable::Delegate * delegate)
{
    VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    for (FabricTable::Delegate * iter = mDelegateListRoot; iter != nullptr; iter = iter->next)
    {
        if (iter == delegate)
        {
            return CHIP_NO_ERROR;
        }
    }
    delegate->next    = mDelegateListRoot;
    mDelegateListRoot = delegate;
    return CHIP_NO_ERROR;
}

void FabricTable::RemoveFabricDelegate(FabricTable::Delegate * delegateToRemove)
{
    VerifyOrReturn(delegateToRemove != nullptr);

    if (delegateToRemove == mDelegateListRoot)
    {
        // Removing head of the list, keep link to next, may
        // be nullptr.
        mDelegateListRoot = mDelegateListRoot->next;
    }
    else
    {
        // Removing some other item: check if next, and
        // remove the link, keeping its neighbour.
        FabricTable::Delegate * currentNode = mDelegateListRoot;

        while (currentNode)
        {
            if (currentNode->next == delegateToRemove)
            {
                FabricTable::Delegate * temp = delegateToRemove->next;
                currentNode->next            = temp;
                delegateToRemove->next       = nullptr;
                return;
            }

            currentNode = currentNode->next;
        }
    }
}

CHIP_ERROR FabricTable::SetLastKnownGoodChipEpochTime(System::Clock::Seconds32 lastKnownGoodChipEpochTime)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    // Find our latest NotBefore time for any installed certificate.
    System::Clock::Seconds32 latestNotBefore = System::Clock::Seconds32(0);
    for (auto & fabric : mStates)
    {
        if (!fabric.IsInitialized())
        {
            continue;
        }
        {
            uint8_t rcacBuf[kMaxCHIPCertLength];
            MutableByteSpan rcacSpan{ rcacBuf };
            SuccessOrExit(err = FetchRootCert(fabric.GetFabricIndex(), rcacSpan));
            chip::System::Clock::Seconds32 rcacNotBefore;
            SuccessOrExit(err = Credentials::ExtractNotBeforeFromChipCert(rcacSpan, rcacNotBefore));
            latestNotBefore = rcacNotBefore > latestNotBefore ? rcacNotBefore : latestNotBefore;
        }
        {
            uint8_t icacBuf[kMaxCHIPCertLength];
            MutableByteSpan icacSpan{ icacBuf };
            SuccessOrExit(err = FetchICACert(fabric.GetFabricIndex(), icacSpan));
            if (!icacSpan.empty())
            {
                chip::System::Clock::Seconds32 icacNotBefore;
                ReturnErrorOnFailure(Credentials::ExtractNotBeforeFromChipCert(icacSpan, icacNotBefore));
                latestNotBefore = icacNotBefore > latestNotBefore ? icacNotBefore : latestNotBefore;
            }
        }
        {
            uint8_t nocBuf[kMaxCHIPCertLength];
            MutableByteSpan nocSpan{ nocBuf };
            SuccessOrExit(err = FetchNOCCert(fabric.GetFabricIndex(), nocSpan));
            chip::System::Clock::Seconds32 nocNotBefore;
            ReturnErrorOnFailure(Credentials::ExtractNotBeforeFromChipCert(nocSpan, nocNotBefore));
            latestNotBefore = nocNotBefore > latestNotBefore ? nocNotBefore : latestNotBefore;
        }
    }
    // Pass this to the LastKnownGoodTime object so it can make determination
    // of the legality of our new proposed time.
    SuccessOrExit(err = mLastKnownGoodTime.SetLastKnownGoodChipEpochTime(lastKnownGoodChipEpochTime, latestNotBefore));
exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(FabricProvisioning, "Failed to update Known Good Time: %" CHIP_ERROR_FORMAT, err.Format());
    }
    return err;
}

namespace {
// Increment a fabric index in a way that ensures that it stays in the valid
// range [kMinValidFabricIndex, kMaxValidFabricIndex].
FabricIndex NextFabricIndex(FabricIndex fabricIndex)
{
    if (fabricIndex == kMaxValidFabricIndex)
    {
        return kMinValidFabricIndex;
    }

    return static_cast<FabricIndex>(fabricIndex + 1);
}
} // anonymous namespace

void FabricTable::UpdateNextAvailableFabricIndex()
{
    // Only called when mNextAvailableFabricIndex.HasValue()
    for (FabricIndex candidate = NextFabricIndex(mNextAvailableFabricIndex.Value()); candidate != mNextAvailableFabricIndex.Value();
         candidate             = NextFabricIndex(candidate))
    {
        if (!FindFabricWithIndex(candidate))
        {
            mNextAvailableFabricIndex.SetValue(candidate);
            return;
        }
    }

    mNextAvailableFabricIndex.ClearValue();
}

CHIP_ERROR FabricTable::StoreFabricIndexInfo() const
{
    uint8_t buf[IndexInfoTLVMaxSize()];
    TLV::TLVWriter writer;
    writer.Init(buf);

    TLV::TLVType outerType;
    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType));

    if (mNextAvailableFabricIndex.HasValue())
    {
        writer.Put(kNextAvailableFabricIndexTag, mNextAvailableFabricIndex.Value());
    }
    else
    {
        writer.PutNull(kNextAvailableFabricIndexTag);
    }

    TLV::TLVType innerContainerType;
    ReturnErrorOnFailure(writer.StartContainer(kFabricIndicesTag, TLV::kTLVType_Array, innerContainerType));
    // Only enumerate the fabrics that are initialized.
    for (const auto & fabric : *this)
    {
        writer.Put(TLV::AnonymousTag(), fabric.GetFabricIndex());
    }
    ReturnErrorOnFailure(writer.EndContainer(innerContainerType));
    ReturnErrorOnFailure(writer.EndContainer(outerType));

    const auto indexInfoLength = writer.GetLengthWritten();
    VerifyOrReturnError(CanCastTo<uint16_t>(indexInfoLength), CHIP_ERROR_BUFFER_TOO_SMALL);

    ReturnErrorOnFailure(mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::FabricIndexInfo().KeyName(), buf,
                                                   static_cast<uint16_t>(indexInfoLength)));

    return CHIP_NO_ERROR;
}

void FabricTable::EnsureNextAvailableFabricIndexUpdated()
{
    if (!mNextAvailableFabricIndex.HasValue() && mFabricCount < kMaxValidFabricIndex)
    {
        // We must have a fabric index available here. This situation could
        // happen if we fail to store fabric index info when deleting a
        // fabric.
        mNextAvailableFabricIndex.SetValue(kMinValidFabricIndex);
        if (FindFabricWithIndex(kMinValidFabricIndex))
        {
            UpdateNextAvailableFabricIndex();
        }
    }
}

CHIP_ERROR FabricTable::ReadFabricInfo(TLV::ContiguousBufferTLVReader & reader)
{
    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
    TLV::TLVType containerType;
    ReturnErrorOnFailure(reader.EnterContainer(containerType));

    ReturnErrorOnFailure(reader.Next(kNextAvailableFabricIndexTag));
    if (reader.GetType() == TLV::kTLVType_Null)
    {
        mNextAvailableFabricIndex.ClearValue();
    }
    else
    {
        ReturnErrorOnFailure(reader.Get(mNextAvailableFabricIndex.Emplace()));
    }

    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, kFabricIndicesTag));
    TLV::TLVType arrayType;
    ReturnErrorOnFailure(reader.EnterContainer(arrayType));

    CHIP_ERROR err;
    while ((err = reader.Next()) == CHIP_NO_ERROR)
    {
        if (mFabricCount >= ArraySize(mStates))
        {
            // We have nowhere to deserialize this fabric info into.
            return CHIP_ERROR_NO_MEMORY;
        }

        auto & fabric                  = mStates[mFabricCount];
        FabricIndex currentFabricIndex = kUndefinedFabricIndex;
        ReturnErrorOnFailure(reader.Get(currentFabricIndex));

        err = LoadFromStorage(&fabric, currentFabricIndex);
        if (err == CHIP_NO_ERROR)
        {
            ++mFabricCount;
        }
        else
        {
            // This could happen if we failed to store our fabric index info
            // after we deleted the fabric from storage.  Just ignore this
            // fabric index and keep going.
        }
    }

    if (err != CHIP_END_OF_TLV)
    {
        return err;
    }

    ReturnErrorOnFailure(reader.ExitContainer(arrayType));

    ReturnErrorOnFailure(reader.ExitContainer(containerType));
    ReturnErrorOnFailure(reader.VerifyEndOfContainer());

    EnsureNextAvailableFabricIndexUpdated();

    return CHIP_NO_ERROR;
}

Crypto::P256Keypair * FabricTable::AllocateEphemeralKeypairForCASE()
{
    if (mOperationalKeystore != nullptr)
    {
        return mOperationalKeystore->AllocateEphemeralKeypairForCASE();
    }

    return Platform::New<Crypto::P256Keypair>();
}

void FabricTable::ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair)
{
    if (mOperationalKeystore != nullptr)
    {
        mOperationalKeystore->ReleaseEphemeralKeypair(keypair);
    }
    else
    {
        Platform::Delete<Crypto::P256Keypair>(keypair);
    }
}

CHIP_ERROR FabricTable::StoreCommitMarker(const CommitMarker & commitMarker)
{
    uint8_t tlvBuf[CommitMarkerContextTLVMaxSize()];
    TLV::TLVWriter writer;
    writer.Init(tlvBuf);

    TLV::TLVType outerType;
    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType));
    ReturnErrorOnFailure(writer.Put(kMarkerFabricIndexTag, commitMarker.fabricIndex));
    ReturnErrorOnFailure(writer.Put(kMarkerIsAdditionTag, commitMarker.isAddition));
    ReturnErrorOnFailure(writer.EndContainer(outerType));

    const auto markerContextTLVLength = writer.GetLengthWritten();
    VerifyOrReturnError(CanCastTo<uint16_t>(markerContextTLVLength), CHIP_ERROR_BUFFER_TOO_SMALL);

    return mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::FailSafeCommitMarkerKey().KeyName(), tlvBuf,
                                     static_cast<uint16_t>(markerContextTLVLength));
}

CHIP_ERROR FabricTable::GetCommitMarker(CommitMarker & outCommitMarker)
{
    uint8_t tlvBuf[CommitMarkerContextTLVMaxSize()];
    uint16_t tlvSize = sizeof(tlvBuf);
    ReturnErrorOnFailure(
        mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::FailSafeCommitMarkerKey().KeyName(), tlvBuf, tlvSize));

    // If buffer was too small, we won't reach here.
    TLV::ContiguousBufferTLVReader reader;
    reader.Init(tlvBuf, tlvSize);
    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));

    TLV::TLVType containerType;
    ReturnErrorOnFailure(reader.EnterContainer(containerType));

    ReturnErrorOnFailure(reader.Next(kMarkerFabricIndexTag));
    ReturnErrorOnFailure(reader.Get(outCommitMarker.fabricIndex));

    ReturnErrorOnFailure(reader.Next(kMarkerIsAdditionTag));
    ReturnErrorOnFailure(reader.Get(outCommitMarker.isAddition));

    // Don't try to exit container: we got all we needed. This allows us to
    // avoid erroring-out on newer versions.

    return CHIP_NO_ERROR;
}

void FabricTable::ClearCommitMarker()
{
    mStorage->SyncDeleteKeyValue(DefaultStorageKeyAllocator::FailSafeCommitMarkerKey().KeyName());
}

bool FabricTable::HasOperationalKeyForFabric(FabricIndex fabricIndex) const
{
    const FabricInfo * fabricInfo = FindFabricWithIndex(fabricIndex);
    VerifyOrReturnError(fabricInfo != nullptr, false);

    if (fabricInfo->HasOperationalKey())
    {
        // Legacy case of manually injected keys: delegate to FabricInfo directly
        return true;
    }
    if (mOperationalKeystore != nullptr)
    {
        return mOperationalKeystore->HasOpKeypairForFabric(fabricIndex);
    }

    return false;
}

CHIP_ERROR FabricTable::SignWithOpKeypair(FabricIndex fabricIndex, ByteSpan message, P256ECDSASignature & outSignature) const
{
    const FabricInfo * fabricInfo = FindFabricWithIndex(fabricIndex);
    VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_KEY_NOT_FOUND);

    if (fabricInfo->HasOperationalKey())
    {
        // Legacy case of manually injected FabricInfo: delegate to FabricInfo directly
        return fabricInfo->SignWithOpKeypair(message, outSignature);
    }
    if (mOperationalKeystore != nullptr)
    {
        return mOperationalKeystore->SignWithOpKeypair(fabricIndex, message, outSignature);
    }

    return CHIP_ERROR_KEY_NOT_FOUND;
}

bool FabricTable::HasPendingOperationalKey(bool & outIsPendingKeyForUpdateNoc) const
{
    // We can only manage commissionable pending fail-safe state if we have a keystore
    bool hasOpKeyPending = mStateFlags.Has(StateFlags::kIsOperationalKeyPending);

    if (hasOpKeyPending)
    {
        // We kept track of whether the last `AllocatePendingOperationalKey` for was for an update,
        // so give it back out here.
        outIsPendingKeyForUpdateNoc = mStateFlags.Has(StateFlags::kIsPendingKeyForUpdateNoc);
    }

    return hasOpKeyPending;
}

bool FabricTable::SetPendingDataFabricIndex(FabricIndex fabricIndex)
{
    bool isLegal = (mFabricIndexWithPendingState == kUndefinedFabricIndex) || (mFabricIndexWithPendingState == fabricIndex);

    if (isLegal)
    {
        mFabricIndexWithPendingState = fabricIndex;
    }
    return isLegal;
}

CHIP_ERROR FabricTable::AllocatePendingOperationalKey(Optional<FabricIndex> fabricIndex, MutableByteSpan & outputCsr)
{
    // We can only manage commissionable pending fail-safe state if we have a keystore
    VerifyOrReturnError(mOperationalKeystore != nullptr, CHIP_ERROR_INCORRECT_STATE);

    // We can only allocate a pending key if no pending state (NOC, ICAC) already present,
    // since there can only be one pending state per fail-safe.
    VerifyOrReturnError(!mStateFlags.Has(StateFlags::kIsPendingFabricDataPresent), CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(outputCsr.size() >= Crypto::kMIN_CSR_Buffer_Size, CHIP_ERROR_BUFFER_TOO_SMALL);

    EnsureNextAvailableFabricIndexUpdated();
    FabricIndex fabricIndexToUse = kUndefinedFabricIndex;

    if (fabricIndex.HasValue())
    {
        // Check we not are trying to do an update but also change the root: forbidden
        ReturnErrorCodeIf(mStateFlags.Has(StateFlags::kIsTrustedRootPending), CHIP_ERROR_INCORRECT_STATE);

        // Fabric update case (e.g. UpdateNOC): we already know the fabric index
        fabricIndexToUse = fabricIndex.Value();
        mStateFlags.Set(StateFlags::kIsPendingKeyForUpdateNoc);
    }
    else if (mNextAvailableFabricIndex.HasValue())
    {
        // Fabric addition case (e.g. AddNOC): we need to allocate for the next pending fabric index
        fabricIndexToUse = mNextAvailableFabricIndex.Value();
        mStateFlags.Clear(StateFlags::kIsPendingKeyForUpdateNoc);
    }
    else
    {
        // Fabric addition, but adding NOC would fail on table full: let's not allocate a key
        return CHIP_ERROR_NO_MEMORY;
    }

    VerifyOrReturnError(IsValidFabricIndex(fabricIndexToUse), CHIP_ERROR_INVALID_FABRIC_INDEX);
    VerifyOrReturnError(SetPendingDataFabricIndex(fabricIndexToUse), CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorOnFailure(mOperationalKeystore->NewOpKeypairForFabric(mFabricIndexWithPendingState, outputCsr));
    mStateFlags.Set(StateFlags::kIsOperationalKeyPending);

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::AddNewPendingTrustedRootCert(const ByteSpan & rcac)
{
    VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE);

    // We should not already have pending NOC chain elements when we get here
    ReturnErrorCodeIf(
        mStateFlags.HasAny(StateFlags::kIsTrustedRootPending, StateFlags::kIsUpdatePending, StateFlags::kIsAddPending),
        CHIP_ERROR_INCORRECT_STATE);

    EnsureNextAvailableFabricIndexUpdated();
    FabricIndex fabricIndexToUse = kUndefinedFabricIndex;

    if (mNextAvailableFabricIndex.HasValue())
    {
        fabricIndexToUse = mNextAvailableFabricIndex.Value();
    }
    else
    {
        // Fabric addition, but adding root would fail on table full: let's not allocate a fabric
        return CHIP_ERROR_NO_MEMORY;
    }

    VerifyOrReturnError(IsValidFabricIndex(fabricIndexToUse), CHIP_ERROR_INVALID_FABRIC_INDEX);
    VerifyOrReturnError(SetPendingDataFabricIndex(fabricIndexToUse), CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorOnFailure(mOpCertStore->AddNewTrustedRootCertForFabric(fabricIndexToUse, rcac));

    mStateFlags.Set(StateFlags::kIsPendingFabricDataPresent);
    mStateFlags.Set(StateFlags::kIsTrustedRootPending);
    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::FindExistingFabricByNocChaining(FabricIndex pendingFabricIndex, const ByteSpan & noc,
                                                        FabricIndex & outMatchingFabricIndex) const
{
    // Check whether we already have a matching fabric from a cert chain perspective.
    // To do so we have to extract the FabricID from the NOC and the root public key from the RCAC.
    // We assume the RCAC is currently readable from OperationalCertificateStore, whether pending
    // or persisted.
    FabricId fabricId;
    {
        NodeId unused;
        ReturnErrorOnFailure(ExtractNodeIdFabricIdFromOpCert(noc, &unused, &fabricId));
    }

    // Try to find the root public key from the current existing fabric
    Crypto::P256PublicKey candidateRootKey;
    {
        uint8_t tempRcac[kMaxCHIPCertLength];
        MutableByteSpan tempRcacSpan{ tempRcac };
        Credentials::P256PublicKeySpan publicKeySpan;
        ReturnErrorOnFailure(FetchRootCert(pendingFabricIndex, tempRcacSpan));
        ReturnErrorOnFailure(ExtractPublicKeyFromChipCert(tempRcacSpan, publicKeySpan));
        candidateRootKey = publicKeySpan;
    }

    for (auto & existingFabric : *this)
    {
        if (existingFabric.GetFabricId() == fabricId)
        {
            P256PublicKey existingRootKey;
            ReturnErrorOnFailure(FetchRootPubkey(existingFabric.GetFabricIndex(), existingRootKey));

            if (existingRootKey.Matches(candidateRootKey))
            {
                outMatchingFabricIndex = existingFabric.GetFabricIndex();
                return CHIP_NO_ERROR;
            }
        }
    }

    // Did not find: set outMatchingFabricIndex to kUndefinedFabricIndex
    outMatchingFabricIndex = kUndefinedFabricIndex;
    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::AddNewPendingFabricCommon(const ByteSpan & noc, const ByteSpan & icac, uint16_t vendorId,
                                                  Crypto::P256Keypair * existingOpKey, bool isExistingOpKeyExternallyOwned,
                                                  AdvertiseIdentity advertiseIdentity, FabricIndex * outNewFabricIndex)
{
    VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(outNewFabricIndex != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    static_assert(kMaxValidFabricIndex <= UINT8_MAX, "Cannot create more fabrics than UINT8_MAX");

    // We should already have a pending root when we get here
    VerifyOrReturnError(mStateFlags.Has(StateFlags::kIsTrustedRootPending), CHIP_ERROR_INCORRECT_STATE);
    // We should not have pending update when we get here
    VerifyOrReturnError(!mStateFlags.Has(StateFlags::kIsUpdatePending), CHIP_ERROR_INCORRECT_STATE);

    EnsureNextAvailableFabricIndexUpdated();
    FabricIndex fabricIndexToUse = kUndefinedFabricIndex;
    if (mNextAvailableFabricIndex.HasValue())
    {
        fabricIndexToUse = mNextAvailableFabricIndex.Value();
    }
    else
    {
        // Fabric addition, but adding fabric would fail on table full: let's not allocate a fabric
        return CHIP_ERROR_NO_MEMORY;
    }

    // Internal consistency check that mNextAvailableFabricIndex is indeed properly updated...
    // TODO: Centralize this a bit.
    VerifyOrReturnError(IsValidFabricIndex(fabricIndexToUse), CHIP_ERROR_INVALID_FABRIC_INDEX);

    if (existingOpKey == nullptr)
    {
        // If existing operational key not provided, we need to have a keystore present.
        // It should already have an operational key pending.
        VerifyOrReturnError(mOperationalKeystore != nullptr, CHIP_ERROR_KEY_NOT_FOUND);
        // Make sure we have an operational key, pending or not
        VerifyOrReturnError(mOperationalKeystore->HasOpKeypairForFabric(fabricIndexToUse) ||
                                mOperationalKeystore->HasPendingOpKeypair(),
                            CHIP_ERROR_KEY_NOT_FOUND);
    }

    // Check for new fabric colliding with an existing fabric
    if (!mStateFlags.Has(StateFlags::kAreCollidingFabricsIgnored))
    {
        FabricIndex collidingFabricIndex = kUndefinedFabricIndex;
        ReturnErrorOnFailure(FindExistingFabricByNocChaining(fabricIndexToUse, noc, collidingFabricIndex));
        ReturnErrorCodeIf(collidingFabricIndex != kUndefinedFabricIndex, CHIP_ERROR_FABRIC_EXISTS);
    }

    // We don't have a collision, handle the temp insert of NOC/ICAC
    ReturnErrorOnFailure(mOpCertStore->AddNewOpCertsForFabric(fabricIndexToUse, noc, icac));
    VerifyOrReturnError(SetPendingDataFabricIndex(fabricIndexToUse), CHIP_ERROR_INCORRECT_STATE);

    CHIP_ERROR err = AddOrUpdateInner(fabricIndexToUse, /* isAddition = */ true, existingOpKey, isExistingOpKeyExternallyOwned,
                                      vendorId, advertiseIdentity);
    if (err != CHIP_NO_ERROR)
    {
        // Revert partial state added on error
        RevertPendingOpCertsExceptRoot();
        return err;
    }

    mStateFlags.Set(StateFlags::kIsAddPending);
    mStateFlags.Set(StateFlags::kIsPendingFabricDataPresent);

    // Notify that NOC was added (at least transiently)
    *outNewFabricIndex = fabricIndexToUse;
    NotifyFabricUpdated(fabricIndexToUse);

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::UpdatePendingFabricCommon(FabricIndex fabricIndex, const ByteSpan & noc, const ByteSpan & icac,
                                                  Crypto::P256Keypair * existingOpKey, bool isExistingOpKeyExternallyOwned,
                                                  AdvertiseIdentity advertiseIdentity)
{
    VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_ARGUMENT);

    if (existingOpKey == nullptr)
    {
        // If existing operational key not provided, we need to have a keystore present.
        // It should already have an operational key pending.
        VerifyOrReturnError(mOperationalKeystore != nullptr, CHIP_ERROR_KEY_NOT_FOUND);
        // Make sure we have an operational key, pending or not
        VerifyOrReturnError(mOperationalKeystore->HasOpKeypairForFabric(fabricIndex) || mOperationalKeystore->HasPendingOpKeypair(),
                            CHIP_ERROR_KEY_NOT_FOUND);
    }

    // We should should not have a pending root when we get here, since we can't update root on update
    VerifyOrReturnError(!mStateFlags.Has(StateFlags::kIsTrustedRootPending), CHIP_ERROR_INCORRECT_STATE);

    // We should not have pending add when we get here, due to internal interlocks
    VerifyOrReturnError(!mStateFlags.Has(StateFlags::kIsAddPending), CHIP_ERROR_INCORRECT_STATE);

    // Make sure we are updating at least an existing FabricIndex
    const auto * fabricInfo = FindFabricWithIndex(fabricIndex);
    ReturnErrorCodeIf(fabricInfo == nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);

    // Check for an existing fabric matching RCAC and FabricID. We must find a correct
    // existing fabric that chains to same root. We assume the stored root is correct.
    if (!mStateFlags.Has(StateFlags::kAreCollidingFabricsIgnored))
    {
        FabricIndex collidingFabricIndex = kUndefinedFabricIndex;
        ReturnErrorOnFailure(FindExistingFabricByNocChaining(fabricIndex, noc, collidingFabricIndex));
        ReturnErrorCodeIf(collidingFabricIndex != fabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX);
    }

    // Handle the temp insert of NOC/ICAC
    ReturnErrorOnFailure(mOpCertStore->UpdateOpCertsForFabric(fabricIndex, noc, icac));
    VerifyOrReturnError(SetPendingDataFabricIndex(fabricIndex), CHIP_ERROR_INCORRECT_STATE);

    CHIP_ERROR err = AddOrUpdateInner(fabricIndex, /* isAddition = */ false, existingOpKey, isExistingOpKeyExternallyOwned,
                                      fabricInfo->GetVendorId(), advertiseIdentity);
    if (err != CHIP_NO_ERROR)
    {
        // Revert partial state added on error
        // TODO: Figure-out if there is a better way. We need to make sure we are not inconsistent on elements
        //       other than the opcerts.
        RevertPendingOpCertsExceptRoot();
        return err;
    }

    mStateFlags.Set(StateFlags::kIsUpdatePending);
    mStateFlags.Set(StateFlags::kIsPendingFabricDataPresent);

    // Notify that NOC was updated (at least transiently)
    NotifyFabricUpdated(fabricIndex);

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::CommitPendingFabricData()
{
    VerifyOrReturnError((mStorage != nullptr) && (mOpCertStore != nullptr), CHIP_ERROR_INCORRECT_STATE);

    bool haveNewTrustedRoot      = mStateFlags.Has(StateFlags::kIsTrustedRootPending);
    bool isAdding                = mStateFlags.Has(StateFlags::kIsAddPending);
    bool isUpdating              = mStateFlags.Has(StateFlags::kIsUpdatePending);
    bool hasPending              = mStateFlags.Has(StateFlags::kIsPendingFabricDataPresent);
    bool onlyHaveNewTrustedRoot  = hasPending && haveNewTrustedRoot && !(isAdding || isUpdating);
    bool hasInvalidInternalState = hasPending && (!IsValidFabricIndex(mFabricIndexWithPendingState) || !(isAdding || isUpdating));

    FabricIndex fabricIndexBeingCommitted = mFabricIndexWithPendingState;

    // Proceed with Update/Add pre-flight checks
    if (hasPending && !hasInvalidInternalState)
    {
        if ((isAdding && isUpdating) || (isAdding && !haveNewTrustedRoot))
        {
            ChipLogError(FabricProvisioning, "Found inconsistent interlocks during commit %u/%u/%u!",
                         static_cast<unsigned>(isAdding), static_cast<unsigned>(isUpdating),
                         static_cast<unsigned>(haveNewTrustedRoot));
            hasInvalidInternalState = true;
        }
    }

    // Make sure we actually have a pending fabric
    FabricInfo * pendingFabricEntry = GetMutableFabricByIndex(fabricIndexBeingCommitted);

    if (isUpdating && hasPending && !hasInvalidInternalState)
    {
        if (!mPendingFabric.IsInitialized() || (mPendingFabric.GetFabricIndex() != fabricIndexBeingCommitted) ||
            (pendingFabricEntry == nullptr))
        {
            ChipLogError(FabricProvisioning, "Missing pending fabric on update during commit!");
            hasInvalidInternalState = true;
        }
    }

    if (isAdding && hasPending && !hasInvalidInternalState)
    {
        bool opCertStoreHasRoot = mOpCertStore->HasCertificateForFabric(fabricIndexBeingCommitted, CertChainElement::kRcac);
        if (!mStateFlags.Has(StateFlags::kIsTrustedRootPending) || !opCertStoreHasRoot)
        {
            ChipLogError(FabricProvisioning, "Missing trusted root for fabric add during commit!");
            hasInvalidInternalState = true;
        }
    }

    if ((isAdding || isUpdating) && hasPending && !hasInvalidInternalState)
    {
        if (!HasOperationalKeyForFabric(fabricIndexBeingCommitted))
        {
            ChipLogError(FabricProvisioning, "Could not find an operational key during commit!");
            hasInvalidInternalState = true;
        }
    }

    // If there was nothing pending, we are either in a completely OK state, or weird internally inconsistent
    // state. In either case, let's clear all pending state anyway, in case it was partially stale!
    if (!hasPending || onlyHaveNewTrustedRoot || hasInvalidInternalState)
    {
        CHIP_ERROR err = CHIP_NO_ERROR;

        if (onlyHaveNewTrustedRoot)
        {
            ChipLogError(FabricProvisioning,
                         "Failed to commit: tried to commit with only a new trusted root cert. No data committed.");
            err = CHIP_ERROR_INCORRECT_STATE;
        }
        else if (hasInvalidInternalState)
        {
            ChipLogError(FabricProvisioning, "Failed to commit: internally inconsistent state!");
            err = CHIP_ERROR_INTERNAL;
        }
        else
        {
            // There was nothing pending and no error...
        }

        // Clear all pending state anyway, in case it was partially stale!
        {
            mStateFlags.ClearAll();
            mFabricIndexWithPendingState = kUndefinedFabricIndex;
            mPendingFabric.Reset();
            mOpCertStore->RevertPendingOpCerts();
            if (mOperationalKeystore != nullptr)
            {
                mOperationalKeystore->RevertPendingKeypair();
            }
        }

        return err;
    }

    // ==== Start of actual commit transaction after pre-flight checks ====
    CHIP_ERROR stickyError  = StoreCommitMarker(CommitMarker{ fabricIndexBeingCommitted, isAdding });
    bool failedCommitMarker = (stickyError != CHIP_NO_ERROR);
    if (failedCommitMarker)
    {
        ChipLogError(FabricProvisioning, "Failed to store commit marker, may be inconsistent if reboot happens during fail-safe!");
    }

    {
        // This scope block is to illustrate the complete commit transaction
        // state. We can see it contains a LARGE number of items...

        // Atomically assume data no longer pending, since we are committing it. Do so here
        // so that FindFabricBy* will return real data and never pending.
        mStateFlags.Clear(StateFlags::kIsPendingFabricDataPresent);

        if (isUpdating)
        {
            // This will get the non-pending fabric
            FabricInfo * existingFabricToUpdate = GetMutableFabricByIndex(fabricIndexBeingCommitted);

            // Multiple interlocks validated the below, so it's fatal if we are somehow incoherent here
            VerifyOrDie((existingFabricToUpdate != nullptr) && (existingFabricToUpdate != &mPendingFabric));

            // Commit the pending entry to local in-memory fabric metadata, which
            // also moves operational keys if not backed by OperationalKeystore
            *existingFabricToUpdate = std::move(mPendingFabric);
        }

        // Store pending metadata first
        FabricInfo * liveFabricEntry = GetMutableFabricByIndex(fabricIndexBeingCommitted);
        VerifyOrDie(liveFabricEntry != nullptr);

        CHIP_ERROR metadataErr = StoreFabricMetadata(liveFabricEntry);
        if (metadataErr != CHIP_NO_ERROR)
        {
            ChipLogError(FabricProvisioning, "Failed to commit pending fabric metadata: %" CHIP_ERROR_FORMAT, metadataErr.Format());
        }
        stickyError = (stickyError != CHIP_NO_ERROR) ? stickyError : metadataErr;

        // We can only manage commissionable pending fail-safe state if we have a keystore
        CHIP_ERROR keyErr = CHIP_NO_ERROR;
        if ((mOperationalKeystore != nullptr) && mOperationalKeystore->HasOpKeypairForFabric(fabricIndexBeingCommitted) &&
            mOperationalKeystore->HasPendingOpKeypair())
        {
            keyErr = mOperationalKeystore->CommitOpKeypairForFabric(fabricIndexBeingCommitted);
            if (keyErr != CHIP_NO_ERROR)
            {
                ChipLogError(FabricProvisioning, "Failed to commit pending operational keypair %" CHIP_ERROR_FORMAT,
                             keyErr.Format());
                mOperationalKeystore->RevertPendingKeypair();
            }
        }
        stickyError = (stickyError != CHIP_NO_ERROR) ? stickyError : keyErr;

        // For testing only, early return (NEVER OCCURS OTHERWISE) during the commit
        // so that clean-ups using the commit marker can be tested.
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
        {
            if (mStateFlags.Has(StateFlags::kAbortCommitForTest))
            {
                // Clear state so that shutdown doesn't attempt clean-up
                mStateFlags.ClearAll();
                mFabricIndexWithPendingState = kUndefinedFabricIndex;
                mPendingFabric.Reset();

                ChipLogError(FabricProvisioning, "Aborting commit in middle of transaction for testing.");
                return CHIP_ERROR_INTERNAL;
            }
        }
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST

        // Commit operational certs
        CHIP_ERROR opCertErr = mOpCertStore->CommitOpCertsForFabric(fabricIndexBeingCommitted);
        if (opCertErr != CHIP_NO_ERROR)
        {
            ChipLogError(FabricProvisioning, "Failed to commit pending operational certificates %" CHIP_ERROR_FORMAT,
                         opCertErr.Format());
            mOpCertStore->RevertPendingOpCerts();
        }
        stickyError = (stickyError != CHIP_NO_ERROR) ? stickyError : opCertErr;

        // Failure to commit Last Known Good Time is non-fatal.  If Last Known
        // Good Time is incorrect and this causes incoming certificates to
        // appear invalid, the certificate validity policy will see this
        // condition and can act appropriately.
        CHIP_ERROR lkgtErr = mLastKnownGoodTime.CommitPendingLastKnownGoodChipEpochTime();
        if (lkgtErr != CHIP_NO_ERROR)
        {
            // Log but this is not sticky...
            ChipLogError(FabricProvisioning, "Failed to commit Last Known Good Time: %" CHIP_ERROR_FORMAT, lkgtErr.Format());
        }

        // If an Add occurred, let's update the fabric index
        CHIP_ERROR fabricIndexErr = CHIP_NO_ERROR;
        if (mStateFlags.Has(StateFlags::kIsAddPending))
        {
            UpdateNextAvailableFabricIndex();
            fabricIndexErr = StoreFabricIndexInfo();
            if (fabricIndexErr != CHIP_NO_ERROR)
            {
                ChipLogError(FabricProvisioning, "Failed to commit pending fabric indices: %" CHIP_ERROR_FORMAT,
                             fabricIndexErr.Format());
            }
        }
        stickyError = (stickyError != CHIP_NO_ERROR) ? stickyError : fabricIndexErr;
    }

    // Commit must have same side-effect as reverting all pending data
    mStateFlags.ClearAll();
    mFabricIndexWithPendingState = kUndefinedFabricIndex;
    mPendingFabric.Reset();

    if (stickyError != CHIP_NO_ERROR)
    {
        // Blow-away everything if we got past any storage, even on Update: system state is broken
        // TODO: Develop a way to properly revert in the future, but this is very difficult
        Delete(fabricIndexBeingCommitted);

        RevertPendingFabricData();
    }
    else
    {
        NotifyFabricCommitted(fabricIndexBeingCommitted);
    }

    // Clear commit marker no matter what: if we got here, there was no reboot and previous clean-ups
    // did their job.
    ClearCommitMarker();

    return stickyError;
}

void FabricTable::RevertPendingFabricData()
{
    // Will clear pending UpdateNoc/AddNOC
    RevertPendingOpCertsExceptRoot();

    if (mOperationalKeystore != nullptr)
    {
        mOperationalKeystore->RevertPendingKeypair();
    }

    // Clear everything else
    if (mOpCertStore != nullptr)
    {
        mOpCertStore->RevertPendingOpCerts();
    }

    mLastKnownGoodTime.RevertPendingLastKnownGoodChipEpochTime();

    mStateFlags.ClearAll();
    mFabricIndexWithPendingState = kUndefinedFabricIndex;
}

void FabricTable::RevertPendingOpCertsExceptRoot()
{
    mPendingFabric.Reset();

    if (mStateFlags.Has(StateFlags::kIsPendingFabricDataPresent))
    {
        ChipLogError(FabricProvisioning, "Reverting pending fabric data for fabric 0x%x",
                     static_cast<unsigned>(mFabricIndexWithPendingState));
    }

    if (mOpCertStore != nullptr)
    {
        mOpCertStore->RevertPendingOpCertsExceptRoot();
    }

    if (mStateFlags.Has(StateFlags::kIsAddPending))
    {
        // If we have a pending add, let's make sure to kill the pending fabric metadata and return it to viable state.
        Delete(mFabricIndexWithPendingState);
    }

    mStateFlags.Clear(StateFlags::kIsAddPending);
    mStateFlags.Clear(StateFlags::kIsUpdatePending);
    if (!mStateFlags.Has(StateFlags::kIsTrustedRootPending))
    {
        mFabricIndexWithPendingState = kUndefinedFabricIndex;
    }
}

CHIP_ERROR FabricTable::SetFabricLabel(FabricIndex fabricIndex, const CharSpan & fabricLabel)
{
    VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);

    ReturnErrorCodeIf(fabricLabel.size() > kFabricLabelMaxLengthInBytes, CHIP_ERROR_INVALID_ARGUMENT);

    FabricInfo * fabricInfo  = GetMutableFabricByIndex(fabricIndex);
    bool fabricIsInitialized = (fabricInfo != nullptr) && fabricInfo->IsInitialized();
    VerifyOrReturnError(fabricIsInitialized, CHIP_ERROR_INVALID_FABRIC_INDEX);

    // Update fabric table current in-memory entry, whether pending or not
    ReturnErrorOnFailure(fabricInfo->SetFabricLabel(fabricLabel));

    if (!mStateFlags.HasAny(StateFlags::kIsAddPending, StateFlags::kIsUpdatePending) && (fabricInfo != &mPendingFabric))
    {
        // Nothing is pending, we have to store immediately.
        ReturnErrorOnFailure(StoreFabricMetadata(fabricInfo));
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::GetFabricLabel(FabricIndex fabricIndex, CharSpan & outFabricLabel)
{
    const FabricInfo * fabricInfo = FindFabricWithIndex(fabricIndex);
    VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);

    outFabricLabel = fabricInfo->GetFabricLabel();
    return CHIP_NO_ERROR;
}

CHIP_ERROR FabricTable::PeekFabricIndexForNextAddition(FabricIndex & outIndex)
{
    EnsureNextAvailableFabricIndexUpdated();
    if (!mNextAvailableFabricIndex.HasValue())
    {
        return CHIP_ERROR_NO_MEMORY;
    }

    FabricIndex index = mNextAvailableFabricIndex.Value();
    VerifyOrReturnError(IsValidFabricIndex(index), CHIP_ERROR_INVALID_FABRIC_INDEX);

    outIndex = index;
    return CHIP_NO_ERROR;
}

} // namespace chip
