
/*
 * =====================================================================================
 *
 *       Filename:  pebble_core.h
 *
 *    Description:  PEBBLE core functions
 *
 *        Version:  1.0
 *        Created:  06/03/2020
 *       Revision:  none
 *       Compiler:  gcc
 *
 *        Company:  Samsung Electronics
 *        Copyright (c) 2020 by Samsung Electronics, All rights reserved.
 *
 * =====================================================================================
 */

#ifndef _PEBBLE_CORE_H_
#define _PEBBLE_CORE_H_

/**
 * Conditional includes
 */
#ifdef CONFIG_QSEE
#include "tz_iccc_comdef.h"
#else
#include "debug_log.h"
#include "Iccc_Interface.h"
#include "icccOperations.h"
#endif

/**
 * PEBBLE includes
 */
#include "tz_pebble_interface.h"
#include "pebble_defs.h"
#include "pebble_utils.h"
#include "pebble_x509.h"
#include "pebble_drk.h"
#include "pebble_platform_interface.h"
#include "pebble_sss.h"

/**
 * External includes
 */
#include <openssl/base.h>
#include "TZ_Vendor_tl.h"

/**
 * @brief
 * check_jws_struct
 * Verify and parse PEBBLE JWS policy
 *
 * - Check JWS length
 * - Split base64 JWS
 * - Decode base64 JWS header
 * - Parse JWS header
 * - Validate x509 certificates chains
 * - Decode base64 signature
 * - Parse JWS signature
 * - Validate jws signature
 * - Decode base64 payload
 * - Parse payload
 * - Check DRK certificate
 * - Validate DRKv2 device id
 * - Check policy version
 * - Copy policy to response
 *
 * @param[in] *tci_msg - tci message
 * @return PEBBLE status code
 */
pebble_return_code_t check_jws_struct(tci_message_t *tci_msg);

/**
 * @brief
 * pebble_ICCC_check
 *
 * Verify device integrity with ICCC device status API
 * @return PEBBLE status code
 */
pebble_return_code_t pebble_ICCC_check(void);

/**
 * @brief
 * pebble_ICCC_check_em_status
 *
 * Verify device EM Status with ICCC read data API
 * - em_status = 0x0 -> PROD device
 * - em_status = 0x1 -> DEV  device
 * - em_status = 0x2 -> Eng token is installed on PROD device
 *
 * @param[out] em_status - EM Status value
 * @return PEBBLE Status
 */
pebble_return_code_t pebble_ICCC_check_em_status(uint32_t *em_status);

/**
 * @brief
 * load key and cert chain for pebble TA
 *
 * @param[in] *tci_msg - tci message
 * @return PEBBLE status code
 */
pebble_return_code_t load_cert(tci_message_t *cmd, tci_message_t *resp);

/*
 * generate a random 256 bit master key, (1) encrypt it with TA, (2) wrap it with Android KeyStore public key
 * Input: cmd (type gen_master_key_cmd_t) contains AES-GCM AAD(gcm_aad), Android Key Store certificate chain.
 * Output: resp (type gen_master_key_resp_t) contains master key wrapped by TA, master key encrypted by AES-GCM (secret_ct, gcm_iv, gcm_tag), aes key encrypted (wrapped_gcm_key) by provided public key.
 */
pebble_return_code_t generate_master_key_and_wrap_it(tci_message_t *cmd, tci_message_t *resp);

/*
 * derive a 256 bit sub key from given master key
 * Input: cmd (type derive_subkey_cmd_t) contains wrapped master key, subkey alias, gcm aad, certificate chain
 * Output: resp (type derive_subkey_resp_t) contains subkey encrypted by AES-GCM (secret_ct, gcm_iv, gcm_tag), aes key encrypted (wrapped_gcm_key) by provided public key.
 */
pebble_return_code_t derive_subkey_and_wrap_it(tci_message_t *cmd, tci_message_t *resp);

/*
 * generate challenge (base64 encoded 16 random bytes) for Android Key Store certificate
 * Input: cmd (type gen_atn_nonce_cmd_t) contains len (required challenge length which is not used now) 
 * Output: resp (type gen_atn_nonce_resp_t) contains nonce (base64 encoded 16 random bytes)
 */
pebble_return_code_t gen_atn_nonce(tci_message_t *cmd, tci_message_t *resp);

/**
 *  TODO let load_cert() in pebble_core.c set up a global variable: drk_rsa_private_key_t priv_key
 *  (or return it as a local variable then pass it to the following functions).
 *  Input: wrapped master key, buddies' cert chains, self private key
 *  Output:
 */
pebble_return_code_t gen_backup_req(tci_message_t *cmd, tci_message_t *resp);

/**
 * Input: backup request JWS string, self private key
 * Output: backup ack JWS string, wrapped key share, error message
 */
pebble_return_code_t handle_backup_req_and_gen_backup_ack(tci_message_t *cmd, tci_message_t *resp);

/**
 * Input: key alias of the master key to be recovered, self private key
 * Output: recovery request JWS string
 */
pebble_return_code_t gen_recovery_req(tci_message_t *cmd, tci_message_t *resp);

/**
 * Input: recovery request JWS string from buddy device, wrapped key share from self, buddy's certificate chain, self private key
 * Output: recovery ack JWS string (containing a key share wrapped by JWE), error message
 */
pebble_return_code_t handle_recovery_req_and_gen_recovery_ack(tci_message_t *cmd, tci_message_t *resp);

/**
 * Input: recovery ack JWS string (containing a key share wrapped by JWE), buddy's certificate chain, self private key
 * Output: key share wrapped by self TA, error message
 */
pebble_return_code_t handle_recovery_ack(tci_message_t *cmd, tci_message_t *resp);

/**
 * reconstruct a master key, and return one copy wrapped by TA, another copy wrapped by Android KeyStore public key
 * Input: all shares for the same master key, AES-GCM AAD(gcm_aad), Android Key Store certificate chain
 * Output: master key wrapped by TA, master key encrypted by AES-GCM (secret_ct, gcm_iv, gcm_tag), aes key encrypted (wrapped_gcm_key) by provided public key
 */
pebble_return_code_t reconstruct_key(tci_message_t *cmd, tci_message_t *resp);

#endif /* _PEBBLE_CORE_H_ */
