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

#pragma once

#include <algorithm>

#include <app/util/basic-types.h>
#include <credentials/CHIPCert.h>
#include <credentials/CHIPCertificateSet.h>
#include <credentials/CertificateValidityPolicy.h>
#include <credentials/LastKnownGoodTime.h>
#include <credentials/OperationalCertificateStore.h>
#include <crypto/CHIPCryptoPAL.h>
#include <crypto/OperationalKeystore.h>
#include <lib/core/CHIPPersistentStorageDelegate.h>
#if CHIP_CRYPTO_HSM
#include <crypto/hsm/CHIPCryptoPALHsm.h>
#endif
#include <lib/core/CHIPEncoding.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/core/Optional.h>
#include <lib/core/ScopedNodeId.h>
#include <lib/core/TLV.h>
#include <lib/support/BitFlags.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/DLLUtil.h>
#include <lib/support/Span.h>

namespace chip {

static constexpr uint8_t kFabricLabelMaxLengthInBytes = 32;

static_assert(kUndefinedFabricIndex < chip::kMinValidFabricIndex, "Undefined fabric index should not be valid");

/**
 * Provides access to the core metadata for a given fabric to which a node is joined.
 *
 * This metadata includes:
 *
 * - FabricIndex within the local set of fabrics
 * - Operational Identity
 *   - NodeId
 *   - Fabric Id
 *   - Public key of operational root CA (to avoid keeping/reloading RCAC (Root CA Certificate) too often)
 *   - Pre-computed "Compressed Fabric ID" used for discovery
 * - Operational public key (if externally injected as opposed to present in an OperationalKeystore)
 * - Fabric Label
 * - VendorID allocated at fabric joining by commissioner
 *
 * NOTE: All the setters of this class are private and only accessible by FabricTable, the
 *       friend class that owns these. The reason is that there are data dependencies between
 *       fabrics that require FabricTable to be the single entrypoint for all mutations, rather
 *       than directly on a FabricInfo instance.
 */
class DLL_EXPORT FabricInfo
{
public:
    FabricInfo() { Reset(); }
    ~FabricInfo() { Reset(); }

    // Non-copyable
    FabricInfo(FabricInfo const &) = delete;
    void operator=(FabricInfo const &) = delete;

    // Returns a span into our internal storage.
    CharSpan GetFabricLabel() const { return CharSpan(mFabricLabel, strnlen(mFabricLabel, kFabricLabelMaxLengthInBytes)); }
    CHIP_ERROR SetFabricLabel(const CharSpan & fabricLabel);

    NodeId GetNodeId() const { return mNodeId; }
    ScopedNodeId GetScopedNodeId() const { return ScopedNodeId(mNodeId, mFabricIndex); }
    ScopedNodeId GetScopedNodeIdForNode(const NodeId node) const { return ScopedNodeId(node, mFabricIndex); }

    // TODO(#15049): Refactor/rename PeerId to OperationalId or OpId throughout source
    PeerId GetPeerId() const { return PeerId(mCompressedFabricId, mNodeId); }
    PeerId GetPeerIdForNode(const NodeId node) const { return PeerId(mCompressedFabricId, node); }

    FabricId GetFabricId() const { return mFabricId; }
    FabricIndex GetFabricIndex() const { return mFabricIndex; }

    CompressedFabricId GetCompressedFabricId() const { return mCompressedFabricId; }
    CHIP_ERROR GetCompressedFabricIdBytes(MutableByteSpan & compressedFabricId) const
    {
        ReturnErrorCodeIf(compressedFabricId.size() != sizeof(uint64_t), CHIP_ERROR_INVALID_ARGUMENT);
        Encoding::BigEndian::Put64(compressedFabricId.data(), GetCompressedFabricId());
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR FetchRootPubkey(Crypto::P256PublicKey & outPublicKey) const;

    VendorId GetVendorId() const { return mVendorId; }

    bool IsInitialized() const { return (mFabricIndex != kUndefinedFabricIndex) && IsOperationalNodeId(mNodeId); }

    bool HasOperationalKey() const { return mOperationalKey != nullptr; }

    friend class FabricTable;

private:
    struct InitParams
    {
        NodeId nodeId                         = kUndefinedNodeId;
        FabricId fabricId                     = kUndefinedFabricId;
        FabricIndex fabricIndex               = kUndefinedFabricIndex;
        CompressedFabricId compressedFabricId = kUndefinedCompressedFabricId;
        Crypto::P256PublicKey rootPublicKey;
        VendorId vendorId                        = VendorId::NotSpecified; /**< Vendor ID for commissioner of fabric */
        Crypto::P256Keypair * operationalKeypair = nullptr;
        bool hasExternallyOwnedKeypair           = false;

        CHIP_ERROR AreValid() const
        {
            VerifyOrReturnError((fabricId != kUndefinedFabricId) && (fabricIndex != kUndefinedFabricIndex),
                                CHIP_ERROR_INVALID_ARGUMENT);
            VerifyOrReturnError(IsOperationalNodeId(nodeId), CHIP_ERROR_INVALID_ARGUMENT);
            // We don't check the root public key validity or the compressed fabric ID, since in the
            // very small usage that exists in private use, the rest should be OK.
            return CHIP_NO_ERROR;
        }
    };

    // Move assignment operator to support setting from pending on fabric table commit
    void operator=(FabricInfo && other);

    /**
     * @brief Initialize a FabricInfo object's metadata given init parameters.
     *
     * Note that certificates are never owned by this object and are assumed pre-validated
     *
     * @param initParams Init parameters to use to initialize the given fabric.
     * @return CHIP_NO_ERROR on success or another internal CHIP_ERROR_* value on failure
     */
    CHIP_ERROR Init(const InitParams & initParams);

    /**
     * Sets the P256Keypair used for this fabric.  This will make a copy of the keypair
     * via the P256Keypair::Serialize and P256Keypair::Deserialize methods.
     *
     * The keyPair argument is safe to deallocate once this method returns.
     *
     * If your P256Keypair does not support serialization, use the
     * `SetExternallyOwnedOperationalKeypair` method instead.
     */
    CHIP_ERROR SetOperationalKeypair(const Crypto::P256Keypair * keyPair);

    /**
     * Sets the P256Keypair used for this fabric, delegating ownership of the
     * key to the caller. The P256Keypair provided here must be freed later by
     * the caller of this method if it was allocated dynamically.
     *
     * This should be used if your P256Keypair does not support serialization
     * and deserialization (e.g. your private key is held in a secure element
     * and cannot be accessed directly), or if you back your operational
     * private keys by external implementation of the cryptographic interfaces.
     *
     * To have the ownership of the key managed for you, use
     * SetOperationalKeypair instead.
     */
    CHIP_ERROR SetExternallyOwnedOperationalKeypair(Crypto::P256Keypair * keyPair);

    /**
     * @brief Sign a message with the fabric's operational private key. This ONLY
     *        works if `SetOperationalKeypair` or `SetExternallyOwnedOperationalKeypair`
     *        had been called and is an API that is present ONLY to be called by FabricTable.
     *
     * @param message - message to sign
     * @param outSignature - buffer to hold the signature
     * @return CHIP_NO_ERROR on success or another CHIP_ERROR on crypto internal errors
     */
    CHIP_ERROR SignWithOpKeypair(ByteSpan message, Crypto::P256ECDSASignature & outSignature) const;

    /**
     *  Reset the state to a completely uninitialized status.
     */
    void Reset()
    {
        mNodeId             = kUndefinedNodeId;
        mFabricId           = kUndefinedFabricId;
        mFabricIndex        = kUndefinedFabricIndex;
        mCompressedFabricId = kUndefinedCompressedFabricId;

        mVendorId       = VendorId::NotSpecified;
        mFabricLabel[0] = '\0';

        if (!mHasExternallyOwnedOperationalKey && mOperationalKey != nullptr)
        {
            chip::Platform::Delete(mOperationalKey);
        }
        mOperationalKey = nullptr;

        mFabricIndex = kUndefinedFabricIndex;
        mNodeId      = kUndefinedNodeId;
    }

    static constexpr size_t MetadataTLVMaxSize()
    {
        return TLV::EstimateStructOverhead(sizeof(uint16_t), kFabricLabelMaxLengthInBytes);
    }

    static constexpr size_t OpKeyTLVMaxSize()
    {
        return TLV::EstimateStructOverhead(sizeof(uint16_t), Crypto::P256SerializedKeypair::Capacity());
    }

    NodeId mNodeId           = kUndefinedNodeId;
    FabricId mFabricId       = kUndefinedFabricId;
    FabricIndex mFabricIndex = kUndefinedFabricIndex;
    // We cache the compressed fabric id since it's used so often and costly to get.
    CompressedFabricId mCompressedFabricId = kUndefinedCompressedFabricId;
    // We cache the root public key since it's used so often and costly to get.
    Crypto::P256PublicKey mRootPublicKey;

    VendorId mVendorId                                  = VendorId::NotSpecified;
    char mFabricLabel[kFabricLabelMaxLengthInBytes + 1] = { '\0' };
    mutable Crypto::P256Keypair * mOperationalKey       = nullptr;
    bool mHasExternallyOwnedOperationalKey              = false;

    CHIP_ERROR CommitToStorage(PersistentStorageDelegate * storage) const;
    CHIP_ERROR LoadFromStorage(PersistentStorageDelegate * storage, FabricIndex newFabricIndex, const ByteSpan & rcac,
                               const ByteSpan & noc);
};

/**
 * Iterates over valid fabrics within a list
 */

class ConstFabricIterator
{
public:
    using value_type = FabricInfo;
    using pointer    = FabricInfo *;
    using reference  = FabricInfo &;

