/**
 * @file       five_api.h
 * @brief      FIVE API for Android native applications.
 *
 * Main purpose of this module is providing interface FIVE
 * authentication functions. API is allowed for high-privileged applications.
 * @author     Oleksandr Fadieiev (o.fadieiev@samsung.com)
 * @version    1.0
 * @date       Created Nov 1, 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 __FIVE_API_H__
#define __FIVE_API_H__

#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include "five_codes.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Identify extend structure of integrity label.
 */
#define FIVE_ID_INTEGRITY_LABEL_EX 0xFFFF

/**
 * Represents hash algorithms.
 */
typedef enum {
  FIVE_HASH_ALGO_SHA1   = 2,
  FIVE_HASH_ALGO_SHA256 = 4,
  FIVE_HASH_ALGO_SHA512 = 6
} FiveHashAlgo;

/**
 * Integrity label version.
 */
typedef enum {
  FIVE_LABEL_VERSION1 = 1,
  FIVE_LABEL_VERSION2 = 2
} FiveIntegrityLabelVersion;

/**
 * @brief Simple integrity label.
 */
typedef struct {
  uint16_t length;
  uint8_t data[0];
} __attribute__((packed)) FiveIntegrityLabel;

/**
 * @brief Extend structure of integrity label.
 * @details If field "len" equals 0xffff then
 * it is extend integrity label, otherwise simple integrity label.
 */
typedef struct {
  uint16_t length;
  uint8_t version;
  uint8_t reserved[2];
  uint8_t hash_algo;
  uint8_t hash[64];
  FiveIntegrityLabel label;
} __attribute__((packed)) FiveIntegrityLabelEx;

/**
 * @brief Structure of reset integrity.
 * @details Contains information about the reason of reset task integrity,
 * inode number and file path.
 */
typedef struct {
	uint64_t i_ino;
	FiveIntegrityResetCause cause;
	uint16_t len_file_name;
	char file_name[0];
} __attribute__((packed)) FiveIntegrityResetFile;

/**
 * @brief Verifies fd in asynchronous mode
 * @details FIVE populates signature field to file struct of this fd after this command
 * @warning This checking affects process integrity flag.
 * @param [in] fd File descriptor
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveVerifyFd(int fd);

/**
 * @brief Verifies fd in synchronize mode
 * @details FIVE populates signature field to file struct of this fd after this command
 * @warning This checking affects process integrity flag.
 * @param [in] fd File descriptor
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveVerifyFdSync(int fd);

/**
 * @brief Signs fd
 * @warning The API can be called only from specific applications
 * @param [in] fd File descriptor
 * @param [in] label Label for FIVE signature (used to union files of an application)
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveSignFd(int fd, const FiveIntegrityLabel *label);

/**
 * @brief Signs fd
 * @warning The API can be called only from specific applications
 * @param [in] fd File descriptor
 * @param [in] label Extend label for FIVE signature (used to union files of an application)
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveSignFdEx(int fd, const FiveIntegrityLabelEx *label);

/**
 * @brief Tells FIVE that this file will be signed
 * @warning The API can be called only from specific applications
 * @param [in] fd File descriptor
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveEditFd(int fd);

/**
 * @brief Tells FIVE that this file will be finish signed
 * @warning The API can be called only from specific applications
 * @param [in] fd File descriptor
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveCloseFd(int fd);

/**
 * @brief Allocates integrity label
 * @param [in] data Data which must be used to create new label
 * @param [in] dataLen Length of data
 * @param [out] label Pointer on allocated label
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveLabelAlloc(const char *data, uint16_t dataLen, FiveIntegrityLabel **label);

/**
 * @brief Frees allocated integrity label
 * @param [in] label Pointer on label to free
 */
void FiveLabelFree(FiveIntegrityLabel *label);

/**
 * @brief Allocates extended integrity label
 * @param [in] hash_algo The hash algorithm that is used for calculating hash file
 * @param [in] hash Hash file is calculated by hash_algo
 * @param [in] hash_len Length of hash file
 * @param [in] data Data which must be used to create new label.
 * Notice the data and data_len can be set NULL and 0, it means "system label",
 * usually use for native applications.
 * @param [in] data_len Length of data
 * @param [out] out_label Pointer on allocated extended label
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveExLabelAlloc(FiveHashAlgo hash_algo,
                            const char *hash, uint16_t hash_len,
                            const char *data, uint16_t data_len,
                            FiveIntegrityLabelEx **out_label);

/**
 * @brief Frees allocated extended integrity label
 * @param [in] ex_label Pointer on extended label to free
 */
void FiveExLabelFree(FiveIntegrityLabelEx *ex_label);

/**
 * @brief Gets integrity of task
 * @param [in] pid Process ID of task to read integrity. 0 means "current task"
 * @param [out] tint Integrity of task in case of successful return or nothing if error occurs
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveTaskGetIntegrity(pid_t pid, FiveIntegrity *tint);

/**
 * @brief Reads integrity of task or current state of integrity verification process
 * @param [in] pid Process ID of task to read integrity. 0 means "current task"
 * @param [in] blocked_read Attempt to read synchronously and wait for verification process completion
 * @param [out] tint Integrity of task in case of successful return or nothing if error occurs
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise
 */
FiveResult FiveTaskReadIntegrity(pid_t pid, bool blocked_read,
                                 FiveIntegrity *tint);

/**
 * @brief Reads and allocates integrity label of task
 * @param [in] pid Process ID of task to read label (0 means current task)
 * @param [out] label Pointer on allocated label
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise.
 * NOTES:
 * - Task doesn't have integrity label if label has been set as NULL
 * - Task has "system label" if label->length == 0
 */
FiveResult FiveTaskGetIntegrityLabel(pid_t pid, FiveIntegrityLabel **label);

/**
 * @brief Reads and allocates integrity label of task
 * @param [in] pid Process ID of task to read label (0 means current task)
 * @param [out] reset_file Pointer on allocated the reset file
 * @return ::FIVE_SUCCESS code in case of success and error code otherwise.
 * NOTES:
 * - Task doesn't have information about reset if reset_file has been set as NULL
 */
FiveResult FiveGetResetFile(pid_t pid, FiveIntegrityResetFile **reset_file);

/**
 * @brief Frees allocated the pointer to reset file
 * @param [in] reset_file Pointer on allocated the reset file
 */
void FiveResetFileFree(FiveIntegrityResetFile *reset_file);

#ifdef __cplusplus
}
#endif

#endif // __FIVE_API_H__
