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

/****************************************************************************
 * @file
 * @brief Implementation for the Operational Credentials Cluster
 ***************************************************************************/

#include <access/AccessControl.h>
#include <app-common/zap-generated/af-structs.h>
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/enums.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app/AttributeAccessInterface.h>
#include <app/CommandHandler.h>
#include <app/ConcreteCommandPath.h>
#include <app/EventLogging.h>
#include <app/InteractionModelEngine.h>
#include <app/reporting/reporting.h>
#include <app/server/Dnssd.h>
#include <app/server/Server.h>
#include <app/util/af.h>
#include <app/util/attribute-storage.h>
#include <credentials/CHIPCert.h>
#include <credentials/CertificationDeclaration.h>
#include <credentials/DeviceAttestationConstructor.h>
#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/FabricTable.h>
#include <credentials/GroupDataProvider.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/core/PeerId.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ScopedBuffer.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <string.h>
#include <trace/trace.h>

using namespace chip;
using namespace ::chip::Transport;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::OperationalCredentials;
using namespace chip::Credentials;
using namespace chip::Protocols::InteractionModel;

namespace {

void SendNOCResponse(app::CommandHandler * commandObj, const ConcreteCommandPath & path, OperationalCertStatus status,
                     uint8_t index, const CharSpan & debug_text);
OperationalCertStatus ConvertToNOCResponseStatus(CHIP_ERROR err);

constexpr uint8_t kDACCertificate = 1;
constexpr uint8_t kPAICertificate = 2;

CHIP_ERROR CreateAccessControlEntryForNewFabricAdministrator(const Access::SubjectDescriptor & subjectDescriptor,
                                                             FabricIndex fabricIndex, uint64_t subject)
{
    NodeId subjectAsNodeID = static_cast<NodeId>(subject);

    if (!IsOperationalNodeId(subjectAsNodeID) && !IsCASEAuthTag(subjectAsNodeID))
    {
        return CHIP_ERROR_INVALID_ADMIN_SUBJECT;
    }

    Access::AccessControl::Entry entry;
    ReturnErrorOnFailure(Access::GetAccessControl().PrepareEntry(entry));
    ReturnErrorOnFailure(entry.SetFabricIndex(fabricIndex));
    ReturnErrorOnFailure(entry.SetPrivilege(Access::Privilege::kAdminister));
    ReturnErrorOnFailure(entry.SetAuthMode(Access::AuthMode::kCase));
    ReturnErrorOnFailure(entry.AddSubject(nullptr, subject));
    CHIP_ERROR err = Access::GetAccessControl().CreateEntry(&subjectDescriptor, fabricIndex, nullptr, entry);

    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Zcl, "OpCreds: Failed to add administrative node ACL entry: %" CHIP_ERROR_FORMAT, err.Format());
        return err;
    }

    ChipLogProgress(Zcl, "OpCreds: ACL entry created for Fabric index 0x%x CASE Admin Subject 0x" ChipLogFormatX64,
                    static_cast<unsigned>(fabricIndex), ChipLogValueX64(subject));

    return CHIP_NO_ERROR;
}

class OperationalCredentialsAttrAccess : public AttributeAccessInterface
{
public:
    // Register for the OperationalCredentials cluster on all endpoints.
    OperationalCredentialsAttrAccess() :
        AttributeAccessInterface(Optional<EndpointId>::Missing(), Clusters::OperationalCredentials::Id)
    {}

    CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;

private:
    CHIP_ERROR ReadNOCs(EndpointId endpoint, AttributeValueEncoder & aEncoder);
    CHIP_ERROR ReadSupportedFabrics(EndpointId endpoint, AttributeValueEncoder & aEncoder);
    CHIP_ERROR ReadCommissionedFabrics(EndpointId endpoint, AttributeValueEncoder & aEncoder);
    CHIP_ERROR ReadFabricsList(EndpointId endpoint, AttributeValueEncoder & aEncoder);
    CHIP_ERROR ReadRootCertificates(EndpointId endpoint, AttributeValueEncoder & aEncoder);
};

CHIP_ERROR OperationalCredentialsAttrAccess::ReadNOCs(EndpointId endpoint, AttributeValueEncoder & aEncoder)
{
    auto accessingFabricIndex = aEncoder.AccessingFabricIndex();

    return aEncoder.EncodeList([accessingFabricIndex](const auto & encoder) -> CHIP_ERROR {
        const auto & fabricTable = Server::GetInstance().GetFabricTable();
        for (const auto & fabricInfo : fabricTable)
        {
            Clusters::OperationalCredentials::Structs::NOCStruct::Type noc;
            uint8_t nocBuf[kMaxCHIPCertLength];
            uint8_t icacBuf[kMaxCHIPCertLength];
            MutableByteSpan nocSpan{ nocBuf };
            MutableByteSpan icacSpan{ icacBuf };
            FabricIndex fabricIndex = fabricInfo.GetFabricIndex();

            noc.fabricIndex = fabricIndex;

            if (accessingFabricIndex == fabricIndex)
            {

                ReturnErrorOnFailure(fabricTable.FetchNOCCert(fabricIndex, nocSpan));
                ReturnErrorOnFailure(fabricTable.FetchICACert(fabricIndex, icacSpan));

                noc.noc = nocSpan;
                if (!icacSpan.empty())
                {
                    noc.icac.SetNonNull(icacSpan);
                }
            }

            ReturnErrorOnFailure(encoder.Encode(noc));
        }

        return CHIP_NO_ERROR;
    });
}

CHIP_ERROR OperationalCredentialsAttrAccess::ReadSupportedFabrics(EndpointId endpoint, AttributeValueEncoder & aEncoder)
{
    uint8_t fabricCount = CHIP_CONFIG_MAX_FABRICS;

    return aEncoder.Encode(fabricCount);
}

CHIP_ERROR OperationalCredentialsAttrAccess::ReadCommissionedFabrics(EndpointId endpoint, AttributeValueEncoder & aEncoder)
{
    return aEncoder.Encode(Server::GetInstance().GetFabricTable().FabricCount());
}