    ConstFabricIterator(const FabricInfo * start, const FabricInfo * pending, size_t index, size_t maxSize) :
        mStart(start), mPending(pending), mIndex(index), mMaxSize(maxSize)
    {
        if (mIndex >= maxSize)
        {
            mIndex = maxSize;
        }
        else if (!mStart[mIndex].IsInitialized())
        {
            Advance();
        }
    }
    ConstFabricIterator(const ConstFabricIterator &) = default;
    ConstFabricIterator & operator=(const ConstFabricIterator &) = default;

    ConstFabricIterator & operator++() { return Advance(); }
    ConstFabricIterator operator++(int)
    {
        ConstFabricIterator other(*this);
        Advance();
        return other;
    }

    const FabricInfo & operator*() const
    {
        VerifyOrDie(!IsAtEnd());

        return *GetCurrent();
    }
    const FabricInfo * operator->() const
    {
        VerifyOrDie(!IsAtEnd());

        return GetCurrent();
    }

    bool operator==(const ConstFabricIterator & other)
    {
        if (IsAtEnd())
        {
            return other.IsAtEnd();
        }

        // Pending entry does not participate in finding this.
        return (mStart == other.mStart) && (mIndex == other.mIndex) && (mMaxSize == other.mMaxSize);
    }
    bool operator!=(const ConstFabricIterator & other) { return !(*this == other); }

    bool IsAtEnd() const { return (mIndex == mMaxSize); }

private:
    const FabricInfo * mStart;
    const FabricInfo * mPending; ///< Pointer to the shadow pending entry, nullptr if none
    size_t mIndex;
    size_t mMaxSize;

    // Helper to get either a given entry of the fabric table, or its pending shadow if
    // a fabric update is currently pending.
    const FabricInfo * GetCurrent() const
    {
        const auto * current = mStart + mIndex;

        // If we reached the pending entry, return that instead of the underlying entry from the mStates.
        if ((mPending != nullptr) && mPending->IsInitialized() && (current->GetFabricIndex() == mPending->GetFabricIndex()))
        {
            current = mPending;
        }

        return current;
    }

    ConstFabricIterator & Advance()
    {
        do
        {
            if (mIndex < mMaxSize)
            {
                mIndex++;
            }
        } while (!IsAtEnd() && !mStart[mIndex].IsInitialized());

        return *this;
    }
};

class DLL_EXPORT FabricTable
{
public:
    struct DLL_EXPORT InitParams
    {
        // PersistentStorageDelegate for Fabric Info metadata storage and Fabric Table index (MANDATORY).
        PersistentStorageDelegate * storage = nullptr;
        // Operational Keystore to abstract access to key. Mandatory for commissionable devices  (e.g.
        // chip::Server-based things) and recommended for controllers. With this set to false, FabricInfo
        // added as new fabrics need to have directly injected operational keys with FabricInfo::Set*OperationalKey.
        Crypto::OperationalKeystore * operationalKeystore = nullptr;
        // Operational Certificate store to hold the NOC/ICAC/RCAC chains (MANDATORY).
        Credentials::OperationalCertificateStore * opCertStore = nullptr;
    };

    class DLL_EXPORT Delegate
    {
    public:
        Delegate() {}
        virtual ~Delegate() {}

        /**
         * Gets called when a fabric is about to be deleted, such as on
         * FabricTable::Delete().  This allows actions to be taken that need the
         * fabric to still be around before we delete it.
         **/
        virtual void FabricWillBeRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) {}

