/**
 * @file lib_common.h
 *
 * @brief This file contains function prototypes and types that is common for all tc
 *        tm and td modules
 *
 * @copyright Copyright 2023 Antaris, Inc.
 *
 * 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.
 *        usage of TC TM Library APIs
 */

#ifndef IPCC_LIB_COMMON_H_
#define IPCC_LIB_COMMON_H_

#include <stdint.h>
#include <time.h>
#include <checksum.h>

#ifdef __cplusplus
extern "C" {
#endif

#define IPCC_EXT_BIT_MASK    0x80
#define IPCC_EXT_BIT_POS     0x7

/// Error code definitions
#define LIB_COMMON_OK                    INT8_C(0)     ///< Success return value
#define LIB_COMMON_NULL_PTR              INT8_C(-1)    ///< Null pointer return value
#define LIB_COMMON_CRYPT_UNSUPPORTED     INT8_C(-2)    ///< Unsupported encryption decryption type
#define SHA256_HASH_SIZE                 (256 / 8)     ///< hash key size

/// Encryption decryption functionality codes

/** 
  * @brief  GPIO Bit SET and Bit RESET enumeration
  */
typedef enum
{
  IPCC_CRYPT_AES_CFB8 = 0,                ///< AES-CFB8 encryption or decryption
  IPCC_CRYPT_AES_CFB8128                  ///< AES-CFB128 encryption or decryption
}e_ipcc_crypt_mode;

typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;

typedef int int32;
typedef short int16;
typedef char int8;

typedef struct
{
    uint8 iv[16];
    uint8 *key;
    size_t key_size;
    e_ipcc_crypt_mode encrypt_mode;
}s_ipcc_crypt_params;

/**
 * @brief Utility structure that helps in searching routing table
 */
typedef struct ipcc_node_struct
{
    uint16 da_id;                 /*!< destination application id */
    void* route_param;            /*!< ptr to routing table */
    struct node_struct *nxt;      /*!< ptr that holds the addr of next node */
}s_node;


/**
 * @brief Control field info structure
 */
typedef struct ipcc_ctrl
{
    uint8_t source_dest : 1;    /*!< Source Destination identifier */
    uint8_t tx_mode     : 1;    /*!< Transmit or re-transmit mode */
    uint8_t comm_mode   : 2;    /*!< cast modes */
    uint8_t auth        : 1;    /*!< Authenticated/Unautheticated */
    uint8_t encrypt     : 1;    /*!< Unencrypted/Encrypted */
    uint8_t reserved_1  : 1;    /*!< Reserved */
    uint8_t reserved_2  : 1;    /*!< Reserved */
}s_ipcc_ctrl;

/**
 * @brief Utility data type to populate s_ipcc_ctrl structure
 */
typedef union
{
    s_ipcc_ctrl ctrl;          /*!< s_ipcc_ctrl structure instance */
    uint8 byte;                /*!< 8 bit utility variable  */
}s_ipcc_ctrl_util;

/**
 * @brief This API returns utc epoch time.
 *
 * @param[in] : void
 *
 * @return epoch time
 * @retval epoch time
 */
time_t ipcc_get_utc_epoch(void);

/**
 * @brief Copies 1 or 2 bytes from the src buffer to dst depending on the
 *        src data. If data is greater than 127, the extension bit (7th bit)
 *        is set and 2 bytes of data is copied to the destination.
 *
 * @param[in] src   : Pointer to source data.
 * @param[out] dst  : Pointer to the destination
 * @param[in] size  : size of the source dara
 *
 * @return size of data copied to destination pointer
 * @retval greather than zero -> Success / TC_NULL_PTR -> Error.
 */
uint16 ipcc_set_extnd_val_16(const uint16 *src, uint8 *dst, size_t size);

/**
 * @brief Copies 1 or 2 bytes from the src buffer to dst depending on the
 *        src data extension bit. If the extension bit (7th bit) is set,
 *        2 bytes of data is copied to the destination else 1 byte is copied
 *
 * @param[in] src   : Pointer to source data.
 * @param[out] dst  : Pointer to the destination
 * @param[in] size  : size of the source dara
 *
 * @return size of data copied to destination pointer
 * @retval greather than zero -> Success / TC_NULL_PTR -> Error.
 */
uint16 ipcc_get_extnd_val_16(const uint8 *src, uint16 *dst, size_t size);

/**
 * @brief This API calculates the hmac with the key and key size
 *         for the passed in buffer of size "datasize" and store
 *         the computed hmac value to the out parameter
 *
 * @param[in] data : Input buffer for which the hmac needs to be calculated
 * @param[in] key     : Key used for the calculation of the hmac
 * @param[in] keysize : size of the input key
 * @param[in] datasize : size of the input buffer
 * @param[out] out    : Pointer to the computed hmac.
 *
 * @return Computed hmac length
 * @retval greather than zero -> success / LIB_COMMON_NULL_PTR  -> Error.
 */
size_t ipcc_compute_hmac (const uint8* data, const uint8* key, const uint32 keysize, const uint32 datasize, void* out);

/**
 * @brief This API encrypts the passed in buffer of size "length" based on the
 *        input encryption "param" and stores the encrypted buffer to the
 *        "output" parameter
 *
 * @param[in] param   : Structure instance of s_ipcc_crypt_params.
 * @param[in] buf     : Input buffer to be encrypted
 * @param[in] length  : size of the input buffer
 * @param[out] output : Pointer to the encrypted buffer.
 *
 * @return Result of API execution status
 * @retval Zero -> Success / LIB_COMMON_NULL_PTR -> Input null pointer
 *         LIB_COMMON_CRYPT_UNSUPPORTED-> If unsupported encryption
 *         method is selected.
 */
int32 ipcc_aes_encrypt_data(s_ipcc_crypt_params *param, const uint8 *buf, int32 length, uint8 *output);

/**
 * @brief This API decrypts the passed in buffer of size "length" based on the
 *        input decryption "param" and stores the decrypted buffer to the
 *        "output" parameter
 *
 * @param[in] param   : Structure instance of s_ipcc_crypt_params.
 * @param[in] buf     : Input buffer to be decrypted
 * @param[in] length  : size of the input buffer
 * @param[out] output : Pointer to the decrypted buffer.
 *
 * @retval Zero -> Success / LIB_COMMON_NULL_PTR -> Input null pointer
 *         LIB_COMMON_CRYPT_UNSUPPORTED-> If unsupported encryption
 *         method is selected.
 */
int32 ipcc_aes_decrypt_data(s_ipcc_crypt_params *param, const uint8 *buf, int32 length, uint8 *output);

#ifdef __cplusplus
}
#endif
#endif /* LIB_COMMON_H_ */