CHIP_ERROR OperationalCredentialsAttrAccess::ReadFabricsList(EndpointId endpoint, AttributeValueEncoder & aEncoder)
{
    return aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR {
        const auto & fabricTable = Server::GetInstance().GetFabricTable();

        for (const auto & fabricInfo : fabricTable)
        {
            Clusters::OperationalCredentials::Structs::FabricDescriptor::Type fabricDescriptor;
            FabricIndex fabricIndex = fabricInfo.GetFabricIndex();

            fabricDescriptor.fabricIndex = fabricIndex;
            fabricDescriptor.nodeId      = fabricInfo.GetPeerId().GetNodeId();
            fabricDescriptor.vendorId    = fabricInfo.GetVendorId();
            fabricDescriptor.fabricId    = fabricInfo.GetFabricId();

            fabricDescriptor.label = fabricInfo.GetFabricLabel();

            Crypto::P256PublicKey pubKey;
            ReturnErrorOnFailure(fabricTable.FetchRootPubkey(fabricIndex, pubKey));
            fabricDescriptor.rootPublicKey = ByteSpan{ pubKey.ConstBytes(), pubKey.Length() };

            ReturnErrorOnFailure(encoder.Encode(fabricDescriptor));
        }

        return CHIP_NO_ERROR;
    });
}

CHIP_ERROR OperationalCredentialsAttrAccess::ReadRootCertificates(EndpointId endpoint, AttributeValueEncoder & aEncoder)
{
    // It is OK to have duplicates.
    return aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR {
        const auto & fabricTable = Server::GetInstance().GetFabricTable();

        for (const auto & fabricInfo : fabricTable)
        {
            uint8_t certBuf[kMaxCHIPCertLength];
            MutableByteSpan cert{ certBuf };
            ReturnErrorOnFailure(fabricTable.FetchRootCert(fabricInfo.GetFabricIndex(), cert));
            ReturnErrorOnFailure(encoder.Encode(ByteSpan{ cert }));
        }

        {
            uint8_t certBuf[kMaxCHIPCertLength];
            MutableByteSpan cert{ certBuf };
            CHIP_ERROR err = fabricTable.FetchPendingNonFabricAssociatedRootCert(cert);
            if (err == CHIP_ERROR_NOT_FOUND)
            {
                // No pending root cert, do nothing
            }
            else if (err != CHIP_NO_ERROR)
            {
                return err;
            }
            else
            {
                ReturnErrorOnFailure(encoder.Encode(ByteSpan{ cert }));
            }
        }

        return CHIP_NO_ERROR;
    });
}

OperationalCredentialsAttrAccess gAttrAccess;

CHIP_ERROR OperationalCredentialsAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
    VerifyOrDie(aPath.mClusterId == Clusters::OperationalCredentials::Id);

    switch (aPath.mAttributeId)
    {
    case Attributes::NOCs::Id: {
        return ReadNOCs(aPath.mEndpointId, aEncoder);
    }
    case Attributes::SupportedFabrics::Id: {
        return ReadSupportedFabrics(aPath.mEndpointId, aEncoder);
    }
    case Attributes::CommissionedFabrics::Id: {
        return ReadCommissionedFabrics(aPath.mEndpointId, aEncoder);
    }
    case Attributes::Fabrics::Id: {
        return ReadFabricsList(aPath.mEndpointId, aEncoder);
    }
    case Attributes::TrustedRootCertificates::Id: {
        return ReadRootCertificates(aPath.mEndpointId, aEncoder);
    }
    case Attributes::CurrentFabricIndex::Id: {
        return aEncoder.Encode(aEncoder.AccessingFabricIndex());
    }
    default:
        break;
    }

    return CHIP_NO_ERROR;
}

const FabricInfo * RetrieveCurrentFabric(CommandHandler * aCommandHandler)
{
    FabricIndex index = aCommandHandler->GetAccessingFabricIndex();
    ChipLogDetail(Zcl, "OpCreds: Finding fabric with fabricIndex 0x%x", static_cast<unsigned>(index));
    return Server::GetInstance().GetFabricTable().FindFabricWithIndex(index);
}

CHIP_ERROR DeleteFabricFromTable(FabricIndex fabricIndex)
{
    ReturnErrorOnFailure(Server::GetInstance().GetFabricTable().Delete(fabricIndex));

    // We need to withdraw the advertisement for the now-removed fabric, so need
    // to restart advertising altogether.
    app::DnssdServer::Instance().StartServer();

    return CHIP_NO_ERROR;
}

void CleanupSessionsForFabric(SessionManager & sessionMgr, FabricIndex fabricIndex)
{
    InteractionModelEngine::GetInstance()->CloseTransactionsFromFabricIndex(fabricIndex);
    sessionMgr.ExpireAllSessionsForFabric(fabricIndex);
}

void FailSafeCleanup(const chip::DeviceLayer::ChipDeviceEvent * event)
{
    ChipLogError(Zcl, "OpCreds: Proceeding to FailSafeCleanup on fail-safe expiry!");

    FabricIndex fabricIndex = event->FailSafeTimerExpired.fabricIndex;

    // If an AddNOC or UpdateNOC command has been successfully invoked, terminate all CASE sessions associated with the Fabric
    // whose Fabric Index is recorded in the Fail-Safe context (see ArmFailSafe Command) by clearing any associated Secure
    // Session Context at the Server.
    if (event->FailSafeTimerExpired.addNocCommandHasBeenInvoked || event->FailSafeTimerExpired.updateNocCommandHasBeenInvoked)
    {
        // TODO(#19259): The following scope will no longer need to exist after #19259 is fixed
        {
            CASESessionManager * caseSessionManager = Server::GetInstance().GetCASESessionManager();
            if (caseSessionManager)
            {
                const FabricInfo * fabricInfo = Server::GetInstance().GetFabricTable().FindFabricWithIndex(fabricIndex);
                VerifyOrReturn(fabricInfo != nullptr);

                caseSessionManager->ReleaseSessionsForFabric(fabricInfo->GetFabricIndex());
            }
        }

        SessionManager & sessionMgr = Server::GetInstance().GetSecureSessionManager();
        CleanupSessionsForFabric(sessionMgr, fabricIndex);
    }

    auto & fabricTable = Server::GetInstance().GetFabricTable();
    fabricTable.RevertPendingFabricData();

    // If an AddNOC command had been successfully invoked, achieve the equivalent effect of invoking the RemoveFabric command
    // against the Fabric Index stored in the Fail-Safe Context for the Fabric Index that was the subject of the AddNOC
    // command.
    if (event->FailSafeTimerExpired.addNocCommandHasBeenInvoked)
    {
        CHIP_ERROR err;
        err = DeleteFabricFromTable(fabricIndex);
        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(Zcl, "OpCreds: failed to delete fabric at index %u: %" CHIP_ERROR_FORMAT, fabricIndex, err.Format());
        }
    }
}

void OnPlatformEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
{
    if (event->Type == DeviceLayer::DeviceEventType::kFailSafeTimerExpired)
    {
        ChipLogError(Zcl, "OpCreds: Got FailSafeTimerExpired");
        FailSafeCleanup(event);
    }
}

} // anonymous namespace

// As per specifications section 11.22.5.1. Constant RESP_MAX
constexpr size_t kMaxRspLen = 900;