        /**
         * Gets called when a fabric is deleted, such as on FabricTable::Delete().
         **/
        virtual void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) {}

        /**
         * Gets called when a fabric in Fabric Table is persisted to storage, by CommitPendingFabricData.
         **/
        virtual void OnFabricCommitted(const FabricTable & fabricTable, FabricIndex fabricIndex){};

        /**
         * Gets called when operational credentials are changed, which may not be persistent.
         *
         * Can be used to affect what is needed for UpdateNOC prior to commit.
         **/
        virtual void OnFabricUpdated(const FabricTable & fabricTable, FabricIndex fabricIndex){};

        // Intrusive list pointer for FabricTable to manage the entries.
        Delegate * next = nullptr;
    };

public:
    FabricTable()  = default;
    ~FabricTable() = default;

    // Non-copyable
    FabricTable(FabricTable const &) = delete;
    void operator=(FabricTable const &) = delete;

    // Returns CHIP_ERROR_NOT_FOUND if there is no fabric for that index.
    CHIP_ERROR Delete(FabricIndex fabricIndex);
    void DeleteAllFabrics();

    // TODO this #if CONFIG_BUILD_FOR_HOST_UNIT_TEST is temporary. There is a change incoming soon
    // that will allow triggering NOC update directly.
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
    void SendUpdateFabricNotificationForTest(FabricIndex fabricIndex) { NotifyFabricUpdated(fabricIndex); }
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST

    /**
     * Collection of methods to help find a matching FabricInfo instance given a set of query criteria
     *
     */

    /**
     * Finds a matching FabricInfo instance given a root public key and fabric ID that uniquely identifies the fabric in any scope.
     *
     * Returns nullptr if no matching instance is found.
     *
     */
    const FabricInfo * FindFabric(const Crypto::P256PublicKey & rootPubKey, FabricId fabricId) const;

    /**
     * Finds a matching FabricInfo instance given a locally-scoped fabric index.
     *
     * Returns nullptr if no matching instance is found.
     *
     */
    const FabricInfo * FindFabricWithIndex(FabricIndex fabricIndex) const;

    /**
     * Finds a matching FabricInfo instance given a root public key, fabric ID AND a matching NodeId. This variant of find
     * is only to be used when it is possible to have colliding fabrics in the table that are on the same logical fabric
     * but may be associated with different node identities.
     *
     * Returns nullptr if no matching instance is found.
     *
     */
    const FabricInfo * FindIdentity(const Crypto::P256PublicKey & rootPubKey, FabricId fabricId, NodeId nodeId) const;

    /**
     * Finds a matching FabricInfo instance given a compressed fabric ID. If there are multiple
     * matching FabricInfo instances given the low but non-zero probability of collision, there is no guarantee
     * on which instance will be returned.
     *
     * Returns nullptr if no matching instance is found.
     */
    const FabricInfo * FindFabricWithCompressedId(CompressedFabricId compressedFabricId) const;

    CHIP_ERROR Init(const FabricTable::InitParams & initParams);
    void Shutdown();

    /**
     * @brief If `Init()` caused a Delete due to partial commit, the fabric index at play is returned.
     *
     * Allows caller to schedule more clean-up. This is because at Init() time, none of the delegates
     * are registered yet, so no other modules would learn of the removal.
     *
     * The value is auto-reset to `kUndefinedFabricIndex` on being returned, so that subsequent
     * `GetDeletedFabricFromCommitMarker()` after one that has a fabric index to give will provide
     * `kUndefinedFabricIndex`.
     *
     * @return the fabric index of a just-deleted fabric, or kUndefinedFabricIndex if none were deleted.
     */
    FabricIndex GetDeletedFabricFromCommitMarker();

    /**
     * @brief Clear the commit marker when we are sure we have proceeded with any remaining clean-up
     */
    void ClearCommitMarker();

    // Forget a fabric in memory: doesn't delete any persistent state, just
    // reverts any pending state (blindly) and then resets the fabric table
    // entry.
    //
    // TODO: We have to determine if we should remove this call.
    void Forget(FabricIndex fabricIndex);

    CHIP_ERROR AddFabricDelegate(FabricTable::Delegate * delegate);
    void RemoveFabricDelegate(FabricTable::Delegate * delegate);

    /**
     * @brief Set the Fabric Label for the fabric referred by `fabricIndex`.
     *
     * If a fabric add/update is pending, only the pending version will be updated,
     * so that on fail-safe expiry, you would actually see the only fabric label if
     * Update fails. If the fabric label is set before UpdateNOC, then the change is immediate.
     *
     * @param fabricIndex - Fabric Index for which to set the label
     * @param fabricLabel - Label to set on the fabric
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_INVALID_FABRIC_INDEX if fabricIndex does not refer to an fabric in the table
     * @retval CHIP_ERROR_INVALID_ARGUMENT on fabric label error (e.g. too large)
     * @retval other CHIP_ERROR on internal errors
     */
    CHIP_ERROR SetFabricLabel(FabricIndex fabricIndex, const CharSpan & fabricLabel);

    /**
     * @brief Get the Fabric Label for a given fabric
     *
     * NOTE: The outFabricLabel argument points to internal memory of the fabric info.
     *       It may become invalid on the next FabricTable API call due to shadow
     *       storage of data.
     *
     * @param fabricIndex - Fabric index for which to get the label
     * @param outFabricLabel - char span that will be set to the label value
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_INVALID_FABRIC_INDEX on error
     * @retval other CHIP_ERROR on internal errors
     */
    CHIP_ERROR GetFabricLabel(FabricIndex fabricIndex, CharSpan & outFabricLabel);

    /**
     * Get the current Last Known Good Time.
     *
     * @param lastKnownGoodChipEpochTime (out) the current last known good time, if any is known
     * @return CHIP_NO_ERROR on success, else an appropriate CHIP_ERROR
     */
    CHIP_ERROR GetLastKnownGoodChipEpochTime(System::Clock::Seconds32 & lastKnownGoodChipEpochTime) const
    {
        return mLastKnownGoodTime.GetLastKnownGoodChipEpochTime(lastKnownGoodChipEpochTime);
    }

