diff --git a/app/main.c b/app/main.c index b2d164e6..66d1c007 100644 --- a/app/main.c +++ b/app/main.c @@ -128,6 +128,24 @@ static fdo_sdk_service_info_module *fdo_sv_info_modules_init(void) } module_info[0].service_info_callback = fdo_sys; + /* module#2: fdo.download */ + if (strncpy_s(module_info[1].module_name, FDO_MODULE_NAME_LEN, + "fdo.download", FDO_MODULE_NAME_LEN) != 0) { + LOG(LOG_ERROR, "Strcpy failed"); + fdo_free(module_info); + return NULL; + } + module_info[1].service_info_callback = fdo_sim_download; + + /* module#3: fdo.command */ + if (strncpy_s(module_info[2].module_name, FDO_MODULE_NAME_LEN, + "fdo.command", FDO_MODULE_NAME_LEN) != 0) { + LOG(LOG_ERROR, "Strcpy failed"); + fdo_free(module_info); + return NULL; + } + module_info[2].service_info_callback = fdo_sim_command; + return module_info; } diff --git a/crypto/include/fdo_crypto_hal.h b/crypto/include/fdo_crypto_hal.h index 1574c039..c6443d00 100644 --- a/crypto/include/fdo_crypto_hal.h +++ b/crypto/include/fdo_crypto_hal.h @@ -54,7 +54,7 @@ int32_t crypto_close(void); /* Calculate hash of "buffer" and place the result in "output". "output" must * be allocated already. */ -int32_t crypto_hal_hash(uint8_t hash_type, const uint8_t *buffer, +int32_t crypto_hal_hash(int hash_type, const uint8_t *buffer, size_t buffer_length, uint8_t *output, size_t output_length); diff --git a/crypto/openssl/openssl_crypto_support.c b/crypto/openssl/openssl_crypto_support.c index 6c7e13eb..6845d854 100644 --- a/crypto/openssl/openssl_crypto_support.c +++ b/crypto/openssl/openssl_crypto_support.c @@ -244,20 +244,16 @@ int32_t crypto_close(void) * return 0 on success. -ve value on failure. */ -int32_t crypto_hal_hash(uint8_t _hash_type, const uint8_t *buffer, +int32_t crypto_hal_hash(int _hash_type, const uint8_t *buffer, size_t buffer_length, uint8_t *output, size_t output_length) { - int hash_type = FDO_CRYPTO_HASH_TYPE_USED; - - (void)_hash_type; /* Unused parameter */ - if (NULL == output || 0 == output_length || NULL == buffer || 0 == buffer_length) { return -1; } - switch (hash_type) { + switch (_hash_type) { case FDO_CRYPTO_HASH_TYPE_SHA_256: if (output_length < SHA256_DIGEST_SIZE) { return -1; diff --git a/device_modules/CMakeLists.txt b/device_modules/CMakeLists.txt index 638948cf..302d6eea 100644 --- a/device_modules/CMakeLists.txt +++ b/device_modules/CMakeLists.txt @@ -6,11 +6,16 @@ client_sdk_include_directories( fdo_sys + fdo_sim ) client_sdk_sources( fdo_sys/fdo_sys.c fdo_sys/sys_utils_linux.c + fdo_sim/fdo_sim.c + fdo_sim/fdo_sim_download.c + fdo_sim/fdo_sim_command.c + fdo_sim/sim_utils_linux.c ) diff --git a/device_modules/fdo_sim/fdo_sim.c b/device_modules/fdo_sim/fdo_sim.c new file mode 100644 index 00000000..77f1e8d7 --- /dev/null +++ b/device_modules/fdo_sim/fdo_sim.c @@ -0,0 +1,213 @@ +/* + * Copyright 2023 Intel Corporation + * SPDX-License-Identifier: Apache 2.0 + */ + +#include "util.h" +#include "fdo_sim.h" +#include "safe_lib.h" +#include +#include +#include +#include "fdo_sim_utils.h" + +// position/offset on the file from which data will be read +static size_t file_seek_pos = 0; +// size of the file from which data will be read +static size_t file_sz = 0; +// EOT value whose value is 0 for 'fetch-data'success, and 1 for failure +static int fetch_data_status = 1; +// local isMore flag that represents whether the module has data/response to +// send in the NEXT messege SHOULD be 'true' if there is data to send, 'false' +// otherwise For simplicity, it is 'false' always (also a valid value) +static bool ismore = false; + +/** + * List of helper functions used in switch case + * + * fdo_si_start + * fdo_si_failure + * fdo_si_has_more_dsi + * fdo_si_is_more_dsi + * fdo_si_get_dsi_count + * fdo_si_get_dsi + * fdo_end + */ + +int fdo_si_start(fdor_t **fdor, fdow_t **fdow) +{ + int result = FDO_SI_INTERNAL_ERROR; + + // Initialize module's CBOR Reader/Writer objects. + *fdow = FSIMModuleAlloc(sizeof(fdow_t)); + if (!fdow_init(*fdow) || + !fdo_block_alloc_with_size(&(*fdow)->b, 8192)) { + LOG(LOG_ERROR, "Module fdo_sim - FDOW " + "Initialization/Allocation failed!\n"); + result = FDO_SI_CONTENT_ERROR; + goto end; + } + + *fdor = FSIMModuleAlloc(sizeof(fdor_t)); + if (!fdor_init(*fdor) || + !fdo_block_alloc_with_size(&(*fdor)->b, 8192)) { + LOG(LOG_ERROR, "Module fdo_sim - FDOR " + "Initialization/Allocation failed!\n"); + goto end; + } + result = FDO_SI_SUCCESS; +end: + return result; +} + +int fdo_si_failure(fdor_t **fdor, fdow_t **fdow) +{ + // perform clean-ups as needed + if (!fsim_process_data(FDO_SIM_MOD_MSG_EXIT, NULL, 0, NULL, NULL)) { + LOG(LOG_ERROR, "Module fdo_sim - Failed to perform " + "clean-up operations\n"); + return FDO_SI_INTERNAL_ERROR; + } + + if (*fdow) { + fdow_flush(*fdow); + FSIMModuleFree(*fdow); + } + if (*fdor) { + fdor_flush(*fdor); + FSIMModuleFree(*fdor); + } + return FDO_SI_SUCCESS; +} + +int fdo_si_has_more_dsi(bool *has_more, bool hasmore) +{ + // calculate whether there is ServiceInfo to send NOW and update + // 'has_more'. For testing purposes, set this to true here, and + // false once first write is done. + if (!has_more) { + return FDO_SI_CONTENT_ERROR; + } + + *has_more = hasmore; + if (*has_more) { + LOG(LOG_INFO, + "Module fdo_sim - There is ServiceInfo to send\n"); + } + return FDO_SI_SUCCESS; +} + +int fdo_si_is_more_dsi(bool *is_more) +{ + // calculate whether there is ServiceInfo to send in the NEXT + // iteration and update 'is_more'. + if (!is_more) { + LOG(LOG_ERROR, "is_more is NULL\n"); + return FDO_SI_CONTENT_ERROR; + } + + // sending either true or false is valid + // for simplicity, setting this to 'false' always, + // since managing 'ismore' by looking-ahead can be error-prone + *is_more = ismore; + return FDO_SI_SUCCESS; +} + +int fdo_si_get_dsi_count(uint16_t *num_module_messages) +{ + // calculate the number of ServiceInfo items to send NOW and update + // 'num_module_messages'. For testing purposes, set this to 1 here, and + // 0 once first write is done. + if (!num_module_messages) { + return FDO_SI_CONTENT_ERROR; + } + *num_module_messages = 1; + return FDO_SI_SUCCESS; +} + +int fdo_si_get_dsi(fdow_t **fdow, size_t mtu, char *module_message, + uint8_t *module_val, size_t *module_val_sz, size_t bin_len, + uint8_t *bin_data, size_t temp_module_val_sz, bool *hasmore, + fdoSimModMsg *write_type, char *filename) +{ + // write Device ServiceInfo using 'fdow' by partitioning the + // messages as per MTU, here. + if (mtu == 0 || !module_message || !module_val || !module_val_sz) { + return FDO_SI_CONTENT_ERROR; + } + + int result = FDO_SI_INTERNAL_ERROR; + + (void)bin_len; + (void)filename; + + // reset and initialize FDOW's encoder for usage + fdo_block_reset(&(*fdow)->b); + if (!fdow_encoder_init(*fdow)) { + LOG(LOG_ERROR, "Module fdo_sim - Failed to initialize " + "FDOW encoder\n"); + goto end; + } + + if (!*hasmore || *write_type == FDO_SIM_MOD_MSG_EXIT) { + LOG(LOG_ERROR, "Module fdo_sim - Invalid state\n"); + goto end; + } + + // TO-DO: Imlement functionality + + if (!fdow_encoded_length(*fdow, &temp_module_val_sz)) { + LOG(LOG_ERROR, + "Module fdo_sim - Failed to get encoded length\n"); + goto end; + } + *module_val_sz = temp_module_val_sz; + if (memcpy_s(module_val, *module_val_sz, (*fdow)->b.block, + *module_val_sz) != 0) { + LOG(LOG_ERROR, "Module fdo_sim - Failed to copy " + "CBOR-encoded module value\n"); + goto end; + } + result = FDO_SI_SUCCESS; +end: + result = + fdo_end(NULL, fdow, result, bin_data, NULL, 0, hasmore, write_type); + return result; +} + +int fdo_end(fdor_t **fdor, fdow_t **fdow, int result, uint8_t *bin_data, + uint8_t **exec_instr, size_t total_exec_array_length, bool *hasmore, + fdoSimModMsg *write_type) +{ + // End of function, clean-up state variables/objects + if (bin_data) { + FSIMModuleFree(bin_data); + } + if (exec_instr && total_exec_array_length > 0) { + int exec_counter = total_exec_array_length - 1; + while (exec_counter >= 0) { + FSIMModuleFree(exec_instr[exec_counter]); + --exec_counter; + } + FSIMModuleFree(exec_instr); + total_exec_array_length = 0; + } + if (result != FDO_SI_SUCCESS) { + // clean-up state variables/objects + *hasmore = false; + file_sz = 0; + file_seek_pos = 0; + fetch_data_status = 1; + *write_type = FDO_SIM_MOD_MSG_EXIT; + + if (*fdow) { + fdow_flush(*fdow); + FSIMModuleFree(*fdow); + } + if (*fdor) { + fdor_flush(*fdor); + FSIMModuleFree(*fdor); + } + } + return result; +} diff --git a/device_modules/fdo_sim/fdo_sim.h b/device_modules/fdo_sim/fdo_sim.h new file mode 100644 index 00000000..8504704d --- /dev/null +++ b/device_modules/fdo_sim/fdo_sim.h @@ -0,0 +1,128 @@ +/* + * Copyright 2023 Intel Corporation + * SPDX-License-Identifier: Apache 2.0 + */ + +#ifndef __FDO_SYS_H__ +#define __FDO_SYS_H__ + +#include +#include +#include "fdomodules.h" +#include "fdo_sim_utils.h" + +// Maximum buffer size to be used for reading/writing CBOR data +#define MOD_MAX_BUFF_SIZE 8192 + +// file path could also be supplied +#define FILE_NAME_LEN 150 + +#define MOD_ACTIVE_TAG "active" +#define MOD_ACTIVE_STATUS "1" + +// maximum length of exec command after combining all arguments of received exec +// array +#define MOD_MAX_EXEC_LEN 1024 +// maximum length of the individual text arguments in the received exec array +#define MOD_MAX_EXEC_ARG_LEN 100 + +/** + * The registered callback method for 'fdo_sim' ServiceInfo module. + * The implementation is responsible for handling the received Owner + * ServiceInfo, and for generating the Device ServiceInfo to send. + * + * When module_message, module_val and module_val_sz are used as inputs in type + * 'FDO_SI_SET_OSI', these represent the moduleMessage, CBOR-encoded + * (bstr-unwrapped) module value i.e ServiceInfoVal cbor.bytes, as received in + * TO2.OwnerServiceInfo (Type 69), and its length. The implementation must parse + * and process the input module value depending on the given module message, and + * return. + * + * However, the same set of variables are used as output parameters in type + * 'FDO_SI_GET_DSI', wherein, module_message stores the current moduleMessage, + * module_val stores the response CBOR-encoded module value (ServiceInfoVal), + * and module_val_sz stores the corresponding length. The implementation is + * responsible for generating the CBOR-encoded module value using any + * mechanisms/third-party library. In the current implementation, the + * CBOR-encoder/decoder from 'lib/fdoblockio.c' is used. These 3 parameters are + * then, used to generate ServiceInfoKV at TO2.DeviceServiceInfo (Type 68), and + * sent to the Owner. + * + * The input FDOW object to be used to write the desired 'ServiceInfo' structure + * as per the specification, that will be sent to the Owner. The FDOW can also + * be used for other purposes such as ServiceInfo message partitioning (fit + * within MTU), or, determining has_more/is_more etc. The module implemenation + * is responsible for maintaining any internal state information, as needed. + * + * The input fdo_sdk_si_type can be used to do specific tasks depending on the + * use-case. (The types could be updated in the future) + * + * @param type - [IN] enum value to describe the operation to be done. + * @param module_message - [IN/OUT] moduleMessage that decides how + * ServiceInfoVal is processed. + * @param module_val - [IN/OUT] bstr-unwrapped ServiceInfoVal corresponding to + * the moduleMessage. + * @param module_val_sz - [IN/OUT] ServiceInfoVal length corresponding to the + * moduleMessage. + * @param num_module_messages - [OUT] Number of ServiceInfoKVs to be sent. + * Currently UNUSED. + * @param has_more - [OUT] pointer to bool whose value must be set to + * 'true' if there is Device ServiceInfo to send NOW/immediately, OR, + * 'false' if there is no Device ServiceInfo to send NOW/immediately. + * @param is_more - [OUT] pointer to bool whose value must be set to + * 'true' if there is Device ServiceInfo to send in the NEXT ietration, OR, + * 'false' if there is no Device ServiceInfo to send in the NEXT iteration. + * @param mtu - [IN] MTU value to be used as the upper bound for the ServiceInfo + * length. + * @return integer value FDO_SI_CONTENT_ERROR (0), FDO_SI_INTERNAL_ERROR (1), + * FDO_SI_SUCCESS (2). + */ +int fdo_sim_download(fdo_sdk_si_type type, char *module_message, + uint8_t *module_val, size_t *module_val_sz, + uint16_t *num_module_messages, bool *has_more, + bool *is_more, size_t mtu); + +int fdo_sim_command(fdo_sdk_si_type type, char *module_message, + uint8_t *module_val, size_t *module_val_sz, + uint16_t *num_module_messages, bool *has_more, + bool *is_more, size_t mtu); + +// Prototype definitions for functions that are implemented in the module +int fdo_si_start(fdor_t **fdor, fdow_t **fdow); +int fdo_si_failure(fdor_t **fdor, fdow_t **fdow); +int fdo_si_has_more_dsi(bool *has_more, bool hasmore); +int fdo_si_is_more_dsi(bool *is_more); +int fdo_si_get_dsi_count(uint16_t *num_module_messages); +int fdo_si_get_dsi(fdow_t **fdow, size_t mtu, char *module_message, + uint8_t *module_val, size_t *module_val_sz, size_t bin_len, + uint8_t *bin_data, size_t temp_module_val_sz, bool *hasmore, + fdoSimModMsg *write_type, char *filename); + +int fdo_si_set_osi_download(char *module_message, uint8_t *module_val, + size_t *module_val_sz, int *strcmp_filedesc, + int *strcmp_length, int *strcmp_sha_384, + int *strcmp_write); + +int fdo_si_set_osi_command(char *module_message, uint8_t *module_val, + size_t *module_val_sz, int *strcmp_cmd, + int *strcmp_args, int *strcmp_may_fail, + int *strcmp_return_stdout, int *strcmp_return_stderr, + int *strcmp_sig, int *strcmp_exec); + +int fdo_si_set_osi_strcmp(size_t bin_len, uint8_t *bin_data); +int fdo_si_set_osi_sha_384(size_t bin_len, uint8_t *bin_data); +int fdo_si_set_osi_length(size_t bin_len); +int fdo_si_set_osi_write(size_t bin_len, uint8_t *bin_data); +int fdo_si_set_osi_may_fail(void); +int fdo_si_set_osi_return_stdout(void); +int fdo_si_set_osi_return_stderr(void); +int fdo_si_set_osi_cmd(size_t bin_len, uint8_t *bin_data); +int fdo_si_set_osi_sig(size_t sigValue); +int fdo_si_set_osi_args(int exec_array_index, size_t *exec_instructions_sz); +int fdo_si_set_osi_exec(uint8_t **exec_instr); +int fdo_si_set_osi_status_cb(size_t *status_cb_array_length); +int fdo_si_set_osi_fetch(size_t bin_len); +int fdo_end(fdor_t **fdor, fdow_t **fdow, int result, uint8_t *bin_data, + uint8_t **exec_instr, size_t total_exec_array_length, bool *hasmore, + fdoSimModMsg *write_type); +#endif /* __FDO_SYS_H__ */ diff --git a/device_modules/fdo_sim/fdo_sim_command.c b/device_modules/fdo_sim/fdo_sim_command.c new file mode 100644 index 00000000..569b26e0 --- /dev/null +++ b/device_modules/fdo_sim/fdo_sim_command.c @@ -0,0 +1,468 @@ +/* + * Copyright 2023 Intel Corporation + * SPDX-License-Identifier: Apache 2.0 + */ + +#include "util.h" +#include "fdo_sim.h" +#include "safe_lib.h" +#include +#include +#include + +// CBOR-decoder. Interchangeable with any other CBOR implementation. +static fdor_t *fdor = NULL; +// CBOR-encoder. Interchangeable with any other CBOR implementation. +static fdow_t *fdow = NULL; + +// filename that will either be read from or written onto +static char filename[FILE_NAME_LEN]; +// Number of items in the exec/exec_cb array +// used to perform clean-up on memory allocated for exec/exec_cb instructions +static size_t total_exec_array_length = 0; +// local hasMore flag that represents whether the module has data/response to +// send NOW 'true' if there is data to send, 'false' otherwise +static bool hasmore = false; +static fdoSimModMsg write_type = FDO_SIM_MOD_MSG_EXIT; +static uint8_t *fdo_cmd = NULL; +static size_t fdo_cmd_len = 0; +static uint8_t **fdo_exec_instr = NULL; + +int fdo_sim_command(fdo_sdk_si_type type, char *module_message, + uint8_t *module_val, size_t *module_val_sz, + uint16_t *num_module_messages, bool *has_more, + bool *is_more, size_t mtu) +{ + int strcmp_cmd = 1; + int strcmp_args = 1; + int strcmp_may_fail = 1; + int strcmp_return_stdout = 1; + int strcmp_return_stderr = 1; + int strcmp_sig = 1; + int strcmp_exec = 1; + int result = FDO_SI_INTERNAL_ERROR; + uint8_t *bin_data = NULL; + size_t bin_len = 0; + size_t exec_array_index = 0; + uint8_t **exec_instr = NULL; + size_t exec_instructions_sz = 0; + size_t temp_module_val_sz = 0; + + switch (type) { + case FDO_SI_START: + result = fdo_si_start(&fdor, &fdow); + goto end; + case FDO_SI_END: + case FDO_SI_FAILURE: + result = fdo_si_failure(&fdor, &fdow); + goto end; + case FDO_SI_HAS_MORE_DSI: + result = fdo_si_has_more_dsi(has_more, hasmore); + goto end; + case FDO_SI_IS_MORE_DSI: + result = fdo_si_is_more_dsi(is_more); + goto end; + case FDO_SI_GET_DSI_COUNT: + result = fdo_si_get_dsi_count(num_module_messages); + goto end; + case FDO_SI_GET_DSI: + result = fdo_si_get_dsi(&fdow, mtu, module_message, module_val, + module_val_sz, bin_len, bin_data, + temp_module_val_sz, &hasmore, + &write_type, filename); + goto end; + case FDO_SI_SET_OSI: + result = fdo_si_set_osi_command( + module_message, module_val, module_val_sz, &strcmp_cmd, + &strcmp_args, &strcmp_may_fail, &strcmp_return_stdout, + &strcmp_return_stderr, &strcmp_sig, &strcmp_exec); + + if (result != FDO_SI_SUCCESS) { + goto end; + } + + if (strcmp_cmd == 0) { + result = fdo_si_set_osi_cmd(bin_len, bin_data); + goto end; + } else if (strcmp_args == 0) { + result = fdo_si_set_osi_args(exec_array_index, + &exec_instructions_sz); + goto end; + } else if (strcmp_may_fail == 0) { + result = fdo_si_set_osi_may_fail(); + goto end; + } else if (strcmp_return_stdout == 0) { + result = fdo_si_set_osi_return_stdout(); + goto end; + } else if (strcmp_return_stderr == 0) { + result = fdo_si_set_osi_return_stderr(); + goto end; + } else if (strcmp_sig == 0) { + result = fdo_si_set_osi_sig(bin_len); + goto end; + } else if (strcmp_exec == 0) { + result = fdo_si_set_osi_exec(fdo_exec_instr); + goto end; + } + default: + result = FDO_SI_FAILURE; + } + +end: + result = fdo_end(&fdor, &fdow, result, bin_data, exec_instr, + total_exec_array_length, &hasmore, &write_type); + return result; +} + +int fdo_si_set_osi_command(char *module_message, uint8_t *module_val, + size_t *module_val_sz, int *strcmp_cmd, + int *strcmp_args, int *strcmp_may_fail, + int *strcmp_return_stdout, int *strcmp_return_stderr, + int *strcmp_sig, int *strcmp_exec) +{ + if (!module_message || !module_val || !module_val_sz || + *module_val_sz > MOD_MAX_BUFF_SIZE) { + return FDO_SI_CONTENT_ERROR; + } + + int result = FDO_SI_INTERNAL_ERROR; + + // Process the received Owner ServiceInfo contained within + // 'fdor', here. + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "command", strcmp_cmd); + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "execute", strcmp_exec); + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "may_fail", + strcmp_may_fail); + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "return_stdout", + strcmp_return_stdout); + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "return_stderr", + strcmp_return_stderr); + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "args", strcmp_args); + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "sig", strcmp_sig); + + if (*strcmp_exec && *strcmp_may_fail && *strcmp_return_stdout && + *strcmp_return_stderr && *strcmp_cmd && *strcmp_args && + *strcmp_sig) { + LOG(LOG_ERROR, "Module fdo.command - Invalid moduleMessage\n"); + result = FDO_SI_CONTENT_ERROR; + goto end; + } + + // reset, copy CBOR data and initialize Parser. + fdo_block_reset(&fdor->b); + if (0 != memcpy_s(fdor->b.block, *module_val_sz, module_val, + *module_val_sz)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to copy buffer " + "into temporary FDOR\n"); + goto end; + } + fdor->b.block_size = *module_val_sz; + + if (!fdor_parser_init(fdor)) { + LOG(LOG_ERROR, + "Module fdo.command - Failed to init FDOR parser\n"); + goto end; + } + result = FDO_SI_SUCCESS; +end: + return result; +} + +int fdo_si_set_osi_may_fail(void) +{ + bool may_fail; + int result = FDO_SI_INTERNAL_ERROR; + + if (!fdor_boolean(fdor, &may_fail)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to read " + "fdo.command:may_fail\n"); + goto end; + } + + // if (may_fail == false) { + // TO-DO - implement functionality + // } + + result = FDO_SI_SUCCESS; +end: + return result; +} + +int fdo_si_set_osi_return_stdout(void) +{ + bool return_stdout; + int result = FDO_SI_INTERNAL_ERROR; + + if (!fdor_boolean(fdor, &return_stdout)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to read " + "fdo.command:return_stdout\n"); + goto end; + } + + if (return_stdout == true) { + // TO-DO - implement functionality + } + result = FDO_SI_SUCCESS; +end: + return result; +} + +int fdo_si_set_osi_return_stderr(void) +{ + bool return_stderr; + int result = FDO_SI_INTERNAL_ERROR; + + if (!fdor_boolean(fdor, &return_stderr)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to read " + "fdo.command:return_stderr\n"); + goto end; + } + + if (return_stderr == true) { + // TO-DO - implement functionality + } + result = FDO_SI_SUCCESS; +end: + return result; +} + +int fdo_si_set_osi_sig(size_t sigValue) +{ + int result = FDO_SI_INTERNAL_ERROR; + + if (!fdor_unsigned_int(fdor, &sigValue)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to process " + "fdo.command:sig\n"); + goto end; + } + + if (sigValue == 0) { + LOG(LOG_ERROR, "Module fdo.command - Empty value received for " + "fdo.command:sig\n"); + // received file name cannot be empty + result = FDO_SI_CONTENT_ERROR; + goto end; + } + LOG(LOG_INFO, + "Module fdo.command:sig - Process Signal received : %ld\n", + sigValue); + + if (sigValue == 9 || sigValue == 15) { + result = fdo_si_failure(&fdor, &fdow); + goto end; + } + + result = FDO_SI_SUCCESS; +end: + return result; +} + +int fdo_si_set_osi_cmd(size_t bin_len, uint8_t *bin_data) +{ + int result = FDO_SI_INTERNAL_ERROR; + + if (!fdor_string_length(fdor, &bin_len)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to read " + "fdo.command:command length\n"); + goto end; + } + + if (bin_len == 0) { + LOG(LOG_ERROR, "Module fdo.command - Empty value received for " + "fdo.command:command\n"); + // received file name cannot be empty + result = FDO_SI_CONTENT_ERROR; + goto end; + } + + bin_data = FSIMModuleAlloc(bin_len * sizeof(uint8_t)); + if (!bin_data) { + LOG(LOG_ERROR, "Module fdo.command - Failed to " + "alloc for fdo.command:command\n"); + goto end; + } + + if (!fdor_text_string(fdor, (char *)bin_data, bin_len)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to " + "read fdo.command:command\n"); + goto end; + } + + fdo_cmd_len = bin_len; + fdo_cmd = FSIMModuleAlloc(fdo_cmd_len * sizeof(uint8_t)); + if (!fdo_cmd) { + LOG(LOG_DEBUG, "Module fdo.command - Failed to " + "alloc for fdo.command:command\n"); + goto end; + } + + if (0 != memcpy_s(fdo_cmd, fdo_cmd_len, (char *)bin_data, bin_len)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to copy command\n"); + goto end; + } + result = FDO_SI_SUCCESS; +end: + result = fdo_end(&fdor, &fdow, result, bin_data, NULL, + total_exec_array_length, &hasmore, &write_type); + return result; +} + +int fdo_si_set_osi_args(int exec_array_index, size_t *exec_instructions_sz) +{ + int result = FDO_SI_INTERNAL_ERROR; + int flag = 0; + size_t exec_array_length = 0; + + if (!fdor_array_length(fdor, &exec_array_length)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to read " + "fdo.command:args array length\n"); + goto end; + } + + if (exec_array_length == 0) { + LOG(LOG_ERROR, "Module fdo.command - Empty array received for " + "fdo.command:args\n"); + // received exec array cannot be empty + result = FDO_SI_CONTENT_ERROR; + goto end; + } + + if (!fdor_start_array(fdor)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to start " + "fdo.command:args array\n"); + goto end; + } + + total_exec_array_length = exec_array_length + 1; + // allocate memory for exec_instr + fdo_exec_instr = (uint8_t **)FSIMModuleAlloc( + sizeof(uint8_t *) * (total_exec_array_length + 1)); + if (!fdo_exec_instr) { + LOG(LOG_ERROR, "Module fdo.command - Failed to alloc for " + "fdo.command:args instructions\n"); + goto end; + } + + fdo_exec_instr[0] = + (uint8_t *)FSIMModuleAlloc(sizeof(uint8_t) * MOD_MAX_EXEC_ARG_LEN); + if (!fdo_exec_instr[0]) { + LOG(LOG_ERROR, "Module fdo.command - Failed to alloc " + "for single fdo.command:args" + " instruction\n"); + goto end; + } + + if (0 != memset_s(fdo_exec_instr[0], + sizeof(sizeof(uint8_t) * MOD_MAX_EXEC_ARG_LEN), 0)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to clear " + "single fdo.command:args" + " instruction\n"); + goto end; + } + + if (0 != memcpy_s(fdo_exec_instr[0], MOD_MAX_EXEC_ARG_LEN, + (char *)fdo_cmd, fdo_cmd_len)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to copy command\n"); + goto end; + } + + for (exec_array_index = 1; exec_array_index <= (int)exec_array_length; + exec_array_index++) { + fdo_exec_instr[exec_array_index] = (uint8_t *)FSIMModuleAlloc( + sizeof(uint8_t) * MOD_MAX_EXEC_ARG_LEN); + if (!fdo_exec_instr[exec_array_index]) { + LOG(LOG_ERROR, "Module fdo.command - Failed to alloc " + "for single fdo.command:args" + " instruction\n"); + goto end; + } + if (0 != + memset_s(fdo_exec_instr[exec_array_index], + sizeof(sizeof(uint8_t) * MOD_MAX_EXEC_ARG_LEN), + 0)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to clear " + "single fdo.command:args" + " instruction\n"); + goto end; + } + if (!fdor_string_length(fdor, exec_instructions_sz) || + *exec_instructions_sz > MOD_MAX_EXEC_ARG_LEN) { + LOG(LOG_ERROR, "Module fdo.command - Failed to read " + "fdo.command:args text " + "length\n"); + goto end; + } + if (!fdor_text_string(fdor, + (char *)fdo_exec_instr[exec_array_index], + *exec_instructions_sz)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to read " + "fdo.command:args text\n"); + goto end; + } + + // last argument is the filename + if (exec_array_index == ((int)exec_array_length - 1)) { + if (memset_s(filename, sizeof(filename), 0) != 0) { + LOG(LOG_ERROR, "Module fdo.command - Failed " + "to clear filename for" + " fdo.command:args\n"); + goto end; + } + if (0 != + strncpy_s(filename, FILE_NAME_LEN, + (char *)fdo_exec_instr[exec_array_index], + *exec_instructions_sz)) { + LOG(LOG_ERROR, "Module fdo.command - Failed " + "to copy filename for" + " fdo.command:args\n"); + goto end; + } + } + } + fdo_exec_instr[exec_array_index] = NULL; + + if (!fdor_end_array(fdor)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to end " + "fdo.command:args array\n"); + goto end; + } + + flag = 1; + result = FDO_SI_SUCCESS; +end: + if (!flag) { + result = + fdo_end(&fdor, &fdow, result, fdo_cmd, fdo_exec_instr, + total_exec_array_length, &hasmore, &write_type); + } else { + result = + fdo_end(&fdor, &fdow, result, fdo_cmd, NULL, + total_exec_array_length, &hasmore, &write_type); + } + return result; +} + +int fdo_si_set_osi_exec(uint8_t **exec_instr) +{ + int result = FDO_SI_INTERNAL_ERROR; + + if (fdor_is_value_null(fdor)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to read " + "fdo.command:execute array length\n"); + goto end; + } + + if (exec_instr) { + if (!fsim_process_data(FDO_SIM_MOD_MSG_EXEC, NULL, 0, filename, + (char **)exec_instr)) { + LOG(LOG_ERROR, "Module fdo.command - Failed to " + "process fdo.command:execute\n"); + goto end; + } + } + result = FDO_SI_SUCCESS; +end: + result = fdo_end(&fdor, &fdow, result, NULL, exec_instr, + total_exec_array_length, &hasmore, &write_type); + return result; +} diff --git a/device_modules/fdo_sim/fdo_sim_download.c b/device_modules/fdo_sim/fdo_sim_download.c new file mode 100644 index 00000000..c6c94f11 --- /dev/null +++ b/device_modules/fdo_sim/fdo_sim_download.c @@ -0,0 +1,378 @@ +/* + * Copyright 2023 Intel Corporation + * SPDX-License-Identifier: Apache 2.0 + */ + +#include "util.h" +#include "fdo_sim.h" +#include "safe_lib.h" +#include +#include +#include +#include "fdo_crypto_hal.h" +#include "fdo_crypto.h" + +// CBOR-decoder. Interchangeable with any other CBOR implementation. +static fdor_t *fdor = NULL; +// // CBOR-encoder. Interchangeable with any other CBOR implementation. +static fdow_t *fdow = NULL; + +// filename that will either be read from or written onto +static char filename[FILE_NAME_LEN]; +// local hasMore flag that represents whether the module has data/response to +// send NOW 'true' if there is data to send, 'false' otherwise +static bool hasmore = false; +// the type of operation to perform, generally used to manage responses +static fdoSimModMsg write_type = FDO_SIM_MOD_MSG_NONE; + +static fdo_hash_t *expectedCheckSum = NULL; + +int fdo_sim_download(fdo_sdk_si_type type, char *module_message, + uint8_t *module_val, size_t *module_val_sz, + uint16_t *num_module_messages, bool *has_more, + bool *is_more, size_t mtu) +{ + int strcmp_filedesc = 1; + int strcmp_sha_384 = 1; + int strcmp_length = 1; + int strcmp_write = 1; + int result = FDO_SI_INTERNAL_ERROR; + uint8_t *bin_data = NULL; + size_t bin_len = 0; + size_t temp_module_val_sz = 0; + + switch (type) { + case FDO_SI_START: + result = fdo_si_start(&fdor, &fdow); + goto end; + case FDO_SI_END: + case FDO_SI_FAILURE: + result = fdo_si_failure(&fdor, &fdow); + goto end; + case FDO_SI_HAS_MORE_DSI: + result = fdo_si_has_more_dsi(has_more, hasmore); + goto end; + case FDO_SI_IS_MORE_DSI: + result = fdo_si_is_more_dsi(is_more); + goto end; + case FDO_SI_GET_DSI_COUNT: + result = fdo_si_get_dsi_count(num_module_messages); + goto end; + case FDO_SI_GET_DSI: + result = fdo_si_get_dsi(&fdow, mtu, module_message, module_val, + module_val_sz, bin_len, bin_data, + temp_module_val_sz, &hasmore, + &write_type, filename); + goto end; + case FDO_SI_SET_OSI: + result = fdo_si_set_osi_download( + module_message, module_val, module_val_sz, &strcmp_filedesc, + &strcmp_length, &strcmp_sha_384, &strcmp_write); + + if (result != FDO_SI_SUCCESS) { + goto end; + } + + if (strcmp_filedesc == 0) { + result = fdo_si_set_osi_strcmp(bin_len, bin_data); + goto end; + } else if (strcmp_length == 0) { + result = fdo_si_set_osi_length(bin_len); + goto end; + } else if (strcmp_sha_384 == 0) { + result = fdo_si_set_osi_sha_384(bin_len, bin_data); + goto end; + } else if (strcmp_write == 0) { + result = fdo_si_set_osi_write(bin_len, bin_data); + goto end; + } + default: + result = FDO_SI_FAILURE; + } + +end: + result = fdo_end(&fdor, &fdow, result, bin_data, NULL, 0, &hasmore, + &write_type); + return result; +} + +int fdo_si_set_osi_download(char *module_message, uint8_t *module_val, + size_t *module_val_sz, int *strcmp_filedesc, + int *strcmp_length, int *strcmp_sha_384, + int *strcmp_write) +{ + if (!module_message || !module_val || !module_val_sz || + *module_val_sz > MOD_MAX_BUFF_SIZE) { + return FDO_SI_CONTENT_ERROR; + } + + int result = FDO_SI_INTERNAL_ERROR; + + // Process the received Owner ServiceInfo contained within + // 'fdor', here. + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "name", strcmp_filedesc); + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "length", strcmp_length); + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "sha-384", strcmp_sha_384); + strcmp_s(module_message, FDO_MODULE_MSG_LEN, "data", strcmp_write); + + if (*strcmp_filedesc && *strcmp_length && *strcmp_sha_384 && + *strcmp_write) { + LOG(LOG_ERROR, "Module fdo.download - Invalid moduleMessage\n"); + result = FDO_SI_CONTENT_ERROR; + goto end; + } + // reset, copy CBOR data and initialize Parser. + fdo_block_reset(&fdow->b); + if (0 != memcpy_s(fdor->b.block, *module_val_sz, module_val, + *module_val_sz)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to copy buffer " + "into temporary FDOR\n"); + goto end; + } + fdor->b.block_size = *module_val_sz; + + if (!fdor_parser_init(fdor)) { + LOG(LOG_ERROR, + "Module fdo.download - Failed to init FDOR parser\n"); + goto end; + } + result = FDO_SI_SUCCESS; +end: + return result; +} + +int fdo_si_set_osi_strcmp(size_t bin_len, uint8_t *bin_data) +{ + int result = FDO_SI_INTERNAL_ERROR; + + if (!fdor_string_length(fdor, &bin_len)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to read " + "fdo.download:name length\n"); + goto end; + } + + if (bin_len == 0) { + LOG(LOG_ERROR, "Module fdo.download - Empty value received for " + "fdo.download:name\n"); + // received file name cannot be empty + result = FDO_SI_CONTENT_ERROR; + goto end; + } + + bin_data = FSIMModuleAlloc(bin_len * sizeof(uint8_t)); + if (!bin_data) { + LOG(LOG_ERROR, "Module fdo.download - Failed to " + "alloc for fdo.download:name\n"); + goto end; + } + + if (!fdor_text_string(fdor, (char *)bin_data, bin_len)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to " + "read fdo.download:name\n"); + goto end; + } + + if (memset_s(filename, sizeof(filename), 0) != 0) { + LOG(LOG_ERROR, "Module fdo.download - Failed to clear " + "fdo.download:name buffer\n"); + goto end; + } + + if (0 != + strncpy_s(filename, FILE_NAME_LEN, (char *)bin_data, bin_len)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to " + "copy fdo.download:name\n"); + goto end; + } + + if (true == fsim_delete_old_file((const char *)filename)) { + result = FDO_SI_SUCCESS; + } + LOG(LOG_INFO, "Module fdo.download - File created on path: %s\n", + filename); +end: + result = fdo_end(&fdor, &fdow, result, bin_data, NULL, 0, &hasmore, + &write_type); + return result; +} + +int fdo_si_set_osi_length(size_t bin_len) +{ + int result = FDO_SI_INTERNAL_ERROR; + + if (!fdor_unsigned_int(fdor, &bin_len)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to process " + "fdo.download:length\n"); + goto end; + } + + if (bin_len == 0) { + LOG(LOG_ERROR, "Module fdo.download - Empty value received for " + "fdo.download:length\n"); + // received file name cannot be empty + result = FDO_SI_CONTENT_ERROR; + goto end; + } + + LOG(LOG_INFO, "Module fdo.download - expected file length %ld\n", + bin_len); + result = FDO_SI_SUCCESS; +end: + return result; +} + +int fdo_si_set_osi_sha_384(size_t bin_len, uint8_t *bin_data) +{ + int result = FDO_SI_INTERNAL_ERROR; + + if (!fdor_string_length(fdor, &bin_len)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to " + "read fdo.download:sha384 length\n"); + goto end; + } + + if (bin_len == 0) { + LOG(LOG_DEBUG, "Module fdo.download - Empty value " + "received for fdo.download:sha384\n"); + // received file content can be empty for an + // empty file do not allocate for the same and + // skip reading the entry + if (!fdor_next(fdor)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to read " + "fdo.download:sha384\n"); + result = FDO_SI_CONTENT_ERROR; + goto end; + } + result = FDO_SI_SUCCESS; + goto end; + } + + bin_data = FSIMModuleAlloc(bin_len * sizeof(uint8_t)); + if (!bin_data) { + LOG(LOG_ERROR, "Module fdo.download - Failed to " + "alloc for fdo.download:sha384\n"); + goto end; + } + + if (!fdor_byte_string(fdor, bin_data, bin_len)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to read value for " + "fdo.download:sha384\n"); + goto end; + } + + expectedCheckSum = + fdo_hash_alloc(FDO_CRYPTO_HASH_TYPE_SHA_384, SHA384_DIGEST_SIZE); + if (!expectedCheckSum) { + LOG(LOG_ERROR, + "Module fdo.download - Failed to alloc expectedCheckSum\n"); + goto end; + } + + if (0 != memcpy_s(expectedCheckSum->hash->bytes, SHA384_DIGEST_SIZE, + (char *)bin_data, bin_len)) { + LOG(LOG_ERROR, + "Module fdo.download - Failed to copy expectedCheckSum\n"); + fdo_hash_free(expectedCheckSum); + goto end; + } + result = FDO_SI_SUCCESS; +end: + result = fdo_end(&fdor, &fdow, result, bin_data, NULL, 0, &hasmore, + &write_type); + return result; +} + +int fdo_si_set_osi_write(size_t bin_len, uint8_t *bin_data) +{ + int result = FDO_SI_INTERNAL_ERROR; + fdo_hash_t *hash = NULL; + size_t file_len = 0; + uint8_t *file_data = NULL; + + if (!fdor_string_length(fdor, &bin_len)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to " + "read fdo.download:data length\n"); + goto end; + } + + if (bin_len == 0) { + // Entire file has been sent + // Validate hash of received file + file_len = fsim_get_file_sz(filename); + file_data = FSIMModuleAlloc(file_len * sizeof(uint8_t)); + if (!file_data) { + LOG(LOG_ERROR, "Module fdo.download - Failed to " + "alloc for fdo.download:data\n"); + goto end; + } + + if (!fsim_read_buffer_from_file_from_pos(filename, file_data, + file_len, 0)) { + LOG(LOG_ERROR, + "Module fdo.download - Failed to read " + "fdo.download:data content from %s\n", + filename); + goto end; + } + + hash = fdo_hash_alloc(FDO_CRYPTO_HASH_TYPE_SHA_384, + SHA384_DIGEST_SIZE); + if (!hash) { + LOG(LOG_ERROR, + "Module fdo.download - Failed to alloc hash\n"); + goto end; + } + + if ((0 != crypto_hal_hash( + FDO_CRYPTO_HASH_TYPE_SHA_384, file_data, file_len, + hash->hash->bytes, hash->hash->byte_sz))) { + LOG(LOG_ERROR, + "Module fdo.download - Failed to calculate hash\n"); + fdo_hash_free(hash); + goto end; + } + + if (!fdo_compare_hashes(hash, expectedCheckSum)) { + LOG(LOG_ERROR, "Module fdo.download: Failed to verify " + " hash\n"); + goto end; + } + LOG(LOG_DEBUG, "Module fdo.download - Hash matched \n"); + result = FDO_SI_SUCCESS; + goto end; + } + + bin_data = FSIMModuleAlloc(bin_len * sizeof(uint8_t)); + if (!bin_data) { + LOG(LOG_ERROR, "Module fdo.download - Failed to " + "alloc for fdo.download:data\n"); + goto end; + } + + if (!fdor_byte_string(fdor, bin_data, bin_len)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to read value for " + "fdo.download:data\n"); + goto end; + } + + if (!fsim_process_data(FDO_SIM_MOD_MSG_WRITE, bin_data, bin_len, + filename, NULL)) { + LOG(LOG_ERROR, "Module fdo.download - Failed to process value " + "for fdo.download:data\n"); + goto end; + } + result = FDO_SI_SUCCESS; +end: + if (!bin_len && hash) { + fdo_hash_free(hash); + } + if (!bin_len && expectedCheckSum) { + fdo_hash_free(expectedCheckSum); + } + if (!bin_len && file_data) { + FSIMModuleFree(file_data); + } + result = fdo_end(&fdor, &fdow, result, bin_data, NULL, 0, &hasmore, + &write_type); + return result; +} diff --git a/device_modules/fdo_sim/fdo_sim_utils.h b/device_modules/fdo_sim/fdo_sim_utils.h new file mode 100644 index 00000000..7c3b32cf --- /dev/null +++ b/device_modules/fdo_sim/fdo_sim_utils.h @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Intel Corporation + * SPDX-License-Identifier: Apache 2.0 + */ + +#ifndef __SYS_UTILS_H__ +#define __SYS_UTILS_H__ + +#include +#include + +#ifdef TARGET_OS_OPTEE +#include +#define FSIMModuleFree(x) \ + { \ + TEE_Free(x); \ + x = NULL; \ + } + +#else +#define FSIMModuleFree(x) \ + { \ + free(x); \ + x = NULL; \ + } +#endif + +typedef enum { + FDO_SIM_MOD_MSG_WRITE, + FDO_SIM_MOD_MSG_EXEC, + FDO_SIM_MOD_MSG_EXEC_CB, + FDO_SIM_MOD_MSG_STATUS_CB, + FDO_SIM_MOD_MSG_DATA, + FDO_SIM_MOD_MSG_EOT, + FDO_SIM_MOD_MSG_EXIT, + FDO_SIM_MOD_MSG_NONE +} fdoSimModMsg; + +void *FSIMModuleAlloc(int size); +bool fsim_process_data(fdoSimModMsg type, uint8_t *data, uint32_t dataLen, + char *file_name, char **command); + +size_t fsim_get_file_sz(char const *filename); +bool fsim_read_buffer_from_file_from_pos(const char *filename, uint8_t *buffer, + size_t size, int from); +bool fsim_delete_old_file(const char *file_name); +#endif /* __SYS_UTILS_H__ */ diff --git a/device_modules/fdo_sim/sim_utils_linux.c b/device_modules/fdo_sim/sim_utils_linux.c new file mode 100644 index 00000000..c934cdc2 --- /dev/null +++ b/device_modules/fdo_sim/sim_utils_linux.c @@ -0,0 +1,276 @@ +/* + * Copyright 2023 Intel Corporation + * SPDX-License-Identifier: Apache 2.0 + */ + +#include "safe_lib.h" +#include +#include +#include +#include +#include +#include "fdo_sim_utils.h" +#include "fdo_sim.h" + +// Process ID of the process created by Module:exec_cb +static pid_t exec_pid = -1; + +void *FSIMModuleAlloc(int size) +{ + if (size <= 0) { + return NULL; + } + void *buf = malloc(size); + if (!buf) { + printf("fdoAlloc failed to allocate\n"); + goto end; + } + + if (memset_s(buf, size, 0) != 0) { + printf("Memset Failed\n"); + free(buf); + buf = NULL; + goto end; + } + +end: + return buf; +} + +bool fsim_process_data(fdoSimModMsg type, uint8_t *data, uint32_t data_len, + char *file_name, char **command) +{ + bool ret = false; + FILE *fp = NULL; + int status = -1; + + // For writing to a file + if (type == FDO_SIM_MOD_MSG_WRITE) { + + if (!data || !data_len) { +#ifdef DEBUG_LOGS + printf("Module fdo.download:data write : Invalid " + "params\n"); +#endif + return false; + } + if (!file_name) { +#ifdef DEBUG_LOGS + printf("Module fdo.download:data write : No filename " + "present for " + "Module fdo.download:data\n"); +#endif + return false; + } + fp = fopen(file_name, "a"); + if (!fp) { +#ifdef DEBUG_LOGS + printf("Module fdo.download:data write : Failed to " + "open file(path): %s\n", + file_name); +#endif + return false; + } + + printf("Module fdo.download:data write : %" PRIu32 + " bytes being written to the file %s\n", + data_len, file_name); + + if (fwrite(data, sizeof(char), data_len, fp) != + (size_t)data_len) { +#ifdef DEBUG_LOGS + printf("Module fdo.download:data write : Failed to " + "write\n"); +#endif + goto end; + } + ret = true; + goto end; + } + + // For exec/exec_cb call + if (type == FDO_SIM_MOD_MSG_EXEC) { + + if (!file_name) { +#ifdef DEBUG_LOGS + printf( + "Module fdo.commmand:execute : Invalid filename\n"); +#endif + return false; + } + + if (!command) { +#ifdef DEBUG_LOGS + printf( + "Module fdo.commmand:execute : Missing command\n"); +#endif + return false; + } + + if (exec_pid != -1) { +#ifdef DEBUG_LOGS + printf("Module fdo.commmand:execute : An exec " + "instruction is " + "currently in progress\n"); +#endif + return false; + } + + printf("Module fdo.commmand:execute : Executing command...\n"); + exec_pid = fork(); + if (exec_pid < 0) { + // error +#ifdef DEBUG_LOGS + printf( + "Module fdo.commmand:execute : Failed to fork.\n"); +#endif + return false; + } else if (exec_pid == 0) { + // child process + status = execvp(command[0], command); + if (status == -1) { +#ifdef DEBUG_LOGS + printf("Module fdo.commmand:execute : Failed " + "to execute " + "command.\n"); +#endif + goto end; + } + } else { + // parent process + // if exec, block until process completes + if (type == FDO_SIM_MOD_MSG_EXEC) { + waitpid(exec_pid, &status, 0); + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) { +#ifdef DEBUG_LOGS + printf("Module " + "fdo.commmand:execute : " + "Proces " + "execution failed.\n"); +#endif + goto end; + + } else { +#ifdef DEBUG_LOGS + printf( + "Module " + "fdo.commmand:execute : " + "Process " + "execution completed.\n"); +#endif + // reset the process ID since + // execution is done + exec_pid = -1; + ret = true; + goto end; + } + } + } + } + ret = true; + } + + // For performing clean-up operations of module exit + if (type == FDO_SIM_MOD_MSG_EXIT) { + if (exec_pid > 0) { + // kill the process as a part of clea-up operations + kill(exec_pid, SIGTERM); + } + ret = true; + } +end: + + if (fp) { + if (fclose(fp) == EOF) { +#ifdef DEBUG_LOGS + printf("Fclose failed\n"); +#endif + } + } + // upon error, kill the forked process + if (!ret && exec_pid > 0) { + kill(exec_pid, SIGTERM); + exec_pid = -1; + } + return ret; +} + +bool fsim_delete_old_file(const char *filename) +{ + FILE *file = NULL; + bool ret = false; + + file = fopen(filename, "w"); + if (file) { + if (!fclose(file)) { + ret = true; + } + } else { + ret = true; + } + return ret; +} + +/** + * Return the length of the given file. + */ +size_t fsim_get_file_sz(char const *filename) +{ + if (!filename || !filename[0]) { + return 0; + } + size_t file_length = 0; + FILE *fp = fopen(filename, "rb"); + + if (fp) { + if (fseek(fp, 0, SEEK_END) != 0) { + printf("fseek() failed in the file"); + if (fclose(fp) == EOF) { + printf("Fclose Failed"); + } + return 0; + } + file_length = ftell(fp); + if (fclose(fp) == EOF) { + printf("Fclose Failed"); + } + } + return file_length; +} + +/** + * Read the filename's content (size bytes) into the given buffer (pre-allocated + * memory) starting at the specified offset (from). + */ +bool fsim_read_buffer_from_file_from_pos(const char *filename, uint8_t *buffer, + size_t size, int from) +{ + FILE *file = NULL; + size_t bytes_read = 0; + + file = fopen(filename, "rb"); + if (!file) { + return false; + } + + if (fseek(file, from, SEEK_SET) != 0) { + printf("fseek() failed in the file"); + if (fclose(file) == EOF) { + printf("Fclose Failed"); + } + return false; + } + bytes_read = fread(buffer, 1, size, file); + if (bytes_read != size) { + if (fclose(file) == EOF) { + printf("Fclose Failed"); + } + return false; + } + + if (fclose(file) == EOF) { + printf("Fclose Failed"); + } + return true; +} diff --git a/include/fdomodules.h b/include/fdomodules.h index 00fed560..f08dd31c 100644 --- a/include/fdomodules.h +++ b/include/fdomodules.h @@ -17,7 +17,7 @@ #ifdef EXTRA_MODULES #define FDO_MAX_MODULES 4 #else -#define FDO_MAX_MODULES 1 +#define FDO_MAX_MODULES 3 #endif #define FDO_MODULE_MESSAGE_ACTIVE "active" @@ -69,4 +69,14 @@ extern int fdo_sys(fdo_sdk_si_type type, char *module_message, uint16_t *num_module_messages, bool *has_more, bool *is_more, size_t mtu); +extern int fdo_sim_download(fdo_sdk_si_type type, char *module_message, + uint8_t *module_val, size_t *module_val_sz, + uint16_t *num_module_messages, bool *has_more, + bool *is_more, size_t mtu); + +extern int fdo_sim_command(fdo_sdk_si_type type, char *module_message, + uint8_t *module_val, size_t *module_val_sz, + uint16_t *num_module_messages, bool *has_more, + bool *is_more, size_t mtu); + #endif /* __FDOTYPES_H__ */ diff --git a/lib/fdo.c b/lib/fdo.c index 737f9998..391816e7 100644 --- a/lib/fdo.c +++ b/lib/fdo.c @@ -699,11 +699,9 @@ static bool add_module_devmod(void) } // should ideally contain supported ServiceInfo module list and its - // count. for now, set this to 1, since we've only 1 module 'fdo_sys' - // TO-DO : Move this to fdotypes later when multiple Device ServiceInfo - // module support is added. + // count. if (!fdo_service_info_add_kv_int(g_fdo_data->service_info, - "devmod:nummodules", 1)) { + "devmod:nummodules", 3)) { LOG(LOG_ERROR, "Failed to add devmod:nummodules\n"); return false; } diff --git a/lib/fdotypes.c b/lib/fdotypes.c index 07bfd206..14c79070 100644 --- a/lib/fdotypes.c +++ b/lib/fdotypes.c @@ -5459,7 +5459,6 @@ bool fdo_supply_serviceinfoval(char *module_name, char *module_message, bool retval = false; bool module_name_found = false; bool active = false; - fdo_sdk_service_info_module_list_t *traverse_list = module_list; fdor_t temp_fdor = {0}; if (!cb_return_val) { @@ -5512,14 +5511,6 @@ bool fdo_supply_serviceinfoval(char *module_name, char *module_message, } if (active) { - // traverse the list to deactivate every - // module - while (traverse_list) { - traverse_list->module.active = - false; - traverse_list = - traverse_list->next; - } // now activate the current module module_list->module.active = active; LOG(LOG_INFO, @@ -6194,25 +6185,41 @@ bool fdo_serviceinfo_modules_list_write(fdow_t *fdow) { bool ret = false; - char module_value[8] = "fdo_sys"; + char module_value1[FDO_MODULE_NAME_LEN] = "fdo_sys"; + char module_value2[FDO_MODULE_NAME_LEN] = "fdo.download"; + char module_value3[FDO_MODULE_NAME_LEN] = "fdo.command"; - if (!fdow_start_array(fdow, 3)) { + if (!fdow_start_array(fdow, 5)) { LOG(LOG_ERROR, "Platform Device ServiceInfoKV: Failed to start " "ServiceInfoVal (modules) array\n"); goto end; } - if (!fdow_signed_int(fdow, 1)) { + if (!fdow_signed_int(fdow, 3)) { LOG(LOG_ERROR, "Platform Device ServiceInfoKV: Failed to write " "ServiceInfoVal (modules) nummodules\n"); goto end; } - if (!fdow_signed_int(fdow, 1)) { + if (!fdow_signed_int(fdow, 3)) { LOG(LOG_ERROR, "Platform Device ServiceInfoKV: Failed to write " "ServiceInfoVal (modules) return count\n"); goto end; } - if (!fdow_text_string(fdow, module_value, - strnlen_s(module_value, FDO_MAX_STR_SIZE))) { + if (!fdow_text_string(fdow, module_value1, + strnlen_s(module_value1, FDO_MAX_STR_SIZE))) { + LOG(LOG_ERROR, "Platform Device ServiceInfoKV: Failed to write " + "ServiceInfoVal (modules) module name\n"); + goto end; + } + + if (!fdow_text_string(fdow, module_value2, + strnlen_s(module_value2, FDO_MAX_STR_SIZE))) { + LOG(LOG_ERROR, "Platform Device ServiceInfoKV: Failed to write " + "ServiceInfoVal (modules) module name\n"); + goto end; + } + + if (!fdow_text_string(fdow, module_value3, + strnlen_s(module_value3, FDO_MAX_STR_SIZE))) { LOG(LOG_ERROR, "Platform Device ServiceInfoKV: Failed to write " "ServiceInfoVal (modules) module name\n"); goto end;