/*
 *    Copyright (c) 2020 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 implements the Matter Checkin protocol.
 */

#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPEncoding.h>
#include <protocols/secure_channel/CheckinMessage.h>
#include <protocols/secure_channel/Constants.h>

using namespace chip::Crypto;

namespace chip {
namespace Protocols {
namespace SecureChannel {

CHIP_ERROR CheckinMessage::GenerateCheckinMessagePayload(const Crypto::Aes128KeyHandle & aes128KeyHandle,
                                                         const Crypto::Hmac128KeyHandle & hmacKeyHandle,
                                                         const CounterType & counter, const ByteSpan & appData,
                                                         MutableByteSpan & output)
{
    VerifyOrReturnError(output.size() >= (appData.size() + kMinPayloadSize), CHIP_ERROR_BUFFER_TOO_SMALL);
    size_t cursorIndex = 0;

    // Generate Nonce from Key and counter value
    {
        MutableByteSpan nonce = output.SubSpan(0, CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES);
        cursorIndex += nonce.size();

        Encoding::LittleEndian::BufferWriter writer(nonce);
        ReturnErrorOnFailure(GenerateCheckInMessageNonce(hmacKeyHandle, counter, writer));
    }

    // Encrypt Counter and Application Data
    {
        MutableByteSpan payloadByteSpan = output.SubSpan(cursorIndex, sizeof(CounterType) + appData.size());
        cursorIndex += payloadByteSpan.size();

        Encoding::LittleEndian::BufferWriter payloadWriter(payloadByteSpan);

        payloadWriter.EndianPut(counter, sizeof(counter));
        payloadWriter.Put(appData.data(), appData.size());
        VerifyOrReturnError(payloadWriter.Fit(), CHIP_ERROR_INTERNAL);

        MutableByteSpan mic = output.SubSpan(cursorIndex, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES);
        cursorIndex += mic.size();

        // Validate that the cursorIndex is within the available output space
        VerifyOrReturnError(cursorIndex <= output.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
        // Validate that the cursorIndex matchs the message length
        VerifyOrReturnError(cursorIndex == appData.size() + kMinPayloadSize, CHIP_ERROR_INTERNAL);

        ReturnErrorOnFailure(Crypto::AES_CCM_encrypt(payloadByteSpan.data(), payloadByteSpan.size(), nullptr, 0, aes128KeyHandle,
                                                     output.data(), CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES, payloadByteSpan.data(),
                                                     mic.data(), mic.size()));
    }

    output.reduce_size(appData.size() + kMinPayloadSize);
    return CHIP_NO_ERROR;
}

CHIP_ERROR CheckinMessage::ParseCheckinMessagePayload(const Crypto::Aes128KeyHandle & aes128KeyHandle,
                                                      const Crypto::Hmac128KeyHandle & hmacKeyHandle, const ByteSpan & payload,
                                                      CounterType & counter, MutableByteSpan & appData)
{
    size_t appDataSize = GetAppDataSize(payload);

    VerifyOrReturnError(payload.size() >= kMinPayloadSize, CHIP_ERROR_INVALID_MESSAGE_LENGTH);
    // To prevent workbuffer usage, appData size needs to be large enough to hold both the appData and the counter
    VerifyOrReturnError(appData.size() >= sizeof(CounterType) + appDataSize, CHIP_ERROR_BUFFER_TOO_SMALL);

    // Decrypt received data
    {
        size_t cursorIndex = 0;

        ByteSpan nonce = payload.SubSpan(cursorIndex, CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES);
        cursorIndex += nonce.size();

        ByteSpan encryptedData = payload.SubSpan(cursorIndex, sizeof(CounterType) + appDataSize);
        cursorIndex += encryptedData.size();

        ByteSpan mic = payload.SubSpan(cursorIndex, CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES);
        cursorIndex += mic.size();

        // Return Invalid message length since the payload isn't the right size
        VerifyOrReturnError(cursorIndex == payload.size(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);

        ReturnErrorOnFailure(Crypto::AES_CCM_decrypt(encryptedData.data(), encryptedData.size(), nullptr, 0, mic.data(), mic.size(),
                                                     aes128KeyHandle, nonce.data(), nonce.size(), appData.data()));
    }

    // Read decrypted counter and application data
    static_assert(sizeof(CounterType) == sizeof(uint32_t), "Expect counter to be 32 bits for correct decoding");
    CounterType tempCounter = Encoding::LittleEndian::Get32(appData.data());

    // Validate that the received nonce is correct
    {
        uint8_t calculatedNonceBuffer[CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES] = { 0 };
        Encoding::LittleEndian::BufferWriter writer(calculatedNonceBuffer, sizeof(calculatedNonceBuffer));

        ReturnErrorOnFailure(GenerateCheckInMessageNonce(hmacKeyHandle, tempCounter, writer));

        // Validate received nonce is the same as the calculated
        ByteSpan nonce = payload.SubSpan(0, CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES);
        VerifyOrReturnError(memcmp(nonce.data(), calculatedNonceBuffer, sizeof(calculatedNonceBuffer)) == 0, CHIP_ERROR_INTERNAL);
    }

    // We have successfully decrypted and validated Check-In message
    // Set output values

    counter = tempCounter;
    // Shift to remove the counter from the appData
    memmove(appData.data(), sizeof(CounterType) + appData.data(), appDataSize);
    appData.reduce_size(appDataSize);

    return CHIP_NO_ERROR;
}

CHIP_ERROR CheckinMessage::GenerateCheckInMessageNonce(const Crypto::Hmac128KeyHandle & hmacKeyHandle, CounterType counter,
                                                       Encoding::LittleEndian::BufferWriter & writer)
{
    VerifyOrReturnError(writer.Available() >= CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES, CHIP_ERROR_BUFFER_TOO_SMALL);

    uint8_t hashWorkBuffer[CHIP_CRYPTO_HASH_LEN_BYTES] = { 0 };
    uint8_t counterBuffer[sizeof(CounterType)];

    // validate that Check-In counter is a uint32_t
    static_assert(sizeof(CounterType) == sizeof(uint32_t), "Expect counter to be 32 bits for correct encoding");
    Encoding::LittleEndian::Put32(counterBuffer, counter);

    chip::Crypto::HMAC_sha shaHandler;
    ReturnErrorOnFailure(
        shaHandler.HMAC_SHA256(hmacKeyHandle, counterBuffer, sizeof(CounterType), hashWorkBuffer, CHIP_CRYPTO_HASH_LEN_BYTES));

    writer.Put(hashWorkBuffer, CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES);
    VerifyOrReturnError(writer.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL);

    return CHIP_NO_ERROR;
}

size_t CheckinMessage::GetAppDataSize(const ByteSpan & payload)
{
    return (payload.size() <= kMinPayloadSize) ? 0 : payload.size() - kMinPayloadSize;
}

} // namespace SecureChannel
} // namespace Protocols
} // namespace chip