class OpCredsFabricTableDelegate : public chip::FabricTable::Delegate
{
public:
    // Gets called when a fabric is about to be deleted
    void FabricWillBeRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override
    {
        // The Leave event SHOULD be emitted by a Node prior to permanently leaving the Fabric.
        for (auto endpoint : EnabledEndpointsWithServerCluster(Basic::Id))
        {
            // If Basic cluster is implemented on this endpoint
            Basic::Events::Leave::Type event;
            event.fabricIndex = fabricIndex;
            EventNumber eventNumber;

            if (CHIP_NO_ERROR != LogEvent(event, endpoint, eventNumber))
            {
                ChipLogError(Zcl, "OpCredsFabricTableDelegate: Failed to record Leave event");
            }
        }

        // Try to send the queued events as soon as possible. If the just emitted leave event won't
        // be sent this time, it will likely not be delivered at all for the following reasons:
        // - removing the fabric expires all associated ReadHandlers, so all subscriptions to
        //   the leave event will be cancelled.
        // - removing the fabric removes all associated access control entries, so generating
        //   subsequent reports containing the leave event will fail the access control check.
        InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleUrgentEventDeliverySync();
    }

    // Gets called when a fabric is deleted
    void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override
    {
        ChipLogProgress(Zcl, "OpCreds: Fabric index 0x%x was removed", static_cast<unsigned>(fabricIndex));

        EventManagement::GetInstance().FabricRemoved(fabricIndex);
        NotifyFabricTableChanged();
    }

    // Gets called when a fabric is added/updated, but not necessarily committed to storage
    void OnFabricUpdated(const FabricTable & fabricTable, FabricIndex fabricIndex) override { NotifyFabricTableChanged(); }

    // Gets called when a fabric in FabricTable is persisted to storage
    void OnFabricCommitted(const FabricTable & fabricTable, FabricIndex fabricIndex) override
    {
        const FabricInfo * fabric = fabricTable.FindFabricWithIndex(fabricIndex);
        // Safety check, but should not happen by the code paths involved
        VerifyOrReturn(fabric != nullptr);

        ChipLogProgress(Zcl,
                        "OpCreds: Fabric index 0x%x was committed to storage. Compressed Fabric Id 0x" ChipLogFormatX64
                        ", FabricId " ChipLogFormatX64 ", NodeId " ChipLogFormatX64 ", VendorId 0x%04X",
                        static_cast<unsigned>(fabric->GetFabricIndex()), ChipLogValueX64(fabric->GetCompressedFabricId()),
                        ChipLogValueX64(fabric->GetFabricId()), ChipLogValueX64(fabric->GetNodeId()), fabric->GetVendorId());
    }

private:
    void NotifyFabricTableChanged()
    {
        // Opcreds cluster is always on Endpoint 0
        MatterReportingAttributeChangeCallback(0, OperationalCredentials::Id,
                                               OperationalCredentials::Attributes::CommissionedFabrics::Id);
        MatterReportingAttributeChangeCallback(0, OperationalCredentials::Id, OperationalCredentials::Attributes::Fabrics::Id);
    }
};

OpCredsFabricTableDelegate gFabricDelegate;

void MatterOperationalCredentialsPluginServerInitCallback(void)
{
    registerAttributeAccessOverride(&gAttrAccess);

    Server::GetInstance().GetFabricTable().AddFabricDelegate(&gFabricDelegate);

    DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler);
}

bool emberAfOperationalCredentialsClusterRemoveFabricCallback(app::CommandHandler * commandObj,
                                                              const app::ConcreteCommandPath & commandPath,
                                                              const Commands::RemoveFabric::DecodableType & commandData)
{
    MATTER_TRACE_EVENT_SCOPE("RemoveFabric", "OperationalCredentials");
    auto & fabricBeingRemoved = commandData.fabricIndex;

    ChipLogProgress(Zcl, "OpCreds: Received a RemoveFabric Command for FabricIndex 0x%x",
                    static_cast<unsigned>(fabricBeingRemoved));

    if (!IsValidFabricIndex(fabricBeingRemoved))
    {
        ChipLogError(Zcl, "OpCreds: Failed RemoveFabric due to invalid FabricIndex");
        commandObj->AddStatus(commandPath, Status::InvalidCommand);
        return true;
    }

    commandObj->FlushAcksRightAwayOnSlowCommand();

    CHIP_ERROR err = DeleteFabricFromTable(fabricBeingRemoved);
    SuccessOrExit(err);

    // Notification was already done by FabricTable delegate

exit:
    // Not using ConvertToNOCResponseStatus here because it's pretty
    // AddNOC/UpdateNOC specific.
    if (err == CHIP_ERROR_NOT_FOUND)
    {
        ChipLogError(Zcl, "OpCreds: Failed RemoveFabric due to FabricIndex not found locally");
        SendNOCResponse(commandObj, commandPath, OperationalCertStatus::kInvalidFabricIndex, fabricBeingRemoved, CharSpan());
    }
    else if (err != CHIP_NO_ERROR)
    {
        // We have no idea what happened; just report failure.
        ChipLogError(Zcl, "OpCreds: Failed RemoveFabric due to internal error (err = %" CHIP_ERROR_FORMAT ")", err.Format());
        StatusIB status(err);
        commandObj->AddStatus(commandPath, status.mStatus);
    }
    else
    {
        ChipLogProgress(Zcl, "OpCreds: RemoveFabric successful");
        SendNOCResponse(commandObj, commandPath, OperationalCertStatus::kSuccess, fabricBeingRemoved, CharSpan());

        chip::Messaging::ExchangeContext * ec = commandObj->GetExchangeContext();
        FabricIndex currentFabricIndex        = commandObj->GetAccessingFabricIndex();
        if (currentFabricIndex == fabricBeingRemoved)
        {
            ec->AbortAllOtherCommunicationOnFabric();
        }
        else
        {
            SessionManager * sessionManager = ec->GetExchangeMgr()->GetSessionManager();
            CleanupSessionsForFabric(*sessionManager, fabricBeingRemoved);
        }
    }
    return true;
}

