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

    bool ShouldAdvertiseIdentity() const { return mShouldAdvertiseIdentity; }

    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;
        bool advertiseIdentity                   = 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;
        mHasExternallyOwnedOperationalKey = false;
        mShouldAdvertiseIdentity          = true;

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

    // mFabricLabel is 33 bytes, so ends on a 1 mod 4 byte boundary.
    char mFabricLabel[kFabricLabelMaxLengthInBytes + 1] = { '\0' };

    // mFabricIndex, mVendorId, mHasExternallyOwnedOperationalKey,
    // mShouldAdvertiseIdentity are 5 bytes and do not include any padding if
    // they come after the 33-byte mFabricLabel, so end on a 2 mod 4 byte
    // boundary.
    FabricIndex mFabricIndex               = kUndefinedFabricIndex;
    VendorId mVendorId                     = VendorId::NotSpecified;
    bool mHasExternallyOwnedOperationalKey = false;
    bool mShouldAdvertiseIdentity          = true;

    // 2 bytes of padding here, since mOperationalKey needs to be void*-aligned,
    // so has to be at a 0 mod 4 byte location.

    mutable Crypto::P256Keypair * mOperationalKey = nullptr;

    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;

    enum class AdvertiseIdentity : uint8_t
    {
        Yes,
        No
    };

    // 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,
                                                          AdvertiseIdentity advertiseIdentity = AdvertiseIdentity::Yes)
    {
        return AddNewPendingFabricCommon(noc, icac, vendorId, nullptr, false, advertiseIdentity, 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,
                                                    AdvertiseIdentity advertiseIdentity = AdvertiseIdentity::Yes)
    {
        return AddNewPendingFabricCommon(noc, icac, vendorId, existingOpKey, isExistingOpKeyExternallyOwned, advertiseIdentity,
                                         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,
                                                          AdvertiseIdentity advertiseIdentity = AdvertiseIdentity::Yes)
    {
        return UpdatePendingFabricCommon(fabricIndex, noc, icac, nullptr, false, advertiseIdentity);
    }

    /**
     * @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,
                                                    AdvertiseIdentity advertiseIdentity = AdvertiseIdentity::Yes)
    {
        return UpdatePendingFabricCommon(fabricIndex, noc, icac, existingOpKey, isExistingOpKeyExternallyOwned, advertiseIdentity);
    }

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

    /**
     * Get the fabric index that will be used for the next fabric that will be
     * added.  Returns error if no more fabrics can be added, otherwise writes
     * the fabric index that will be used for the next addition into the
     * outparam.
     */
    CHIP_ERROR PeekFabricIndexForNextAddition(FabricIndex & outIndex);

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, AdvertiseIdentity advertiseIdentity);

    // 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,
                                         AdvertiseIdentity advertiseIdentity, 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,
                                         AdvertiseIdentity advertiseIdentity);

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