/*
 *    Copyright (c) 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.
 */
#include "Efr32PsaOperationalKeystore.h"

#include <crypto/OperationalKeystore.h>
#include <lib/core/CHIPError.h>
#include <lib/core/CHIPTLV.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>

#include "Efr32OpaqueKeypair.h"
#include <platform/silabs/EFR32Config.h>

namespace chip {
namespace DeviceLayer {
namespace Internal {

static_assert((sizeof(FabricIndex) == 1), "Implementation is not prepared for large fabric indices");
static_assert(SL_MATTER_MAX_STORED_OP_KEYS <= (kEFR32OpaqueKeyIdPersistentMax - kEFR32OpaqueKeyIdPersistentMin),
              "Not enough opaque keys available to cover all requested operational keys");
static_assert((CHIP_CONFIG_MAX_FABRICS + 1) <= SL_MATTER_MAX_STORED_OP_KEYS,
              "Not enough operational keys requested to cover all potential fabrics (+1 staging for fabric update)");
static_assert(SL_MATTER_MAX_STORED_OP_KEYS >= 1, "Minimum supported amount of operational keys is 1");

using namespace chip::Crypto;

using chip::Platform::MemoryCalloc;
using chip::Platform::MemoryFree;

Efr32PsaOperationalKeystore::~Efr32PsaOperationalKeystore()
{
    Deinit();
}

CHIP_ERROR Efr32PsaOperationalKeystore::Init()
{
    // Detect existing keymap size
    CHIP_ERROR error   = CHIP_NO_ERROR;
    size_t wantedLen   = SL_MATTER_MAX_STORED_OP_KEYS * sizeof(FabricIndex);
    size_t existingLen = 0;
    bool update_cache  = false;

    if (EFR32Config::ConfigValueExists(EFR32Config::kConfigKey_OpKeyMap, existingLen))
    {
        // There's a pre-existing key map on disk. Size the map to read it fully.
        size_t outLen = 0;

        if (existingLen > (kEFR32OpaqueKeyIdPersistentMax - kEFR32OpaqueKeyIdPersistentMin) * sizeof(FabricIndex))
        {
            return CHIP_ERROR_INTERNAL;
        }

        // Upsize the map if the config was changed
        if (existingLen < wantedLen)
        {
            existingLen = wantedLen;
        }

        mKeyMap = (FabricIndex *) MemoryCalloc(1, existingLen);
        VerifyOrExit(mKeyMap, error = CHIP_ERROR_NO_MEMORY);

        // Read the existing key map
        error = EFR32Config::ReadConfigValueBin(EFR32Config::kConfigKey_OpKeyMap, (uint8_t *) mKeyMap, existingLen, outLen);
        SuccessOrExit(error);

        // If upsizing, extend the map with undefined indices
        for (size_t i = (outLen / sizeof(FabricIndex)); i < (existingLen / sizeof(FabricIndex)); i++)
        {
            mKeyMap[i] = kUndefinedFabricIndex;
        }

        // If the config has changed, check whether it can be downsized fully or partially
        if (existingLen > wantedLen)
        {
            size_t highest_found_index = 0;
            for (size_t i = (wantedLen / sizeof(FabricIndex)); i < (existingLen / sizeof(FabricIndex)); i++)
            {
                if (mKeyMap[i] != kUndefinedFabricIndex)
                {
                    highest_found_index = i;
                }
            }

            // set size to the smallest that will fit the upper opaque key ID in use
            if (highest_found_index > 0)
            {
                existingLen  = (highest_found_index + 1) * sizeof(FabricIndex);
                update_cache = true;
            }
        }

        // Set the key map size
        mKeyMapSize = existingLen;
    }
    else
    {
        // No key map on disk. Create and initialize a new one.
        mKeyMap = (FabricIndex *) MemoryCalloc(1, wantedLen);
        VerifyOrExit(mKeyMap, error = CHIP_ERROR_NO_MEMORY);

        for (size_t i = 0; i < (wantedLen / sizeof(FabricIndex)); i++)
        {
            mKeyMap[i] = kUndefinedFabricIndex;
        }

        mKeyMapSize = wantedLen;

        update_cache = true;
    }

    // Write-out keymap if needed
    if (update_cache)
    {
        error = EFR32Config::WriteConfigValueBin(EFR32Config::kConfigKey_OpKeyMap, mKeyMap, mKeyMapSize);
        SuccessOrExit(error);
    }

    // Initialize cache key
    mCachedKey = Platform::New<EFR32OpaqueP256Keypair>();
    VerifyOrExit(mCachedKey, error = CHIP_ERROR_NO_MEMORY);

exit:
    if (error != CHIP_NO_ERROR)
    {
        Deinit();
        return error;
    }

    mIsInitialized = true;
    return CHIP_NO_ERROR;
}

EFR32OpaqueKeyId Efr32PsaOperationalKeystore::FindKeyIdForFabric(FabricIndex fabricIndex) const
{
    // Search the map linearly to find a matching index slot
    for (size_t i = 0; i < (mKeyMapSize / sizeof(FabricIndex)); i++)
    {
        if (mKeyMap[i] == fabricIndex)
        {
            // Found a match
            return i + kEFR32OpaqueKeyIdPersistentMin;
        }
    }

    return kEFR32OpaqueKeyIdUnknown;
}

bool Efr32PsaOperationalKeystore::HasOpKeypairForFabric(FabricIndex fabricIndex) const
{
    VerifyOrReturnError(mIsInitialized, false);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), false);