bool emberAfOperationalCredentialsClusterUpdateFabricLabelCallback(app::CommandHandler * commandObj,
                                                                   const app::ConcreteCommandPath & commandPath,
                                                                   const Commands::UpdateFabricLabel::DecodableType & commandData)
{
    MATTER_TRACE_EVENT_SCOPE("UpdateFabricLabel", "OperationalCredentials");
    auto & label        = commandData.label;
    auto ourFabricIndex = commandObj->GetAccessingFabricIndex();
    auto finalStatus    = Status::Failure;
    auto & fabricTable  = Server::GetInstance().GetFabricTable();

    ChipLogProgress(Zcl, "OpCreds: Received an UpdateFabricLabel command");

    if (label.size() > 32)
    {
        ChipLogError(Zcl, "OpCreds: Failed UpdateFabricLabel due to invalid label size %u", static_cast<unsigned>(label.size()));
        commandObj->AddStatus(commandPath, Status::InvalidCommand);
        return true;
    }

    for (const auto & fabricInfo : fabricTable)
    {
        if (fabricInfo.GetFabricLabel().data_equal(label) && fabricInfo.GetFabricIndex() != ourFabricIndex)
        {
            ChipLogError(Zcl, "Fabric label already in use");
            SendNOCResponse(commandObj, commandPath, OperationalCertStatus::kLabelConflict, ourFabricIndex, CharSpan());
            return true;
        }
    }

    // Set Label on fabric. Any error on this is basically an internal error...
    // NOTE: if an UpdateNOC had caused a pending fabric, that pending fabric is
    //       the one updated thereafter. Otherwise, the data is committed to storage
    //       as soon as the update is done.
    CHIP_ERROR err = fabricTable.SetFabricLabel(ourFabricIndex, label);
    VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::Failure);

    finalStatus = Status::Success;

    // Succeeded at updating the label, mark Fabrics table changed.
    MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OperationalCredentials::Id,
                                           OperationalCredentials::Attributes::Fabrics::Id);
exit:
    if (finalStatus == Status::Success)
    {
        SendNOCResponse(commandObj, commandPath, OperationalCertStatus::kSuccess, ourFabricIndex, CharSpan());
    }
    else
    {
        commandObj->AddStatus(commandPath, finalStatus);
    }
    return true;
}

namespace {

void SendNOCResponse(app::CommandHandler * commandObj, const ConcreteCommandPath & path, OperationalCertStatus status,
                     uint8_t index, const CharSpan & debug_text)
{
    Commands::NOCResponse::Type payload;
    payload.statusCode = status;
    if (status == OperationalCertStatus::kSuccess)
    {
        payload.fabricIndex.Emplace(index);
    }
    if (!debug_text.empty())
    {
        // Max length of DebugText is 128 in the spec.
        const CharSpan & to_send = debug_text.size() > 128 ? debug_text.SubSpan(0, 128) : debug_text;
        payload.debugText.Emplace(to_send);
    }

    commandObj->AddResponse(path, payload);
}

OperationalCertStatus ConvertToNOCResponseStatus(CHIP_ERROR err)
{
    if (err == CHIP_NO_ERROR)
    {
        return OperationalCertStatus::kSuccess;
    }
    if (err == CHIP_ERROR_INVALID_PUBLIC_KEY)
    {
        return OperationalCertStatus::kInvalidPublicKey;
    }
    if (err == CHIP_ERROR_WRONG_NODE_ID)
    {
        return OperationalCertStatus::kInvalidNodeOpId;
    }
    if (err == CHIP_ERROR_UNSUPPORTED_CERT_FORMAT)
    {
        return OperationalCertStatus::kInvalidNOC;
    }
    if (err == CHIP_ERROR_WRONG_CERT_DN)
    {
        return OperationalCertStatus::kInvalidNOC;
    }
    if (err == CHIP_ERROR_INCORRECT_STATE)
    {
        return OperationalCertStatus::kMissingCsr;
    }
    if (err == CHIP_ERROR_NO_MEMORY)
    {
        return OperationalCertStatus::kTableFull;
    }
    if (err == CHIP_ERROR_FABRIC_EXISTS)
    {
        return OperationalCertStatus::kFabricConflict;
    }
    if (err == CHIP_ERROR_INVALID_FABRIC_INDEX)
    {
        return OperationalCertStatus::kInvalidFabricIndex;
    }
    if (err == CHIP_ERROR_INVALID_ADMIN_SUBJECT)
    {
        return OperationalCertStatus::kInvalidAdminSubject;
    }

    return OperationalCertStatus::kInvalidNOC;
}

} // namespace

