/*
 *    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 <credentials/CHIPCert.h>
#include <lib/core/CHIPError.h>
#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/core/CHIPTLV.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/SafeInt.h>
#include <lib/support/ScopedBuffer.h>

#include "PersistentStorageOpCertStore.h"

namespace chip {
namespace Credentials {

namespace {

using CertChainElement = OperationalCertificateStore::CertChainElement;

StorageKeyName GetStorageKeyForCert(FabricIndex fabricIndex, CertChainElement element)
{
    switch (element)
    {
    case CertChainElement::kNoc:
        return DefaultStorageKeyAllocator::FabricNOC(fabricIndex);
        break;
    case CertChainElement::kIcac:
        return DefaultStorageKeyAllocator::FabricICAC(fabricIndex);
        break;
    case CertChainElement::kRcac:
        return DefaultStorageKeyAllocator::FabricRCAC(fabricIndex);
        break;
    default:
        break;
    }

    return StorageKeyName::Uninitialized();
}

bool StorageHasCertificate(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element)
{
    StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);

    if (!storageKey)
    {
        return false;
    }

    // TODO(#16958): need to actually read the cert to know if it's there due to platforms not
    //               properly enforcing CHIP_ERROR_BUFFER_TOO_SMALL behavior needed by
    //               PersistentStorageDelegate.
    uint8_t placeHolderCertBuffer[kMaxCHIPCertLength];

    uint16_t keySize = sizeof(placeHolderCertBuffer);
    CHIP_ERROR err   = storage->SyncGetKeyValue(storageKey.KeyName(), &placeHolderCertBuffer[0], keySize);

    return (err == CHIP_NO_ERROR);
}

CHIP_ERROR LoadCertFromStorage(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element,
                               MutableByteSpan & outCert)
{
    StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);
    if (!storageKey)
    {
        return CHIP_ERROR_INTERNAL;
    }

    uint16_t keySize = static_cast<uint16_t>(outCert.size());
    CHIP_ERROR err   = storage->SyncGetKeyValue(storageKey.KeyName(), outCert.data(), keySize);

    // Not finding an ICAC means we don't have one, so adjust to meet the API contract, where
    // outCert.empty() will be true;
    if ((element == CertChainElement::kIcac) && (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND))
    {
        outCert.reduce_size(0);
        return CHIP_ERROR_NOT_FOUND;
    }

    if (err == CHIP_NO_ERROR)
    {
        outCert.reduce_size(keySize);
    }
    else if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
    {
        // Convert persisted storage error to CHIP_ERROR_NOT_FOUND so that
        // `PersistentStorageOpCertStore::GetCertificate` doesn't need to convert.
        err = CHIP_ERROR_NOT_FOUND;
    }

    return err;
}

CHIP_ERROR SaveCertToStorage(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element,
                             const ByteSpan & cert)
{
    StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);
    if (!storageKey)
    {
        return CHIP_ERROR_INTERNAL;
    }

    // If provided an empty ICAC, we delete the ICAC key previously used. If not there, it's OK
    if ((element == CertChainElement::kIcac) && (cert.empty()))
    {
        CHIP_ERROR err = storage->SyncDeleteKeyValue(storageKey.KeyName());
        if ((err == CHIP_NO_ERROR) || (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND))
        {
            return CHIP_NO_ERROR;
        }
        return err;
    }

    return storage->SyncSetKeyValue(storageKey.KeyName(), cert.data(), static_cast<uint16_t>(cert.size()));
}

CHIP_ERROR DeleteCertFromStorage(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element)
{
    StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);
    if (!storageKey)
    {
        return CHIP_ERROR_INTERNAL;
    }
    return storage->SyncDeleteKeyValue(storageKey.KeyName());
}

} // namespace

bool PersistentStorageOpCertStore::HasPendingRootCert() const
{
    if (mStorage == nullptr)
    {
        return false;
    }

    return (mPendingRcac.Get() != nullptr) && mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled);
}

bool PersistentStorageOpCertStore::HasPendingNocChain() const
{
    if (mStorage == nullptr)
    {
        return false;
    }

    return (mPendingNoc.Get() != nullptr) && mStateFlags.HasAny(StateFlags::kAddNewOpCertsCalled, StateFlags::kUpdateOpCertsCalled);
}

bool PersistentStorageOpCertStore::HasCertificateForFabric(FabricIndex fabricIndex, CertChainElement element) const
{
    if ((mStorage == nullptr) || !IsValidFabricIndex(fabricIndex))
    {
        return false;
    }

    // FabricIndex matches pending, we MAY have some pending data
    if (fabricIndex == mPendingFabricIndex)
    {
        switch (element)
        {
        case CertChainElement::kRcac:
            if (mPendingRcac.Get() != nullptr)
            {
                return true;
            }
            break;
        case CertChainElement::kIcac:
            if (mPendingIcac.Get() != nullptr)
            {
                return true;
            }
            // If we have a pending NOC and no pending ICAC, don't delegate to storage, return not found here
            // since in the pending state, there truly is nothing.
            if (mPendingNoc.Get() != nullptr)
            {
                return false;
            }
            break;
        case CertChainElement::kNoc:
            if (mPendingNoc.Get() != nullptr)
            {
                return true;
            }
            break;
        default:
            return false;
        }
    }

    return StorageHasCertificate(mStorage, fabricIndex, element);
}

CHIP_ERROR PersistentStorageOpCertStore::AddNewTrustedRootCertForFabric(FabricIndex fabricIndex, const ByteSpan & rcac)
{
    ReturnErrorCodeIf(mStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(!IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
    ReturnErrorCodeIf(rcac.empty() || (rcac.size() > Credentials::kMaxCHIPCertLength), CHIP_ERROR_INVALID_ARGUMENT);

    ReturnErrorCodeIf(mStateFlags.HasAny(StateFlags::kUpdateOpCertsCalled, StateFlags::kAddNewTrustedRootCalled,
                                         StateFlags::kAddNewOpCertsCalled),
                      CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kRcac), CHIP_ERROR_INCORRECT_STATE);

    Platform::ScopedMemoryBufferWithSize<uint8_t> rcacBuf;
    ReturnErrorCodeIf(!rcacBuf.Alloc(rcac.size()), CHIP_ERROR_NO_MEMORY);
    memcpy(rcacBuf.Get(), rcac.data(), rcac.size());

    mPendingRcac = std::move(rcacBuf);

    mPendingFabricIndex = fabricIndex;
    mStateFlags.Set(StateFlags::kAddNewTrustedRootCalled);

    return CHIP_NO_ERROR;
}

CHIP_ERROR PersistentStorageOpCertStore::AddNewOpCertsForFabric(FabricIndex fabricIndex, const ByteSpan & noc,
                                                                const ByteSpan & icac)
{
    ReturnErrorCodeIf(mStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(!IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
    ReturnErrorCodeIf(noc.empty() || (noc.size() > Credentials::kMaxCHIPCertLength), CHIP_ERROR_INVALID_ARGUMENT);
    ReturnErrorCodeIf(icac.size() > Credentials::kMaxCHIPCertLength, CHIP_ERROR_INVALID_ARGUMENT);

    // Can't have called UpdateOpCertsForFabric first, or called with pending certs
    ReturnErrorCodeIf(mStateFlags.HasAny(StateFlags::kUpdateOpCertsCalled, StateFlags::kAddNewOpCertsCalled),
                      CHIP_ERROR_INCORRECT_STATE);

    // Need to have trusted roots installed to make the chain valid
    ReturnErrorCodeIf(!mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled), CHIP_ERROR_INCORRECT_STATE);

    // fabricIndex must match the current pending fabric
    ReturnErrorCodeIf(fabricIndex != mPendingFabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX);

    // Can't have persisted NOC/ICAC for same fabric if adding
    ReturnErrorCodeIf(StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kNoc), CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kIcac), CHIP_ERROR_INCORRECT_STATE);

    Platform::ScopedMemoryBufferWithSize<uint8_t> nocBuf;
    ReturnErrorCodeIf(!nocBuf.Alloc(noc.size()), CHIP_ERROR_NO_MEMORY);
    memcpy(nocBuf.Get(), noc.data(), noc.size());

    Platform::ScopedMemoryBufferWithSize<uint8_t> icacBuf;
    if (icac.size() > 0)
    {
        ReturnErrorCodeIf(!icacBuf.Alloc(icac.size()), CHIP_ERROR_NO_MEMORY);
        memcpy(icacBuf.Get(), icac.data(), icac.size());
    }

    mPendingNoc  = std::move(nocBuf);
    mPendingIcac = std::move(icacBuf);

    mStateFlags.Set(StateFlags::kAddNewOpCertsCalled);

    return CHIP_NO_ERROR;
}

CHIP_ERROR PersistentStorageOpCertStore::UpdateOpCertsForFabric(FabricIndex fabricIndex, const ByteSpan & noc,
                                                                const ByteSpan & icac)
{
    ReturnErrorCodeIf(mStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorCodeIf(!IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
    ReturnErrorCodeIf(noc.empty() || (noc.size() > Credentials::kMaxCHIPCertLength), CHIP_ERROR_INVALID_ARGUMENT);
    ReturnErrorCodeIf(icac.size() > Credentials::kMaxCHIPCertLength, CHIP_ERROR_INVALID_ARGUMENT);

    // Can't have called AddNewOpCertsForFabric first, and should never get here after AddNewTrustedRootCertForFabric.
    ReturnErrorCodeIf(mStateFlags.HasAny(StateFlags::kAddNewOpCertsCalled, StateFlags::kAddNewTrustedRootCalled),
                      CHIP_ERROR_INCORRECT_STATE);

    // Can't have already pending NOC from UpdateOpCerts not yet committed
    ReturnErrorCodeIf(mStateFlags.Has(StateFlags::kUpdateOpCertsCalled), CHIP_ERROR_INCORRECT_STATE);

    // Need to have trusted roots installed to make the chain valid
    ReturnErrorCodeIf(!StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kRcac), CHIP_ERROR_INCORRECT_STATE);

    // Must have persisted NOC for same fabric if updating
    ReturnErrorCodeIf(!StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kNoc), CHIP_ERROR_INCORRECT_STATE);

    // Don't check for ICAC, we may not have had one before, but assume that if NOC is there, a
    // previous chain was at least partially there

    Platform::ScopedMemoryBufferWithSize<uint8_t> nocBuf;
    ReturnErrorCodeIf(!nocBuf.Alloc(noc.size()), CHIP_ERROR_NO_MEMORY);
    memcpy(nocBuf.Get(), noc.data(), noc.size());

    Platform::ScopedMemoryBufferWithSize<uint8_t> icacBuf;
    if (icac.size() > 0)
    {
        ReturnErrorCodeIf(!icacBuf.Alloc(icac.size()), CHIP_ERROR_NO_MEMORY);
        memcpy(icacBuf.Get(), icac.data(), icac.size());
    }

    mPendingNoc  = std::move(nocBuf);
    mPendingIcac = std::move(icacBuf);

    // For NOC update, UpdateOpCertsForFabric is what determines the pending fabric index,
    // not a previous AddNewTrustedRootCertForFabric call.
    mPendingFabricIndex = fabricIndex;

    mStateFlags.Set(StateFlags::kUpdateOpCertsCalled);

    return CHIP_NO_ERROR;
}

CHIP_ERROR PersistentStorageOpCertStore::CommitOpCertsForFabric(FabricIndex fabricIndex)
{
    VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);

    VerifyOrReturnError(HasPendingNocChain(), CHIP_ERROR_INCORRECT_STATE);
    if (HasPendingRootCert())
    {
        // Neither of these conditions should have occurred based on other interlocks, but since
        // committing certificates is a dangerous operation, we absolutely validate our assumptions.
        ReturnErrorCodeIf(mStateFlags.Has(StateFlags::kUpdateOpCertsCalled), CHIP_ERROR_INCORRECT_STATE);
        ReturnErrorCodeIf(!mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled), CHIP_ERROR_INCORRECT_STATE);
    }

    // TODO: Handle transaction marking to revert partial certs at next boot if we get interrupted by reboot.

    // Start committing NOC first so we don't have dangling roots if one was added.
    ByteSpan pendingNocSpan{ mPendingNoc.Get(), mPendingNoc.AllocatedSize() };
    CHIP_ERROR nocErr = SaveCertToStorage(mStorage, mPendingFabricIndex, CertChainElement::kNoc, pendingNocSpan);

    // ICAC storage handles deleting on empty/missing
    ByteSpan pendingIcacSpan{ mPendingIcac.Get(), mPendingIcac.AllocatedSize() };
    CHIP_ERROR icacErr = SaveCertToStorage(mStorage, mPendingFabricIndex, CertChainElement::kIcac, pendingIcacSpan);

    CHIP_ERROR rcacErr = CHIP_NO_ERROR;
    if (HasPendingRootCert())
    {
        ByteSpan pendingRcacSpan{ mPendingRcac.Get(), mPendingRcac.AllocatedSize() };
        rcacErr = SaveCertToStorage(mStorage, mPendingFabricIndex, CertChainElement::kRcac, pendingRcacSpan);
    }

    // Remember which was the first error, and if any error occurred.
    CHIP_ERROR stickyErr = nocErr;
    stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : icacErr;
    stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : rcacErr;

    if (stickyErr != CHIP_NO_ERROR)
    {
        // On Adds rather than updates, remove anything possibly stored for the new fabric on partial
        // failure.
        if (mStateFlags.Has(StateFlags::kAddNewOpCertsCalled))
        {
            (void) DeleteCertFromStorage(mStorage, mPendingFabricIndex, CertChainElement::kNoc);
            (void) DeleteCertFromStorage(mStorage, mPendingFabricIndex, CertChainElement::kIcac);
        }
        if (mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled))
        {
            (void) DeleteCertFromStorage(mStorage, mPendingFabricIndex, CertChainElement::kRcac);
        }
        if (mStateFlags.Has(StateFlags::kUpdateOpCertsCalled))
        {
            // Can't do anything to clean-up here, but pretty sure the fabric is broken now...
            // TODO: Handle transaction marking to revert certs if somehow failing store on update by pre-backing-up opcerts
        }

        return stickyErr;
    }

    // If we got here, we succeeded and can reset the pending certs: next `GetCertificate` will use the stored certs
    RevertPendingOpCerts();
    return CHIP_NO_ERROR;
}

bool PersistentStorageOpCertStore::HasAnyCertificateForFabric(FabricIndex fabricIndex) const
{
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), false);

    bool rcacMissing = !StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kRcac);
    bool icacMissing = !StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kIcac);
    bool nocMissing  = !StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kNoc);
    bool anyPending  = (mPendingRcac.Get() != nullptr) || (mPendingIcac.Get() != nullptr) || (mPendingNoc.Get() != nullptr);

    if (rcacMissing && icacMissing && nocMissing && !anyPending)
    {
        return false;
    }

    return true;
}

CHIP_ERROR PersistentStorageOpCertStore::RemoveOpCertsForFabric(FabricIndex fabricIndex)
{
    VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);

    // If there was *no* state, pending or persisted, we have an error
    ReturnErrorCodeIf(!HasAnyCertificateForFabric(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);

    // Clear any pending state
    RevertPendingOpCerts();

    // Remove all persisted certs for the given fabric, blindly
    CHIP_ERROR nocErr  = DeleteCertFromStorage(mStorage, fabricIndex, CertChainElement::kNoc);
    CHIP_ERROR icacErr = DeleteCertFromStorage(mStorage, fabricIndex, CertChainElement::kIcac);
    CHIP_ERROR rcacErr = DeleteCertFromStorage(mStorage, fabricIndex, CertChainElement::kRcac);

    // Ignore missing cert errors
    nocErr  = (nocErr == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) ? CHIP_NO_ERROR : nocErr;
    icacErr = (icacErr == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) ? CHIP_NO_ERROR : icacErr;
    rcacErr = (rcacErr == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) ? CHIP_NO_ERROR : rcacErr;

    // Find the first error and return that
    CHIP_ERROR stickyErr = nocErr;
    stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : icacErr;
    stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : rcacErr;

    return stickyErr;
}

CHIP_ERROR PersistentStorageOpCertStore::GetPendingCertificate(FabricIndex fabricIndex, CertChainElement element,
                                                               MutableByteSpan & outCertificate) const
{
    if (fabricIndex != mPendingFabricIndex)
    {
        return CHIP_ERROR_NOT_FOUND;
    }

    // FabricIndex matches pending, we MAY have some pending data
    switch (element)
    {
    case CertChainElement::kRcac:
        if (mPendingRcac.Get() != nullptr)
        {
            ByteSpan rcacSpan{ mPendingRcac.Get(), mPendingRcac.AllocatedSize() };
            return CopySpanToMutableSpan(rcacSpan, outCertificate);
        }
        break;
    case CertChainElement::kIcac:
        if (mPendingIcac.Get() != nullptr)
        {
            ByteSpan icacSpan{ mPendingIcac.Get(), mPendingIcac.AllocatedSize() };
            return CopySpanToMutableSpan(icacSpan, outCertificate);
        }
        break;
    case CertChainElement::kNoc:
        if (mPendingNoc.Get() != nullptr)
        {
            ByteSpan nocSpan{ mPendingNoc.Get(), mPendingNoc.AllocatedSize() };
            return CopySpanToMutableSpan(nocSpan, outCertificate);
        }
        break;
    default:
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    return CHIP_ERROR_NOT_FOUND;
}

CHIP_ERROR PersistentStorageOpCertStore::GetCertificate(FabricIndex fabricIndex, CertChainElement element,
                                                        MutableByteSpan & outCertificate) const
{
    VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);

    // Handle case of pending data
    CHIP_ERROR err = GetPendingCertificate(fabricIndex, element, outCertificate);
    if ((err == CHIP_NO_ERROR) || (err != CHIP_ERROR_NOT_FOUND))
    {
        // Found in pending, or got a deeper error: return the pending cert status.
        return err;
    }

    // If we have a pending NOC and no pending ICAC, don't delegate to storage, return not found here
    // since in the pending state, there truly is nothing.

    if ((err == CHIP_ERROR_NOT_FOUND) && (element == CertChainElement::kIcac) && (mPendingNoc.Get() != nullptr))
    {
        // Don't delegate to storage if we just have a pending NOC and are missing the ICAC
        return CHIP_ERROR_NOT_FOUND;
    }

    // Not found in pending, let's look in persisted
    return LoadCertFromStorage(mStorage, fabricIndex, element, outCertificate);
}

} // namespace Credentials
} // namespace chip
