
/*
 * =====================================================================================
 *
 *       Filename:  process_cmd.c
 *
 *    Description:  PEBBLE process command
 *
 *        Version:  1.0
 *        Created:  06/02/2020
 *       Revision:  none
 *       Compiler:  gcc
 *
 *        Company:  Samsung Electronics
 *        Copyright (c) 2020 by Samsung Electronics, All rights reserved.
 *
 * =====================================================================================
 */

/** Includes */
#include "process_cmd.h"
#include "pebble_sss.h"

#if 0
/**
 * @brief
 * generate_jws_response
 * Aux function to generates the response JWS for a policy update
 *
 * @param[in]     response_type - response type
 * @param[in]    *tci_req       - TA request buffer
 * @param[out]   *tci_resp      - TA response buffer
 * @param[in]     res_code      - the response code
 *
 * @return Status Code
*/
pebble_return_code_t generate_jws_response(uint32_t response_type, tci_message_t *tci_req, tci_message_t *tci_resp, uint32_t res_code) {
        uint32_t ret = PEBBLE_STATUS_FAIL;
        uint32_t buffer_size = JWS_LEN;

        switch(res_code) {
                case PEBBLE_INVALID_JWS:
                case PEBBLE_JWS_INVALID_FORMAT:
                case PEBBLE_JWS_INVALID_LENGTH:
                        /*
                         * Error parsing JWS policy, not possible to generate the JWS response.
                         */
                        break;
                default:
                        ret = pebble_generate_response(response_type, tci_req, res_code, tci_resp->jws_message.data, &buffer_size);
                        tci_resp->jws_message.len = buffer_size;
                        if (ret != PEBBLE_STATUS_SUCCESS) {
                                PEBBLE_LOG("pebble_generate_response FAIL");
                                PEBBLE_LOG_DEBUG("pebble_generate_response FAIL ret = %d", ret);
                                return ret;
                        }
                        break;
        }

        return res_code;
}
#endif
/**
 * @brief
 * process_cmd
 * Process command
 *
 * @param[in] commandId - command id
 * @param[in] tci_msg   - tci message
 *
 * @return PEBBLE status code
 */
pebble_return_code_t process_cmd(uint32_t commandId, tci_message_t *tci_req, tci_message_t *tci_resp) {
        PEBBLE_LOG("process_cmd()");

        pebble_return_code_t ret = PEBBLE_STATUS_SUCCESS;
        uint32_t resp_len = JWS_LEN;
        uint32_t current_policy;
        uint32_t index = 0, offset = 0;
        uint8_t shares[3][SSS_SHARE_MAX_LEN];
        uint8_t key[SSS_KEY_MAX_LEN];
        int k = 0;
        int n = 0;
        size_t len = 0;
        size_t share_len = 0;
        // Device integrity check
        device_status = pebble_ICCC_check();
        if (device_status != PEBBLE_DEVICE_OK) {
                PEBBLE_LOG("pebble_ICCC_check FAIL");
        }

        switch (commandId) {
                case CMD_LOAD_CERT:
                        PEBBLE_LOG("CMD_LOAD_CERT");
                        ret = load_cert(tci_req, tci_resp);
                        return ret;

                case CMD_GEN_ATN_NONCE:
                        PEBBLE_LOG("CMD_GEN_ATN_NONCE");
                        ret = gen_atn_nonce(tci_req, tci_resp);
                        return ret;

                case CMD_GEN_MASTER_KEY:
                        PEBBLE_LOG("CMD_GEN_MASTER_KEY");
                        ret = generate_master_key_and_wrap_it(tci_req, tci_resp);
                        return ret;

                case CMD_DERIVE_SUBKEY:
                        PEBBLE_LOG("CMD_DERIVE_SUBKEY");
                        ret = derive_subkey_and_wrap_it(tci_req, tci_resp);
                        return ret;

#if 0
                case CMD_SSS_SPLIT: // for testing purpose only
                        PEBBLE_LOG("CMD_SSS_SPLIT");
                        //check len

                        //check split_num

                        k = tci_req->payload.split_cmd.k;
                        n = tci_req->payload.split_cmd.n;
                        len = tci_req->payload.split_cmd.len;
                        split(tci_req->payload.split_cmd.data, len, n, k, shares, &share_len);
                        tci_resp->payload.split_resp.count = k;
                        tci_resp->payload.split_resp.len = share_len;
                        TEE_MemMove(tci_resp->payload.split_resp.data0, shares[0], share_len);
                        TEE_MemMove(tci_resp->payload.split_resp.data1, shares[1], share_len);
                        TEE_MemMove(tci_resp->payload.split_resp.data2, shares[2], share_len);
                        ret = PEBBLE_STATUS_SUCCESS;
                        return ret;

                case CMD_SSS_JOIN: // for testing purpose only
                        PEBBLE_LOG("CMD_SSS_JOIN");
                        k = tci_req->payload.join_cmd.count;
                        share_len = tci_req->payload.join_cmd.len;
                        //check k and len

                        TEE_MemMove(shares[0], tci_req->payload.join_cmd.data0, share_len);
                        TEE_MemMove(shares[1], tci_req->payload.join_cmd.data1, share_len);
                        TEE_MemMove(shares[2], tci_req->payload.join_cmd.data2, share_len);
                        join(shares, share_len, k, key, &len);
                        TEE_MemMove(tci_resp->payload.join_resp.data, key, len);
                        tci_resp->payload.join_resp.len = len;
                        ret = PEBBLE_STATUS_SUCCESS;
                        return ret;

                case CMD_GET_DEVICE_ID: // reserved, not used for now
                        PEBBLE_LOG("CMD_GET_DEVICE_ID");
			ret = PEBBLE_STATUS_SUCCESS;
                        return ret;
#endif

                case CMD_GEN_BACKUP_REQ:
                        PEBBLE_LOG("CMD_GEN_BACKUP_REQ");
			ret = gen_backup_req(tci_req, tci_resp);
                        return ret;

                case CMD_GEN_BACKUP_ACK:
                        PEBBLE_LOG("CMD_GEN_BACKUP_ACK");
			ret = handle_backup_req_and_gen_backup_ack(tci_req, tci_resp);
                        return ret;

                case CMD_GEN_RECOVERY_REQ:
                        PEBBLE_LOG("CMD_GEN_RECOVERY_REQ");
			ret = gen_recovery_req(tci_req, tci_resp);
                        return ret;

                case CMD_GEN_RECOVERY_ACK:
                        PEBBLE_LOG("CMD_GEN_RECOVERY_ACK");
			ret = handle_recovery_req_and_gen_recovery_ack(tci_req, tci_resp);
                        return ret;

                case CMD_HANDLE_RECOVERY_ACK:
                        PEBBLE_LOG("CMD_PROCESS_RECOVERY_ACK");
			ret = handle_recovery_ack(tci_req, tci_resp);
                        return ret;

                case CMD_RECONSTRUCT_KEY:
                        PEBBLE_LOG("CMD_RECONSTRUCT_KEY");
			ret = reconstruct_key(tci_req, tci_resp);
                        return ret;

                default:
                        PEBBLE_LOG("received unknown command!");
                        PEBBLE_LOG_DEBUG("received unknown command: %d", commandId);
                        /* Unknown command ID */
                        ret = PEBBLE_STATUS_FAIL;
                        break;
        }

exit:
        return ret;
}