bool emberAfOperationalCredentialsClusterAddNOCCallback(app::CommandHandler * commandObj,
                                                        const app::ConcreteCommandPath & commandPath,
                                                        const Commands::AddNOC::DecodableType & commandData)
{
    MATTER_TRACE_EVENT_SCOPE("AddNOC", "OperationalCredentials");
    auto & NOCValue          = commandData.NOCValue;
    auto & ICACValue         = commandData.ICACValue;
    auto & adminVendorId     = commandData.adminVendorId;
    auto & ipkValue          = commandData.IPKValue;
    auto * groupDataProvider = Credentials::GetGroupDataProvider();
    auto nocResponse         = OperationalCertStatus::kSuccess;
    auto nonDefaultStatus    = Status::Success;
    bool needRevert          = false;

    CHIP_ERROR err             = CHIP_NO_ERROR;
    FabricIndex newFabricIndex = kUndefinedFabricIndex;
    Credentials::GroupDataProvider::KeySet keyset;
    const FabricInfo * newFabricInfo = nullptr;
    auto & fabricTable               = Server::GetInstance().GetFabricTable();

    auto * secureSession   = commandObj->GetExchangeContext()->GetSessionHandle()->AsSecureSession();
    auto & failSafeContext = Server::GetInstance().GetFailSafeContext();

    uint8_t compressed_fabric_id_buffer[sizeof(uint64_t)];
    MutableByteSpan compressed_fabric_id(compressed_fabric_id_buffer);

    bool csrWasForUpdateNoc = false; //< Output param of HasPendingOperationalKey
    bool hasPendingKey      = fabricTable.HasPendingOperationalKey(csrWasForUpdateNoc);

    ChipLogProgress(Zcl, "OpCreds: Received an AddNOC command");

    VerifyOrExit(NOCValue.size() <= Credentials::kMaxCHIPCertLength, nonDefaultStatus = Status::InvalidCommand);
    VerifyOrExit(!ICACValue.HasValue() || ICACValue.Value().size() <= Credentials::kMaxCHIPCertLength,
                 nonDefaultStatus = Status::InvalidCommand);
    VerifyOrExit(ipkValue.size() == Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES, nonDefaultStatus = Status::InvalidCommand);
    VerifyOrExit(IsVendorIdValidOperationally(adminVendorId), nonDefaultStatus = Status::InvalidCommand);

    VerifyOrExit(failSafeContext.IsFailSafeArmed(commandObj->GetAccessingFabricIndex()),
                 nonDefaultStatus = Status::FailsafeRequired);

    VerifyOrExit(!failSafeContext.NocCommandHasBeenInvoked(), nonDefaultStatus = Status::ConstraintError);

    // Must have had a previous CSR request, not tagged for UpdateNOC
    VerifyOrExit(hasPendingKey, nocResponse = OperationalCertStatus::kMissingCsr);
    VerifyOrExit(!csrWasForUpdateNoc, nonDefaultStatus = Status::ConstraintError);

    // Internal error that would prevent IPK from being added
    VerifyOrExit(groupDataProvider != nullptr, nonDefaultStatus = Status::Failure);

    // Flush acks before really slow work
    commandObj->FlushAcksRightAwayOnSlowCommand();

    // We can't possibly have a matching root based on the fact that we don't have
    // a shared root store. Therefore we would later fail path validation due to
    // missing root. Let's early-bail with InvalidNOC.
    VerifyOrExit(failSafeContext.AddTrustedRootCertHasBeenInvoked(), nocResponse = OperationalCertStatus::kInvalidNOC);

    err = fabricTable.AddNewPendingFabricWithOperationalKeystore(NOCValue, ICACValue.ValueOr(ByteSpan{}), adminVendorId,
                                                                 &newFabricIndex);
    VerifyOrExit(err == CHIP_NO_ERROR, nocResponse = ConvertToNOCResponseStatus(err));

    // From here if we error-out, we should revert the fabric table pending updates
    needRevert = true;

    newFabricInfo = fabricTable.FindFabricWithIndex(newFabricIndex);
    VerifyOrExit(newFabricInfo != nullptr, nonDefaultStatus = Status::Failure);

    // Set the Identity Protection Key (IPK)
    // The IPK SHALL be the operational group key under GroupKeySetID of 0
    keyset.keyset_id     = Credentials::GroupDataProvider::kIdentityProtectionKeySetId;
    keyset.policy        = GroupKeyManagement::GroupKeySecurityPolicy::kTrustFirst;
    keyset.num_keys_used = 1;
    memcpy(keyset.epoch_keys[0].key, ipkValue.data(), Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES);

    err = newFabricInfo->GetCompressedFabricIdBytes(compressed_fabric_id);
    VerifyOrExit(err == CHIP_NO_ERROR, nonDefaultStatus = Status::Failure);

    err = groupDataProvider->SetKeySet(newFabricIndex, compressed_fabric_id, keyset);
    VerifyOrExit(err == CHIP_NO_ERROR, nocResponse = ConvertToNOCResponseStatus(err));

    /**
     * . If the current secure session was established with PASE,
     *   the receiver SHALL:
     *     .. Augment the secure session context with the `FabricIndex` generated above
     *        such that subsequent interactions have the proper accessing fabric.
     *
     * . If the current secure session was established with CASE, subsequent configuration
     *   of the newly installed Fabric requires the opening of a new CASE session from the
     *   Administrator from the Fabric just installed. This Administrator is the one listed
     *   in the `caseAdminSubject` argument.
     *
     */
    if (secureSession->GetSecureSessionType() == SecureSession::Type::kPASE)
    {
        err = secureSession->AdoptFabricIndex(newFabricIndex);
        VerifyOrExit(err == CHIP_NO_ERROR, nonDefaultStatus = Status::Failure);
    }

    // Creating the initial ACL must occur after the PASE session has adopted the fabric index
    // (see above) so that the concomitant event, which is fabric scoped, is properly handled.
    err = CreateAccessControlEntryForNewFabricAdministrator(commandObj->GetSubjectDescriptor(), newFabricIndex,
                                                            commandData.caseAdminSubject);
    VerifyOrExit(err != CHIP_ERROR_INTERNAL, nonDefaultStatus = Status::Failure);
    VerifyOrExit(err == CHIP_NO_ERROR, nocResponse = ConvertToNOCResponseStatus(err));

    // The Fabric Index associated with the armed fail-safe context SHALL be updated to match the Fabric
    // Index just allocated.
    failSafeContext.SetAddNocCommandInvoked(newFabricIndex);

    // Done all intermediate steps, we are now successful
    needRevert = false;

    // We might have a new operational identity, so we should start advertising it right away.
    app::DnssdServer::Instance().AdvertiseOperational();

    // Notify the attributes containing fabric metadata can be read with new data
    MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OperationalCredentials::Id,
                                           OperationalCredentials::Attributes::Fabrics::Id);

    // Notify we have one more fabric
    MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OperationalCredentials::Id,
                                           OperationalCredentials::Attributes::CommissionedFabrics::Id);

exit:
    if (needRevert)
    {
        // Here, on revert, we DO NOT call FabricTable::Delete as this would also remove the existing
        // trusted root previously added. It possibly got reverted in case of the worst kinds of errors,
        // but a better impl of the innards of FabricTable::CommitPendingFabricData would make it work.
        fabricTable.RevertPendingOpCertsExceptRoot();

        // Revert IPK and ACL entries added, ignoring errors, since some steps may have been skipped
        // and error handling does not assist.
        if (groupDataProvider != nullptr)
        {
            (void) groupDataProvider->RemoveFabric(newFabricIndex);
        }

        (void) Access::GetAccessControl().DeleteAllEntriesForFabric(newFabricIndex);

        MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OperationalCredentials::Id,
                                               OperationalCredentials::Attributes::CommissionedFabrics::Id);
        MatterReportingAttributeChangeCallback(commandPath.mEndpointId, OperationalCredentials::Id,
                                               OperationalCredentials::Attributes::Fabrics::Id);
    }

    // We have an NOC response
    if (nonDefaultStatus == Status::Success)
    {
        SendNOCResponse(commandObj, commandPath, nocResponse, newFabricIndex, CharSpan());
        // Failed to add NOC
        if (nocResponse != OperationalCertStatus::kSuccess)
        {
            ChipLogError(Zcl, "OpCreds: Failed AddNOC request (err=%" CHIP_ERROR_FORMAT ") with OperationalCert error %d",
                         err.Format(), to_underlying(nocResponse));
        }
        // Success
        else
        {
            ChipLogProgress(Zcl, "OpCreds: successfully created fabric index 0x%x via AddNOC",
                            static_cast<unsigned>(newFabricIndex));
        }
    }
    // No NOC response - Failed constraints
    else
    {
        commandObj->AddStatus(commandPath, nonDefaultStatus);
        ChipLogError(Zcl, "OpCreds: Failed AddNOC request with IM error 0x%02x", to_underlying(nonDefaultStatus));
    }

    return true;
}