    /**
     * Validate that the passed Last Known Good Time is within bounds and then
     * store this and write back to storage.  Legal values are those which are
     * not earlier than firmware build time or any of our stored certificates'
     * NotBefore times:
     *
     *    3.5.6.1. Last Known Good UTC Time
     *
     *    A Node MAY adjust the Last Known Good UTC Time backwards if it
     *    believes the current Last Known Good UTC Time is incorrect and it has
     *    a good time value from a trusted source. The Node SHOULD NOT adjust
     *    the Last Known Good UTC to a time before the later of:
     *      • The build timestamp of its currently running software image
     *      • The not-before timestamp of any of its operational certificates
     *
     * @param lastKnownGoodChipEpochTime Last Known Good Time in seconds since CHIP epoch
     * @return CHIP_NO_ERROR on success, else an appopriate CHIP_ERROR
     */
    CHIP_ERROR SetLastKnownGoodChipEpochTime(System::Clock::Seconds32 lastKnownGoodChipEpochTime);

    /**
     * @return the number of fabrics currently accessible/usable/iterable.
     */
    uint8_t FabricCount() const { return mFabricCount; }

    ConstFabricIterator cbegin() const
    {
        const FabricInfo * pending = GetShadowPendingFabricEntry();
        return ConstFabricIterator(mStates, pending, 0, CHIP_CONFIG_MAX_FABRICS);
    }
    ConstFabricIterator cend() const
    {
        return ConstFabricIterator(mStates, nullptr, CHIP_CONFIG_MAX_FABRICS, CHIP_CONFIG_MAX_FABRICS);
    }
    ConstFabricIterator begin() const { return cbegin(); }
    ConstFabricIterator end() const { return cend(); }

    /**
     * @brief Get the RCAC (operational root certificate) associated with a fabric.
     *
     * If a root is pending for `fabricIndex` from `AddNewPendingTrustedRootCert`, it is returned.
     *
     * @param fabricIndex - Fabric for which to get the RCAC
     * @param outCert - MutableByteSpan to receive the certificate. Resized to actual size.
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_BUFFER_TOO_SMALL if `outCert` is too small
     * @retval CHIP_ERROR_NOT_FOUND if not found/available
     * @retval other CHIP_ERROR values on invalid arguments or internal errors.
     */
    CHIP_ERROR FetchRootCert(FabricIndex fabricIndex, MutableByteSpan & outCert) const;

    /**
     * @brief Get the pending root certificate which is not associated with a fabric, if there is one.
     *
     * If a root is pending from `AddNewPendingTrustedRootCert`, and there is no
     * fabric associated with the corresponding fabric index yet
     * (i.e. `AddNewPendingFabric*` has not been called yet) it is returned.
     *
     * @param outCert - MutableByteSpan to receive the certificate. Resized to actual size.
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_BUFFER_TOO_SMALL if `outCert` is too small.
     * @retval CHIP_ERROR_NOT_FOUND if there is no pending root certificate
     *                              that's not yet associated with a fabric.
     * @retval other CHIP_ERROR values on invalid arguments or internal errors.
     */
    CHIP_ERROR FetchPendingNonFabricAssociatedRootCert(MutableByteSpan & outCert) const;

    /**
     * @brief Get the ICAC (operational intermediate certificate) associated with a fabric.
     *
     * If a fabric is pending from add/update operation for the given `fabricIndex`, its
     * ICAC is returned.
     *
     * If an NOC exists, but the ICAC is not present in the chain, CHIP_NO_ERROR is
     * returned and `outCert` is resized to 0 length so that its `empty()` method returns true.
     *
     * @param fabricIndex - Fabric for which to get the ICAC
     * @param outCert - MutableByteSpan to receive the certificate. Resized to actual size.
     * @retval CHIP_NO_ERROR on success, including if absent within an existing chain
     * @retval CHIP_ERROR_BUFFER_TOO_SMALL if `outCert` is too small
     * @retval CHIP_ERROR_NOT_FOUND if not found/available
     * @retval other CHIP_ERROR values on invalid arguments or internal errors.
     */
    CHIP_ERROR FetchICACert(FabricIndex fabricIndex, MutableByteSpan & outCert) const;

    /**
     * @brief Get the NOC (Node Operational Certificate) associated with a fabric.
     *
     * If a fabric is pending from add/update operation for the given `fabricIndex`, its
     * NOC is returned.
     *
     * @param fabricIndex - Fabric for which to get the NOC
     * @param outCert - MutableByteSpan to receive the certificate. Resized to actual size.
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_BUFFER_TOO_SMALL if `outCert` is too small
     * @retval CHIP_ERROR_NOT_FOUND if not found/available
     * @retval other CHIP_ERROR values on invalid arguments or internal errors.
     */
    CHIP_ERROR FetchNOCCert(FabricIndex fabricIndex, MutableByteSpan & outCert) const;

    /**
     * @brief Get the root public key by value for the given `fabricIndex`.
     *
     * @param fabricIndex - Fabric for which to get the root public key (subject public key of RCAC)
     * @param outPublicKey - PublicKey instance to receive the public key contents
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_BUFFER_TOO_SMALL if `outCert` is too small
     * @retval CHIP_ERROR_INVALID_FABRIC_INDEX if not found/available, or `fabricIndex` has a bad value
     * @retval other CHIP_ERROR values on other invalid arguments or internal errors.
     */
    CHIP_ERROR FetchRootPubkey(FabricIndex fabricIndex, Crypto::P256PublicKey & outPublicKey) const;

    /**
     * @brief Get the CASE Authenticated Tags from the NOC for the given `fabricIndex`.
     *
     * @param fabricIndex - Fabric for which to get the root public key (subject public key of RCAC)
     * @param cats - CATValues struct to write the NOC CATs for the given fabric index
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_INVALID_FABRIC_INDEX if not found/available, or `fabricIndex` has a bad value
     * @retval other CHIP_ERROR values on other invalid arguments or internal errors.
     */
    CHIP_ERROR FetchCATs(const FabricIndex fabricIndex, CATValues & cats) const;

    /**
     * @brief Sign a message with a given fabric's operational keypair. This is used for
     *        CASE and the only way the key should be used.
     *
     * This will use a pending key activated with `ActivatePendingOperationalKey` but
     * not yet persisted, if one is available for the fabric.
     *
     * @param fabricIndex - Fabric index whose operational key touse
     * @param message - Message to sign
     * @param outSignature - Signature object to receive the signature
     *
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_INVALID_FABRIC_INDEX if no active key is found for the given `fabricIndex` or if
     *                                         `fabricIndex` is invalid.
     * @retval other CHIP_ERROR value on internal errors
     */
    CHIP_ERROR SignWithOpKeypair(FabricIndex fabricIndex, ByteSpan message, Crypto::P256ECDSASignature & outSignature) const;