    // If there was a pending keypair, then there's really a usable key
    if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex) && (mPendingKeypair != nullptr))
    {
        return true;
    }

    // Check whether we have a match in the map
    if (FindKeyIdForFabric(fabricIndex) != kEFR32OpaqueKeyIdUnknown)
    {
        return true;
    }

    return false;
}

CHIP_ERROR Efr32PsaOperationalKeystore::NewOpKeypairForFabric(FabricIndex fabricIndex,
                                                              MutableByteSpan & outCertificateSigningRequest)
{
    CHIP_ERROR error = CHIP_NO_ERROR;
    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);

    // If a key is pending, we cannot generate for a different fabric index until we commit or revert.
    if ((mPendingFabricIndex != kUndefinedFabricIndex) && (fabricIndex != mPendingFabricIndex))
    {
        return CHIP_ERROR_INVALID_FABRIC_INDEX;
    }

    VerifyOrReturnError(outCertificateSigningRequest.size() >= Crypto::kMAX_CSR_Length, CHIP_ERROR_BUFFER_TOO_SMALL);

    // Generate new key
    EFR32OpaqueKeyId id = kEFR32OpaqueKeyIdUnknown;

    if (mPendingFabricIndex != kUndefinedFabricIndex)
    {
        // If we already have a pending key, delete it and put a new one in its place
        id = mPendingKeypair->GetKeyId();
        if (id == kEFR32OpaqueKeyIdUnknown)
        {
            ResetPendingKey();
        }
        else
        {
            mPendingKeypair->Delete();
            if (id == kEFR32OpaqueKeyIdVolatile)
            {
                id = kEFR32OpaqueKeyIdUnknown;
            }
        }
    }

    if (id == kEFR32OpaqueKeyIdUnknown)
    {
        // Try to find an available opaque ID in the map
        id = FindKeyIdForFabric(kUndefinedFabricIndex);

        if (!mPendingKeypair)
        {
            mPendingKeypair = Platform::New<EFR32OpaqueP256Keypair>();
        }
    }

    if (id == kEFR32OpaqueKeyIdUnknown)
    {
        // Could not find a free spot in the map
        return CHIP_ERROR_NO_MEMORY;
    }

    // Create new key on the old or found key ID
    error = mPendingKeypair->Create(id, EFR32OpaqueKeyUsages::ECDSA_P256_SHA256);
    if (error != CHIP_NO_ERROR)
    {
        ResetPendingKey();
        return error;
    }

    // Set CSR and state
    size_t csrLength = outCertificateSigningRequest.size();
    error            = mPendingKeypair->NewCertificateSigningRequest(outCertificateSigningRequest.data(), csrLength);
    if (error != CHIP_NO_ERROR)
    {
        ResetPendingKey();
        return error;
    }

    outCertificateSigningRequest.reduce_size(csrLength);
    mPendingFabricIndex = fabricIndex;

    return CHIP_NO_ERROR;
}

CHIP_ERROR Efr32PsaOperationalKeystore::ActivateOpKeypairForFabric(FabricIndex fabricIndex,
                                                                   const Crypto::P256PublicKey & nocPublicKey)
{
    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
    VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);

    // Validate public key being activated matches last generated pending keypair
    VerifyOrReturnError(mPendingKeypair->Pubkey().Matches(nocPublicKey), CHIP_ERROR_INVALID_PUBLIC_KEY);

    mIsPendingKeypairActive = true;

    return CHIP_NO_ERROR;
}

CHIP_ERROR Efr32PsaOperationalKeystore::CommitOpKeypairForFabric(FabricIndex fabricIndex)
{
    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
    VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
    VerifyOrReturnError(mIsPendingKeypairActive == true, CHIP_ERROR_INCORRECT_STATE);

    // Add key association to key map
    EFR32OpaqueKeyId id = mPendingKeypair->GetKeyId();

    if (id == kEFR32OpaqueKeyIdUnknown || id == kEFR32OpaqueKeyIdVolatile)
    {
        ResetPendingKey();
        return CHIP_ERROR_INTERNAL;
    }

    // Guard against array out-of-bounds (should not happen with correctly initialised keys)
    size_t keymap_index = id - kEFR32OpaqueKeyIdPersistentMin;
    if (keymap_index >= (mKeyMapSize / sizeof(FabricIndex)))
    {
        return CHIP_ERROR_INTERNAL;
    }

    if (mKeyMap[keymap_index] != kUndefinedFabricIndex)
    {
        ResetPendingKey();
        return CHIP_ERROR_INTERNAL;
    }

    mKeyMap[keymap_index] = fabricIndex;

    // Persist key map
    CHIP_ERROR error = EFR32Config::WriteConfigValueBin(EFR32Config::kConfigKey_OpKeyMap, mKeyMap, mKeyMapSize);
    if (error != CHIP_NO_ERROR)
    {
        return error;
    }

    // There's a good chance we'll need the key again soon
    mCachedKey->Load(id);

    mPendingKeypair         = nullptr;
    mIsPendingKeypairActive = false;
    mPendingFabricIndex     = kUndefinedFabricIndex;

    return CHIP_NO_ERROR;
}