bool emberAfOperationalCredentialsClusterUpdateNOCCallback(app::CommandHandler * commandObj,
                                                           const app::ConcreteCommandPath & commandPath,
                                                           const Commands::UpdateNOC::DecodableType & commandData)
{
    MATTER_TRACE_EVENT_SCOPE("UpdateNOC", "OperationalCredentials");
    auto & NOCValue  = commandData.NOCValue;
    auto & ICACValue = commandData.ICACValue;

    auto nocResponse      = OperationalCertStatus::kSuccess;
    auto nonDefaultStatus = Status::Success;

    CHIP_ERROR err          = CHIP_NO_ERROR;
    FabricIndex fabricIndex = 0;

    ChipLogProgress(Zcl, "OpCreds: Received an UpdateNOC command");

    auto & fabricTable            = Server::GetInstance().GetFabricTable();
    auto & failSafeContext        = Server::GetInstance().GetFailSafeContext();
    const FabricInfo * fabricInfo = RetrieveCurrentFabric(commandObj);

    bool csrWasForUpdateNoc = false; //< Output param of HasPendingOperationalKey
    bool hasPendingKey      = fabricTable.HasPendingOperationalKey(csrWasForUpdateNoc);

    VerifyOrExit(NOCValue.size() <= Credentials::kMaxCHIPCertLength, nonDefaultStatus = Status::InvalidCommand);
    VerifyOrExit(!ICACValue.HasValue() || ICACValue.Value().size() <= Credentials::kMaxCHIPCertLength,
                 nonDefaultStatus = Status::InvalidCommand);
    VerifyOrExit(failSafeContext.IsFailSafeArmed(commandObj->GetAccessingFabricIndex()),
                 nonDefaultStatus = Status::FailsafeRequired);

    VerifyOrExit(!failSafeContext.NocCommandHasBeenInvoked(), nonDefaultStatus = Status::ConstraintError);

    // Must have had a previous CSR request, tagged for UpdateNOC
    VerifyOrExit(hasPendingKey, nocResponse = OperationalCertStatus::kMissingCsr);
    VerifyOrExit(csrWasForUpdateNoc, nonDefaultStatus = Status::ConstraintError);

    // If current fabric is not available, command was invoked over PASE which is not legal
    VerifyOrExit(fabricInfo != nullptr, nocResponse = ConvertToNOCResponseStatus(CHIP_ERROR_INSUFFICIENT_PRIVILEGE));
    fabricIndex = fabricInfo->GetFabricIndex();

    // Flush acks before really slow work
    commandObj->FlushAcksRightAwayOnSlowCommand();

    err = fabricTable.UpdatePendingFabricWithOperationalKeystore(fabricIndex, NOCValue, ICACValue.ValueOr(ByteSpan{}));
    VerifyOrExit(err == CHIP_NO_ERROR, nocResponse = ConvertToNOCResponseStatus(err));

    // Flag on the fail-safe context that the UpdateNOC command was invoked.
    failSafeContext.SetUpdateNocCommandInvoked();

    // We might have a new operational identity, so we should start advertising
    // it right away.  Also, we need to withdraw our old operational identity.
    // So we need to StartServer() here.
    app::DnssdServer::Instance().StartServer();

    // Attribute notification was already done by fabric table
exit:
    // We have an NOC response
    if (nonDefaultStatus == Status::Success)
    {
        SendNOCResponse(commandObj, commandPath, nocResponse, fabricIndex, CharSpan());
        // Failed to update NOC
        if (nocResponse != OperationalCertStatus::kSuccess)
        {
            ChipLogError(Zcl, "OpCreds: Failed UpdateNOC request (err=%" CHIP_ERROR_FORMAT ") with OperationalCert error %d",
                         err.Format(), to_underlying(nocResponse));
        }
        // Success
        else
        {
            ChipLogProgress(Zcl, "OpCreds: UpdateNOC successful.");

            // On success, revoke all CASE sessions on the fabric hosting the exchange.
            // From spec:
            //
            //    All internal data reflecting the prior operational identifier of the Node within the Fabric
            //    SHALL be revoked and removed, to an outcome equivalent to the disappearance of the prior Node,
            //    except for the ongoing CASE session context, which SHALL temporarily remain valid until the
            //    `NOCResponse` has been successfully delivered or until the next transport-layer error, so
            //    that the response can be received by the Administrator invoking the command.

            commandObj->GetExchangeContext()->AbortAllOtherCommunicationOnFabric();
        }
    }
    // No NOC response - Failed constraints
    else
    {
        commandObj->AddStatus(commandPath, nonDefaultStatus);
        ChipLogError(Zcl, "OpCreds: Failed AddNOC request with IM error 0x%02x", to_underlying(nonDefaultStatus));
    }

    return true;
}

bool emberAfOperationalCredentialsClusterCertificateChainRequestCallback(
    app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
    const Commands::CertificateChainRequest::DecodableType & commandData)
{
    MATTER_TRACE_EVENT_SCOPE("CertificateChainRequest", "OperationalCredentials");
    auto & certificateType = commandData.certificateType;

    CHIP_ERROR err = CHIP_NO_ERROR;

    uint8_t derBuf[Credentials::kMaxDERCertLength];
    MutableByteSpan derBufSpan(derBuf);

    Commands::CertificateChainResponse::Type response;

    Credentials::DeviceAttestationCredentialsProvider * dacProvider = Credentials::GetDeviceAttestationCredentialsProvider();

    VerifyOrExit(commandObj != nullptr, err = CHIP_ERROR_INCORRECT_STATE);

    if (certificateType == kDACCertificate)
    {
        ChipLogProgress(Zcl, "OpCreds: Certificate Chain request received for DAC");
        SuccessOrExit(err = dacProvider->GetDeviceAttestationCert(derBufSpan));
    }
    else if (certificateType == kPAICertificate)
    {
        ChipLogProgress(Zcl, "OpCreds: Certificate Chain request received for PAI");
        SuccessOrExit(err = dacProvider->GetProductAttestationIntermediateCert(derBufSpan));
    }
    else
    {
        ChipLogError(Zcl, "OpCreds: Certificate Chain request received for unknown type: %d", static_cast<int>(certificateType));
        commandObj->AddStatus(commandPath, Status::InvalidCommand);
        return true;
    }

    response.certificate = derBufSpan;
    commandObj->AddResponse(commandPath, response);

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Zcl, "OpCreds: Failed CertificateChainRequest: %" CHIP_ERROR_FORMAT, err.Format());
        commandObj->AddStatus(commandPath, Status::Failure);
    }

    return true;
}