    /**
     * @brief Create an ephemeral keypair for use in session establishment.
     *
     * WARNING: The return value MUST be released by `ReleaseEphemeralKeypair`. This is because
     *          Matter CHIPMem.h does not properly support UniquePtr in a way that would
     *          safely allow classes derived from Crypto::P256Keypair to be released properly.
     *
     * This delegates to the OperationalKeystore if one exists, otherwise it directly allocates a base
     * Crypto::P256Keypair instance
     *
     * @return a pointer to a dynamically P256Keypair (or derived class thereof), which may evaluate to nullptr
     *         if running out of memory.
     */
    Crypto::P256Keypair * AllocateEphemeralKeypairForCASE();

    /**
     * @brief Release an ephemeral keypair previously created by `AllocateEphemeralKeypairForCASE()`
     */
    void ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair);

    /**
     * This initializes a new keypair for the given fabric and generates a CSR for it,
     * so that it can be passed in a CSRResponse.
     *
     * The keypair is temporary and becomes usable for `SignWithOpKeypair` only after either
     * `ActivatePendingOperationalKey` is called. It is destroyed if
     * `RevertPendingFabricData` is called before `CommitPendingFabricData`.
     *  If a pending keypair for the provided fabricIndex (if present) already existed, it is replaced by this call.
     *
     *  Only one pending operational keypair is supported at a time.
     *
     * @param fabricIndex - Existing FabricIndex for which a new keypair must be made available. If it
     *                      doesn't have a value, the key will be marked pending for the next available
     *                      fabric index that would apply for `AddNewFabric`.
     * @param outputCsr - Buffer to contain the CSR. Must be at least `kMAX_CSR_Length` large.
     *
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_BUFFER_TOO_SMALL if `outputCsr` buffer is too small
     * @retval CHIP_ERROR_INVALID_FABRIC_INDEX if there is already a pending keypair for another `fabricIndex` value
     *                                         or if fabricIndex is an invalid value.
     * @retval other CHIP_ERROR value on internal errors
     */
    CHIP_ERROR AllocatePendingOperationalKey(Optional<FabricIndex> fabricIndex, MutableByteSpan & outputCsr);

    /**
     * @brief Returns whether an operational key is pending (true if `AllocatePendingOperationalKey` was
     *        previously successfully called, false otherwise).
     *
     * @param outIsPendingKeyForUpdateNoc this is set to true if the `AllocatePendingOperationalKey` had an
     *                                    associated fabric index attached, indicating it's for UpdateNoc
     */
    bool HasPendingOperationalKey(bool & outIsPendingKeyForUpdateNoc) const;

    /**
     * @brief Returns whether an operational key can be used to sign for given FabricIndex
     *
     * @param fabricIndex - Fabric index for which an operational key must be found
     * @return true if a pending fabric or committed fabric for fabricIndex has an operational key, false otherwise.
     */
    bool HasOperationalKeyForFabric(FabricIndex fabricIndex) const;

    /**
     * @brief Returns the operational keystore. This is used for
     *        CASE and the only way the keystore should be used.
     *
     * @return The operational keystore, nullptr otherwise.
     */
    const Crypto::OperationalKeystore * GetOperationalKeystore() { return mOperationalKeystore; }

    /**
     * @brief Add a pending trusted root certificate for the next fabric created with `AddNewPendingFabric*` methods.
     *
     * The root only becomes actually pending when the `AddNewPendingFabric*` is called afterwards. It is reverted
     * if `RevertPendingFabricData` is called.
     *
     * This method with fail with CHIP_ERROR_INCORRECT_STATE in a variety of illogical/inconsistent conditions,
     * which always can be cleared with `RevertPendingFabricData`. Such a situation is calling this method after
     * `UpdatePendingFabric` which would mean logical collision of an addition and an update.
     *
     * @param rcac - Root certificate in Matter Operational Certificate Encoding (TLV) format
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_INCORRECT_STATE if this is called in an inconsistent order
     * @retval CHIP_ERROR_NO_MEMORY if there is insufficient memory to make the root pending
     * @retval CHIP_ERROR_INVALID_ARGUMENT if the RCAC is too large (further checks are done on `AddNewPendingFabric*`)
     * @retval other CHIP_ERROR on internal errors.
     */
    CHIP_ERROR AddNewPendingTrustedRootCert(const ByteSpan & rcac);

    /**
     * @brief Use an NOC and optional ICAC chaining back to the pending RCAC to activate a new fabric
     *
     * Operational key is assumed to be pending or committed in the associated mOperationalKeystore.
     *
     * The fabric becomes temporarily active for purposes of `Fetch*` and `SignWithOpKeyPair`, etc.
     * The new fabric becomes permanent/persisted on successful `CommitPendingFabricData`. It disappears
     * on `RevertPendingFabricData` or `RevertPendingOpCertsExceptRoot`.
     *
     * This method with fail with CHIP_ERROR_INCORRECT_STATE in a variety of illogical/inconsistent conditions,
     * which always can be cleared with `RevertPendingFabricData`. Such a situation is calling this method after
     * `UpdatePendingFabric*` which would mean logical collision of an addition and an update.
     *
     * If a pending key was present in the OperationalKeystore associated with this FabricTable,
     * it is activated on success.
     *
     *
     * @param noc - NOC for the fabric. Must match an existing or pending operational keypair in the mOperationalKeystore.
     * @param icac - ICAC for the fabric. Can be empty if absent from the chain.
     * @param vendorId - VendorID to use for the new fabric
     * @param outNewFabricIndex - Pointer where the new fabric index for the fabric just added will be set. Cannot be nullptr.
     *
     * @retval CHIP_NO_ERROR on success.
     * @retval CHIP_ERROR_INCORRECT_STATE if this is called in an inconsistent order.
     * @retval CHIP_ERROR_NO_MEMORY if there is insufficient memory to make the fabric pending.
     * @retval CHIP_ERROR_INVALID_ARGUMENT if any of the arguments are invalid such as too large or out of bounds.
     * @retval CHIP_ERROR_FABRIC_EXISTS if operational identity collides with one already present.
     * @retval other CHIP_ERROR_* on internal errors or certificate validation errors.
     */
    CHIP_ERROR AddNewPendingFabricWithOperationalKeystore(const ByteSpan & noc, const ByteSpan & icac, uint16_t vendorId,
                                                          FabricIndex * outNewFabricIndex)
    {
        return AddNewPendingFabricCommon(noc, icac, vendorId, nullptr, false, outNewFabricIndex);
    };

    /**
     * @brief Use an NOC and optional ICAC chaining back to the pending RCAC to activate a new fabric
     *
     * Operational key is injected, and then owned by the fabric (!isExistingOpKeyExternallyOwned) or
     * owned externally if `isExistingOpKeyExternallyOwned` is true).
     *
     * WARNING: Copying keypairs is unsafe and not recommended. Consider using
     *          AddNewPendingFabricWithOperationalKeystore and an associated OperationalKeystore
     *          or always using `isExistingOpKeyExternallyOwned`, with `existingOpKey` being a safe
     *          class derived from P256Keypair that avoids the true private key persisting in memory.
     *
     * For rest of semantics outside of operational key, @see AddNewPendingFabricWithOperationalKeystore
     *
     * @param noc - NOC for the fabric. Public key must match the `existingOpKey`'s public key
     * @param icac - ICAC for the fabric. Can be empty if absent from the chain.
     * @param vendorId - VendorID to use for the new fabric
     * @param existingOpKey - Existing operational key to ingest for use in the fabric. Cannot be nullptr.
     * @param isExistingOpKeyExternallyOwned - if true, operational key must outlive the fabric. If false, the key is
     *                                         copied using P256Keypair::Serialize/Deserialize and owned in heap of a FabricInfo.
     * @param outNewFabricIndex - Pointer where the new fabric index for the fabric just added will be set. Cannot be nullptr.
     *
     * @retval CHIP_NO_ERROR on success.
     * @retval CHIP_ERROR_INCORRECT_STATE if this is called in an inconsistent order.
     * @retval CHIP_ERROR_NO_MEMORY if there is insufficient memory to make the fabric pending.
     * @retval CHIP_ERROR_INVALID_ARGUMENT if any of the arguments are invalid such as too large or out of bounds.
     * @retval CHIP_ERROR_FABRIC_EXISTS if operational identity collides with one already present.
     * @retval other CHIP_ERROR_* on internal errors or certificate validation errors.
     */
    CHIP_ERROR AddNewPendingFabricWithProvidedOpKey(const ByteSpan & noc, const ByteSpan & icac, uint16_t vendorId,
                                                    Crypto::P256Keypair * existingOpKey, bool isExistingOpKeyExternallyOwned,
                                                    FabricIndex * outNewFabricIndex)
    {
        return AddNewPendingFabricCommon(noc, icac, vendorId, existingOpKey, isExistingOpKeyExternallyOwned, outNewFabricIndex);
    };

    /**
     * @brief Use an NOC and optional ICAC to update an existing fabric
     *
     * Operational key is assumed to be pending or committed in the associated mOperationalKeystore.
     *
     * The new NOC chain becomes temporarily active for purposes of `Fetch*` and `SignWithOpKeyPair`, etc.
     * The RCAC remains as before. For this method call to succeed, NOC chain must chain back to the existing RCAC.
     * The update fabric becomes permanent/persisted on successful `CommitPendingFabricData`. Changes revert
     * on `RevertPendingFabricData` or `RevertPendingOpCertsExceptRoot`. FabricId CANNOT be updated, but
     * CAT tags and Node ID in NOC can change between previous and new NOC for a given FabricId.
     *
     * This method with fail with CHIP_ERROR_INCORRECT_STATE in a variety of illogical/inconsistent conditions,
     * which always can be cleared with `RevertPendingFabricData`. Such a situation is calling this method after
     * `AddNewPending*` which would mean logical collision of an addition and an update.
     *
     * If a pending key was present in the OperationalKeystore associated with this FabricTable,
     * it is activated on success.
     *
     * @param fabricIndex - fabricIndex of the existing fabric to update
     * @param noc - Updated NOC for the fabric. Must match an existing or pending operational keypair in the mOperationalKeystore.
     * @param icac - Update ICAC for the fabric. Can be empty if absent from the chain.
     *
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_INVALID_FABRIC_INDEX if the `fabricIndex` is not an existing fabric
     * @retval CHIP_ERROR_INCORRECT_STATE if this is called in an inconsistent order
     * @retval CHIP_ERROR_NO_MEMORY if there is insufficient memory to store the pending updates
     * @retval CHIP_ERROR_INVALID_ARGUMENT if any of the arguments are invalid such as too large or out of bounds.
     * @retval other CHIP_ERROR_* on internal errors or certificate validation errors.
     */
    CHIP_ERROR UpdatePendingFabricWithOperationalKeystore(FabricIndex fabricIndex, const ByteSpan & noc, const ByteSpan & icac)
    {
        return UpdatePendingFabricCommon(fabricIndex, noc, icac, nullptr, false);
    }

    /**
     * @brief Use an NOC and optional ICAC to update an existing fabric
     *
     * Operational key is injected, and then owned by the fabric (!isExistingOpKeyExternallyOwned) or
     * owned externally if `isExistingOpKeyExternallyOwned` is true).
     *
     * WARNING: Copying keypairs is unsafe and not recommended. Consider using
     *          AddNewPendingFabricWithOperationalKeystore and an associated OperationalKeystore
     *          or always using `isExistingOpKeyExternallyOwned`, with `existingOpKey` being a safe
     *          class derived from P256Keypair that avoids the true private key persisting in memory.
     *
     * For rest of semantics outside of operational key, @see UpdatePendingFabricWithOperationalKeystore
     *
     * @param fabricIndex - fabricIndex of the existing fabric to update
     * @param noc - Updated NOC for the fabric. Must match an existing or pending operational keypair in the mOperationalKeystore.
     * @param icac - Update ICAC for the fabric. Can be empty if absent from the chain.
     * @param existingOpKey - Existing operational key to ingest for use in the fabric with new NOC. Cannot be nullptr.
     * @param isExistingOpKeyExternallyOwned - if true, operational key must outlive the fabric. If false, the key is
     *                                         copied using P256Keypair::Serialize/Deserialize and owned in heap of a FabricInfo.
     *
     * @retval CHIP_NO_ERROR on success
     * @retval CHIP_ERROR_INVALID_FABRIC_INDEX if the `fabricIndex` is not an existing fabric
     * @retval CHIP_ERROR_INCORRECT_STATE if this is called in an inconsistent order
     * @retval CHIP_ERROR_NO_MEMORY if there is insufficient memory to store the pending updates
     * @retval CHIP_ERROR_INVALID_ARGUMENT if any of the arguments are invalid such as too large or out of bounds.
     * @retval other CHIP_ERROR_* on internal errors or certificate validation errors.
     */

    CHIP_ERROR UpdatePendingFabricWithProvidedOpKey(FabricIndex fabricIndex, const ByteSpan & noc, const ByteSpan & icac,
                                                    Crypto::P256Keypair * existingOpKey, bool isExistingOpKeyExternallyOwned)
    {
        return UpdatePendingFabricCommon(fabricIndex, noc, icac, existingOpKey, isExistingOpKeyExternallyOwned);
    }

    /**
     * @brief Commit any pending temporary FabricTable state. This is used mostly for affecting
     *        CommissioningComplete.
     *
     * On success, any pending information is committed such that after a restart, it would
     * be found to be the same in persistent storage.
     *
     * If no changes were pending and state is internally consistent, this appears as a no-op and returns
     * CHIP_NO_ERROR.
     *
     * If there is any internally inconsistent state, this methods acts the same as RevertPendingFabricData(),
     * and all state is lost.
     *
     * In rare circumstances, and depending on the storage backend for opcerts and operational keys,
     * an inconsistent state could be left, such as if restarting during storage writes of
     * CommitPendingFabricData(). If this happens, the next FabricTable::Init() will attempt
     * to clean-up the pieces.
     *
     * @return CHIP_NO_ERROR on success or any other CHIP_ERROR value on internal errors
     */
    CHIP_ERROR CommitPendingFabricData();

    /**
     * @brief Revert any pending state.
     *
     * This is used to handle fail-safe expiry of partially configured fabrics, or to recover
     * from situations where partial state was written and configuration cannot continue properly.
     *
     * All pending certificates and operational keys and pending fabric metadata are cleared.
     */
    void RevertPendingFabricData();

    /**
     * @brief Revert only the pending NOC/ICAC and pending added fabric, not RCAC. Used for error handling
     *        during commissioning.
     */
    void RevertPendingOpCertsExceptRoot();

    // Verifies credentials, using the root certificate of the provided fabric index.
    CHIP_ERROR VerifyCredentials(FabricIndex fabricIndex, const ByteSpan & noc, const ByteSpan & icac,
                                 Credentials::ValidationContext & context, CompressedFabricId & outCompressedFabricId,
                                 FabricId & outFabricId, NodeId & outNodeId, Crypto::P256PublicKey & outNocPubkey,
                                 Crypto::P256PublicKey * outRootPublicKey = nullptr) const;

    // Verifies credentials, using the provided root certificate.
    static CHIP_ERROR VerifyCredentials(const ByteSpan & noc, const ByteSpan & icac, const ByteSpan & rcac,
                                        Credentials::ValidationContext & context, CompressedFabricId & outCompressedFabricId,
                                        FabricId & outFabricId, NodeId & outNodeId, Crypto::P256PublicKey & outNocPubkey,
                                        Crypto::P256PublicKey * outRootPublicKey = nullptr);
    /**
     * @brief Enables FabricInfo instances to collide and reference the same logical fabric (i.e Root Public Key + FabricId).
     *
     * *WARNING* This is ONLY to be used when creating multiple controllers on the same fabric OR for test.
     *
     */
    void PermitCollidingFabrics() { mStateFlags.Set(StateFlags::kAreCollidingFabricsIgnored); }

    // Add a new fabric for testing. The Operational Key is a raw P256Keypair (public key and private key raw bits) that will
    // get copied (directly) into the fabric table.
    CHIP_ERROR AddNewFabricForTest(const ByteSpan & rootCert, const ByteSpan & icacCert, const ByteSpan & nocCert,
                                   const ByteSpan & opKeySpan, FabricIndex * outFabricIndex);

    // Same as AddNewFabricForTest, but ignore if we are colliding with same <Root Public Key, Fabric Id>, so
    // that a single fabric table can have N nodes for same fabric. This usually works, but is bad form.
    CHIP_ERROR AddNewFabricForTestIgnoringCollisions(const ByteSpan & rootCert, const ByteSpan & icacCert, const ByteSpan & nocCert,
                                                     const ByteSpan & opKeySpan, FabricIndex * outFabricIndex)
    {
        PermitCollidingFabrics();
        CHIP_ERROR err = AddNewFabricForTest(rootCert, icacCert, nocCert, opKeySpan, outFabricIndex);
        mStateFlags.Clear(StateFlags::kAreCollidingFabricsIgnored);
        return err;
    }

    // For test only. See definition of `StateFlags::kAbortCommitForTest`.
    void SetForceAbortCommitForTest(bool abortCommitForTest)
    {
        (void) abortCommitForTest;
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
        if (abortCommitForTest)
        {
            mStateFlags.Set(StateFlags::kAbortCommitForTest);
        }
        else
        {
            mStateFlags.Clear(StateFlags::kAbortCommitForTest);
        }
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
    }

