/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2021 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#ifndef NDN_CXX_SECURITY_KEY_PARAMS_HPP
#define NDN_CXX_SECURITY_KEY_PARAMS_HPP

#include "ndn-cxx/security/security-common.hpp"
#include "ndn-cxx/name-component.hpp"

namespace ndn {

/**
 * @brief Base class for key parameters.
 *
 * Its subclasses are used to store parameters for key generation.
 */
class KeyParams
{
public:
  class Error : public std::runtime_error
  {
  public:
    using std::runtime_error::runtime_error;
  };

  virtual
  ~KeyParams();

  KeyType
  getKeyType() const
  {
    return m_keyType;
  }

  KeyIdType
  getKeyIdType() const
  {
    return m_keyIdType;
  }

  const name::Component&
  getKeyId() const
  {
    return m_keyId;
  }

  void
  setKeyId(const name::Component& keyId)
  {
    m_keyId = keyId;
  }

protected:
  /**
   * @brief Constructor
   *
   * @param keyType Type of the created key
   * @param keyIdType The method how the key id should be generated; must not be
   *                  KeyIdType::USER_SPECIFIED
   */
  KeyParams(KeyType keyType, KeyIdType keyIdType);

  /**
   * @brief Constructor
   *
   * @param keyType Type of the created key
   * @param keyId The user-specified key id. The keyIdType will be set to KeyIdType::USER_SPECIFIED.
   *              keyId MUST NOT be the empty component.
   * @post getKeyIdType() == KeyIdType::USER_SPECIFIED
   */
  KeyParams(KeyType keyType, const name::Component& keyId);

private:
  KeyType m_keyType;
  KeyIdType m_keyIdType;
  name::Component m_keyId;
};


namespace detail {

/// @brief RsaKeyParamInfo is used to instantiate SimplePublicKeyParams for RSA keys.
class RsaKeyParamsInfo
{
public:
  static constexpr KeyType
  getType()
  {
    return KeyType::RSA;
  }

  /**
   * @brief check if @p size is valid and supported for this key type.
   *
   * @throw KeyParams::Error if the key size is not supported.
   */
  static uint32_t
  checkKeySize(uint32_t size);

  static uint32_t
  getDefaultSize();
};

/// @brief EcKeyParamInfo is used to instantiate SimplePublicKeyParams for elliptic curve keys.
class EcKeyParamsInfo
{
public:
  static constexpr KeyType
  getType()
  {
    return KeyType::EC;
  }

  /**
   * @brief check if @p size is valid and supported for this key type.
   *
   * @throw KeyParams::Error if the key size is not supported.
   */
  static uint32_t
  checkKeySize(uint32_t size);

  static uint32_t
  getDefaultSize();
};

} // namespace detail


/// @brief SimplePublicKeyParams is a template for public keys with only one parameter: size.
template<typename KeyParamsInfo>
class SimplePublicKeyParams : public KeyParams
{
public:
  /// @brief Create key parameters with user-specified key id.
  explicit
  SimplePublicKeyParams(const name::Component& keyId,
                        uint32_t size = KeyParamsInfo::getDefaultSize())
    : KeyParams(KeyParamsInfo::getType(), keyId)
  {
    setKeySize(size);
  }

  /**
   * @brief Create key parameters with auto-generated key id.
   *
   * This method is used only if user does not want to maintain the uniqueness of key name.
   * By default, an 8-byte random number will be used as key id.
   */
  explicit
  SimplePublicKeyParams(uint32_t size = KeyParamsInfo::getDefaultSize(),
                        KeyIdType keyIdType = KeyIdType::RANDOM)
    : KeyParams(KeyParamsInfo::getType(), keyIdType)
  {
    setKeySize(size);
  }

  uint32_t
  getKeySize() const
  {
    return m_size;
  }

private:
  void
  setKeySize(uint32_t size)
  {
    m_size = KeyParamsInfo::checkKeySize(size);
  }

  uint32_t
  getDefaultKeySize() const
  {
    return KeyParamsInfo::getDefaultSize();
  }

private:
  uint32_t m_size;
};

/// @brief RsaKeyParams carries parameters for RSA key.
typedef SimplePublicKeyParams<detail::RsaKeyParamsInfo> RsaKeyParams;

/// @brief EcKeyParams carries parameters for EC key.
typedef SimplePublicKeyParams<detail::EcKeyParamsInfo> EcKeyParams;


namespace detail {

/// @brief AesKeyParamsInfo is used to instantiate SimpleSymmetricKeyParams for AES keys.
class AesKeyParamsInfo
{
public:
  static constexpr KeyType
  getType()
  {
    return KeyType::AES;
  }

  /**
   * @brief check if @p size is valid and supported for this key type.
   *
   * @throw KeyParams::Error if the key size is not supported.
   */
  static uint32_t
  checkKeySize(uint32_t size);

  static uint32_t
  getDefaultSize();
};

/// @brief HmacKeyParamsInfo is used to instantiate SimpleSymmetricKeyParams for HMAC keys.
class HmacKeyParamsInfo
{
public:
  static constexpr KeyType
  getType()
  {
    return KeyType::HMAC;
  }

  /**
   * @brief check if @p size is valid and supported for this key type.
   *
   * @throw KeyParams::Error if the key size is not supported.
   */
  static uint32_t
  checkKeySize(uint32_t size);

  static uint32_t
  getDefaultSize();
};

} // namespace detail


/// @brief SimpleSymmetricKeyParams is a template for symmetric keys with only one parameter: size.
template<typename KeyParamsInfo>
class SimpleSymmetricKeyParams : public KeyParams
{
public:
  /// @brief Create key parameters with user-specified key id.
  explicit
  SimpleSymmetricKeyParams(const name::Component& keyId,
                           uint32_t size = KeyParamsInfo::getDefaultSize())
    : KeyParams(KeyParamsInfo::getType(), keyId)
  {
    setKeySize(size);
  }

  /**
   * @brief Create key parameters with auto-generated key id.
   *
   * This method is used only if user does not want to maintain the uniqueness of key name.
   * By default, an 8-byte random number will be used as key id.
   */
  explicit
  SimpleSymmetricKeyParams(uint32_t size = KeyParamsInfo::getDefaultSize(),
                           KeyIdType keyIdType = KeyIdType::RANDOM)
    : KeyParams(KeyParamsInfo::getType(), keyIdType)
  {
    setKeySize(size);
  }

  uint32_t
  getKeySize() const
  {
    return m_size;
  }

private:
  void
  setKeySize(uint32_t size)
  {
    m_size = KeyParamsInfo::checkKeySize(size);
  }

  uint32_t
  getDefaultKeySize() const
  {
    return KeyParamsInfo::getDefaultSize();
  }

private:
  uint32_t m_size;
};

/// @brief AesKeyParams carries parameters for AES key.
typedef SimpleSymmetricKeyParams<detail::AesKeyParamsInfo> AesKeyParams;

/// @brief HmacKeyParams carries parameters for HMAC key.
typedef SimpleSymmetricKeyParams<detail::HmacKeyParamsInfo> HmacKeyParams;

} // namespace ndn

#endif // NDN_CXX_SECURITY_KEY_PARAMS_HPP