bool emberAfOperationalCredentialsClusterAttestationRequestCallback(app::CommandHandler * commandObj,
                                                                    const app::ConcreteCommandPath & commandPath,
                                                                    const Commands::AttestationRequest::DecodableType & commandData)
{
    MATTER_TRACE_EVENT_SCOPE("AttestationRequest", "OperationalCredentials");
    auto & attestationNonce = commandData.attestationNonce;

    auto finalStatus = Status::Failure;
    CHIP_ERROR err   = CHIP_ERROR_INVALID_ARGUMENT;
    ByteSpan tbsSpan;

    Platform::ScopedMemoryBuffer<uint8_t> attestationElements;
    size_t attestationElementsLen = 0;
    MutableByteSpan attestationElementsSpan;
    uint8_t certDeclBuf[Credentials::kMaxCMSSignedCDMessage]; // Sized to hold the example certificate declaration with 100 PIDs.
                                                              // See DeviceAttestationCredsExample
    MutableByteSpan certDeclSpan(certDeclBuf);

    // TODO: Create an alternative way to retrieve the Attestation Challenge without this huge amount of calls.
    // Retrieve attestation challenge
    ByteSpan attestationChallenge =
        commandObj->GetExchangeContext()->GetSessionHandle()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge();

    // TODO: in future versions, retrieve vendor information to populate the fields below.
    uint32_t timestamp = 0;
    Credentials::DeviceAttestationVendorReservedConstructor emptyVendorReserved(nullptr, 0);

    // TODO: in future versions, also retrieve and use firmware Information
    const ByteSpan kEmptyFirmwareInfo;

    ChipLogProgress(Zcl, "OpCreds: Received an AttestationRequest command");

    // Flush acks before really slow work
    commandObj->FlushAcksRightAwayOnSlowCommand();

    Credentials::DeviceAttestationCredentialsProvider * dacProvider = Credentials::GetDeviceAttestationCredentialsProvider();

    VerifyOrExit(attestationNonce.size() == Credentials::kExpectedAttestationNonceSize, finalStatus = Status::InvalidCommand);

    if (dacProvider == nullptr)
    {
        err = CHIP_ERROR_INTERNAL;
        VerifyOrExit(dacProvider != nullptr, finalStatus = Status::Failure);
    }

    err = dacProvider->GetCertificationDeclaration(certDeclSpan);
    VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::Failure);

    attestationElementsLen = TLV::EstimateStructOverhead(certDeclSpan.size(), attestationNonce.size(), sizeof(uint64_t) * 8);

    if (!attestationElements.Alloc(attestationElementsLen + attestationChallenge.size()))
    {
        err = CHIP_ERROR_NO_MEMORY;
        VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::ResourceExhausted);
    }

    attestationElementsSpan = MutableByteSpan{ attestationElements.Get(), attestationElementsLen };
    err = Credentials::ConstructAttestationElements(certDeclSpan, attestationNonce, timestamp, kEmptyFirmwareInfo,
                                                    emptyVendorReserved, attestationElementsSpan);
    VerifyOrExit((err == CHIP_NO_ERROR) && (attestationElementsSpan.size() <= kMaxRspLen), finalStatus = Status::Failure);

    // Append attestation challenge in the back of the reserved space for the signature
    memcpy(attestationElements.Get() + attestationElementsSpan.size(), attestationChallenge.data(), attestationChallenge.size());
    tbsSpan = ByteSpan{ attestationElements.Get(), attestationElementsSpan.size() + attestationChallenge.size() };

    {
        Crypto::P256ECDSASignature signature;
        MutableByteSpan signatureSpan{ signature.Bytes(), signature.Capacity() };

        // Getnerate attestation signature
        err = dacProvider->SignWithDeviceAttestationKey(tbsSpan, signatureSpan);
        ClearSecretData(attestationElements.Get() + attestationElementsSpan.size(), attestationChallenge.size());
        VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::Failure);
        VerifyOrExit(signatureSpan.size() == Crypto::P256ECDSASignature::Capacity(), finalStatus = Status::Failure);

        Commands::AttestationResponse::Type response;

        response.attestationElements = attestationElementsSpan;
        response.signature           = signatureSpan;

        ChipLogProgress(Zcl, "OpCreds: AttestationRequest successful.");
        finalStatus = Status::Success;
        commandObj->AddResponse(commandPath, response);
    }

exit:
    if (finalStatus != Status::Success)
    {
        commandObj->AddStatus(commandPath, finalStatus);
        ChipLogError(Zcl, "OpCreds: Failed AttestationRequest request with IM error 0x%02x (err = %" CHIP_ERROR_FORMAT ")",
                     to_underlying(finalStatus), err.Format());
    }

    return true;
}

