/*
 *
 *    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 defines the CHIP Secure Session object that provides
 *      APIs for encrypting/decryting data using cryptographic keys.
 *
 */

#pragma once

#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPCore.h>
#include <lib/support/Span.h>
#include <transport/raw/MessageHeader.h>

namespace chip {

class DLL_EXPORT CryptoContext
{
public:
    static constexpr size_t kPrivacyNonceMicFragmentOffset = 5;
    static constexpr size_t kPrivacyNonceMicFragmentLength = 11;
    static constexpr size_t kAESCCMNonceLen                = 13;
    using NonceStorage                                     = std::array<uint8_t, kAESCCMNonceLen>;
    using NonceView                                        = FixedSpan<uint8_t, kAESCCMNonceLen>;
    using ConstNonceView                                   = FixedSpan<const uint8_t, kAESCCMNonceLen>;

    CryptoContext();
    ~CryptoContext();
    CryptoContext(CryptoContext &&)      = default;
    CryptoContext(const CryptoContext &) = default;
    CryptoContext(Crypto::SymmetricKeyContext * context) : mKeyContext(context){};
    CryptoContext & operator=(const CryptoContext &) = default;
    CryptoContext & operator=(CryptoContext &&) = default;

    /**
     *    Whether the current node initiated the session, or it is responded to a session request.
     */
    enum class SessionRole
    {
        kInitiator, /**< We initiated the session. */
        kResponder, /**< We responded to the session request. */
    };

    enum class SessionInfoType
    {
        kSessionEstablishment, /**< A new secure session is established. */
        kSessionResumption,    /**< An old session is being resumed. */
    };

    /**
     * @brief
     *   Derive a shared key. The derived key will be used for encrypting/decrypting
     *   data exchanged on the secure channel.
     *
     * @param local_keypair      A reference to local ECP keypair
     * @param remote_public_key  A reference to peer's public key
     * @param salt               A reference to the initial salt used for deriving the keys
     * @param infoType           The info buffer to use for deriving session keys
     * @param role               Role of the new session (initiator or responder)
     * @return CHIP_ERROR        The result of key derivation
     */
    CHIP_ERROR InitFromKeyPair(const Crypto::P256Keypair & local_keypair, const Crypto::P256PublicKey & remote_public_key,
                               const ByteSpan & salt, SessionInfoType infoType, SessionRole role);

    /**
     * @brief
     *   Derive a shared key. The derived key will be used for encrypting/decrypting
     *   data exchanged on the secure channel.
     *
     * @param secret             A reference to the shared secret
     * @param salt               A reference to the initial salt used for deriving the keys
     * @param infoType           The info buffer to use for deriving session keys
     * @param role               Role of the new session (initiator or responder)
     * @return CHIP_ERROR        The result of key derivation
     */
    CHIP_ERROR InitFromSecret(const ByteSpan & secret, const ByteSpan & salt, SessionInfoType infoType, SessionRole role);

    /** @brief Build a Nonce buffer using given parameters for encrypt or decrypt. */
    static CHIP_ERROR BuildNonce(NonceView nonce, uint8_t securityFlags, uint32_t messageCounter, NodeId nodeId);

    /** @brief Build a Nonce buffer using given parameters for encrypt or decrypt. */
    static CHIP_ERROR BuildPrivacyNonce(NonceView nonce, uint16_t sessionId, const MessageAuthenticationCode & mac);

    /**
     * @brief
     *   Encrypt the input data using keys established in the secure channel
     *
     * @param input Unencrypted input data
     * @param input_length Length of the input data
     * @param output Output buffer for encrypted data
     * @param nonce Nonce buffer for encrypt
     * @param header message header structure. Encryption type will be set on the header.
     * @param mac - output the resulting mac
     *
     * @return CHIP_ERROR The result of encryption
     */
    CHIP_ERROR Encrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce, PacketHeader & header,
                       MessageAuthenticationCode & mac) const;

    /**
     * @brief
     *   Decrypt the input data using keys established in the secure channel
     *
     * @param input Encrypted input data
     * @param input_length Length of the input data
     * @param output Output buffer for decrypted data
     * @param nonce Nonce buffer for decrypt
     * @param header message header structure
     * @return CHIP_ERROR The result of decryption
     * @param mac Input mac
     */
    CHIP_ERROR Decrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce,
                       const PacketHeader & header, const MessageAuthenticationCode & mac) const;

    CHIP_ERROR PrivacyEncrypt(const uint8_t * input, size_t input_length, uint8_t * output, PacketHeader & header,
                              MessageAuthenticationCode & mac) const;

    CHIP_ERROR PrivacyDecrypt(const uint8_t * input, size_t input_length, uint8_t * output, const PacketHeader & header,
                              const MessageAuthenticationCode & mac) const;

    ByteSpan GetAttestationChallenge() const { return ByteSpan(mKeys[kAttestationChallengeKey], Crypto::kAES_CCM128_Key_Length); }

    /**
     * @brief
     *   Memory overhead of encrypting data. The overhead is independent of size of
     *   the data being encrypted. The extra space is used for storing the common header.
     *
     * @return number of bytes.
     */
    size_t EncryptionOverhead();

    bool IsInitiator() const { return mKeyAvailable && mSessionRole == SessionRole::kInitiator; }

    bool IsResponder() const { return mKeyAvailable && mSessionRole == SessionRole::kResponder; }

private:
    typedef uint8_t CryptoKey[Crypto::kAES_CCM128_Key_Length];

    enum KeyUsage
    {
        kI2RKey                  = 0,
        kR2IKey                  = 1,
        kAttestationChallengeKey = 2,
        kNumCryptoKeys           = 3
    };

    SessionRole mSessionRole;

    bool mKeyAvailable;
    CryptoKey mKeys[KeyUsage::kNumCryptoKeys];
    Crypto::SymmetricKeyContext * mKeyContext = nullptr;

    // Use unencrypted header as additional authenticated data (AAD) during encryption and decryption.
    // The encryption operations includes AAD when message authentication tag is generated. This tag
    // is used at the time of decryption to integrity check the received data.
    static CHIP_ERROR GetAdditionalAuthData(const PacketHeader & header, uint8_t * aad, uint16_t & len);
};

} // namespace chip