private:
    enum class StateFlags : uint16_t
    {
        // If true, we are in the process of a fail-safe and there was at least one
        // operation that caused partial data in the fabric table.
        kIsPendingFabricDataPresent = (1u << 0),
        kIsTrustedRootPending       = (1u << 1),
        kIsUpdatePending            = (1u << 2),
        kIsAddPending               = (1u << 3),

        // Only true when `AllocatePendingOperationalKey` has been called
        kIsOperationalKeyPending = (1u << 4),
        // True if `AllocatePendingOperationalKey` was for an existing fabric
        kIsPendingKeyForUpdateNoc = (1u << 5),

        // True if we allow more than one fabric with same root and fabricId in the fabric table
        // for test purposes. This disables a collision check.
        kAreCollidingFabricsIgnored = (1u << 6),

        // If set to true (only possible on test builds), will cause `CommitPendingFabricData()` to early
        // return during commit, skipping clean-ups, so that we can validate commit marker fabric removal.
        kAbortCommitForTest = (1u << 7),
    };

    // Stored to indicate a commit is in progress, so that it can be cleaned-up on next boot
    // if stopped in the middle.
    struct CommitMarker
    {
        CommitMarker() = default;
        CommitMarker(FabricIndex fabricIndex_, bool isAddition_)
        {
            this->fabricIndex = fabricIndex_;
            this->isAddition  = isAddition_;
        }
        FabricIndex fabricIndex = kUndefinedFabricIndex;
        bool isAddition         = false;
    };

    /**
     * @brief Get a mutable FabricInfo entry from the table by FabricIndex.
     *
     * NOTE: This is private for use within the FabricTable itself. All mutations have to go through the
     *       FabricTable public methods that take a FabricIndex so that there are no mutations about which
     *       the FabricTable is unaware, since this would break expectations regarding shadow/pending
     *       entries used during fail-safe.
     *
     * @param fabricIndex - fabric index for which to get a mutable FabricInfo entry
     * @return the FabricInfo entry for the fabricIndex if found, or nullptr if not found
     */
    FabricInfo * GetMutableFabricByIndex(FabricIndex fabricIndex);

    // Load a FabricInfo metatada item from storage for a given new fabric index. Returns internal error on failure.
    CHIP_ERROR LoadFromStorage(FabricInfo * fabric, FabricIndex newFabricIndex);

    // Store a given fabric metadata directly/immediately. Used by internal operations.
    CHIP_ERROR StoreFabricMetadata(const FabricInfo * fabricInfo) const;

    // Tries to set `mFabricIndexWithPendingState` and returns false if there's a clash.
    bool SetPendingDataFabricIndex(FabricIndex fabricIndex);

    // Core validation logic for fabric additions/updates
    CHIP_ERROR AddOrUpdateInner(FabricIndex fabricIndex, bool isAddition, Crypto::P256Keypair * existingOpKey,
                                bool isExistingOpKeyExternallyOwned, uint16_t vendorId);

    // Common code for fabric addition, for either OperationalKeystore or injected key scenarios.
    CHIP_ERROR AddNewPendingFabricCommon(const ByteSpan & noc, const ByteSpan & icac, uint16_t vendorId,
                                         Crypto::P256Keypair * existingOpKey, bool isExistingOpKeyExternallyOwned,
                                         FabricIndex * outNewFabricIndex);

    // Common code for fabric updates, for either OperationalKeystore or injected key scenarios.
    CHIP_ERROR UpdatePendingFabricCommon(FabricIndex fabricIndex, const ByteSpan & noc, const ByteSpan & icac,
                                         Crypto::P256Keypair * existingOpKey, bool isExistingOpKeyExternallyOwned);

    // Common code for looking up a fabric given a root public key, a fabric ID and an optional node id scoped to that fabric.
    const FabricInfo * FindFabricCommon(const Crypto::P256PublicKey & rootPubKey, FabricId fabricId,
                                        NodeId nodeId = kUndefinedNodeId) const;

    /**
     * UpdateNextAvailableFabricIndex should only be called when
     * mNextAvailableFabricIndex has a value and that value stops being
     * available.  It will set mNextAvailableFabricIndex to the next available
     * value, or no value if there is none available.
     */
    void UpdateNextAvailableFabricIndex();

    /**
     * Ensure that we have a valid next available fabric index, if that's at all possible.  This covers
     * some FabricIndex allocation corner cases.  After this is called, the only way we can fail to have
     * a next available fabric index is if our fabric table is max-sized (254 entries) and full.
     */
    void EnsureNextAvailableFabricIndexUpdated();

    /**
     * Store our current fabric index state: what our next available index is
     * and what indices we're using right now.
     */
    CHIP_ERROR StoreFabricIndexInfo() const;

    /**
     * @brief Delete all metadata from storage for the given fabric
     *
     * @param fabricIndex FabricIndex for which to delete the metadadata
     * @return CHIP_NO_ERROR on success or another CHIP_ERROR on failure
     */
    CHIP_ERROR DeleteMetadataFromStorage(FabricIndex fabricIndex);

    /**
     * @brief Determine if a collision (undesired on AddNOC, necessary on UpdateNOC) exists
     *        between the FabricID in the given noc, and the RCAC found for `currentFabricIndex`
     *        in the op cert store, against an existing fabric in the FabricTable (which could be pending)
     *
     * @param currentFabricIndex - pending fabricIndex for which we are trying to Add/Update a NOC
     * @param noc - NOC cert received that contains FabricID whose collision we care to validate
     * @param outMatchingFabricIndex - set to the FabricIndex matching the collision or kUndefinedFabricIndex on no collision found
     * @return CHIP_NO_ERROR on successful update of outMatchingFabricIndex or other CHIP_ERROR on internal errors
     */
    CHIP_ERROR FindExistingFabricByNocChaining(FabricIndex currentFabricIndex, const ByteSpan & noc,
                                               FabricIndex & outMatchingFabricIndex) const;

    /**
     * @brief Get the shadow FabricInfo entry that is pending for updates, if an
     *        update is in progress.
     *
     * @return a pointer to the shadow pending fabric or nullptr if none is active.
     */
    const FabricInfo * GetShadowPendingFabricEntry() const { return HasPendingFabricUpdate() ? &mPendingFabric : nullptr; }

    // Returns true if we have a shadow entry pending for a fabric update.
    bool HasPendingFabricUpdate() const
    {
        return mPendingFabric.IsInitialized() &&
            mStateFlags.HasAll(StateFlags::kIsPendingFabricDataPresent, StateFlags::kIsUpdatePending);
    }

    // Validate an NOC chain at time of adding/updating a fabric (uses VerifyCredentials with additional checks).
    // The `existingFabricId` is passed for UpdateNOC, and must match the Fabric, to make sure that we are
    // not trying to change FabricID with UpdateNOC. If set to kUndefinedFabricId, we are doing AddNOC and
    // we don't need to check match to pre-existing fabric.
    static CHIP_ERROR 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);

    /**
     * Read our fabric index info from the given TLV reader and set up the
     * fabric table accordingly.
     */
    CHIP_ERROR ReadFabricInfo(TLV::ContiguousBufferTLVReader & reader);

    CHIP_ERROR NotifyFabricUpdated(FabricIndex fabricIndex);
    CHIP_ERROR NotifyFabricCommitted(FabricIndex fabricIndex);

    // Commit management clean-up APIs
    CHIP_ERROR StoreCommitMarker(const CommitMarker & commitMarker);
    CHIP_ERROR GetCommitMarker(CommitMarker & outCommitMarker);

    FabricInfo mStates[CHIP_CONFIG_MAX_FABRICS];
    // Used for UpdateNOC pending fabric updates
    FabricInfo mPendingFabric;
    PersistentStorageDelegate * mStorage                    = nullptr;
    Crypto::OperationalKeystore * mOperationalKeystore      = nullptr;
    Credentials::OperationalCertificateStore * mOpCertStore = nullptr;

    // FabricTable::Delegate link to first node, since FabricTable::Delegate is a form
    // of intrusive linked-list item.
    FabricTable::Delegate * mDelegateListRoot = nullptr;

    // When mStateFlags.Has(kIsPendingFabricDataPresent) is true, this holds the index of the fabric
    // for which there is currently pending data.
    FabricIndex mFabricIndexWithPendingState = kUndefinedFabricIndex;

    // For when a revert occurs during init, so that more clean-up can be scheduled by caller.
    FabricIndex mDeletedFabricIndexFromInit = kUndefinedFabricIndex;

    LastKnownGoodTime mLastKnownGoodTime;

    // We may not have an mNextAvailableFabricIndex if our table is as large as
    // it can go and is full.
    Optional<FabricIndex> mNextAvailableFabricIndex;
    uint8_t mFabricCount = 0;

    BitFlags<StateFlags> mStateFlags;
};

} // namespace chip
