/*
 *
 *    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>

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);

    // 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;

    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
{
    DefaultStorageKeyAllocator keyAlloc;

    {
        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(keyAlloc.FabricMetadata(mFabricIndex), 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)
{
    DefaultStorageKeyAllocator keyAlloc;

    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(keyAlloc.FabricMetadata(mFabricIndex), 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);

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

    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
{
    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
{
    // 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)
{
    // 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 Upating 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;
    }

    // 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);
    DefaultStorageKeyAllocator keyAlloc;
    CHIP_ERROR err = mStorage->SyncGetKeyValue(keyAlloc.FabricIndexInfo(), 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);

    DefaultStorageKeyAllocator keyAlloc;
    ReturnErrorOnFailure(mStorage->SyncSetKeyValue(keyAlloc.FabricIndexInfo(), 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)
{
    DefaultStorageKeyAllocator keyAlloc;
    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(keyAlloc.FailSafeCommitMarkerKey(), tlvBuf, static_cast<uint16_t>(markerContextTLVLength));
}

CHIP_ERROR FabricTable::GetCommitMarker(CommitMarker & outCommitMarker)
{
    DefaultStorageKeyAllocator keyAlloc;
    uint8_t tlvBuf[CommitMarkerContextTLVMaxSize()];
    uint16_t tlvSize = sizeof(tlvBuf);
    ReturnErrorOnFailure(mStorage->SyncGetKeyValue(keyAlloc.FailSafeCommitMarkerKey(), 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()
{
    DefaultStorageKeyAllocator keyAlloc;
    mStorage->SyncDeleteKeyValue(keyAlloc.FailSafeCommitMarkerKey());
}

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::kMAX_CSR_Length, 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,
                                                  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);
    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)
{
    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());
    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;
}

} // namespace chip
