
/*
 * =====================================================================================
 *
 *       Filename:  hdm_utils.h
 *
 *    Description:  HDM utils functions
 *
 *        Version:  1.0
 *        Created:  09/16/2019 15:26:11 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *        Company:  Samsung Electronics
 *        Copyright (c) 2015 by Samsung Electronics, All rights reserved.
 *
 * =====================================================================================
 */

#ifndef _HDM_UTILS_H_
#define _HDM_UTILS_H_

/**
 * Conditional includes
 */
#ifdef CONFIG_QSEE
#else
#include "tees_secure_object.h"
#endif

/**
 * HDM includes
 */
#include "tz_hdm_interface.h"
#include "hdm_defs.h"
#include "hdm_drk.h"
#include "hdm_x509.h"
#include "hdm_core.h"

/**
 * External includes
 */
#include "TZ_Vendor_tl.h"
#include <openssl/x509v3.h>
#include <openssl/crypto.h>

/**
 * String fields verification parameters
 */
#define MIN_STRING_FIELD_LEN  2

/**
 * Fit to uint32_t macro
 */
#define FIT_TO_UINT32(X) (X >= 0 && X <= 0xFFFFFFFF) ? (uint32_t)X : 0

/**
 * @brief
 * hex2int
 * Converts hexadecimal to integer
 *
 * @param[in] *hex - hexadecimal number
 * @return Integer
 */
int64_t hex2int(uint8_t *hex);

/**
 * @brief
 * check_policy_version
 * Check if policu version if greater than RPMB policy version
 *
 * @param[in] payload     - policy payload
 * @param[in] *rpmb_data  - rpmb data
 * @return HDM status code
 */
hdm_return_code_t check_policy_version(tz_hdm_payload_t payload, tz_hdm_rpmb_t *rpmb_data);

/**
 * @brief
 * check_hdm_magic
 * Check if HDM is activated, or not
 *
 * @param[in] *rpmb_data - RPMB data
 * @return HDM status code
 */
hdm_return_code_t check_hdm_magic(tz_hdm_rpmb_t *rpmb_data);

/**
 * @brief
 * get_rpmb_version
 * return rpmb data version for data migration
 *
 * @param[in] *rpmb_data - RPMB data
 * @return HDM rpmb version
 */
uint32_t get_rpmb_version(tz_hdm_rpmb_t *rpmb_data);

/**
 * @brief
 * check_device_id
 * Check if device id in payload matches device id in RPMB
 *
 * @param[in] payload     - policy payload
 * @param[in] *rpmb_data  - rpmb data
 * @return HDM status code
 */
hdm_return_code_t check_device_id(tz_hdm_payload_t payload, tz_hdm_rpmb_t *rpmb_data);

/**
 * @brief
 * get_curr_service_index
 * Get current service index in RPMB
 * This API should called after hdm_rpmb_read is called
 * index is stored in current_service_index.
 *
 * @param[in] rpmb_data - RPMB data
 * @param[in] *name - service name
 * @return HDM status code
 */
hdm_return_code_t get_curr_service_index(tz_hdm_rpmb_t rpmb_data, uint8_t *name);

#ifdef CONFIG_QSEE
/**
 * @brief
 * hdm_get_status
 * return rpmb data
 *
 * @param[in] rpmb_data - RPMB data
 * @param[out] *buffer - return buffer
 * @param[in] buff_size - return buffer size
 * @return return length
 */
uint32_t hdm_get_status(tz_hdm_rpmb_t rpmb_data, uint8_t *buffer, uint32_t buff_size);
#endif

/**
 * @brief
 * hdm_is_need_reboot
 * When some subsystem is unlocked, reboot is necessary
 * changed policy = bl policy ^ applied policy
 * unlocked policy = changed policy & bl policy
 * reboot policy = unlocked policy & HDM_SUBSYS_NEED_REBOOT
 *
 * @param[in]  applied_policy - applied policy
 *
 * @return if reboot is necessary or not
 */
uint32_t hdm_is_need_reboot(uint32_t applied_policy);

/**
 * @brief
 * Check nextReboot flag
 * 
 * @param[in] device_block - device_block policy
 * @param[in] service_name - service name of policy
 * 
 * @return HDM status code
 */
uint32_t isNextReboot(uint32_t device_block, uint8_t* service_name);

/**
 * @brief
 * hdm_check_jws_string_field
 * Check if is empty
 * Check length
 *
 * @param [in] string_field - String field
 * @return HDM status code
 */
hdm_return_code_t hdm_check_jws_string_field(uint8_t *string_field, uint8_t *type);

/**
 * @brief
 * get_error_string
 * Get error string from error code
 *
 * @param[in] error_code - Error code
 *
 * @return The error string
 */
uint8_t* get_error_string(uint32_t error_code);

/**
 * @brief
 * hex_to_byte_stream
 * Transforms given HEX input string into a
 * byte formatted stream.
 *
 * @param[in]  hex_string - representation of HEX number
 * @param[in]  str_len    - length of the HEX string
 * @param[out] buff       - output pointer to the byte stream
 *
 * @return nothing
 */
void hex_to_byte_stream(uint8_t hex_string[], int str_len,
                        uint8_t **buff);

/**
 * @brief
 * change string "\x5cn" to "\n".
 *
 * @param[in/out]  certificate - pointer to certificate
 *
 * @return nothing
 */
void settle_certificate_to_openssl(uint8_t *certificate);

/**
 * @brief
 * merge all policies that don't belong to a "service name"
 * 
 * @param[in] service_name - name of the service to exclude from merge
 * @param[out] merged_policy - pointer to store merged policies
 * 
 * @return HDM status code
 */
hdm_return_code_t merge_rpmb_policies_service_name(uint8_t *service_name, uint32_t *merged_policy);

/**
 * @brief
 * merge all policies stored in RPMB
 * 
 * @param[out] merged_policy - pointer to store merged policy
 * 
 * @return HDM status code
 */
hdm_return_code_t merge_rpmb_policies(uint32_t *merged_policy);

/**
 * Debug functions prototypes
 */
#ifdef DEBUG_HDM
void dump_jws_header(tz_hdm_header_t *header);
void dump_jws_payload(tz_hdm_payload_t *payload);
void dump_jws_sinature(tz_hdm_signature_t *signature);
void dump_rpmb_data(tz_hdm_rpmb_t *rpmb_data);
void printRange(uint8_t *buff, int len, char *tag);
#endif /* DEBUG_HDM */

#endif /* _HDM_UTILS_H_ */
