#pragma once

#include "crypt_algo.hpp"
#include "integrity_algo.hpp"

#include <array>
#include <cstddef>
#include <string>
#include <vector>

namespace cipher
{
namespace rakp_auth
{
constexpr size_t USER_KEY_MAX_LENGTH = 20;
constexpr size_t BMC_RANDOM_NUMBER_LEN = 16;
constexpr size_t REMOTE_CONSOLE_RANDOM_NUMBER_LEN = 16;
extern const std::string userName;

/**
 * @enum RAKP Authentication Algorithms
 *
 * RMCP+ Authenticated Key-Exchange Protocol (RAKP)
 *
 * RAKP-None is not supported as per the following recommendation
 * (https://www.us-cert.gov/ncas/alerts/TA13-207A)
 * ("cipher 0" is an option enabled by default on many IPMI enabled devices that
 * allows authentication to be bypassed.  Disable "cipher 0" to prevent
 * attackers from bypassing authentication and sending arbitrary IPMI commands.)
 */
enum class Algorithms : uint8_t
{
    RAKP_NONE = 0,    // Mandatory (implemented, not supported)
    RAKP_HMAC_SHA1,   // Mandatory (implemented, default choice in ipmitool)
    RAKP_HMAC_MD5,    // Optional (not implemented)
    RAKP_HMAC_SHA256, // Optional (implemented, best available)
    // Reserved used to indicate an invalid authentication algorithm
    RAKP_HMAC_INVALID = 0xB0
};

/**
 * @class Interface
 *
 * Interface is the base class for the Authentication Algorithms.
 * The Authentication Algorithm specifies the type of authentication “handshake”
 * process that is used and identifies any particular variations of hashing or
 * signature algorithm that is used as part of the process.
 *
 */
class Interface
{
  public:
    explicit Interface(integrity::Algorithms intAlgo,
                       crypt::Algorithms cryptAlgo) :
        intAlgo(intAlgo),
        cryptAlgo(cryptAlgo)
    {}

    Interface() = delete;
    virtual ~Interface() = default;
    Interface(const Interface&) = default;
    Interface& operator=(const Interface&) = default;
    Interface(Interface&&) = default;
    Interface& operator=(Interface&&) = default;

    /**
     * @brief Generate the Hash Message Authentication Code
     *
     * This API is invoked to generate the Key Exchange Authentication Code
     * in the RAKP2 and RAKP4 sequence and for generating the Session
     * Integrity Key.
     *
     * @param input message
     *
     * @return hash output
     *
     * @note The user key which is the secret key for the hash operation
     *        needs to be set before this operation.
     */
    std::vector<uint8_t> virtual generateHMAC(
        const std::vector<uint8_t>& input) const = 0;

    /**
     * @brief Generate the Integrity Check Value
     *
     * This API is invoked in the RAKP4 sequence for generating the
     * Integrity Check Value.
     *
     * @param input message
     *
     * @return hash output
     *
     * @note The session integrity key which is the secret key for the
     *        hash operation needs to be set before this operation.
     */
    std::vector<uint8_t> virtual generateICV(
        const std::vector<uint8_t>& input) const = 0;

    /**
     * @brief Check if the Authentication algorithm is supported
     *
     * @param[in] algo - authentication algorithm
     *
     * @return true if algorithm is supported else false
     *
     */
    static bool isAlgorithmSupported(Algorithms algo)
    {
        if (algo == Algorithms::RAKP_HMAC_SHA256)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    // User Key is hardcoded to PASSW0RD till the IPMI User account
    // management is in place.
    std::array<uint8_t, USER_KEY_MAX_LENGTH> userKey = {"0penBmc"};

    // Managed System Random Number
    std::array<uint8_t, BMC_RANDOM_NUMBER_LEN> bmcRandomNum;

    // Remote Console Random Number
    std::array<uint8_t, REMOTE_CONSOLE_RANDOM_NUMBER_LEN> rcRandomNum;

    // Session Integrity Key
    std::vector<uint8_t> sessionIntegrityKey;

    /**
     * Integrity Algorithm is activated and set in the session data only
     * once the session setup is succeeded in the RAKP34 command. But the
     * integrity algorithm is negotiated in the Open Session Request command
     * . So the integrity algorithm successfully negotiated is stored
     * in the authentication algorithm's instance.
     */
    integrity::Algorithms intAlgo;

    /**
     * Confidentiality Algorithm is activated and set in the session data
     * only once the session setup is succeeded in the RAKP34 command. But
     * the confidentiality algorithm is negotiated in the Open Session
     * Request command. So the confidentiality algorithm successfully
     * negotiated is stored in the authentication algorithm's instance.
     */
    crypt::Algorithms cryptAlgo;
};

/**
 * @class AlgoSHA1
 *
 * RAKP-HMAC-SHA1 specifies the use of RAKP messages for the key exchange
 * portion of establishing the session, and that HMAC-SHA1 (per [RFC2104]) is
 * used to create 20-byte Key Exchange Authentication Code fields in RAKP
 * Message 2 and RAKP Message 3. HMAC-SHA1-96(per [RFC2404]) is used for
 * generating a 12-byte Integrity Check Value field for RAKP Message 4.
 */

class AlgoSHA1 : public Interface
{
  public:
    static constexpr size_t integrityCheckValueLength = 12;

    explicit AlgoSHA1(integrity::Algorithms intAlgo,
                      crypt::Algorithms cryptAlgo) :
        Interface(intAlgo, cryptAlgo)
    {}

    AlgoSHA1() = delete;
    ~AlgoSHA1() = default;
    AlgoSHA1(const AlgoSHA1&) = default;
    AlgoSHA1& operator=(const AlgoSHA1&) = default;
    AlgoSHA1(AlgoSHA1&&) = default;
    AlgoSHA1& operator=(AlgoSHA1&&) = default;

    std::vector<uint8_t>
        generateHMAC(const std::vector<uint8_t>& input) const override;

    std::vector<uint8_t>
        generateICV(const std::vector<uint8_t>& input) const override;
};

/**
 * @class AlgoSHA256
 *
 * RAKP-HMAC-SHA256 specifies the use of RAKP messages for the key exchange
 * portion of establishing the session, and that HMAC-SHA256 (per [FIPS 180-2]
 * and [RFC4634] and is used to create a 32-byte Key Exchange Authentication
 * Code fields in RAKP Message 2 and RAKP Message 3. HMAC-SHA256-128 (per
 * [RFC4868]) is used for generating a 16-byte Integrity Check Value field for
 * RAKP Message 4.
 */

class AlgoSHA256 : public Interface
{
  public:
    static constexpr size_t integrityCheckValueLength = 16;

    explicit AlgoSHA256(integrity::Algorithms intAlgo,
                        crypt::Algorithms cryptAlgo) :
        Interface(intAlgo, cryptAlgo)
    {}

    ~AlgoSHA256() = default;
    AlgoSHA256(const AlgoSHA256&) = default;
    AlgoSHA256& operator=(const AlgoSHA256&) = default;
    AlgoSHA256(AlgoSHA256&&) = default;
    AlgoSHA256& operator=(AlgoSHA256&&) = default;

    std::vector<uint8_t>
        generateHMAC(const std::vector<uint8_t>& input) const override;

    std::vector<uint8_t>
        generateICV(const std::vector<uint8_t>& input) const override;
};

} // namespace rakp_auth

} // namespace cipher
