/**
 * @file       crypto.h
 * @brief      Crypto functions for PA driver module
 * @author     Oleksandr Kanievskyi (o.kanievskyi@samsung.com)
 * @version    1.0
 * @date       Created July 14, 2016
 * @copyright  In Samsung Ukraine R&D Center (SURC) under a contract between
 * @copyright  LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine) and
 * @copyright  "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
 * @copyright  Copyright: (c) Samsung Electronics Co, Ltd 2016. All rights reserved.
**/

#ifndef PA_TZ_DRV_SRC_CRYPTO_H_
#define PA_TZ_DRV_SRC_CRYPTO_H_

#include "pa_tz_api.h"

/**
 *  @brief Enumeration type that contains
 *  basic hash types
 */
typedef enum {
  kSha1 = 0x00,
  kSha224,
  kSha256,
  kSha384,
  kSha512
} HashType;

/**
 * @brief Sizes of hash digest
 */
enum {
  kSha1Size = 20,
  kSha224Size = 28,
  kSha256Size = 32,
  kSha384Size = 48,
  kSha512Size = 64,
  kHashMaxSize = 64
};

/**
 *  @brief Enumeration type that contains
 *  basic RSA key types
 */
typedef enum {
  kRSA1024 = 0x00,
  kRSA2048,
  kRSA3072
} RsaKeyType;

/**
 *  @brief Modulus and public exponent are the part of
 *  public key in RSA cryptosystem
 */
typedef struct StructRsaPublicKey {
  const uint8_t *modulus;
  size_t modulus_size;
  const uint8_t *public_exponent;
  size_t exponent_size;
  RsaKeyType key_type;
} RsaPublicKey;

/**
 * @brief Verifies signature in config
 * @param [in] data Data to be verified
 * @param [in] data_len Data size
 * @param [in] signature Signature to be verified
 * @param [in] signature_len Signature size
 * @param [in] public_key Key for signature verification
 * @return ::PA_TZ_SUCCESS if verified
 * ::PA_TZ_GENERAL_ERROR if input arguments are incorrect,
 * ::PA_TZ_SINGATURE_VALIDATION_FAILURE if signature is incorrect
 */
PaTzResult RsaSignatureVerification(const uint8_t *data, size_t data_len,
                                    const uint8_t *signature, size_t singature_len,
                                    const RsaPublicKey *public_key, HashType hash_type);

/**
 * @brief Returns size of RSA key in bytes
 * @param [in] type Type of RSA key
 * @return value bigger than 0 if success, 0 otherwise
 */
size_t CryptoGetRsaSignatureSize(RsaKeyType type);

/**
 * @brief Returns size of hash in bytes
 * @param [in] type Hash type
 * @return value bigger than 0 if success, 0 otherwise
 */
size_t CryptoGetHashSize(HashType type);

/**
 * @brief Generate HMAC signature
 * @param [in] data,data_length Data
 * @param [in] hash_type Hash type (only SHA256 is supported now)
 * @param [out] signature,signature_length Output signature, signature_length
 * should be at least size of hash_type
 * @return ::PA_TZ_SUCCESS if verified, code of error in other case
 */
PaTzResult CryptoHmacSignatureGenerate(const uint8_t *data, size_t data_length,
                                       HashType hash_type,
                                       uint8_t *signature, size_t *signature_length);

/**
 * @brief Check HMAC signature
 * @param [in] data,data_length Data
 * @param [in] hash_type Hash type
 * @param [in] signature,signature_length Signature
 * @return ::PA_TZ_SUCCESS if verified, code of error in other case
 */

PaTzResult CryptoHmacSignatureVerification(const uint8_t *data, size_t data_length,
                                           HashType hash_type,
                                           const uint8_t *signature, size_t signature_length);

/**
 * @brief Calculates SHA256 algorithm.
 * @param [in] data, data_length Memory input data.
 * @param [out] out_md Hash value (size of 32 bytes).
 * @return ::PA_TZ_SUCCESS if hash was calculated successfully,
 * ::PA_TZ_GENERAL_ERROR if arguments are incorrect or another code of error
 */
PaTzResult CryptoSha256(const uint8_t *data, size_t data_length, uint8_t *out_md);

#endif // PA_TZ_DRV_SRC_CRYPTO_H_
