Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
storage_esfs.c
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // 00008 // http://www.apache.org/licenses/LICENSE-2.0 00009 // 00010 // Unless required by applicable law or agreed to in writing, software 00011 // distributed under the License is distributed on an "AS IS" BASIS, 00012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 // See the License for the specific language governing permissions and 00014 // limitations under the License. 00015 // ---------------------------------------------------------------------------- 00016 #ifndef MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT 00017 #include <stdbool.h> 00018 #include "pv_error_handling.h" 00019 #include "pv_macros.h" 00020 #include "storage.h" 00021 #include "esfs.h" 00022 #include "fcc_malloc.h" 00023 #include "sotp.h" 00024 00025 /** 00026 * sotp type lookup record, correlating sotp type and name 00027 */ 00028 typedef struct storage_sotp_type_lookup_record_ { 00029 sotp_type_e sotp_type; 00030 const char *type_name; 00031 } storage_sotp_type_lookup_record_s; 00032 #define STORAGE_SOTP_NUMBER_OF_TYPES 9 00033 /** 00034 * sotp type table, correlating for each sotp type and name. 00035 */ 00036 static const storage_sotp_type_lookup_record_s storage_sotp_type_lookup_table[STORAGE_SOTP_NUMBER_OF_TYPES] = { 00037 { SOTP_TYPE_FACTORY_DONE, STORAGE_RBP_FACTORY_DONE_NAME }, 00038 { SOTP_TYPE_RANDOM_SEED, STORAGE_RBP_RANDOM_SEED_NAME }, 00039 { SOTP_TYPE_SAVED_TIME, STORAGE_RBP_SAVED_TIME_NAME }, 00040 { SOTP_TYPE_LAST_TIME_BACK, STORAGE_RBP_LAST_TIME_BACK_NAME }, 00041 { SOTP_TYPE_ROT, STORAGE_RBP_ROT_NAME }, 00042 { SOTP_TYPE_TRUSTED_TIME_SRV_ID, STORAGE_RBP_TRUSTED_TIME_SRV_ID_NAME }, 00043 { SOTP_TYPE_EXECUTION_MODE, STORAGE_RBP_EXECUTION_MODE_NAME }, 00044 { SOTP_TYPE_OEM_TRANSFER_MODE_ENABLED, STORAGE_RBP_OEM_TRANSFER_MODE_ENABLED_NAME }, 00045 { SOTP_TYPE_MIN_FW_VERSION, STORAGE_RBP_MIN_FW_VERSION_NAME }, 00046 }; 00047 00048 00049 extern bool g_kcm_initialized; 00050 00051 static bool storage_get_sotp_type(const char *sotp_item, sotp_type_e *sotp_type) 00052 { 00053 int index = 0; 00054 00055 for (index = 0; index < STORAGE_SOTP_NUMBER_OF_TYPES; index++) { 00056 if (strlen(sotp_item) == strlen(storage_sotp_type_lookup_table[index].type_name)){ 00057 if (memcmp(storage_sotp_type_lookup_table[index].type_name, sotp_item, strlen(storage_sotp_type_lookup_table[index].type_name)) == 0) { 00058 *sotp_type = storage_sotp_type_lookup_table[index].sotp_type; 00059 return true; 00060 } 00061 } 00062 00063 } 00064 return false; 00065 } 00066 static kcm_status_e sotp_to_kcm_error_translation(sotp_result_e err) 00067 { 00068 kcm_status_e kcm_status; 00069 switch (err) 00070 { 00071 case SOTP_SUCCESS: 00072 kcm_status = KCM_STATUS_SUCCESS; 00073 break; 00074 case SOTP_NOT_FOUND: 00075 kcm_status = KCM_STATUS_ITEM_NOT_FOUND; 00076 break; 00077 case SOTP_ALREADY_EXISTS: 00078 kcm_status = KCM_STATUS_FILE_EXIST;//FCC_STATUS_INTERNAL_ITEM_ALREADY_EXIST 00079 break; 00080 case SOTP_READ_ERROR: 00081 case SOTP_WRITE_ERROR: 00082 case SOTP_DATA_CORRUPT: 00083 case SOTP_BAD_VALUE: 00084 case SOTP_BUFF_TOO_SMALL: 00085 case SOTP_FLASH_AREA_TOO_SMALL: 00086 case SOTP_OS_ERROR: 00087 case SOTP_BUFF_NOT_ALIGNED: 00088 default: 00089 kcm_status = KCM_STATUS_RBP_ERROR; 00090 break; 00091 } 00092 return kcm_status; 00093 } 00094 00095 static bool storage_get_sotp_type_size(sotp_type_e sotp_type, uint16_t *required_size_out) 00096 { 00097 size_t required_size; 00098 00099 switch (sotp_type) { 00100 case SOTP_TYPE_ROT: 00101 required_size = FCC_ROT_SIZE; 00102 break; 00103 case SOTP_TYPE_FACTORY_DONE: 00104 required_size = FCC_FACTORY_DISABLE_FLAG_SIZE; 00105 break; 00106 case SOTP_TYPE_RANDOM_SEED: 00107 required_size = FCC_ENTROPY_SIZE; 00108 break; 00109 case SOTP_TYPE_SAVED_TIME: 00110 required_size = sizeof(uint64_t); 00111 break; 00112 case SOTP_TYPE_TRUSTED_TIME_SRV_ID: 00113 required_size = FCC_CA_IDENTIFICATION_SIZE; 00114 break; 00115 default: 00116 SA_PV_LOG_ERR("Wrong sotp_type"); 00117 return false; 00118 } 00119 00120 // Success 00121 *required_size_out = (uint16_t)required_size; 00122 00123 return true; 00124 } 00125 00126 00127 static kcm_status_e storage_allocate_and_create_compelete_name(const uint8_t *kcm_name, size_t kcm_name_len, const char *prefix, uint8_t **kcm_buffer_out, size_t *kcm_buffer_size_allocated_out) 00128 { 00129 size_t prefix_length = 0; 00130 size_t total_length = 0; 00131 00132 SA_PV_LOG_TRACE_FUNC_ENTER("name len=%" PRIu32 "", (uint32_t)kcm_name_len); 00133 00134 //Check parameters 00135 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_buffer_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_buffer_out parameter"); 00136 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_buffer_size_allocated_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_buffer_size_allocated_out parameter"); 00137 00138 // Check that name is not too long. This is done only in this function since all KCM APIs using file names go through here. 00139 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_name_len > KCM_MAX_FILENAME_SIZE), KCM_STATUS_FILE_NAME_TOO_LONG, "kcm_item_name_len must be %d or less", KCM_MAX_FILENAME_SIZE); 00140 00141 prefix_length = strlen(prefix); 00142 total_length = kcm_name_len + prefix_length; 00143 00144 // This Should never happen. This means that the total larger than permitted was used. 00145 SA_PV_ERR_RECOVERABLE_RETURN_IF((total_length > STORAGE_FILENAME_MAX_SIZE), KCM_STATUS_INVALID_PARAMETER, "KCM file name too long"); 00146 00147 *kcm_buffer_out = (uint8_t *)fcc_malloc(total_length); 00148 SA_PV_ERR_RECOVERABLE_RETURN_IF((*kcm_buffer_out == NULL), KCM_STATUS_OUT_OF_MEMORY, "Failed allocating kcm_buffer_out"); 00149 00150 /* Append prefix and name to allocated buffer */ 00151 memcpy(*kcm_buffer_out, (uint8_t *)prefix, prefix_length); 00152 memcpy(*kcm_buffer_out + prefix_length, kcm_name, kcm_name_len); 00153 00154 *kcm_buffer_size_allocated_out = total_length; 00155 00156 SA_PV_LOG_TRACE_FUNC_EXIT("kcm_buffer_size_allocated_out= %" PRIu32 "", (uint32_t)*kcm_buffer_size_allocated_out); 00157 return KCM_STATUS_SUCCESS; 00158 } 00159 00160 static kcm_status_e storage_build_complete_item_name(kcm_item_type_e kcm_item_type, 00161 kcm_data_source_type_e data_source_type, 00162 const uint8_t *kcm_item_name, 00163 size_t kcm_item_name_len, 00164 uint8_t **kcm_complete_name, 00165 size_t *kcm_complete_name_size) 00166 { 00167 const char *prefix = "DFghdfj"; 00168 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00169 00170 kcm_status = storage_item_name_get_prefix(kcm_item_type, data_source_type, &prefix); 00171 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_item_name_get_prefix"); 00172 00173 kcm_status = storage_allocate_and_create_compelete_name(kcm_item_name, kcm_item_name_len, prefix, kcm_complete_name, kcm_complete_name_size); 00174 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_allocate_and_create_compelete_name"); 00175 00176 return kcm_status; 00177 } 00178 00179 static kcm_status_e error_handler(esfs_result_e esfs_status) 00180 { 00181 switch (esfs_status) { 00182 case ESFS_SUCCESS: 00183 return KCM_STATUS_SUCCESS; 00184 case ESFS_INVALID_PARAMETER: 00185 return KCM_STATUS_INVALID_PARAMETER; 00186 case ESFS_BUFFER_TOO_SMALL: 00187 return KCM_STATUS_INSUFFICIENT_BUFFER; 00188 case ESFS_EXISTS: 00189 return KCM_STATUS_FILE_EXIST; 00190 case ESFS_NOT_EXISTS: 00191 return KCM_STATUS_ITEM_NOT_FOUND; 00192 case ESFS_INVALID_FILE_VERSION: 00193 return KCM_STATUS_INVALID_FILE_VERSION; 00194 case ESFS_CMAC_DOES_NOT_MATCH: 00195 return KCM_STATUS_FILE_CORRUPTED; 00196 case ESFS_ERROR: 00197 return KCM_STATUS_STORAGE_ERROR; 00198 case ESFS_HASH_CONFLICT: 00199 return KCM_STATUS_FILE_NAME_CORRUPTED; 00200 case ESFS_FILE_OPEN_FOR_READ: 00201 case ESFS_FILE_OPEN_FOR_WRITE: 00202 return KCM_STATUS_INVALID_FILE_ACCESS_MODE; 00203 default: 00204 return KCM_STATUS_UNKNOWN_STORAGE_ERROR; 00205 } 00206 } 00207 00208 00209 static bool is_file_accessible(const kcm_ctx_s *ctx) 00210 { 00211 // FIXME - We need to check file access availability by comparing KCM context TLVs vs the target file header stored in ESFS that contains 00212 // TLVs and access rights. In order to retrieve ESFS file TLVs and access rights we should use the following methods 00213 // that are currently not implemented: 00214 // - esfs_get_meta_data_qty 00215 // - esfs_get_meta_data_types 00216 // - esfs_get_meta_data_buffer_size 00217 // - esfs_read_meta_data 00218 // - esfs_get_meta_data_qty 00219 00220 PV_DEBUG_USE(ctx); // currently unused 00221 00222 return true; 00223 } 00224 00225 kcm_status_e storage_init() 00226 { 00227 esfs_result_e esfs_status; 00228 00229 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 00230 00231 esfs_status = esfs_init(); 00232 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed initializing ESFS (esfs_status %d)", esfs_status); 00233 00234 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 00235 00236 return KCM_STATUS_SUCCESS; 00237 } 00238 00239 kcm_status_e storage_finalize() 00240 { 00241 esfs_result_e esfs_status; 00242 00243 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 00244 00245 esfs_status = esfs_finalize(); 00246 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed finalizing ESFS (esfs_status %d)", esfs_status); 00247 00248 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 00249 00250 return KCM_STATUS_SUCCESS; 00251 } 00252 00253 kcm_status_e storage_reset() 00254 { 00255 esfs_result_e esfs_status; 00256 sotp_result_e sotp_status; 00257 00258 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 00259 00260 esfs_status = esfs_reset(); 00261 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reset ESFS (esfs_status %d)", esfs_status); 00262 00263 sotp_status = sotp_reset(); 00264 SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_status != SOTP_SUCCESS), KCM_STATUS_STORAGE_ERROR, "Failed to reset sotp storage "); 00265 00266 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 00267 00268 return KCM_STATUS_SUCCESS; 00269 } 00270 00271 00272 kcm_status_e storage_factory_reset() 00273 { 00274 esfs_result_e esfs_status; 00275 00276 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 00277 00278 esfs_status = esfs_factory_reset(); 00279 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed factory reset ESFS (esfs_status %d)", esfs_status); 00280 00281 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 00282 00283 return KCM_STATUS_SUCCESS; 00284 } 00285 00286 palStatus_t storage_rbp_read( 00287 const char *item_name, 00288 uint8_t *data, 00289 size_t data_size, 00290 size_t *data_actual_size_out) 00291 { 00292 bool status = false; 00293 sotp_type_e sotp_type = SOTP_MAX_TYPES; 00294 sotp_result_e sotp_result = SOTP_SUCCESS; 00295 00296 // Validate function parameters 00297 SA_PV_ERR_RECOVERABLE_RETURN_IF((item_name == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid item_name"); 00298 SA_PV_LOG_INFO_FUNC_ENTER("item name = %s", (char*)item_name); 00299 SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid data"); 00300 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size == 0 || data_size > UINT16_MAX), PAL_ERR_INVALID_ARGUMENT , "Invalid data_length"); 00301 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_actual_size_out == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid data_actual_size_out"); 00302 00303 status = storage_get_sotp_type(item_name, &sotp_type); 00304 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != true), PAL_ERR_INVALID_ARGUMENT , "Invalid sotp data name"); 00305 00306 sotp_result = sotp_get(sotp_type,(uint16_t)data_size, (uint32_t*)data, (uint16_t*)data_actual_size_out); 00307 if (sotp_result == SOTP_NOT_FOUND) { 00308 //item not found. Print info level error 00309 SA_PV_LOG_INFO("SOTP item not found"); 00310 return PAL_ERR_ITEM_NOT_EXIST ; 00311 } 00312 SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result != SOTP_SUCCESS), PAL_ERR_GENERIC_FAILURE , "SOTP get failed"); 00313 00314 return PAL_SUCCESS; 00315 } 00316 00317 palStatus_t storage_rbp_write( 00318 const char *item_name, 00319 const uint8_t *data, 00320 size_t data_size, 00321 bool is_write_once) 00322 { 00323 bool status = false; 00324 sotp_type_e sotp_type = SOTP_MAX_TYPES; 00325 sotp_result_e sotp_result = SOTP_SUCCESS; 00326 uint16_t sotp_buffer_size = 0; 00327 00328 // Validate function parameters 00329 SA_PV_ERR_RECOVERABLE_RETURN_IF((item_name == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid item_name"); 00330 SA_PV_LOG_INFO_FUNC_ENTER("item name = %s", (char*)item_name); 00331 SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid data"); 00332 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size == 0 || data_size > UINT16_MAX), PAL_ERR_INVALID_ARGUMENT , "Invalid data_length"); 00333 00334 status = storage_get_sotp_type(item_name, &sotp_type); 00335 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != true), PAL_ERR_INVALID_ARGUMENT , "Invalid sotp data name"); 00336 00337 if (is_write_once == true) { 00338 //Check if current type was already written to sotp by triyng to get the data 00339 sotp_result = sotp_get_item_size(sotp_type, &sotp_buffer_size); 00340 SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result == SOTP_SUCCESS), PAL_ERR_ITEM_EXIST , "The item was already written to sotp"); 00341 } 00342 00343 sotp_result = sotp_set(sotp_type, (uint16_t)data_size, (const uint32_t*)data); 00344 SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result != SOTP_SUCCESS), PAL_ERR_GENERIC_FAILURE , "SOTP set failed"); 00345 00346 return PAL_SUCCESS; 00347 } 00348 00349 00350 #ifdef RBP_TESTING 00351 palStatus_t storage_rbp_delete(const char *item_name) 00352 { 00353 bool status = false; 00354 sotp_type_e sotp_type = SOTP_MAX_TYPES; 00355 sotp_result_e sotp_result = SOTP_SUCCESS; 00356 00357 SA_PV_ERR_RECOVERABLE_RETURN_IF((item_name == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid item_name"); 00358 00359 00360 status = storage_get_sotp_type(item_name, &sotp_type); 00361 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != true), PAL_ERR_INVALID_ARGUMENT , "Invalid sotp data name"); 00362 00363 //Remove the item 00364 sotp_result = sotp_delete(sotp_type); 00365 SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result == SOTP_NOT_FOUND), PAL_ERR_ITEM_NOT_EXIST , "SOTP item not found"); 00366 SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result != SOTP_SUCCESS), PAL_ERR_GENERIC_FAILURE , "SOTP delete failed"); 00367 00368 return PAL_SUCCESS; 00369 } 00370 #endif 00371 00372 00373 kcm_status_e storage_fcc_rbp_write( 00374 const char *item_name, 00375 const uint8_t *data, 00376 size_t data_size, 00377 bool is_write_once) 00378 { 00379 bool success; 00380 sotp_result_e sotp_result; 00381 uint16_t required_size = 0; 00382 int64_t aligned_8_bytes_buffer[MAX_SOTP_BUFFER_SIZE / 8]; 00383 uint16_t sotp_buffer_size = 0; 00384 sotp_type_e sotp_type = SOTP_MAX_TYPES; 00385 00386 SA_PV_ERR_RECOVERABLE_RETURN_IF((item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid item_name"); 00387 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size > UINT16_MAX || data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid param data"); 00388 SA_PV_LOG_INFO_FUNC_ENTER("data_size = %" PRIu32 " item_name = %s", (uint32_t)data_size, item_name); 00389 SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid param data"); 00390 00391 PV_UNUSED_PARAM(is_write_once); 00392 00393 success = storage_get_sotp_type(item_name, &sotp_type); 00394 SA_PV_ERR_RECOVERABLE_RETURN_IF((success != true), KCM_STATUS_INVALID_PARAMETER, "Invalid sotp data name"); 00395 00396 success = storage_get_sotp_type_size(sotp_type, &required_size); 00397 SA_PV_ERR_RECOVERABLE_RETURN_IF((!success), KCM_STATUS_INVALID_PARAMETER, "Failed for get_sotp_type_size()"); 00398 00399 if (sotp_type != SOTP_TYPE_SAVED_TIME) { 00400 //Check if current type was already written to sotp by triyng to get the data 00401 sotp_result = sotp_get_item_size(sotp_type, &sotp_buffer_size); 00402 SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result == SOTP_SUCCESS), KCM_STATUS_FILE_EXIST, "The item was already written to sotp"); 00403 } 00404 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size != required_size), KCM_STATUS_INVALID_PARAMETER, "Wrong buf_size provided. Must be size of exactly %" PRIu32 " bytes", (uint32_t)required_size); 00405 00406 // Write buf to SOTP. Cast is OK since size must be divisible by 8 00407 00408 /* 00409 * Copy from data (uint8_t*) to aligned_8_bytes_buffer (uint64_t*) to make sure that data is 8 byte aligned. 00410 * Since sotp_set() gets a pointer to int64_t, if it is not aligned, and we just cast it to uint8_t*, 00411 * ARMCC functions like memcpy will assume 8 byte alignment resulting in possible access of unallocated memory. 00412 */ 00413 memcpy(aligned_8_bytes_buffer, data, data_size); 00414 00415 sotp_result = sotp_set(sotp_type, (uint16_t)(data_size), (const uint32_t*)aligned_8_bytes_buffer); 00416 SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result != SOTP_SUCCESS), sotp_to_kcm_error_translation(sotp_result), "sotp_set failed"); 00417 00418 00419 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00420 00421 return KCM_STATUS_SUCCESS; 00422 } 00423 00424 /** FCC initiated operation, writes a rollback protected data. 00425 * 00426 * @param[in] item_name A string name of the rollback protected item 00427 * @param[in] data A pointer to memory with the data to write into the storage. Can be NULL if data_length is 0. 00428 * @param[in] data_size The data length in bytes. Can be 0 if we wish to write an empty file. 00429 * @param[in] is_write_once Write once flag. 00430 * @returns 00431 * KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise. 00432 */ 00433 kcm_status_e storage_fcc_rbp_read( 00434 const char *item_name, 00435 uint8_t *data, 00436 size_t data_size, 00437 size_t *data_actual_size_out) 00438 { 00439 00440 bool success; 00441 sotp_result_e sotp_result; 00442 uint16_t required_size = 0; 00443 int64_t aligned_8_bytes_buffer[MAX_SOTP_BUFFER_SIZE / 8] = { 0 }; 00444 size_t actual_data_size = 0; 00445 sotp_type_e sotp_type = SOTP_MAX_TYPES; 00446 00447 SA_PV_ERR_RECOVERABLE_RETURN_IF((item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid item_name"); 00448 SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid param data"); 00449 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size == 0 || data_size > UINT16_MAX ), KCM_STATUS_INVALID_PARAMETER, "Invalid data_size"); 00450 SA_PV_LOG_INFO_FUNC_ENTER("data_size = %" PRIu32 " item_name = %s", (uint32_t)data_size, item_name); 00451 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_actual_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid data_actual_size_out"); 00452 00453 success = storage_get_sotp_type(item_name, &sotp_type); 00454 SA_PV_ERR_RECOVERABLE_RETURN_IF((success != true), KCM_STATUS_INVALID_PARAMETER, "Invalid sotp data name"); 00455 00456 00457 success = storage_get_sotp_type_size(sotp_type, &required_size); 00458 SA_PV_ERR_RECOVERABLE_RETURN_IF((!success), KCM_STATUS_INVALID_PARAMETER, "Failed for get_sotp_type_size()"); 00459 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size < required_size), KCM_STATUS_INVALID_PARAMETER, "Wrong buf_size provided. Must be size of exactly %" PRIu32 " bytes", (uint32_t)required_size); 00460 00461 sotp_result = sotp_get(sotp_type, (uint16_t)data_size, (uint32_t*)aligned_8_bytes_buffer, (uint16_t*)&actual_data_size); 00462 SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result != SOTP_SUCCESS), sotp_to_kcm_error_translation(sotp_result), "sotp_get failed"); 00463 00464 // Copy from aligned buffer to callers uint8_t* buffer 00465 memcpy(data, aligned_8_bytes_buffer, actual_data_size); 00466 00467 *data_actual_size_out = (size_t)(actual_data_size); 00468 00469 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00470 00471 return KCM_STATUS_SUCCESS; 00472 00473 } 00474 00475 00476 00477 kcm_status_e storage_data_write_impl(const uint8_t * kcm_item_name, 00478 size_t kcm_item_name_len, 00479 kcm_item_type_e kcm_item_type, 00480 bool kcm_item_is_factory, 00481 bool kcm_item_is_encrypted, 00482 kcm_data_source_type_e data_source_type, 00483 const uint8_t * kcm_item_data, 00484 size_t kcm_item_data_size) 00485 { 00486 uint8_t *kcm_complete_name = NULL; //Filename including prefix 00487 size_t kcm_complete_name_size; 00488 kcm_ctx_s ctx; 00489 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00490 00491 //Build complete item name 00492 kcm_status = storage_build_complete_item_name(kcm_item_type, data_source_type, kcm_item_name, kcm_item_name_len, &kcm_complete_name, &kcm_complete_name_size); 00493 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_build_complete_item_name"); 00494 00495 //Store the item using the full name 00496 kcm_status = storage_file_write(&ctx, kcm_complete_name, kcm_complete_name_size, kcm_item_data, kcm_item_data_size, NULL, kcm_item_is_factory, kcm_item_is_encrypted); 00497 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed writing file to storage"); 00498 00499 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00500 00501 Exit: 00502 fcc_free(kcm_complete_name); 00503 return kcm_status; 00504 } 00505 00506 kcm_status_e storage_data_size_read( 00507 const uint8_t * kcm_item_name, 00508 size_t kcm_item_name_len, 00509 kcm_item_type_e kcm_item_type, 00510 kcm_data_source_type_e data_source_type, 00511 size_t * kcm_item_data_size_out) 00512 { 00513 uint8_t *kcm_complete_name = NULL; //Filename including prefix 00514 size_t kcm_complete_name_size; 00515 kcm_ctx_s ctx; 00516 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00517 size_t kcm_data_size = 0; 00518 00519 // Validate function parameters 00520 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name"); 00521 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len"); 00522 SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len=%" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len); 00523 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type"); 00524 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Kcm size out pointer is NULL"); 00525 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 00526 00527 // Check if KCM initialized, if not initialize it 00528 if (!g_kcm_initialized) { 00529 kcm_status = kcm_init(); 00530 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00531 } 00532 00533 //Build complete item name 00534 kcm_status = storage_build_complete_item_name(kcm_item_type, data_source_type, kcm_item_name, kcm_item_name_len, &kcm_complete_name, &kcm_complete_name_size); 00535 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_build_complete_item_name"); 00536 00537 //Get data item 00538 kcm_status = storage_file_size_get(&ctx, kcm_complete_name, kcm_complete_name_size, &kcm_data_size); 00539 if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) { 00540 //We don't want print log in case the item wasn't found 00541 goto Exit; 00542 } 00543 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Failed getting file size"); 00544 00545 *kcm_item_data_size_out = kcm_data_size; 00546 SA_PV_LOG_INFO_FUNC_EXIT("kcm data size = %" PRIu32 "", (uint32_t)*kcm_item_data_size_out); 00547 00548 Exit: 00549 fcc_free(kcm_complete_name); 00550 return kcm_status; 00551 00552 } 00553 00554 kcm_status_e storage_data_read( 00555 const uint8_t * kcm_item_name, 00556 size_t kcm_item_name_len, 00557 kcm_item_type_e kcm_item_type, 00558 kcm_data_source_type_e data_source_type, 00559 uint8_t *kcm_item_data_out, 00560 size_t kcm_item_data_max_size, 00561 size_t *kcm_item_data_act_size_out) 00562 { 00563 00564 uint8_t *kcm_complete_name = NULL; //Filename including prefix 00565 size_t kcm_complete_name_size; 00566 kcm_ctx_s ctx; 00567 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00568 size_t meta_data_size; 00569 uint16_t chain_len_to_read; 00570 00571 // Validate function parameters 00572 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name"); 00573 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len"); 00574 SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len = %" PRIu32 ", data max size = %" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len, (uint32_t)kcm_item_data_max_size); 00575 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 00576 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type"); 00577 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_data_act_size_out"); 00578 SA_PV_ERR_RECOVERABLE_RETURN_IF(((kcm_item_data_out == NULL) && (kcm_item_data_max_size > 0)), KCM_STATUS_INVALID_PARAMETER, "Provided kcm_item_data NULL and kcm_item_data_size greater than 0"); 00579 00580 // Check if KCM initialized, if not initialize it 00581 if (!g_kcm_initialized) { 00582 kcm_status = kcm_init(); 00583 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00584 } 00585 00586 //Build complete item name 00587 kcm_status = storage_build_complete_item_name(kcm_item_type, data_source_type, kcm_item_name, kcm_item_name_len, &kcm_complete_name, &kcm_complete_name_size); 00588 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_build_complete_item_name"); 00589 00590 //Open the file 00591 kcm_status = storage_file_open(&ctx, kcm_complete_name, kcm_complete_name_size); 00592 if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) { 00593 goto Exit; 00594 } 00595 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Failed to open the given file"); 00596 00597 if (kcm_item_type == KCM_CERTIFICATE_ITEM) { 00598 // check if there is meta data 00599 kcm_status = storage_file_get_meta_data_size(&ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, &meta_data_size); 00600 if (kcm_status == KCM_STATUS_SUCCESS) { 00601 kcm_status = storage_file_read_meta_data_by_type(&ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, (uint8_t*)&chain_len_to_read, meta_data_size, &meta_data_size); 00602 if (kcm_status == KCM_STATUS_SUCCESS && chain_len_to_read > 1) { 00603 SA_PV_LOG_WARN("Warning: Reading certificate chain using single certificate API"); 00604 } 00605 } 00606 } 00607 00608 kcm_status = storage_file_read_with_ctx(&ctx, kcm_item_data_out, kcm_item_data_max_size, kcm_item_data_act_size_out); 00609 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed reading file from storage (%d)", kcm_status); 00610 SA_PV_LOG_INFO_FUNC_EXIT("kcm data size = %" PRIu32 "", (uint32_t)*kcm_item_data_act_size_out); 00611 00612 Exit: 00613 if (kcm_status != KCM_STATUS_ITEM_NOT_FOUND) { 00614 storage_file_close(&ctx); 00615 } 00616 fcc_free(kcm_complete_name); 00617 00618 return kcm_status; 00619 } 00620 00621 kcm_status_e storage_data_delete( 00622 const uint8_t * kcm_item_name, 00623 size_t kcm_item_name_len, 00624 kcm_item_type_e kcm_item_type, 00625 kcm_data_source_type_e data_source_type) 00626 { 00627 uint8_t *kcm_complete_name = NULL; //Filename including prefix 00628 size_t kcm_complete_name_size; 00629 kcm_ctx_s ctx; 00630 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00631 00632 // Validate function parameters 00633 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name"); 00634 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len"); 00635 SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len = %" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len); 00636 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type"); 00637 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 00638 00639 // Check if KCM initialized, if not initialize it 00640 if (!g_kcm_initialized) { 00641 kcm_status = kcm_init(); 00642 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00643 } 00644 00645 //Build complete item name 00646 kcm_status = storage_build_complete_item_name(kcm_item_type, data_source_type, kcm_item_name, kcm_item_name_len, &kcm_complete_name, &kcm_complete_name_size); 00647 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_build_complete_item_name"); 00648 00649 kcm_status = storage_file_delete(&ctx, kcm_complete_name, kcm_complete_name_size); 00650 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed deleting kcm data"); 00651 00652 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00653 00654 Exit: 00655 fcc_free(kcm_complete_name); 00656 return kcm_status; 00657 00658 } 00659 00660 void storage_cert_chain_update_name_prefixe(uint8_t *complete_file_name, uint32_t index, kcm_data_source_type_e data_source_type) 00661 { 00662 if (index == 0) { 00663 if (data_source_type == KCM_ORIGINAL_ITEM) { 00664 memcpy(complete_file_name, KCM_FILE_PREFIX_CERT_CHAIN_0, strlen(KCM_FILE_PREFIX_CERT_CHAIN_0)); 00665 } 00666 else { 00667 memcpy(complete_file_name, KCM_RENEWAL_FILE_PREFIX_CERT_CHAIN_0, strlen(KCM_RENEWAL_FILE_PREFIX_CERT_CHAIN_0)); 00668 } 00669 return; 00670 } 00671 if (data_source_type == KCM_ORIGINAL_ITEM) { 00672 memcpy(complete_file_name, KCM_FILE_PREFIX_CERT_CHAIN_X, strlen(KCM_FILE_PREFIX_CERT_CHAIN_X)); 00673 complete_file_name[KCM_FILE_PREFIX_CERT_CHAIN_X_OFFSET] = (uint8_t)('0' + (uint8_t)index); 00674 } 00675 else { 00676 memcpy(complete_file_name, KCM_RENEWAL_FILE_PREFIX_CERT_CHAIN_X, strlen(KCM_RENEWAL_FILE_PREFIX_CERT_CHAIN_X)); 00677 complete_file_name[KCM_RENEWAL_FILE_PREFIX_CERT_CHAIN_X_OFFSET] = (uint8_t)('0' + (uint8_t)index); 00678 } 00679 00680 } 00681 static void storage_cert_chain_files_delete(kcm_cert_chain_context_int_s *chain_context, kcm_data_source_type_e data_source_type) 00682 { 00683 00684 do { 00685 storage_cert_chain_update_name_prefixe(chain_context->chain_name, chain_context->current_cert_index, data_source_type); 00686 //we don't check the result of storage_file_delete, as it is possible that not all certificates were saved to the storage 00687 (void)storage_file_delete(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len); 00688 if (chain_context->current_cert_index == 0) { 00689 break; 00690 } 00691 chain_context->current_cert_index--; 00692 } while (true); 00693 } 00694 kcm_status_e storage_cert_chain_create(kcm_cert_chain_handle *kcm_chain_handle, const uint8_t *kcm_chain_name, size_t kcm_chain_name_len, size_t kcm_chain_len, bool kcm_chain_is_factory, kcm_data_source_type_e data_source_type) 00695 { 00696 uint8_t *kcm_complete_name = NULL; // Filename including prefix 00697 size_t kcm_complete_name_size; 00698 kcm_meta_data_list_s kcm_meta_data; 00699 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00700 kcm_cert_chain_context_int_s *chain_context = NULL; 00701 uint16_t chain_len_to_write = (uint16_t)kcm_chain_len; 00702 00703 // Validate function parameters 00704 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name"); 00705 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name len"); 00706 SA_PV_LOG_INFO_FUNC_ENTER("chain name = %.*s, chain len =%" PRIu32 "", (int)kcm_chain_name_len, kcm_chain_name, (uint32_t)kcm_chain_len); 00707 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 00708 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid handle"); 00709 *kcm_chain_handle = NULL; 00710 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_len == 0 || kcm_chain_len > KCM_MAX_NUMBER_OF_CERTITICATES_IN_CHAIN), KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Invalid chain len"); 00711 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type == KCM_BACKUP_ITEM && kcm_chain_is_factory == true), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_chain_is_factory"); 00712 00713 // Check if KCM initialized, if not initialize it 00714 if (!g_kcm_initialized) { 00715 kcm_status = kcm_init(); 00716 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00717 } 00718 00719 if (data_source_type == KCM_ORIGINAL_ITEM) { 00720 kcm_status = storage_allocate_and_create_compelete_name(kcm_chain_name, kcm_chain_name_len, KCM_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size); 00721 } 00722 else { 00723 kcm_status = storage_allocate_and_create_compelete_name(kcm_chain_name, kcm_chain_name_len, KCM_RENEWAL_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size); 00724 } 00725 00726 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_allocate_and_create_compelete_name"); 00727 00728 // allocate the context 00729 chain_context = (kcm_cert_chain_context_int_s*)fcc_malloc(sizeof(kcm_cert_chain_context_int_s)); 00730 memset(chain_context, 0, sizeof(kcm_cert_chain_context_int_s)); 00731 00732 // Prepare one meta data item for saving kcm_chain_len as meta data of the first file 00733 kcm_meta_data.meta_data[0].type = KCM_CERT_CHAIN_LEN_MD_TYPE; 00734 kcm_meta_data.meta_data[0].data_size = sizeof(chain_len_to_write); 00735 kcm_meta_data.meta_data[0].data = (uint8_t*)&chain_len_to_write; 00736 kcm_meta_data.meta_data_count = 1; 00737 00738 kcm_status = storage_file_create(&chain_context->current_kcm_ctx, kcm_complete_name, kcm_complete_name_size, &kcm_meta_data, kcm_chain_is_factory, false); 00739 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed creating kcm chain file"); 00740 00741 chain_context->operation_type = KCM_CHAIN_OP_TYPE_CREATE; 00742 chain_context->chain_name = kcm_complete_name; 00743 chain_context->chain_name_len = kcm_complete_name_size; 00744 chain_context->num_of_certificates_in_chain = kcm_chain_len; 00745 chain_context->current_cert_index = 0; 00746 chain_context->chain_is_factory = kcm_chain_is_factory; 00747 00748 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00749 Exit: 00750 if (kcm_status != KCM_STATUS_SUCCESS) { 00751 fcc_free(kcm_complete_name); 00752 fcc_free(chain_context); 00753 *kcm_chain_handle = NULL; 00754 } 00755 else { 00756 // set the handle only if success 00757 *kcm_chain_handle = (kcm_cert_chain_handle)chain_context; 00758 } 00759 return kcm_status; 00760 } 00761 00762 kcm_status_e storage_chain_add_next(kcm_cert_chain_handle kcm_chain_handle, const uint8_t *kcm_cert_data, size_t kcm_cert_data_size, kcm_data_source_type_e data_source_type) 00763 { 00764 kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 00765 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00766 00767 SA_PV_LOG_INFO_FUNC_ENTER("cert_data_size =%" PRIu32 "", (uint32_t)kcm_cert_data_size); 00768 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 00769 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle"); 00770 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm context"); 00771 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data == NULL || kcm_cert_data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data or kcm_cert_data_size"); 00772 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_CREATE), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type"); 00773 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->current_cert_index >= chain_context->num_of_certificates_in_chain), KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Invalid certificate index"); 00774 00775 // Check if KCM initialized, if not initialize it 00776 if (!g_kcm_initialized) { 00777 kcm_status = kcm_init(); 00778 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00779 } 00780 00781 if (chain_context->current_cert_index > 0) { 00782 // only on the first certificate, the file is open 00783 // update file name by changing last char suffix and create the file 00784 storage_cert_chain_update_name_prefixe(chain_context->chain_name, chain_context->current_cert_index, data_source_type); 00785 kcm_status = storage_file_create(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len, NULL, chain_context->chain_is_factory, false); 00786 if (kcm_status == KCM_STATUS_FILE_EXIST) { 00787 // trying to recover by deleting the existing file 00788 SA_PV_LOG_INFO("Certificate chain file for index %" PRIu32 " already exists. File will be overwritten.", (uint32_t)chain_context->current_cert_index); 00789 00790 kcm_status = storage_file_delete(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len); 00791 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed to delete existing kcm chain file"); 00792 00793 kcm_status = storage_file_create(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len, NULL, chain_context->chain_is_factory, false); 00794 } 00795 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Failed creating kcm chain file"); 00796 } 00797 00798 kcm_status = storage_file_write_with_ctx(&chain_context->current_kcm_ctx, kcm_cert_data, kcm_cert_data_size); 00799 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed writing kcm chain file"); 00800 00801 kcm_status = storage_file_close(&chain_context->current_kcm_ctx); 00802 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed closing kcm chain file"); 00803 00804 // file written, increase current_cert_index 00805 chain_context->current_cert_index++; 00806 00807 Exit: 00808 if (kcm_status != KCM_STATUS_SUCCESS) { 00809 if (chain_context->current_cert_index > 0) { 00810 storage_file_close(&chain_context->current_kcm_ctx); 00811 } 00812 } 00813 return kcm_status; 00814 } 00815 00816 kcm_status_e storage_cert_chain_get_next_size(kcm_cert_chain_handle *kcm_chain_handle, kcm_data_source_type_e data_source_type, size_t *kcm_out_cert_data_size) 00817 { 00818 kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 00819 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00820 00821 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS(); 00822 00823 // Validate function parameters 00824 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 00825 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle"); 00826 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain"); 00827 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_out_cert_data_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_out_cert_data_size"); 00828 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_OPEN), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type"); 00829 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->current_cert_index >= chain_context->num_of_certificates_in_chain), KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Invalid certificate index"); 00830 00831 // Check if KCM initialized, if not initialize it 00832 if (!g_kcm_initialized) { 00833 kcm_status = kcm_init(); 00834 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00835 } 00836 00837 if (chain_context->current_cert_index > 0) { 00838 // only on the first certificate, the file is open 00839 // update file name by changing last char suffix and open the file 00840 storage_cert_chain_update_name_prefixe(chain_context->chain_name, chain_context->current_cert_index, data_source_type); 00841 kcm_status = storage_file_open(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len); 00842 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed opening kcm chain file"); 00843 } 00844 00845 kcm_status = storage_file_size_get_with_ctx(&chain_context->current_kcm_ctx, kcm_out_cert_data_size); 00846 if (kcm_status != KCM_STATUS_SUCCESS) { 00847 if (chain_context->current_cert_index > 0) { 00848 // close the file only if was open in that function 00849 storage_file_close(&chain_context->current_kcm_ctx); 00850 } 00851 SA_PV_ERR_RECOVERABLE_RETURN(kcm_status, "Failed getting kcm chain file size"); 00852 } 00853 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00854 return kcm_status; 00855 } 00856 00857 kcm_status_e storage_cert_chain_get_next_data(kcm_cert_chain_handle *kcm_chain_handle, uint8_t *kcm_cert_data, size_t kcm_max_cert_data_size, kcm_data_source_type_e data_source_type, size_t *kcm_actual_cert_data_size) 00858 { 00859 kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 00860 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00861 size_t expected_data_size = 0; 00862 00863 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS(); 00864 00865 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 00866 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle"); 00867 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain"); 00868 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data"); 00869 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_max_cert_data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_max_cert_data_size"); 00870 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_actual_cert_data_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_actual_cert_data_size"); 00871 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_OPEN), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type"); 00872 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->current_cert_index >= chain_context->num_of_certificates_in_chain), KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Invalid certificate index"); 00873 // Check if KCM initialized, if not initialize it 00874 if (!g_kcm_initialized) { 00875 kcm_status = kcm_init(); 00876 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00877 } 00878 00879 if (chain_context->current_kcm_ctx.is_file_size_checked == false) { 00880 // if user skip call to kcm_cert_chain_get_next_size 00881 kcm_status = storage_cert_chain_get_next_size((kcm_cert_chain_handle*)chain_context, data_source_type, &expected_data_size); 00882 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed getting kcm chain file size"); 00883 } 00884 else { 00885 expected_data_size = chain_context->current_kcm_ctx.file_size; 00886 } 00887 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_max_cert_data_size < expected_data_size), KCM_STATUS_INSUFFICIENT_BUFFER, "Certificate data buffer too small"); 00888 00889 kcm_status = storage_file_read_with_ctx(&chain_context->current_kcm_ctx, kcm_cert_data, kcm_max_cert_data_size, kcm_actual_cert_data_size); 00890 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed read kcm chain file"); 00891 00892 kcm_status = storage_file_close(&chain_context->current_kcm_ctx); 00893 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed closing kcm chain file"); 00894 00895 // file read, increase current_cert_index 00896 chain_context->current_cert_index++; 00897 00898 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00899 return kcm_status; 00900 } 00901 00902 kcm_status_e storage_cert_chain_open(kcm_cert_chain_handle *kcm_chain_handle, const uint8_t *kcm_chain_name, size_t kcm_chain_name_len, kcm_data_source_type_e data_source_type, size_t *kcm_chain_len_out) 00903 { 00904 kcm_cert_chain_context_int_s *chain_context = NULL; 00905 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00906 uint8_t *kcm_complete_name = NULL; // Filename including prefix 00907 size_t kcm_complete_name_size; 00908 size_t meta_data_size; 00909 uint16_t chain_len_to_read; 00910 bool is_chain_opened = false; 00911 00912 // Validate function parameters 00913 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 00914 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name"); 00915 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name len"); 00916 SA_PV_LOG_INFO_FUNC_ENTER("chain name = %.*s", (int)kcm_chain_name_len, kcm_chain_name); 00917 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid handle"); 00918 *kcm_chain_handle = NULL; 00919 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 00920 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_len_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain len out"); 00921 00922 // Check if KCM initialized, if not initialize it 00923 if (!g_kcm_initialized) { 00924 kcm_status = kcm_init(); 00925 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00926 } 00927 00928 if (data_source_type == KCM_ORIGINAL_ITEM) { 00929 kcm_status = storage_allocate_and_create_compelete_name(kcm_chain_name, kcm_chain_name_len, KCM_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size); 00930 } 00931 else { 00932 kcm_status = storage_allocate_and_create_compelete_name(kcm_chain_name, kcm_chain_name_len, KCM_RENEWAL_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size); 00933 } 00934 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_allocate_and_create_compelete_name"); 00935 00936 // allocate the context 00937 chain_context = (kcm_cert_chain_context_int_s*)fcc_malloc(sizeof(kcm_cert_chain_context_int_s)); 00938 memset(chain_context, 0, sizeof(kcm_cert_chain_context_int_s)); 00939 00940 kcm_status = storage_file_open(&chain_context->current_kcm_ctx, kcm_complete_name, kcm_complete_name_size); 00941 if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) { 00942 // skip the error log msg 00943 goto Exit; 00944 } 00945 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed opening kcm chain file"); 00946 00947 //Set chain handle flag 00948 is_chain_opened = true; 00949 00950 kcm_status = storage_file_get_meta_data_size(&chain_context->current_kcm_ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, &meta_data_size); 00951 if (kcm_status == KCM_STATUS_META_DATA_NOT_FOUND) { 00952 // treat single cert as chain with size 1 00953 chain_len_to_read = 1; 00954 kcm_status = KCM_STATUS_SUCCESS; 00955 chain_context->is_meta_data = false; 00956 } 00957 else { 00958 chain_context->is_meta_data = true; 00959 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed getting kcm meta data size"); 00960 SA_PV_ERR_RECOVERABLE_GOTO_IF((meta_data_size != sizeof(chain_len_to_read)), (kcm_status = KCM_STATUS_META_DATA_SIZE_ERROR), Exit, "Wrong meta data size"); 00961 00962 kcm_status = storage_file_read_meta_data_by_type(&chain_context->current_kcm_ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, (uint8_t*)&chain_len_to_read, meta_data_size, &meta_data_size); 00963 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed reading file's metadata"); 00964 // Test if the read len is legitimate number 00965 SA_PV_ERR_RECOVERABLE_GOTO_IF((chain_len_to_read == 0 || chain_len_to_read > KCM_MAX_NUMBER_OF_CERTITICATES_IN_CHAIN), (kcm_status = KCM_STATUS_CORRUPTED_CHAIN_FILE), Exit, "Illegitimate chain len in file's metadata"); 00966 } 00967 00968 chain_context->operation_type = KCM_CHAIN_OP_TYPE_OPEN; 00969 chain_context->chain_name = kcm_complete_name; 00970 chain_context->chain_name_len = kcm_complete_name_size; 00971 chain_context->num_of_certificates_in_chain = (size_t)chain_len_to_read; 00972 chain_context->current_cert_index = 0; 00973 00974 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00975 Exit: 00976 if (kcm_status != KCM_STATUS_SUCCESS) { 00977 if (is_chain_opened == true) { 00978 storage_file_close(&chain_context->current_kcm_ctx); 00979 } 00980 fcc_free(kcm_complete_name); 00981 fcc_free(chain_context); 00982 *kcm_chain_handle = NULL; 00983 } 00984 else { 00985 *kcm_chain_len_out = chain_context->num_of_certificates_in_chain; 00986 // set the handle only if success 00987 *kcm_chain_handle = (kcm_cert_chain_handle)chain_context; 00988 } 00989 return kcm_status; 00990 } 00991 00992 kcm_status_e storage_cert_chain_delete(const uint8_t *kcm_chain_name, size_t kcm_chain_name_len, kcm_data_source_type_e data_source_type) 00993 { 00994 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00995 kcm_status_e first_status_err = KCM_STATUS_SUCCESS; 00996 size_t kcm_chain_len = 0; 00997 uint8_t *kcm_complete_name = NULL; // Filename including prefix 00998 size_t kcm_complete_name_size; 00999 kcm_ctx_s kcm_ctx; 01000 kcm_cert_chain_handle kcm_chain_handle; 01001 kcm_cert_chain_context_int_s *chain_context; 01002 01003 // Validate function parameters 01004 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_chain_name"); 01005 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_chain_name_len"); 01006 SA_PV_LOG_INFO_FUNC_ENTER("chain name = %.*s", (int)kcm_chain_name_len, kcm_chain_name); 01007 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 01008 01009 // Check if KCM initialized, if not initialize it 01010 if (!g_kcm_initialized) { 01011 kcm_status = kcm_init(); 01012 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 01013 } 01014 01015 // open the first file and read the kcm_chain_len from meta data 01016 kcm_status = storage_cert_chain_open(&kcm_chain_handle, kcm_chain_name, kcm_chain_name_len, data_source_type, &kcm_chain_len); 01017 if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) { 01018 return kcm_status; 01019 } 01020 else if (kcm_status != KCM_STATUS_SUCCESS) { 01021 if (data_source_type == KCM_ORIGINAL_ITEM) { 01022 kcm_status = storage_allocate_and_create_compelete_name(kcm_chain_name, kcm_chain_name_len, KCM_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size); 01023 } 01024 else { 01025 kcm_status = storage_allocate_and_create_compelete_name(kcm_chain_name, kcm_chain_name_len, KCM_RENEWAL_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size); 01026 } 01027 01028 if (kcm_status == KCM_STATUS_SUCCESS) { 01029 kcm_status = storage_file_delete(&kcm_ctx, kcm_complete_name, kcm_complete_name_size); 01030 fcc_free(kcm_complete_name); 01031 } 01032 first_status_err = kcm_status; 01033 goto Exit; 01034 } 01035 01036 chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 01037 01038 if (kcm_status == KCM_STATUS_SUCCESS) { 01039 // close the file before calling delete 01040 storage_file_close(&chain_context->current_kcm_ctx); 01041 } 01042 01043 for (; chain_context->current_cert_index < kcm_chain_len; chain_context->current_cert_index++) { 01044 storage_cert_chain_update_name_prefixe(chain_context->chain_name, chain_context->current_cert_index, data_source_type); 01045 kcm_status = storage_file_delete(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len); 01046 // if there was an error, return the first one that occur 01047 if (kcm_status != KCM_STATUS_SUCCESS && first_status_err == KCM_STATUS_SUCCESS) { 01048 first_status_err = kcm_status; 01049 } 01050 } 01051 01052 // close the chain to release the context 01053 (void)storage_cert_chain_close(kcm_chain_handle, data_source_type); 01054 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 01055 Exit: 01056 SA_PV_ERR_RECOVERABLE_RETURN_IF((first_status_err != KCM_STATUS_SUCCESS), first_status_err, "Delete chain but with errors"); 01057 return first_status_err; 01058 } 01059 01060 kcm_status_e storage_cert_chain_close(kcm_cert_chain_handle kcm_chain_handle, kcm_data_source_type_e data_source_type) 01061 { 01062 kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 01063 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01064 01065 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 01066 01067 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_source_type != KCM_ORIGINAL_ITEM && data_source_type != KCM_BACKUP_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid data_source_type"); 01068 01069 if (kcm_chain_handle == NULL) { 01070 goto Exit; // and return KCM_STATUS_SUCCESS 01071 } 01072 01073 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain"); 01074 // Check if KCM initialized, if not initialize it 01075 if (!g_kcm_initialized) { 01076 kcm_status = kcm_init(); 01077 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 01078 } 01079 01080 if (chain_context->current_cert_index == 0 || 01081 (chain_context->operation_type == KCM_CHAIN_OP_TYPE_OPEN && 01082 chain_context->current_cert_index < chain_context->num_of_certificates_in_chain && 01083 chain_context->current_kcm_ctx.is_file_size_checked)) { 01084 // close open file (after create/open or between get_next_size to get_next_data) 01085 // if is_file_size_checked is true, the file had open before 01086 kcm_status = storage_file_close(&chain_context->current_kcm_ctx); 01087 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed closing kcm chain file"); 01088 } 01089 01090 if (chain_context->operation_type == KCM_CHAIN_OP_TYPE_CREATE && 01091 chain_context->current_cert_index < chain_context->num_of_certificates_in_chain) { 01092 // user added less certificates than num_of_certificates_in_chain, delete all and return error 01093 storage_cert_chain_files_delete(chain_context, KCM_ORIGINAL_ITEM); 01094 SA_PV_ERR_RECOVERABLE_GOTO_IF(true, (kcm_status = KCM_STATUS_CLOSE_INCOMPLETE_CHAIN), Exit, "Closing incomplete kcm chain"); 01095 } 01096 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 01097 Exit: 01098 if (chain_context != NULL) { 01099 fcc_free(chain_context->chain_name); 01100 fcc_free(chain_context); 01101 } 01102 return kcm_status; 01103 } 01104 01105 01106 kcm_status_e storage_file_write(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, const uint8_t *data, size_t data_length, const kcm_meta_data_list_s *kcm_meta_data_list, bool is_factory, bool is_encrypted) 01107 { 01108 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01109 kcm_status_e close_file_status = KCM_STATUS_SUCCESS; 01110 01111 kcm_status = storage_file_create(ctx, file_name, file_name_length, kcm_meta_data_list, is_factory, is_encrypted); 01112 SA_PV_ERR_RECOVERABLE_RETURN_IF(kcm_status != KCM_STATUS_SUCCESS, kcm_status, "Failed to create new file"); 01113 01114 kcm_status = storage_file_write_with_ctx(ctx, data, data_length);// we don't check error because we need to close the file in any case 01115 01116 // Data is only guaranteed to be flushed to the media on efs_close. 01117 close_file_status = storage_file_close(ctx); 01118 01119 if (kcm_status != KCM_STATUS_SUCCESS) { // delete the file if didn't succeed to write 01120 (void)storage_file_delete(ctx, file_name, file_name_length); 01121 SA_PV_ERR_RECOVERABLE_RETURN(kcm_status, "Failed to write data"); 01122 } 01123 01124 SA_PV_ERR_RECOVERABLE_RETURN_IF(close_file_status != KCM_STATUS_SUCCESS, close_file_status, "Failed to close file"); 01125 01126 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01127 01128 return kcm_status; 01129 } 01130 01131 kcm_status_e storage_file_size_get(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, size_t *file_size_out) 01132 { 01133 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01134 kcm_status_e close_staus = KCM_STATUS_SUCCESS; 01135 01136 SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 "", (uint32_t)file_name_length); 01137 01138 kcm_status = storage_file_open(ctx, file_name, file_name_length); 01139 if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) { 01140 goto exit; 01141 } 01142 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to open the given file"); 01143 01144 kcm_status = storage_file_size_get_with_ctx(ctx, file_size_out); 01145 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed getting file size"); 01146 01147 exit: 01148 if (kcm_status != KCM_STATUS_ITEM_NOT_FOUND) { 01149 close_staus = storage_file_close(ctx); 01150 } 01151 if (kcm_status == KCM_STATUS_SUCCESS) { 01152 kcm_status = close_staus; 01153 } 01154 01155 return kcm_status; 01156 } 01157 01158 kcm_status_e storage_file_read(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out) 01159 { 01160 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01161 kcm_status_e close_status = KCM_STATUS_SUCCESS; 01162 01163 kcm_status = storage_file_open(ctx, file_name, file_name_length); 01164 if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) { 01165 goto exit; 01166 } 01167 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to open the given file"); 01168 01169 kcm_status = storage_file_read_with_ctx(ctx, buffer_out, buffer_size, buffer_actual_size_out); 01170 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed ti read file"); 01171 01172 exit: 01173 if (kcm_status != KCM_STATUS_ITEM_NOT_FOUND) { 01174 close_status = storage_file_close(ctx); 01175 } 01176 if (kcm_status == KCM_STATUS_SUCCESS) { 01177 kcm_status = close_status; 01178 } 01179 01180 return kcm_status; 01181 } 01182 01183 kcm_status_e storage_file_delete(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length) 01184 { 01185 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01186 esfs_result_e esfs_status; 01187 uint16_t esfs_mode = 0; // FIXME - Unused, yet implemented 01188 bool success; 01189 01190 SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 "", (uint32_t)file_name_length); 01191 01192 SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid file name context"); 01193 SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name_length == 0), KCM_STATUS_INVALID_PARAMETER, "Got empty file name"); 01194 01195 esfs_status = esfs_open(file_name, file_name_length, &esfs_mode, &ctx->esfs_file_h); 01196 01197 //file does not exists, exit from delete function 01198 if (esfs_status == ESFS_NOT_EXISTS) { 01199 return error_handler(esfs_status); 01200 } 01201 01202 if (esfs_status != ESFS_SUCCESS) { //file exists but there is some corruption. We will delete the file without checking it's permissions 01203 SA_PV_LOG_ERR("The file exists but corrupted. Delete it without checking permissions"); 01204 esfs_status = ESFS_SUCCESS; 01205 01206 } else { // check permissions 01207 success = is_file_accessible(ctx); 01208 if (!success) { 01209 SA_PV_LOG_ERR("Caller has no access rights to the given file"); 01210 kcm_status = KCM_STATUS_NOT_PERMITTED; 01211 } 01212 01213 esfs_status = esfs_close(&ctx->esfs_file_h); 01214 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed closing file (esfs_status %d)", esfs_status); 01215 01216 if (kcm_status == KCM_STATUS_NOT_PERMITTED) { 01217 return kcm_status; 01218 } 01219 } 01220 01221 // Delete the file 01222 esfs_status = esfs_delete(file_name, file_name_length); 01223 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed deleting file (esfs_status %d)", esfs_status); 01224 01225 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01226 01227 return kcm_status; 01228 } 01229 01230 01231 kcm_status_e storage_file_create(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, const kcm_meta_data_list_s *kcm_meta_data_list, bool is_factory, bool is_encrypted) 01232 { 01233 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01234 esfs_result_e esfs_status; 01235 esfs_tlv_item_t meta_data_items[KCM_MD_TYPE_MAX_SIZE]; 01236 size_t meta_data_count = 0; 01237 uint16_t access_flags = 0; // owner, signed, encrypted, factory, extended ACL bit mask 01238 01239 SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 " ", (uint32_t)file_name_length); 01240 01241 SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context"); 01242 SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid file name context"); 01243 SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name_length == 0), KCM_STATUS_INVALID_PARAMETER, "Got empty file name"); 01244 01245 memset(ctx, 0, sizeof(kcm_ctx_s)); 01246 01247 if (is_factory) { 01248 access_flags |= ESFS_FACTORY_VAL; 01249 } 01250 if (is_encrypted) { 01251 access_flags |= ESFS_ENCRYPTED; 01252 } 01253 01254 // Convert kcm_meta_data_list to array of esfs_tlv_item 01255 if (kcm_meta_data_list != NULL) { 01256 for (meta_data_count = 0; meta_data_count < kcm_meta_data_list->meta_data_count; meta_data_count++) { 01257 meta_data_items[meta_data_count].type = kcm_meta_data_list->meta_data[meta_data_count].type; 01258 meta_data_items[meta_data_count].length_in_bytes = (uint16_t)kcm_meta_data_list->meta_data[meta_data_count].data_size; 01259 meta_data_items[meta_data_count].value = (void*)kcm_meta_data_list->meta_data[meta_data_count].data; 01260 } 01261 } 01262 01263 esfs_status = esfs_create(file_name, file_name_length, meta_data_items, meta_data_count, access_flags, &ctx->esfs_file_h); 01264 SA_PV_ERR_RECOVERABLE_GOTO_IF((esfs_status == ESFS_EXISTS), kcm_status = KCM_STATUS_FILE_EXIST, Exit, "File already exist in ESFS (esfs_status %" PRIu32 ")", (uint32_t)esfs_status); 01265 SA_PV_ERR_RECOVERABLE_GOTO_IF((esfs_status != ESFS_SUCCESS), kcm_status = error_handler(esfs_status), Exit, "Failed creating file (esfs_status %" PRIu32 ")", (uint32_t)esfs_status); 01266 01267 Exit: 01268 if (kcm_status != KCM_STATUS_SUCCESS) { 01269 memset(ctx, 0, sizeof(kcm_ctx_s)); 01270 } 01271 01272 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01273 01274 return kcm_status; 01275 } 01276 01277 /** Open existing file 01278 * 01279 * @param ctx KCM operation context. 01280 * @param file_name A binary blob that uniquely identifies the file 01281 * @param file_name_length The binary blob length in bytes. 01282 @param is_factory True if KCM item is factory item, or false otherwise 01283 @param is_encrypted True if KCM item should be encrypted, or false otherwise 01284 * 01285 * @returns 01286 * KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors 01287 */ 01288 kcm_status_e storage_file_open(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length) 01289 { 01290 01291 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01292 esfs_result_e esfs_status; 01293 uint16_t esfs_mode = 0; // FIXME - Unused, yet implemented 01294 bool success; 01295 01296 SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 "", (uint32_t)file_name_length); 01297 01298 SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context"); 01299 SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid file name context"); 01300 SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name_length == 0), KCM_STATUS_INVALID_PARAMETER, "Got empty file name"); 01301 01302 memset(ctx, 0, sizeof(kcm_ctx_s)); 01303 01304 esfs_status = esfs_open(file_name, file_name_length, &esfs_mode, &ctx->esfs_file_h); 01305 if (esfs_status == ESFS_NOT_EXISTS) { 01306 kcm_status = error_handler(esfs_status); 01307 goto Exit; 01308 } 01309 SA_PV_ERR_RECOVERABLE_GOTO_IF((esfs_status != ESFS_SUCCESS), kcm_status = error_handler(esfs_status), Exit, "Failed opening file (esfs_status %d)", esfs_status); 01310 01311 success = is_file_accessible(ctx); 01312 if (!success) { 01313 kcm_status = KCM_STATUS_NOT_PERMITTED; 01314 esfs_close(&ctx->esfs_file_h); 01315 memset(ctx, 0, sizeof(kcm_ctx_s)); 01316 } 01317 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Caller has no access rights to the given file"); 01318 01319 Exit: 01320 if (kcm_status != KCM_STATUS_SUCCESS) { 01321 memset(ctx, 0, sizeof(kcm_ctx_s)); 01322 } 01323 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01324 01325 return kcm_status; 01326 } 01327 01328 /** Close file in storage 01329 * 01330 * @param ctx KCM operation context. 01331 @param is_factory True if KCM item is factory item, or false otherwise 01332 @param is_encrypted True if KCM item should be encrypted, or false otherwise 01333 * 01334 * @returns 01335 * KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors 01336 */ 01337 kcm_status_e storage_file_close(kcm_ctx_s *ctx) 01338 { 01339 esfs_result_e esfs_status; 01340 01341 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 01342 01343 SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context"); 01344 01345 // Data is only guaranteed to be flushed to the media on efs_close. 01346 esfs_status = esfs_close(&ctx->esfs_file_h); 01347 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed closing file (esfs_status %d)", esfs_status); 01348 01349 memset(ctx, 0, sizeof(kcm_ctx_s)); 01350 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01351 01352 return KCM_STATUS_SUCCESS; 01353 } 01354 01355 01356 kcm_status_e storage_file_write_with_ctx(kcm_ctx_s *ctx, const uint8_t *data, size_t data_length) 01357 { 01358 esfs_result_e esfs_status; 01359 01360 SA_PV_LOG_TRACE_FUNC_ENTER("data_length=%" PRIu32 "", (uint32_t)data_length); 01361 01362 SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context"); 01363 SA_PV_ERR_RECOVERABLE_RETURN_IF(((data == NULL) && (data_length > 0)), KCM_STATUS_INVALID_PARAMETER, "Provided NULL data buffer and data_length greater than 0"); 01364 01365 if (data_length != 0) { 01366 esfs_status = esfs_write(&ctx->esfs_file_h, data, data_length); 01367 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed writing (%" PRIu32 " B) size to file (esfs_status %" PRIu32 ")", (uint32_t)data_length, (uint32_t)esfs_status); 01368 } 01369 01370 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01371 01372 return KCM_STATUS_SUCCESS; 01373 01374 } 01375 01376 kcm_status_e storage_file_size_get_with_ctx(kcm_ctx_s *ctx, size_t *file_size_out) 01377 { 01378 esfs_result_e esfs_status; 01379 01380 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 01381 01382 SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context"); 01383 SA_PV_ERR_RECOVERABLE_RETURN_IF((file_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to file size"); 01384 01385 esfs_status = esfs_file_size(&ctx->esfs_file_h, file_size_out); 01386 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed getting file size (esfs_status %d)", esfs_status); 01387 01388 ctx->is_file_size_checked = true; 01389 ctx->file_size = *file_size_out; 01390 01391 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01392 01393 return KCM_STATUS_SUCCESS; 01394 } 01395 01396 01397 kcm_status_e storage_file_read_with_ctx(kcm_ctx_s *ctx, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out) 01398 { 01399 esfs_result_e esfs_status; 01400 kcm_status_e kcm_status; 01401 01402 SA_PV_LOG_TRACE_FUNC_ENTER("buffer_size=%" PRIu32 "", (uint32_t)buffer_size); 01403 01404 SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context"); 01405 SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_out == NULL && buffer_size != 0), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to read buffer"); 01406 SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_actual_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to output size"); 01407 01408 *buffer_actual_size_out = 0; 01409 01410 if (ctx->is_file_size_checked == false) { 01411 kcm_status = storage_file_size_get_with_ctx(ctx, buffer_actual_size_out); 01412 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed getting file data size (kcm_status %d)", kcm_status); 01413 } 01414 01415 SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_size < ctx->file_size), KCM_STATUS_INSUFFICIENT_BUFFER, "Buffer too small"); 01416 01417 if (ctx->file_size != 0) { 01418 esfs_status = esfs_read(&ctx->esfs_file_h, buffer_out, buffer_size, buffer_actual_size_out); 01419 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reading file data (esfs_status %d)", esfs_status); 01420 } 01421 01422 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01423 01424 return KCM_STATUS_SUCCESS; 01425 } 01426 01427 static kcm_status_e storage_file_get_meta_data_size_and_index(kcm_ctx_s *ctx, kcm_meta_data_type_e type, size_t *meta_data_size_out, uint32_t *meta_data_index_out) 01428 { 01429 esfs_result_e esfs_status; 01430 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01431 esfs_tlv_properties_t *meta_data_properties = NULL; 01432 uint32_t index = 0; 01433 01434 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 01435 01436 SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context"); 01437 SA_PV_ERR_RECOVERABLE_RETURN_IF((meta_data_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to meta_data_size_out"); 01438 SA_PV_ERR_RECOVERABLE_RETURN_IF((meta_data_index_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to meta_data_index_out"); 01439 SA_PV_ERR_RECOVERABLE_RETURN_IF((type >= KCM_MD_TYPE_MAX_SIZE), KCM_STATUS_INVALID_PARAMETER, "Invalid meta data type"); 01440 01441 esfs_status = esfs_get_meta_data_properties(&ctx->esfs_file_h, &meta_data_properties); 01442 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reading meta data properties (esfs_status %d)", esfs_status); 01443 01444 for (index = 0; index < meta_data_properties->number_of_items; index++) { 01445 if (type == meta_data_properties->tlv_items[index].type) { 01446 01447 *meta_data_size_out = (size_t)meta_data_properties->tlv_items[index].length_in_bytes; 01448 *meta_data_index_out = index; 01449 kcm_status = KCM_STATUS_SUCCESS; 01450 break; 01451 } 01452 } 01453 01454 if (index >= meta_data_properties->number_of_items) { 01455 return KCM_STATUS_META_DATA_NOT_FOUND; 01456 } 01457 01458 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01459 return kcm_status; 01460 } 01461 01462 kcm_status_e storage_file_get_meta_data_size(kcm_ctx_s *ctx, kcm_meta_data_type_e type, size_t *meta_data_size_out) 01463 { 01464 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01465 uint32_t index = 0; 01466 01467 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 01468 01469 kcm_status = storage_file_get_meta_data_size_and_index(ctx, type, meta_data_size_out, &index); 01470 01471 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01472 return kcm_status; 01473 } 01474 01475 kcm_status_e storage_file_read_meta_data_by_type(kcm_ctx_s *ctx, kcm_meta_data_type_e type, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out) 01476 { 01477 esfs_result_e esfs_status; 01478 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01479 esfs_tlv_item_t meta_data_item; 01480 uint32_t index = 0; 01481 01482 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 01483 01484 SA_PV_ERR_RECOVERABLE_RETURN_IF(buffer_out == NULL, KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to kcm_meta_data"); 01485 01486 kcm_status = storage_file_get_meta_data_size_and_index(ctx, type, buffer_actual_size_out, &index); 01487 if (kcm_status == KCM_STATUS_META_DATA_NOT_FOUND) { 01488 return kcm_status; 01489 } 01490 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed reading meta data size and index"); 01491 01492 // return error in case the data buffer to read is too small 01493 SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_size < *buffer_actual_size_out), KCM_STATUS_INSUFFICIENT_BUFFER, "Data buffer to read is too small"); 01494 01495 meta_data_item.value = buffer_out; 01496 esfs_status = esfs_read_meta_data(&ctx->esfs_file_h, index, &meta_data_item); 01497 SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reading meta data (esfs_status %d)", esfs_status); 01498 01499 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 01500 01501 return kcm_status; 01502 } 01503 #endif
Generated on Tue Jul 12 2022 20:21:03 by
