/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    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
 *    This file contains class definition of an example operational certificate
 *    issuer for CHIP devices. The class can be used as a guideline on how to
 *    construct your own certificate issuer. It can also be used in tests and tools
 *    if a specific signing authority is not required.
 *
 *    NOTE: This class stores the encryption key in clear storage. This is not suited
 *          for production use. This should only be used in test tools.
 */

#pragma once

#include <controller/OperationalCredentialsDelegate.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CASEAuthTag.h>
#include <lib/core/CHIPError.h>
#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/Span.h>

namespace chip {
namespace Controller {

class DLL_EXPORT ExampleOperationalCredentialsIssuer : public OperationalCredentialsDelegate
{
public:
    //
    // Constructor to create an instance of this object that vends out operational credentials for a given fabric.
    //
    // An index should be provided to numerically identify this instance relative to others in a multi-fabric deployment. This is
    // needed given the interactions of this object with persistent storage. Consequently, the index is used to scope the entries
    // read/written to/from storage.
    //
    // It is recommended that this index track the fabric index within which this issuer is operating.
    //
    ExampleOperationalCredentialsIssuer(uint32_t index = 0) { mIndex = index; }
    ~ExampleOperationalCredentialsIssuer() override {}

    CHIP_ERROR GenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & attestationSignature, const ByteSpan & DAC,
                                const ByteSpan & PAI, const ByteSpan & PAA,
                                Callback::Callback<OnNOCChainGeneration> * onCompletion) override;

    void SetNodeIdForNextNOCRequest(NodeId nodeId) override
    {
        mNextRequestedNodeId = nodeId;
        mNodeIdRequested     = true;
    }

    void SetFabricIdForNextNOCRequest(FabricId fabricId) override { mNextFabricId = fabricId; }

    /**
     * @brief Initialize the issuer with the keypair in the storage.
     *        If the storage doesn't have one, it'll create one, and it to the storage.
     *
     * @param[in] storage  A reference to the storage, where the keypair is stored.
     *                     The object of ExampleOperationalCredentialsIssuer doesn't hold
     *                     on the reference of storage.
     *
     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
     **/
    [[deprecated("This class stores the encryption key in clear storage. Don't use it for production code.")]] CHIP_ERROR
    Initialize(PersistentStorageDelegate & storage);

    void SetIssuerId(uint32_t id) { mIssuerId = id; }

    void SetCurrentEpoch(uint32_t epoch) { mNow = epoch; }

    void SetCertificateValidityPeriod(uint32_t validity) { mValidity = validity; }

    /**
     * Generate a random operational node id.
     *
     * @param[out] aNodeId where to place the generated id.
     *
     * On error no guarantees are made about the state of aNodeId.
     */
    static CHIP_ERROR GetRandomOperationalNodeId(NodeId * aNodeId);

    /**
     * This is a utility method that generates a operational certificate chain for the given public key.
     * This method is expected to be called once all the checks (e.g. device attestation, CSR verification etc)
     * have been completed, or not required (e.g. for self trusted devices such as commissioner apps).
     */
    CHIP_ERROR GenerateNOCChainAfterValidation(NodeId nodeId, FabricId fabricId, const CATValues & cats,
                                               const Crypto::P256PublicKey & pubkey, MutableByteSpan & rcac, MutableByteSpan & icac,
                                               MutableByteSpan & noc);

private:
    Crypto::P256Keypair mIssuer;
    Crypto::P256Keypair mIntermediateIssuer;
    bool mInitialized              = false;
    uint32_t mIssuerId             = 0;
    uint32_t mIntermediateIssuerId = 1;
    uint32_t mNow                  = 0;

    // By default, let's set validity to 10 years
    uint32_t mValidity = 365 * 24 * 60 * 60 * 10;

    NodeId mNextAvailableNodeId          = 1;
    PersistentStorageDelegate * mStorage = nullptr;

    NodeId mNextRequestedNodeId = 1;
    FabricId mNextFabricId      = 1;
    bool mNodeIdRequested       = false;
    uint64_t mIndex             = 0;
};

} // namespace Controller
} // namespace chip