CHIP_ERROR Efr32PsaOperationalKeystore::RemoveOpKeypairForFabric(FabricIndex fabricIndex)
{
    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);

    // Remove pending keypair if we have it and the fabric ID matches
    if ((mPendingKeypair != nullptr) && (fabricIndex == mPendingFabricIndex))
    {
        RevertPendingKeypair();
    }

    EFR32OpaqueKeyId id = FindKeyIdForFabric(fabricIndex);
    if (id == kEFR32OpaqueKeyIdUnknown)
    {
        // Fabric is not in the map, so assume it's gone already
        return CHIP_NO_ERROR;
    }

    // Guard against array out-of-bounds (should not happen with correctly initialised keys)
    size_t keymap_index = id - kEFR32OpaqueKeyIdPersistentMin;
    if (keymap_index >= (mKeyMapSize / sizeof(FabricIndex)))
    {
        return CHIP_ERROR_INTERNAL;
    }

    // Reset the key mapping since we'll be deleting this key
    mKeyMap[keymap_index] = kUndefinedFabricIndex;

    // Persist key map
    CHIP_ERROR error = EFR32Config::WriteConfigValueBin(EFR32Config::kConfigKey_OpKeyMap, mKeyMap, mKeyMapSize);
    if (error != CHIP_NO_ERROR)
    {
        return error;
    }

    // Check if key is cached
    EFR32OpaqueKeyId cachedId = mCachedKey->GetKeyId();

    if (id == cachedId)
    {
        // Delete from persistent storage and unload
        mCachedKey->Delete();
        return CHIP_NO_ERROR;
    }

    // Load it for purposes of deletion
    error = mCachedKey->Load(id);
    if (error != CHIP_NO_ERROR && error != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
    {
        return CHIP_ERROR_INTERNAL;
    }

    mCachedKey->Delete();

    return CHIP_NO_ERROR;
}

void Efr32PsaOperationalKeystore::RevertPendingKeypair()
{
    if (mIsInitialized)
    {
        // Just delete the pending key from storage
        ResetPendingKey();
    }
}

CHIP_ERROR Efr32PsaOperationalKeystore::SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
                                                          Crypto::P256ECDSASignature & outSignature) const
{
    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);

    // Check to see whether the key is an activated pending key
    if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex))
    {
        VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INTERNAL);
        return mPendingKeypair->ECDSA_sign_msg(message.data(), message.size(), outSignature);
    }

    // Figure out which key ID we're looking for
    EFR32OpaqueKeyId id = FindKeyIdForFabric(fabricIndex);

    if (id == kEFR32OpaqueKeyIdUnknown)
    {
        // Fabric is not in the map, but the caller thinks it's there?
        return CHIP_ERROR_INTERNAL;
    }

    // Check whether we have the key in cache
    EFR32OpaqueKeyId cachedId = mCachedKey->GetKeyId();

    if (id == cachedId)
    {
        return mCachedKey->ECDSA_sign_msg(message.data(), message.size(), outSignature);
    }

    // If not, we need to recreate from the backend
    CHIP_ERROR error = mCachedKey->Load(id);
    if (error != CHIP_NO_ERROR)
    {
        return CHIP_ERROR_INTERNAL;
    }

    // Sign with retrieved key
    error = mCachedKey->ECDSA_sign_msg(message.data(), message.size(), outSignature);
    if (error != CHIP_NO_ERROR)
    {
        return CHIP_ERROR_INTERNAL;
    }

    return CHIP_NO_ERROR;
}

Crypto::P256Keypair * Efr32PsaOperationalKeystore::AllocateEphemeralKeypairForCASE()
{
    EFR32OpaqueP256Keypair * new_key = Platform::New<EFR32OpaqueP256Keypair>();

    if (new_key != nullptr)
    {
        new_key->Create(kEFR32OpaqueKeyIdVolatile, EFR32OpaqueKeyUsages::ECDH_P256);
    }

    return new_key;
}

void Efr32PsaOperationalKeystore::ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair)
{
    Platform::Delete<EFR32OpaqueP256Keypair>((EFR32OpaqueP256Keypair *) keypair);
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