bool emberAfOperationalCredentialsClusterCSRRequestCallback(app::CommandHandler * commandObj,
                                                            const app::ConcreteCommandPath & commandPath,
                                                            const Commands::CSRRequest::DecodableType & commandData)
{
    MATTER_TRACE_EVENT_SCOPE("CSRRequest", "OperationalCredentials");
    ChipLogProgress(Zcl, "OpCreds: Received a CSRRequest command");

    chip::Platform::ScopedMemoryBuffer<uint8_t> nocsrElements;
    MutableByteSpan nocsrElementsSpan;
    auto finalStatus = Status::Failure;
    ByteSpan tbsSpan;

    // Start with CHIP_ERROR_INVALID_ARGUMENT so that cascading errors yield correct
    // logs by the end. We use finalStatus as our overall success marker, not error
    CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT;

    auto & fabricTable     = Server::GetInstance().GetFabricTable();
    auto & failSafeContext = Server::GetInstance().GetFailSafeContext();

    auto & CSRNonce     = commandData.CSRNonce;
    bool isForUpdateNoc = commandData.isForUpdateNOC.ValueOr(false);

    // TODO: Create an alternative way to retrieve the Attestation Challenge without this huge amount of calls.
    // Retrieve attestation challenge
    ByteSpan attestationChallenge =
        commandObj->GetExchangeContext()->GetSessionHandle()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge();

    failSafeContext.SetCsrRequestForUpdateNoc(isForUpdateNoc);
    const FabricInfo * fabricInfo = RetrieveCurrentFabric(commandObj);

    VerifyOrExit(CSRNonce.size() == Credentials::kExpectedAttestationNonceSize, finalStatus = Status::InvalidCommand);

    // If current fabric is not available, command was invoked over PASE which is not legal if IsForUpdateNOC is true.
    VerifyOrExit(!isForUpdateNoc || (fabricInfo != nullptr), finalStatus = Status::InvalidCommand);

    VerifyOrExit(failSafeContext.IsFailSafeArmed(commandObj->GetAccessingFabricIndex()), finalStatus = Status::FailsafeRequired);
    VerifyOrExit(!failSafeContext.NocCommandHasBeenInvoked(), finalStatus = Status::ConstraintError);

    // Flush acks before really slow work
    commandObj->FlushAcksRightAwayOnSlowCommand();

    // Prepare NOCSRElements structure
    {
        constexpr size_t csrLength = Crypto::kMAX_CSR_Length;
        size_t nocsrLengthEstimate = 0;
        ByteSpan kNoVendorReserved;
        Platform::ScopedMemoryBuffer<uint8_t> csr;
        MutableByteSpan csrSpan;

        // Generate the actual CSR from the ephemeral key
        if (!csr.Alloc(csrLength))
        {
            err = CHIP_ERROR_NO_MEMORY;
            VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::ResourceExhausted);
        }
        csrSpan = MutableByteSpan{ csr.Get(), csrLength };

        Optional<FabricIndex> fabricIndexForCsr;
        if (isForUpdateNoc)
        {
            fabricIndexForCsr.SetValue(commandObj->GetAccessingFabricIndex());
        }

        err = fabricTable.AllocatePendingOperationalKey(fabricIndexForCsr, csrSpan);

        if (csrSpan.size() > Crypto::kMAX_CSR_Length)
        {
            err = CHIP_ERROR_INTERNAL;
        }

        if (err != CHIP_NO_ERROR)
        {
            ChipLogError(Zcl, "OpCreds: AllocatePendingOperationalKey returned %" CHIP_ERROR_FORMAT, err.Format());
            VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::Failure);
        }

        ChipLogProgress(Zcl, "OpCreds: AllocatePendingOperationalKey succeeded");

        // Encode the NOCSR elements with the CSR and Nonce
        nocsrLengthEstimate = TLV::EstimateStructOverhead(csrSpan.size(),  // CSR buffer
                                                          CSRNonce.size(), // CSR Nonce
                                                          0u               // no vendor reserved data
        );

        if (!nocsrElements.Alloc(nocsrLengthEstimate + attestationChallenge.size()))
        {
            err = CHIP_ERROR_NO_MEMORY;
            VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::ResourceExhausted);
        }

        nocsrElementsSpan = MutableByteSpan{ nocsrElements.Get(), nocsrLengthEstimate };

        err = Credentials::ConstructNOCSRElements(ByteSpan{ csrSpan.data(), csrSpan.size() }, CSRNonce, kNoVendorReserved,
                                                  kNoVendorReserved, kNoVendorReserved, nocsrElementsSpan);
        VerifyOrExit((err == CHIP_NO_ERROR) && (nocsrElementsSpan.size() <= kMaxRspLen), finalStatus = Status::Failure);

        // Append attestation challenge in the back of the reserved space for the signature
        memcpy(nocsrElements.Get() + nocsrElementsSpan.size(), attestationChallenge.data(), attestationChallenge.size());
        tbsSpan = ByteSpan{ nocsrElements.Get(), nocsrElementsSpan.size() + attestationChallenge.size() };

        {
            Credentials::DeviceAttestationCredentialsProvider * dacProvider =
                Credentials::GetDeviceAttestationCredentialsProvider();
            Crypto::P256ECDSASignature signature;
            MutableByteSpan signatureSpan{ signature.Bytes(), signature.Capacity() };

            // Getnerate attestation signature
            err = dacProvider->SignWithDeviceAttestationKey(tbsSpan, signatureSpan);
            ClearSecretData(nocsrElements.Get() + nocsrElementsSpan.size(), attestationChallenge.size());
            VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::Failure);
            VerifyOrExit(signatureSpan.size() == Crypto::P256ECDSASignature::Capacity(), finalStatus = Status::Failure);

            Commands::CSRResponse::Type response;

            response.NOCSRElements        = nocsrElementsSpan;
            response.attestationSignature = signatureSpan;

            ChipLogProgress(Zcl, "OpCreds: CSRRequest successful.");
            finalStatus = Status::Success;
            commandObj->AddResponse(commandPath, response);
        }
    }

exit:
    // If failed constraints or internal errors, send a status report instead of the response sent above
    if (finalStatus != Status::Success)
    {
        commandObj->AddStatus(commandPath, finalStatus);
        ChipLogError(Zcl, "OpCreds: Failed CSRRequest request with IM error 0x%02x (err = %" CHIP_ERROR_FORMAT ")",
                     to_underlying(finalStatus), err.Format());
    }

    return true;
}

bool emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback(
    app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
    const Commands::AddTrustedRootCertificate::DecodableType & commandData)
{
    MATTER_TRACE_EVENT_SCOPE("AddTrustedRootCertificate", "OperationalCredentials");

    auto & fabricTable = Server::GetInstance().GetFabricTable();
    auto finalStatus   = Status::Failure;

    // Start with CHIP_ERROR_INVALID_ARGUMENT so that cascading errors yield correct
    // logs by the end. We use finalStatus as our overall success marker, not error
    CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT;

    auto & rootCertificate = commandData.rootCertificate;
    auto & failSafeContext = Server::GetInstance().GetFailSafeContext();

    ChipLogProgress(Zcl, "OpCreds: Received an AddTrustedRootCertificate command");

    VerifyOrExit(rootCertificate.size() <= Credentials::kMaxCHIPCertLength, finalStatus = Status::InvalidCommand);

    VerifyOrExit(failSafeContext.IsFailSafeArmed(commandObj->GetAccessingFabricIndex()), finalStatus = Status::FailsafeRequired);

    // Can only add a single trusted root cert per fail-safe
    VerifyOrExit(!failSafeContext.AddTrustedRootCertHasBeenInvoked(), finalStatus = Status::ConstraintError);

    // If we successfully invoked AddNOC/UpdateNOC, this command cannot possibly
    // be useful in the context.
    VerifyOrExit(!failSafeContext.NocCommandHasBeenInvoked(), finalStatus = Status::ConstraintError);

    // Flush acks before really slow work
    commandObj->FlushAcksRightAwayOnSlowCommand();

    err = ValidateChipRCAC(rootCertificate);
    VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::InvalidCommand);

    err = fabricTable.AddNewPendingTrustedRootCert(rootCertificate);
    VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, finalStatus = Status::ResourceExhausted);

    // CHIP_ERROR_INVALID_ARGUMENT by the time we reach here means bad format
    VerifyOrExit(err != CHIP_ERROR_INVALID_ARGUMENT, finalStatus = Status::InvalidCommand);
    VerifyOrExit(err == CHIP_NO_ERROR, finalStatus = Status::Failure);

    // Got here, so we succeeded, mark AddTrustedRootCert has having been invoked.
    ChipLogProgress(Zcl, "OpCreds: AddTrustedRootCertificate successful.");
    finalStatus = Status::Success;
    failSafeContext.SetAddTrustedRootCertInvoked();

exit:
    if (finalStatus != Status::Success)
    {
        ChipLogError(Zcl, "OpCreds: Failed AddTrustedRootCertificate request with IM error 0x%02x (err = %" CHIP_ERROR_FORMAT ")",
                     to_underlying(finalStatus), err.Format());
    }

    commandObj->AddStatus(commandPath, finalStatus);
    return true;
}
