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.
storage.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 #ifdef MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT 00017 00018 #include <stdbool.h> 00019 #include "pv_error_handling.h" 00020 #include "pv_macros.h" 00021 #include "storage.h" 00022 #include "esfs.h" 00023 #include "fcc_malloc.h" 00024 #include "pal_sst.h" 00025 00026 extern bool g_kcm_initialized; 00027 //TODO: add short explanation about certificate chains naming 00028 #define STORAGE_MAX_ITEM_PREFIX_SIZE 16 00029 #define STORAGE_CHAIN_CERTIFICATE_INDEX_OFFSET_IN_PREFIX 3 //a,b,c,.. ==> Certa__, Certb__, 00030 #define STORAGE_CHAIN_CERTIFICATE_END_SIGN_OFFSET_IN_PREFIX 4 // e ==> Certae_ 00031 #define STORAGE_CHAIN_CERTIFICATE_END_OFFSET_IN_NAME strlen(KCM_FILE_PREFIX_CERTIFICATE)//6 Size of certificate chain prefixes,the same for all chain certificates 00032 00033 00034 00035 00036 00037 static kcm_status_e storage_error_handler(palStatus_t pal_status) 00038 { 00039 kcm_status_e kcm_status; 00040 00041 switch (pal_status) 00042 { 00043 case PAL_SUCCESS: 00044 kcm_status = KCM_STATUS_SUCCESS; 00045 break; 00046 case PAL_ERR_SST_ITEM_NOT_FOUND: 00047 kcm_status = KCM_STATUS_ITEM_NOT_FOUND; 00048 break; 00049 case PAL_ERR_SST_INVALID_SIZE: 00050 case PAL_ERR_INVALID_ARGUMENT : 00051 kcm_status = KCM_STATUS_INVALID_PARAMETER; 00052 break; 00053 case PAL_ERR_SST_WRITE_PROTECTED: 00054 case PAL_ERR_SST_NOT_READY: 00055 case PAL_ERR_SST_READ_FAILED: 00056 case PAL_ERR_SST_INVALID_DATA_DETECTED: 00057 case PAL_ERR_SST_FAILED_OPERATION: 00058 default: 00059 kcm_status = KCM_STATUS_ERROR; 00060 break; 00061 } 00062 return kcm_status; 00063 } 00064 static kcm_status_e storage_get_prefix( 00065 kcm_item_type_e kcm_item_type, 00066 kcm_data_source_type_e data_source_type, 00067 kcm_chain_cert_name_info_s *cert_name_info, 00068 char* prefix, 00069 size_t max_prefix_size) 00070 { 00071 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00072 char *kcm_type_prefix; 00073 00074 if (cert_name_info == NULL) { 00075 00076 //For non-chain items use common function that returns item's prefix 00077 kcm_status = storage_item_name_get_prefix((kcm_item_type_e)kcm_item_type, data_source_type,(const char**)&kcm_type_prefix); 00078 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during _kcm_item_name_get_prefix"); 00079 SA_PV_ERR_RECOVERABLE_RETURN_IF((strlen(kcm_type_prefix) > max_prefix_size), kcm_status = KCM_STATUS_INVALID_PARAMETER, "Failed during _kcm_item_name_get_prefix"); 00080 00081 memcpy((uint8_t*)prefix, kcm_type_prefix, strlen(kcm_type_prefix) + 1); 00082 00083 } else { 00084 00085 //In case of chain build prefix according to current index 00086 if (data_source_type == KCM_ORIGINAL_ITEM) { 00087 SA_PV_ERR_RECOVERABLE_RETURN_IF((strlen(KCM_FILE_PREFIX_FIRST_CHAIN_CERTIFICATE) > max_prefix_size), kcm_status = KCM_STATUS_INVALID_PARAMETER, "prefix exceedes max size"); 00088 00089 memcpy((uint8_t*)prefix, KCM_FILE_PREFIX_FIRST_CHAIN_CERTIFICATE, strlen(KCM_FILE_PREFIX_FIRST_CHAIN_CERTIFICATE) + 1);//1 for '\0' from the KCM_FILE_PREFIX_FIRST_CHAIN_CERTIFICATE define 00090 } else { 00091 SA_PV_ERR_RECOVERABLE_RETURN_IF((strlen(KCM_RENEWAL_FILE_PREFIX_FIRST_CHAIN_CERTIFICATE) > max_prefix_size), kcm_status = KCM_STATUS_INVALID_PARAMETER, "prefix exceedes max size"); 00092 00093 memcpy((uint8_t*)prefix, KCM_RENEWAL_FILE_PREFIX_FIRST_CHAIN_CERTIFICATE, strlen(KCM_RENEWAL_FILE_PREFIX_FIRST_CHAIN_CERTIFICATE) + 1);//1 for '\0' from the KCM_RENEWAL_FILE_PREFIX_FIRST_CHAIN_CERTIFICATE define 00094 } 00095 00096 SA_PV_ERR_RECOVERABLE_RETURN_IF((STORAGE_CHAIN_CERTIFICATE_INDEX_OFFSET_IN_PREFIX > max_prefix_size), kcm_status = KCM_STATUS_INVALID_PARAMETER, "index exceedes max size"); 00097 prefix[STORAGE_CHAIN_CERTIFICATE_INDEX_OFFSET_IN_PREFIX] =(char) (cert_name_info->certificate_index + 'a'); 00098 00099 if (cert_name_info->is_last_certificate == true) { 00100 SA_PV_ERR_RECOVERABLE_RETURN_IF((STORAGE_CHAIN_CERTIFICATE_END_SIGN_OFFSET_IN_PREFIX > max_prefix_size), kcm_status = KCM_STATUS_INVALID_PARAMETER, "index exceedes max size"); 00101 prefix[STORAGE_CHAIN_CERTIFICATE_END_SIGN_OFFSET_IN_PREFIX] = 'e'; 00102 } 00103 } 00104 00105 return kcm_status; 00106 } 00107 00108 static kcm_status_e check_name_validity(const uint8_t * kcm_item_name, size_t kcm_item_name_len) 00109 { 00110 size_t i; 00111 int ascii_val; 00112 00113 // Check size 00114 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_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); 00115 00116 // Iterate all the characters and make sure all belong to {'A'-'Z' , 'a'-'z' , '0'-'9' , '.' , '-' , '_' } 00117 // Regular expression match: "^[a-zA-Z0-9_.-]*$" 00118 for (i = 0; i < kcm_item_name_len; i++) { 00119 ascii_val = (int)kcm_item_name[i]; 00120 if (!( 00121 (ascii_val >= 'A' && ascii_val <= 'Z') || 00122 (ascii_val >= 'a' && ascii_val <= 'z') || 00123 (ascii_val == '.') || 00124 (ascii_val == '-') || 00125 (ascii_val == '_') || 00126 (ascii_val >= '0' && ascii_val <= '9') 00127 )) { 00128 return KCM_STATUS_FILE_NAME_INVALID; 00129 } 00130 } 00131 00132 return KCM_STATUS_SUCCESS; 00133 } 00134 00135 kcm_status_e storage_create_compelete_data_name( 00136 kcm_item_type_e kcm_item_type, 00137 kcm_data_source_type_e data_source_type, 00138 const char *working_dir, 00139 kcm_chain_cert_name_info_s *cert_name_info, 00140 const uint8_t *kcm_name, 00141 size_t kcm_name_len, 00142 char *kcm_buffer_out) 00143 { 00144 size_t prefix_length = 0; 00145 size_t total_length = 0; 00146 char prefix[STORAGE_MAX_ITEM_PREFIX_SIZE + 1]; //prefix length and null terminator 00147 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00148 00149 SA_PV_LOG_TRACE_FUNC_ENTER("name len=%" PRIu32 "", (uint32_t)kcm_name_len); 00150 00151 //Check parameters 00152 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_buffer_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_buffer_out parameter"); 00153 kcm_status = check_name_validity(kcm_name, kcm_name_len); 00154 // Check that name is not too long. This is done only in this function since all KCM APIs using file names go through here. 00155 SA_PV_ERR_RECOVERABLE_RETURN_IF(kcm_status != KCM_STATUS_SUCCESS, kcm_status, "Invalid KCM name"); 00156 00157 //Get item prefix according to source type and kcm type (including chains) 00158 kcm_status = storage_get_prefix((kcm_item_type_e)kcm_item_type, data_source_type, cert_name_info,(char*) &prefix, sizeof(prefix)- 1); 00159 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to get item prefix"); 00160 00161 //Calculate total size of complete item name 00162 prefix_length = strlen(prefix); 00163 total_length = strlen(STORAGE_PELION_PREFIX) + strlen(working_dir)+ prefix_length + kcm_name_len ; 00164 00165 // This Should never happen. This means that the total larger than permitted was used. 00166 SA_PV_ERR_RECOVERABLE_RETURN_IF((total_length > KCM_MAX_FILENAME_SIZE), KCM_STATUS_INVALID_PARAMETER, "KCM data name too long"); 00167 00168 /* Append prefix and name to allocated buffer */ 00169 memcpy(kcm_buffer_out, STORAGE_PELION_PREFIX, strlen(STORAGE_PELION_PREFIX)); 00170 memcpy(kcm_buffer_out + strlen(STORAGE_PELION_PREFIX), (uint8_t *)working_dir, strlen(working_dir)); 00171 memcpy(kcm_buffer_out + strlen(STORAGE_PELION_PREFIX)+ strlen(working_dir), (uint8_t *)prefix, prefix_length); 00172 memcpy(kcm_buffer_out + strlen(STORAGE_PELION_PREFIX) + strlen(working_dir)+ prefix_length, (uint8_t *)kcm_name, kcm_name_len); 00173 kcm_buffer_out[total_length] = '\0'; 00174 00175 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 00176 return KCM_STATUS_SUCCESS; 00177 } 00178 00179 00180 kcm_status_e storage_init() 00181 { 00182 palStatus_t pal_status = PAL_SUCCESS; 00183 size_t actual_size; 00184 00185 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 00186 //check if flag file exists 00187 pal_status = pal_SSTGet (STORAGE_FACTORY_RESET_IN_PROGRESS_ITEM, NULL, 0, &actual_size); 00188 if (pal_status == PAL_ERR_SST_ITEM_NOT_FOUND) { 00189 //flag file was not found - positive scenario 00190 return KCM_STATUS_SUCCESS; 00191 } else if (pal_status == PAL_SUCCESS) { 00192 //flag file can be opened for reading 00193 //previous factory reset failed during execution 00194 //call factory reset to complete the process 00195 pal_status = storage_factory_reset(); 00196 } 00197 00198 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 00199 00200 return storage_error_handler(pal_status); 00201 } 00202 00203 kcm_status_e storage_finalize() 00204 { 00205 return KCM_STATUS_SUCCESS; 00206 } 00207 00208 kcm_status_e storage_reset() 00209 { 00210 palStatus_t pal_status = PAL_SUCCESS; 00211 00212 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 00213 00214 pal_status = pal_SSTReset (); 00215 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), storage_error_handler(pal_status), "Failed pal_SSTReset (%" PRIu32 ")", pal_status); 00216 00217 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 00218 00219 return KCM_STATUS_SUCCESS; 00220 } 00221 00222 kcm_status_e storage_factory_reset() 00223 { 00224 palStatus_t pal_status = PAL_SUCCESS; 00225 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00226 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 00227 palSSTIterator_t sst_iterator = 0; 00228 palSSTItemInfo_t item_info = { 0 }; 00229 uint8_t* data_buffer = NULL; 00230 size_t actual_data_size; 00231 00232 SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS(); 00233 00234 // set factory reset in progress item flag 00235 pal_status = pal_SSTSet (STORAGE_FACTORY_RESET_IN_PROGRESS_ITEM, NULL, 0, PAL_SST_REPLAY_PROTECTION_FLAG); 00236 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), exit, "Failed pal_SSTSet (%" PRIu32 ")", pal_status); 00237 00238 //open iterator with working prefix 00239 pal_status = pal_SSTIteratorOpen (&sst_iterator, STORAGE_WORKING); 00240 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), exit, "Failed pal_SSTIteratorOpen (%" PRIu32 ")", pal_status); 00241 00242 //iterate over items with 'working' prefix and remove all items 00243 while ((pal_status = pal_SSTIteratorNext (sst_iterator, (char*)kcm_complete_name, KCM_MAX_FILENAME_SIZE)) == PAL_SUCCESS) { 00244 00245 pal_status = pal_SSTRemove ((const char*)kcm_complete_name); 00246 if (pal_status != PAL_SUCCESS) { 00247 // output warining in case of failure, but continue factory reset process 00248 SA_PV_LOG_ERR("Warning: failed to remove item. Continue factory reset..."); 00249 } 00250 } 00251 00252 //verify that we went over all items 00253 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_ERR_SST_ITEM_NOT_FOUND), kcm_status = storage_error_handler(pal_status), iterator_close_end_exit, "Failed pal_SSTIteratorNext (%" PRIu32 ")", pal_status); 00254 00255 //close iterator 00256 pal_status = pal_SSTIteratorClose (sst_iterator); 00257 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), exit, "Failed pal_SSTIteratorClose (%" PRIu32 ")", pal_status); 00258 00259 //open iterator with backup prefix 00260 pal_status = pal_SSTIteratorOpen (&sst_iterator, STORAGE_BACKUP); 00261 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), exit, "Failed pal_SSTIteratorOpen (%" PRIu32 ")", pal_status); 00262 00263 //iterate over items with 'backup' prefix 00264 while ((pal_status = pal_SSTIteratorNext (sst_iterator, (char*)kcm_complete_name, KCM_MAX_FILENAME_SIZE)) == PAL_SUCCESS) { 00265 00266 //retreive item info (size and flags) 00267 pal_status = pal_SSTGetInfo ((const char*)kcm_complete_name, &item_info); 00268 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), iterator_close_end_exit, "Failed pal_SSTGetInfo (%" PRIu32 ")", pal_status); 00269 00270 //allocate buffer for the data according to its size 00271 data_buffer = malloc(item_info.itemSize); 00272 SA_PV_ERR_RECOVERABLE_GOTO_IF((data_buffer == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, iterator_close_end_exit, "Failed to allocate bffer"); 00273 00274 //read factory item to the buffer 00275 pal_status = pal_SSTGet ((const char*)kcm_complete_name, data_buffer, item_info.itemSize, &actual_data_size); 00276 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), free_memory_and_exit, "Failed pal_SSTGet (%" PRIu32 ")", pal_status); 00277 SA_PV_ERR_RECOVERABLE_GOTO_IF((item_info.itemSize != actual_data_size), kcm_status = KCM_STATUS_FILE_CORRUPTED, free_memory_and_exit, "Failed pal_SSTGet (%" PRIu32 ")", pal_status); 00278 00279 //change item name prefix to STORAGE_DEFAULT_PATH ('working' prefix) 00280 memcpy(kcm_complete_name, STORAGE_WORKING, strlen(STORAGE_WORKING)); 00281 00282 //write item with 'working' prefix 00283 pal_status = pal_SSTSet ((const char*)kcm_complete_name, data_buffer, item_info.itemSize, item_info.SSTFlagsBitmap); 00284 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), free_memory_and_exit, "Failed pal_SSTSet (%" PRIu32 ")", pal_status); 00285 00286 //free allocated buffer 00287 free(data_buffer); 00288 } 00289 00290 //verify that we went over all items 00291 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_ERR_SST_ITEM_NOT_FOUND), kcm_status = storage_error_handler(pal_status), iterator_close_end_exit, "Failed pal_SSTIteratorNext (%" PRIu32 ")", pal_status); 00292 00293 //close iterator 00294 pal_status = pal_SSTIteratorClose (sst_iterator); 00295 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), exit, "Failed pal_SSTIteratorClose (%" PRIu32 ")", pal_status); 00296 00297 //delete temporary file. if failed, set special status to `kcm_backup_status` since factory reset succedeed. 00298 pal_status = pal_SSTRemove (STORAGE_FACTORY_RESET_IN_PROGRESS_ITEM); 00299 00300 if (pal_status != PAL_SUCCESS) { 00301 // output warining in case of failure, but continue factory reset process 00302 SA_PV_LOG_ERR("Warning: failed to remove item. Continue factory reset..."); 00303 } 00304 00305 goto exit; 00306 00307 free_memory_and_exit: 00308 00309 //free allocated memory 00310 free(data_buffer); 00311 00312 iterator_close_end_exit: 00313 00314 //close iterator 00315 pal_status = pal_SSTIteratorClose (sst_iterator); 00316 SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), exit, "Failed pal_SSTIteratorClose (%" PRIu32 ")", pal_status); 00317 00318 exit: 00319 00320 SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS(); 00321 00322 return kcm_status; 00323 } 00324 00325 00326 palStatus_t storage_rbp_read( 00327 const char *item_name, 00328 uint8_t *data, 00329 size_t data_size, 00330 size_t *data_actual_size_out) 00331 { 00332 palStatus_t pal_status = PAL_SUCCESS; 00333 palSSTItemInfo_t palItemInfo; 00334 00335 // Validate function parameters 00336 SA_PV_ERR_RECOVERABLE_RETURN_IF((item_name == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid item_name"); 00337 SA_PV_LOG_INFO_FUNC_ENTER("item name = %s", (char*)item_name); 00338 SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid data"); 00339 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size == 0 || data_size > UINT16_MAX), PAL_ERR_INVALID_ARGUMENT , "Invalid data_length"); 00340 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_actual_size_out == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid data_actual_size_out"); 00341 00342 pal_status = pal_SSTGetInfo (item_name, &palItemInfo); 00343 if (pal_status == PAL_ERR_SST_ITEM_NOT_FOUND) { 00344 //item not found. Print info level error 00345 SA_PV_LOG_INFO("Item not found"); 00346 return PAL_ERR_ITEM_NOT_EXIST ; 00347 } 00348 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), PAL_ERR_GENERIC_FAILURE , "pal_SSTGetInfo failed"); 00349 SA_PV_ERR_RECOVERABLE_RETURN_IF((palItemInfo.itemSize > data_size), PAL_ERR_BUFFER_TOO_SMALL , "data_size is too small"); 00350 00351 pal_status = pal_SSTGet (item_name, data, data_size, data_actual_size_out); 00352 SA_PV_ERR_RECOVERABLE_RETURN_IF(pal_status != PAL_SUCCESS, PAL_ERR_GENERIC_FAILURE , "Failed to get data"); 00353 00354 return pal_status; 00355 } 00356 00357 palStatus_t storage_rbp_write( 00358 const char *item_name, 00359 const uint8_t *data, 00360 size_t data_size, 00361 bool is_write_once) 00362 { 00363 uint32_t flag_mask = PAL_SST_REPLAY_PROTECTION_FLAG | PAL_SST_CONFIDENTIALITY_FLAG; 00364 palStatus_t pal_status = PAL_SUCCESS; 00365 00366 SA_PV_ERR_RECOVERABLE_RETURN_IF((item_name == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid item_name"); 00367 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size > UINT16_MAX || data_size == 0), PAL_ERR_INVALID_ARGUMENT , "Invalid param data"); 00368 SA_PV_LOG_INFO_FUNC_ENTER("data_size = %" PRIu32 " item_name = %s", (uint32_t)data_size, item_name); 00369 SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), PAL_ERR_INVALID_ARGUMENT , "Invalid param data"); 00370 00371 if (is_write_once == true) { 00372 flag_mask |= PAL_SST_WRITE_ONCE_FLAG; 00373 } 00374 00375 pal_status = pal_SSTSet (item_name, data, data_size, flag_mask); 00376 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_ERR_SST_WRITE_PROTECTED), PAL_ERR_ITEM_EXIST , "Failed to write rbp data"); 00377 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), PAL_ERR_GENERIC_FAILURE , "Failed to write rbp data"); 00378 00379 SA_PV_LOG_INFO_FUNC_EXIT(); 00380 return pal_status; 00381 } 00382 00383 00384 /** 00385 * rbp lookup record, correlating name and size of data 00386 */ 00387 typedef struct storage_rbp_lookup_record_ { 00388 size_t rbp_required_size; 00389 const char *rbp_data_name; 00390 } storage_rbp_lookup_record_s; 00391 00392 /** 00393 * sotp type table, correlating for each sotp type and name. 00394 */ 00395 //todo : remove all items except rot and entropy 00396 static const storage_rbp_lookup_record_s storage_rbp_lookup_table[] = { 00397 { FCC_FACTORY_DISABLE_FLAG_SIZE, STORAGE_RBP_FACTORY_DONE_NAME }, 00398 { FCC_TIME_SIZE, STORAGE_RBP_SAVED_TIME_NAME }, 00399 { FCC_TIME_SIZE, STORAGE_RBP_LAST_TIME_BACK_NAME }, 00400 { FCC_CA_IDENTIFICATION_SIZE, STORAGE_RBP_TRUSTED_TIME_SRV_ID_NAME } 00401 }; 00402 00403 #define ARRAY_LENGTH(array) (sizeof(array)/sizeof((array)[0])) 00404 00405 #define STORAGE_SOTP_NUMBER_OF_TYPES ARRAY_LENGTH(storage_rbp_lookup_table) 00406 00407 static bool storage_check_name_and_get_required_size(const char *item_name, uint16_t *required_size_out) 00408 { 00409 size_t index = 0; 00410 00411 for (index = 0; index < STORAGE_SOTP_NUMBER_OF_TYPES; index++) { 00412 if (strlen(item_name) == strlen(storage_rbp_lookup_table[index].rbp_data_name)) { 00413 if (memcmp(storage_rbp_lookup_table[index].rbp_data_name, item_name, strlen(storage_rbp_lookup_table[index].rbp_data_name)) == 0) { 00414 *required_size_out = (uint16_t)storage_rbp_lookup_table[index].rbp_required_size; 00415 return true; 00416 } 00417 } 00418 } 00419 return false; 00420 } 00421 00422 kcm_status_e storage_fcc_rbp_write( 00423 const char *item_name, 00424 const uint8_t *data, 00425 size_t data_size, 00426 bool is_write_once) 00427 { 00428 bool success; 00429 uint16_t required_size = 0; 00430 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00431 uint32_t flag_mask = PAL_SST_REPLAY_PROTECTION_FLAG; 00432 palStatus_t pal_status = PAL_SUCCESS; 00433 00434 SA_PV_ERR_RECOVERABLE_RETURN_IF((item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid item_name"); 00435 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size > UINT16_MAX || data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid param data"); 00436 SA_PV_LOG_INFO_FUNC_ENTER("data_size = %" PRIu32 " item_name = %s", (uint32_t)data_size, item_name); 00437 SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid param data"); 00438 00439 success = storage_check_name_and_get_required_size(item_name, &required_size); 00440 SA_PV_ERR_RECOVERABLE_RETURN_IF((!success), KCM_STATUS_INVALID_PARAMETER, "storage_check_name_and_get_required_size failed "); 00441 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); 00442 00443 if (is_write_once == true) { 00444 flag_mask |= PAL_SST_WRITE_ONCE_FLAG; 00445 } 00446 00447 pal_status = pal_SSTSet (item_name, data, data_size, flag_mask); 00448 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_ERR_SST_WRITE_PROTECTED), kcm_status = KCM_STATUS_FILE_EXIST, "Failed to write fcc rbp data"); 00449 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), "Failed to write fcc rbp data"); 00450 00451 return kcm_status; 00452 } 00453 00454 /** FCC initiated operation, writes a rollback protected data. 00455 * 00456 * @param[in] item_name A string name of the rollback protected item 00457 * @param[in] data A pointer to memory with the data to write into the storage. Can be NULL if data_length is 0. 00458 * @param[in] data_size The data length in bytes. Can be 0 if we wish to write an empty file. 00459 * @param[in] is_write_once Write once flag. 00460 * @returns 00461 * KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise. 00462 */ 00463 kcm_status_e storage_fcc_rbp_read( 00464 const char *item_name, 00465 uint8_t *data, 00466 size_t data_size, 00467 size_t *data_actual_size_out) 00468 { 00469 bool success; 00470 uint16_t required_size = 0; 00471 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00472 palStatus_t pal_status = PAL_SUCCESS; 00473 00474 SA_PV_ERR_RECOVERABLE_RETURN_IF((item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid item_name"); 00475 SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid param data"); 00476 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size == 0 || data_size > UINT16_MAX), KCM_STATUS_INVALID_PARAMETER, "Invalid data_size"); 00477 SA_PV_LOG_INFO_FUNC_ENTER("data_size = %" PRIu32 " item_name = %s", (uint32_t)data_size, item_name); 00478 SA_PV_ERR_RECOVERABLE_RETURN_IF((data_actual_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid data_actual_size_out"); 00479 00480 success = storage_check_name_and_get_required_size(item_name, &required_size); 00481 SA_PV_ERR_RECOVERABLE_RETURN_IF((!success), KCM_STATUS_INVALID_PARAMETER, "Failed for get_sotp_type_size()"); 00482 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); 00483 00484 pal_status = pal_SSTGet (item_name, data, data_size, data_actual_size_out); 00485 SA_PV_ERR_RECOVERABLE_RETURN_IF(pal_status != PAL_SUCCESS, kcm_status = storage_error_handler(pal_status), "Failed to get data size"); 00486 00487 return kcm_status; 00488 } 00489 00490 00491 /** Writes a new item to storage 00492 * 00493 * @param[in] kcm_item_name KCM item name. 00494 * @param[in] kcm_item_name_len KCM item name length. 00495 * @param[in] kcm_item_type KCM item type as defined in `::kcm_item_type_e` 00496 * @param[in] kcm_item_is_factory True if the KCM item is a factory item, otherwise false. 00497 * @param[in] data_source_type KCM item data source (original or backup). 00498 * @param[in] kcm_item_data KCM item data buffer. Can be NULL if `kcm_item_data_size` is 0. 00499 * @param[in] kcm_item_data_size KCM item data buffer size in bytes. Can be 0 if you wish to 00500 * store an empty file. 00501 * 00502 * @returns 00503 * KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.*/ 00504 kcm_status_e storage_data_write_impl(const uint8_t * kcm_item_name, 00505 size_t kcm_item_name_len, 00506 kcm_item_type_e kcm_item_type, 00507 bool kcm_item_is_factory, 00508 bool kcm_item_is_encrypted, 00509 kcm_data_source_type_e data_source_type, 00510 const uint8_t * kcm_item_data, 00511 size_t kcm_item_data_size) 00512 { 00513 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 00514 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00515 palStatus_t pal_status = PAL_SUCCESS; 00516 palSSTItemInfo_t palItemInfo; 00517 uint32_t flag_mask = 0; 00518 00519 //Build complete data name (also checks name validity) 00520 kcm_status = storage_create_compelete_data_name(kcm_item_type, data_source_type, STORAGE_WORKING_ACRONYM, NULL, kcm_item_name, kcm_item_name_len, kcm_complete_name); 00521 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to build complete data name"); 00522 00523 pal_status = pal_SSTGetInfo (kcm_complete_name, &palItemInfo); 00524 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_SUCCESS), kcm_status = KCM_STATUS_FILE_EXIST, "Data already exists"); 00525 00526 //Check if certificate chain with the same name is exists, if yes -> return an error 00527 if (kcm_item_type == KCM_CERTIFICATE_ITEM) { 00528 00529 kcm_chain_cert_name_info_s cert_name_info = { 0 }; 00530 cert_name_info.certificate_index = 0; 00531 cert_name_info.is_last_certificate = false; 00532 00533 //Build complete name of first chain certificate 00534 kcm_status = storage_create_compelete_data_name(kcm_item_type, data_source_type, STORAGE_WORKING_ACRONYM, &cert_name_info, kcm_item_name, kcm_item_name_len, kcm_complete_name); 00535 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to change single certificate name"); 00536 00537 pal_status = pal_SSTGetInfo (kcm_complete_name, &palItemInfo); 00538 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_SUCCESS), kcm_status = KCM_STATUS_FILE_EXIST, "Data already exists"); 00539 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_ERR_SST_ITEM_NOT_FOUND), kcm_status = storage_error_handler(pal_status), "pal_SSTGetInfo FAILED"); 00540 00541 //Revert the name to certificate complete name 00542 //Build complete name of single certificate 00543 kcm_status = storage_create_compelete_data_name(kcm_item_type, data_source_type, STORAGE_WORKING_ACRONYM, NULL, kcm_item_name, kcm_item_name_len, kcm_complete_name); 00544 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to change first certificate name"); 00545 } 00546 00547 //Create flag mask 00548 if (kcm_item_is_encrypted == true) { 00549 flag_mask |= PAL_SST_CONFIDENTIALITY_FLAG; 00550 } 00551 00552 if (kcm_item_is_factory == true) { 00553 //Set the complete name to backup path 00554 kcm_status = storage_create_compelete_data_name(kcm_item_type, data_source_type, STORAGE_BACKUP_ACRONYM, NULL, kcm_item_name, kcm_item_name_len, kcm_complete_name); 00555 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to change first certificate name to backup path"); 00556 00557 //Write the data to backup path 00558 pal_status = pal_SSTSet (kcm_complete_name, kcm_item_data, kcm_item_data_size, flag_mask); 00559 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), "Failed to write data to backup"); 00560 00561 //Set the backup path back to working 00562 kcm_status = storage_create_compelete_data_name(kcm_item_type, data_source_type, STORAGE_WORKING_ACRONYM, NULL, kcm_item_name, kcm_item_name_len, kcm_complete_name); 00563 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to change first certificate nameFailed to change to backup path"); 00564 00565 } 00566 00567 //Write the data to working path 00568 pal_status = pal_SSTSet (kcm_complete_name, kcm_item_data, kcm_item_data_size, flag_mask); 00569 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), "Failed to write data"); 00570 00571 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00572 return kcm_status; 00573 } 00574 00575 kcm_status_e storage_data_size_read( 00576 const uint8_t * kcm_item_name, 00577 size_t kcm_item_name_len, 00578 kcm_item_type_e kcm_item_type, 00579 kcm_data_source_type_e data_source_type, 00580 size_t * kcm_item_data_size_out) 00581 { 00582 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 00583 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00584 palSSTItemInfo_t palItemInfo; 00585 palStatus_t pal_status = PAL_SUCCESS; 00586 00587 // Validate function parameters 00588 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name"); 00589 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len"); 00590 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); 00591 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type"); 00592 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Kcm size out pointer is NULL"); 00593 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"); 00594 00595 // Check if KCM initialized, if not initialize it 00596 if (!g_kcm_initialized) { 00597 kcm_status = kcm_init(); 00598 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00599 } 00600 00601 //Build complete data name 00602 kcm_status = storage_create_compelete_data_name(kcm_item_type, data_source_type, STORAGE_WORKING_ACRONYM, NULL, kcm_item_name, kcm_item_name_len, kcm_complete_name); 00603 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to to build complete name"); 00604 00605 00606 //Try to get data info 00607 pal_status = pal_SSTGetInfo (kcm_complete_name, &palItemInfo); 00608 00609 //If the item is not found,at this stage we keep the error we need to read first certificate of a chain 00610 if (pal_status == PAL_ERR_SST_ITEM_NOT_FOUND) { 00611 return KCM_STATUS_ITEM_NOT_FOUND; 00612 } 00613 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), "Failed to get data size"); 00614 00615 //Set value of data size 00616 *kcm_item_data_size_out = palItemInfo.itemSize; 00617 SA_PV_LOG_INFO_FUNC_EXIT("kcm data size = %" PRIu32 "", (uint32_t)*kcm_item_data_size_out); 00618 return kcm_status; 00619 } 00620 00621 kcm_status_e storage_data_read( 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 uint8_t *kcm_item_data_out, 00627 size_t kcm_item_data_max_size, 00628 size_t *kcm_item_data_act_size_out) 00629 { 00630 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 00631 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00632 palStatus_t pal_status = PAL_SUCCESS; 00633 palSSTItemInfo_t palItemInfo; 00634 00635 // Validate function parameters 00636 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name"); 00637 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len"); 00638 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); 00639 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"); 00640 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type"); 00641 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_data_act_size_out"); 00642 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"); 00643 00644 // Check if KCM initialized, if not initialize it 00645 if (!g_kcm_initialized) { 00646 kcm_status = kcm_init(); 00647 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00648 } 00649 00650 //Build complete data name 00651 kcm_status = storage_create_compelete_data_name(kcm_item_type, data_source_type, STORAGE_WORKING_ACRONYM, NULL, kcm_item_name, kcm_item_name_len, kcm_complete_name); 00652 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to to build complete name"); 00653 00654 //Get size 00655 pal_status = pal_SSTGetInfo (kcm_complete_name, &palItemInfo); 00656 00657 if (pal_status == PAL_ERR_SST_ITEM_NOT_FOUND && kcm_item_type == KCM_CERTIFICATE_ITEM) { 00658 00659 kcm_chain_cert_name_info_s cert_name_info = { 0 }; 00660 cert_name_info.certificate_index = 0; 00661 cert_name_info.is_last_certificate = false; 00662 00663 //Change complete certificate name to first certificate in chain with the same name 00664 kcm_status = storage_create_compelete_data_name(kcm_item_type, data_source_type, STORAGE_WORKING_ACRONYM, &cert_name_info, kcm_item_name, kcm_item_name_len, kcm_complete_name); 00665 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to change single certificate name"); 00666 00667 //Get size 00668 pal_status = pal_SSTGetInfo (kcm_complete_name, &palItemInfo); 00669 if (pal_status == PAL_ERR_SST_ITEM_NOT_FOUND) { 00670 return KCM_STATUS_ITEM_NOT_FOUND; 00671 } 00672 SA_PV_ERR_RECOVERABLE_RETURN_IF(pal_status != PAL_SUCCESS, kcm_status = storage_error_handler(pal_status), "Failed to get data size"); 00673 00674 SA_PV_LOG_WARN("Warning: Reading certificate chain using single certificate API"); 00675 } 00676 if (pal_status == PAL_ERR_SST_ITEM_NOT_FOUND) { 00677 //item not found. Print info level error 00678 SA_PV_LOG_INFO("Item not found"); 00679 return KCM_STATUS_ITEM_NOT_FOUND; 00680 } 00681 SA_PV_ERR_RECOVERABLE_RETURN_IF(pal_status != PAL_SUCCESS, kcm_status = storage_error_handler(pal_status), "Failed to get data size"); 00682 SA_PV_ERR_RECOVERABLE_RETURN_IF((palItemInfo.itemSize > kcm_item_data_max_size), kcm_status = KCM_STATUS_INSUFFICIENT_BUFFER, "Data out buffer too small"); 00683 00684 pal_status = pal_SSTGet (kcm_complete_name, kcm_item_data_out, kcm_item_data_max_size, kcm_item_data_act_size_out); 00685 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), "Failed to get data "); 00686 00687 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00688 return kcm_status; 00689 } 00690 00691 kcm_status_e storage_data_delete( 00692 const uint8_t * kcm_item_name, 00693 size_t kcm_item_name_len, 00694 kcm_item_type_e kcm_item_type, 00695 kcm_data_source_type_e data_source_type) 00696 { 00697 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 00698 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00699 palStatus_t pal_status = PAL_SUCCESS; 00700 00701 // Validate function parameters 00702 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name"); 00703 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len"); 00704 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); 00705 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type"); 00706 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"); 00707 00708 // Check if KCM initialized, if not initialize it 00709 if (!g_kcm_initialized) { 00710 kcm_status = kcm_init(); 00711 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00712 } 00713 00714 //Build complete data name 00715 kcm_status = storage_create_compelete_data_name(kcm_item_type, data_source_type, STORAGE_WORKING_ACRONYM, NULL, kcm_item_name, kcm_item_name_len, kcm_complete_name); 00716 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to to build complete name"); 00717 00718 //Remove the item name 00719 pal_status = pal_SSTRemove (kcm_complete_name); 00720 SA_PV_ERR_RECOVERABLE_RETURN_IF(pal_status != PAL_SUCCESS, kcm_status = storage_error_handler(pal_status), "Failed to delete data"); 00721 00722 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00723 return kcm_status; 00724 00725 } 00726 00727 static kcm_status_e storage_check_if_certificate_exists(const uint8_t *kcm_chain_name, size_t kcm_chain_name_len, kcm_data_source_type_e data_source_type) { 00728 00729 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00730 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 00731 palStatus_t pal_status = PAL_SUCCESS; 00732 palSSTItemInfo_t palItemInfo = { 0 }; 00733 kcm_chain_cert_name_info_s cert_name_info = { 0 }; 00734 00735 //Build complete name of single certificate with given certificate chain name 00736 kcm_status = storage_create_compelete_data_name(KCM_CERTIFICATE_ITEM, data_source_type, STORAGE_WORKING_ACRONYM, NULL, kcm_chain_name, kcm_chain_name_len, kcm_complete_name); 00737 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to build complete data name"); 00738 00739 //If single certificate with the chain name is exists in the data base - return an error 00740 pal_status = pal_SSTGetInfo (kcm_complete_name, &palItemInfo); 00741 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_SUCCESS), kcm_status = KCM_STATUS_FILE_EXIST, "Data with the same name already exists"); 00742 00743 //Build complete name of first certificate name in the chain 00744 cert_name_info.certificate_index = 0; 00745 cert_name_info.is_last_certificate = false; 00746 kcm_status = storage_create_compelete_data_name(KCM_CERTIFICATE_ITEM, data_source_type, STORAGE_WORKING_ACRONYM, &cert_name_info, kcm_chain_name, kcm_chain_name_len, kcm_complete_name); 00747 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to build complete data name"); 00748 00749 //If first certificate with the chain name is exists in the data base - return an error 00750 pal_status = pal_SSTGetInfo (kcm_complete_name, &palItemInfo); 00751 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_SUCCESS), kcm_status = KCM_STATUS_FILE_EXIST, "Data with the same name already exists"); 00752 00753 return kcm_status; 00754 } 00755 kcm_status_e storage_cert_chain_create( 00756 kcm_cert_chain_handle *kcm_chain_handle, 00757 const uint8_t *kcm_chain_name, 00758 size_t kcm_chain_name_len, 00759 size_t kcm_chain_len, 00760 bool kcm_chain_is_factory, 00761 kcm_data_source_type_e data_source_type) 00762 { 00763 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00764 kcm_cert_chain_context_int_s *chain_context = NULL; 00765 uint8_t *certificate_chain_name = NULL; 00766 00767 00768 // Validate function parameters 00769 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"); 00770 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name"); 00771 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name len"); 00772 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); 00773 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid handle"); 00774 *kcm_chain_handle = NULL; 00775 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"); 00776 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"); 00777 00778 // Check if KCM initialized, if not initialize it 00779 if (!g_kcm_initialized) { 00780 kcm_status = kcm_init(); 00781 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00782 } 00783 00784 //Check if certificate chain or single certificate with the same name already exists 00785 kcm_status = storage_check_if_certificate_exists(kcm_chain_name, kcm_chain_name_len, data_source_type); 00786 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Data with the same name alredy exists"); 00787 00788 // allocate the context 00789 chain_context = (kcm_cert_chain_context_int_s*)fcc_malloc(sizeof(kcm_cert_chain_context_int_s)); 00790 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, "Failed to allocate memory for certificate chain context"); 00791 memset(chain_context, 0, sizeof(kcm_cert_chain_context_int_s)); 00792 00793 certificate_chain_name = fcc_malloc(kcm_chain_name_len); 00794 SA_PV_ERR_RECOVERABLE_GOTO_IF((certificate_chain_name == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, Exit, "Failed to allocate memory for certificate chain name"); 00795 memcpy(certificate_chain_name, kcm_chain_name, kcm_chain_name_len); 00796 00797 //Prepare certificate chain context 00798 chain_context->operation_type = KCM_CHAIN_OP_TYPE_CREATE; 00799 chain_context->chain_name = (uint8_t*)certificate_chain_name; 00800 chain_context->chain_name_len = kcm_chain_name_len; 00801 chain_context->num_of_certificates_in_chain = kcm_chain_len; 00802 chain_context->current_cert_index = 0; 00803 chain_context->chain_is_factory = kcm_chain_is_factory; 00804 00805 *kcm_chain_handle = (kcm_cert_chain_handle)chain_context; 00806 00807 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00808 00809 Exit: 00810 if (kcm_status != KCM_STATUS_SUCCESS) { 00811 fcc_free(chain_context); 00812 } 00813 return kcm_status; 00814 } 00815 00816 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) 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 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 00821 palSSTItemInfo_t palItemInfo = { 0 }; 00822 kcm_chain_cert_name_info_s cert_name_info = { 0 }; 00823 uint32_t flag_mask = 0; 00824 palStatus_t pal_status = PAL_SUCCESS; 00825 00826 SA_PV_LOG_INFO_FUNC_ENTER("cert_data_size =%" PRIu32 "", (uint32_t)kcm_cert_data_size); 00827 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"); 00828 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle"); 00829 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm context"); 00830 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"); 00831 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_CREATE), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type"); 00832 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"); 00833 00834 // Check if KCM initialized, if not initialize it 00835 if (!g_kcm_initialized) { 00836 kcm_status = kcm_init(); 00837 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00838 } 00839 00840 //Set is the certificate is last in the chain 00841 if (chain_context->current_cert_index == chain_context->num_of_certificates_in_chain -1 ) { 00842 cert_name_info.is_last_certificate = true; 00843 } else { 00844 cert_name_info.is_last_certificate = false; 00845 } 00846 //Set current certificate index 00847 cert_name_info.certificate_index = chain_context->current_cert_index; 00848 00849 //Build complete name of current certificate 00850 kcm_status = storage_create_compelete_data_name(KCM_CERTIFICATE_ITEM, data_source_type, STORAGE_WORKING_ACRONYM, NULL, chain_context->chain_name, chain_context->chain_name_len, kcm_complete_name); 00851 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to build complete data name"); 00852 00853 //If single certificate with the chain name is exists in the data base - return an error 00854 pal_status = pal_SSTGetInfo (kcm_complete_name, &palItemInfo); 00855 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_SUCCESS), kcm_status = KCM_STATUS_FILE_EXIST, "Data with the same name already exists"); 00856 //TODO : Add remove of the certificate and continue +add SA_PV_LOG_INFO 00857 00858 if (chain_context->chain_is_factory == true) { 00859 00860 //Set the complete name to backup path 00861 kcm_status = storage_create_compelete_data_name(KCM_CERTIFICATE_ITEM, data_source_type, STORAGE_BACKUP_ACRONYM, &cert_name_info, chain_context->chain_name, chain_context->chain_name_len, kcm_complete_name); 00862 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to change certificate name to backup path"); 00863 00864 //Write the data to backup path 00865 pal_status = pal_SSTSet (kcm_complete_name, kcm_cert_data, kcm_cert_data_size, flag_mask); 00866 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), "Failed to write certificate to backup"); 00867 } 00868 00869 //Set the backup complete name 00870 kcm_status = storage_create_compelete_data_name(KCM_CERTIFICATE_ITEM, data_source_type, STORAGE_WORKING_ACRONYM, &cert_name_info, chain_context->chain_name, chain_context->chain_name_len, kcm_complete_name); 00871 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to build complete data name"); 00872 00873 //Write the certificate to the storage 00874 pal_status = pal_SSTSet (kcm_complete_name, kcm_cert_data, kcm_cert_data_size, flag_mask); 00875 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), "Failed to write data to storage"); 00876 00877 //Increase chian current index 00878 chain_context->current_cert_index++; 00879 00880 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00881 return KCM_STATUS_SUCCESS; 00882 } 00883 00884 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) 00885 { 00886 kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 00887 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00888 int certificate_index =(int)chain_context->current_cert_index; 00889 00890 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS(); 00891 00892 // Validate function parameters 00893 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"); 00894 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle"); 00895 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain"); 00896 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_out_cert_data_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_out_cert_data_size"); 00897 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_OPEN), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type"); 00898 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"); 00899 00900 // Check if KCM initialized, if not initialize it 00901 if (!g_kcm_initialized) { 00902 kcm_status = kcm_init(); 00903 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00904 } 00905 00906 //Retrieve current certificate size (was already read at open stage) 00907 *kcm_out_cert_data_size = chain_context->certificates_info[certificate_index]; 00908 00909 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00910 return kcm_status; 00911 } 00912 00913 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) 00914 { 00915 kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 00916 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00917 kcm_chain_cert_name_info_s cert_name_info = { 0 , false }; 00918 palStatus_t pal_status = PAL_SUCCESS; 00919 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 00920 00921 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS(); 00922 00923 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"); 00924 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle"); 00925 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain"); 00926 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data"); 00927 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_max_cert_data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_max_cert_data_size"); 00928 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_actual_cert_data_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_actual_cert_data_size"); 00929 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_OPEN), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type"); 00930 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"); 00931 // Check if KCM initialized, if not initialize it 00932 if (!g_kcm_initialized) { 00933 kcm_status = kcm_init(); 00934 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 00935 } 00936 00937 cert_name_info.certificate_index = chain_context->current_cert_index; 00938 if ((chain_context->num_of_certificates_in_chain - 1) == chain_context->current_cert_index) { 00939 cert_name_info.is_last_certificate = true; 00940 } 00941 00942 //Build certificate name according to its index in certificate chain 00943 kcm_status = storage_create_compelete_data_name(KCM_LAST_ITEM, data_source_type, STORAGE_WORKING_ACRONYM, &cert_name_info, chain_context->chain_name, chain_context->chain_name_len, kcm_complete_name); 00944 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to build complete data name"); 00945 00946 pal_status = pal_SSTGet ((const char*)kcm_complete_name, kcm_cert_data, kcm_max_cert_data_size, kcm_actual_cert_data_size); 00947 SA_PV_ERR_RECOVERABLE_RETURN_IF(pal_status != PAL_SUCCESS, kcm_status = storage_error_handler(pal_status), "Failed to get data size"); 00948 00949 // file read, increase current_cert_index 00950 chain_context->current_cert_index++; 00951 00952 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00953 return kcm_status; 00954 } 00955 00956 00957 static kcm_status_e set_certificates_info(kcm_cert_chain_context_int_s *chain_context, kcm_data_source_type_e data_source_type) 00958 { 00959 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 00960 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 00961 palSSTItemInfo_t palItemInfo = { 0 }; 00962 kcm_chain_cert_name_info_s cert_name_info = { 0 , false}; 00963 palStatus_t pal_status = PAL_SUCCESS; 00964 int certificate_index = 0; 00965 00966 //Try to read all certificate in the chain, retrieve the number of certificates in the chain and their sizes 00967 for (certificate_index = 0; (certificate_index < KCM_MAX_NUMBER_OF_CERTITICATES_IN_CHAIN) && ( cert_name_info.is_last_certificate == false); certificate_index++) 00968 { 00969 00970 cert_name_info.certificate_index = (uint32_t)certificate_index; 00971 00972 //Build certificate name according to its index in certificate chain 00973 kcm_status = storage_create_compelete_data_name(KCM_LAST_ITEM, data_source_type, STORAGE_WORKING_ACRONYM, &cert_name_info, chain_context->chain_name, chain_context->chain_name_len, kcm_complete_name); 00974 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to build complete data name"); 00975 00976 //Try to read certificate as not last certificate 00977 pal_status = pal_SSTGetInfo ((const char*)kcm_complete_name, &palItemInfo); 00978 //If current name wasn't found, try to read the certificate as last one in the chain 00979 if (pal_status == PAL_ERR_SST_ITEM_NOT_FOUND) { 00980 00981 cert_name_info.is_last_certificate = true; 00982 00983 //Set the name certificate as last certificate in the chain 00984 kcm_status = storage_create_compelete_data_name(KCM_LAST_ITEM, data_source_type, STORAGE_WORKING_ACRONYM, &cert_name_info, chain_context->chain_name, chain_context->chain_name_len, kcm_complete_name); 00985 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to build complete data name"); 00986 00987 //retrieve item info (size and flags) 00988 pal_status = pal_SSTGetInfo ((const char*)kcm_complete_name, &palItemInfo); 00989 00990 //Indication for last certificate 00991 if (pal_status == PAL_SUCCESS) { 00992 cert_name_info.is_last_certificate = true; 00993 } 00994 00995 } 00996 SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = storage_error_handler(pal_status), "Failed pal_SSTGetInfo (%" PRIu32 ")", pal_status); 00997 00998 //Set in certificate info array the size of current index 00999 chain_context->certificates_info[certificate_index] = palItemInfo.itemSize; 01000 } 01001 SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_name_info.is_last_certificate != true ), kcm_status = KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Failed to set size of certificate chain"); 01002 01003 chain_context->num_of_certificates_in_chain = (uint32_t)(certificate_index ); 01004 return kcm_status; 01005 } 01006 01007 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) 01008 { 01009 kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 01010 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01011 uint8_t *certificate_chain_name = NULL; 01012 01013 // Validate function parameters 01014 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"); 01015 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name"); 01016 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name len"); 01017 SA_PV_LOG_INFO_FUNC_ENTER("chain name = %.*s", (int)kcm_chain_name_len, kcm_chain_name); 01018 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid handle"); 01019 *kcm_chain_handle = NULL; 01020 //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"); 01021 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_len_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain len out"); 01022 01023 // Check if KCM initialized, if not initialize it 01024 if (!g_kcm_initialized) { 01025 kcm_status = kcm_init(); 01026 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 01027 } 01028 01029 // allocate the context 01030 chain_context = (kcm_cert_chain_context_int_s*)fcc_malloc(sizeof(kcm_cert_chain_context_int_s)); 01031 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, "Failed to allocate memory for certificate chain context"); 01032 memset(chain_context, 0, sizeof(kcm_cert_chain_context_int_s)); 01033 01034 //Allocate memory for the certificate chain name 01035 certificate_chain_name = fcc_malloc(kcm_chain_name_len); 01036 SA_PV_ERR_RECOVERABLE_GOTO_IF((certificate_chain_name == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, Exit, "Failed to allocate memory for certificate chain name"); 01037 memcpy(certificate_chain_name, kcm_chain_name, kcm_chain_name_len); 01038 01039 //Prepare certificate chain context 01040 chain_context->operation_type = KCM_CHAIN_OP_TYPE_OPEN; 01041 chain_context->chain_name = (uint8_t*)certificate_chain_name; 01042 chain_context->chain_name_len = kcm_chain_name_len; 01043 chain_context->current_cert_index = 0; 01044 01045 //Set certificates_info structure 01046 kcm_status = set_certificates_info(chain_context, data_source_type); 01047 SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit,"Failed to set certificate chain context data"); 01048 01049 *kcm_chain_len_out = chain_context->num_of_certificates_in_chain; 01050 01051 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 01052 Exit: 01053 if (kcm_status != KCM_STATUS_SUCCESS) { 01054 fcc_free(certificate_chain_name); 01055 fcc_free(chain_context); 01056 *kcm_chain_handle = NULL; 01057 } else { 01058 *kcm_chain_handle = (kcm_cert_chain_handle)chain_context; 01059 } 01060 01061 return kcm_status; 01062 } 01063 01064 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) 01065 { 01066 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01067 kcm_status_e final_kcm_status = KCM_STATUS_SUCCESS; 01068 size_t kcm_chain_len = 0; 01069 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 01070 kcm_cert_chain_handle kcm_chain_handle; 01071 kcm_cert_chain_context_int_s *chain_context; 01072 kcm_chain_cert_name_info_s cert_name_info = { 0, false }; 01073 palStatus_t pal_status = PAL_SUCCESS; 01074 01075 // Validate function parameters 01076 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_chain_name"); 01077 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_chain_name_len"); 01078 SA_PV_LOG_INFO_FUNC_ENTER("chain name = %.*s", (int)kcm_chain_name_len, kcm_chain_name); 01079 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"); 01080 01081 // Check if KCM initialized, if not initialize it 01082 if (!g_kcm_initialized) { 01083 kcm_status = kcm_init(); 01084 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 01085 } 01086 // open the first file and read the kcm_chain_len from meta data 01087 kcm_status = storage_cert_chain_open(&kcm_chain_handle, kcm_chain_name, kcm_chain_name_len, data_source_type, &kcm_chain_len); 01088 if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) { 01089 return kcm_status; 01090 } 01091 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to open certificate chain\n"); 01092 01093 chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 01094 01095 //Go over all chain certificates and delete 01096 for (; chain_context->current_cert_index < kcm_chain_len; chain_context->current_cert_index++) { 01097 01098 cert_name_info.certificate_index = chain_context->current_cert_index; 01099 if (chain_context->current_cert_index == kcm_chain_len - 1) { 01100 cert_name_info.is_last_certificate = true; 01101 } 01102 01103 //Set the name certificate as last certificate in the chain 01104 kcm_status = storage_create_compelete_data_name(KCM_CERTIFICATE_ITEM, 01105 data_source_type, 01106 STORAGE_WORKING_ACRONYM, 01107 &cert_name_info, 01108 chain_context->chain_name, 01109 chain_context->chain_name_len, 01110 kcm_complete_name); 01111 01112 //Remove certificate only if complete_data_name is valid 01113 if (kcm_status == KCM_STATUS_SUCCESS) { 01114 //Remove the certificate 01115 pal_status = pal_SSTRemove (kcm_complete_name); 01116 if (pal_status != PAL_SUCCESS) { 01117 //If Remove failed, record the error and continue delete process 01118 final_kcm_status = storage_error_handler(pal_status); 01119 } 01120 } 01121 } 01122 01123 (void)storage_cert_chain_close(kcm_chain_handle, data_source_type); 01124 01125 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 01126 return final_kcm_status; 01127 } 01128 01129 static void storage_cert_chain_files_delete(kcm_cert_chain_context_int_s *chain_context, kcm_data_source_type_e data_source_type, kcm_chain_operation_type_e operation_type) 01130 { 01131 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01132 kcm_chain_cert_name_info_s cert_name_info = { 0, false }; 01133 char kcm_complete_name[KCM_MAX_FILENAME_SIZE] = { 0 }; 01134 01135 do { 01136 cert_name_info.certificate_index = chain_context->current_cert_index; 01137 01138 //Set the name of the certificate in working 01139 kcm_status = storage_create_compelete_data_name(KCM_CERTIFICATE_ITEM, 01140 data_source_type, 01141 STORAGE_WORKING_ACRONYM, 01142 &cert_name_info, 01143 chain_context->chain_name, 01144 chain_context->chain_name_len, 01145 kcm_complete_name); 01146 01147 //we don't check the result of storage_file_delete, as it is possible that not all certificates were saved to the storage 01148 if (kcm_status == KCM_STATUS_SUCCESS) { 01149 pal_SSTRemove (kcm_complete_name); 01150 } 01151 01152 //Only in case of invalid create operation we will remove wrong chain from backup path too 01153 if (operation_type == KCM_CHAIN_OP_TYPE_CREATE) { 01154 //Set the name the certificate in backup (factory) 01155 kcm_status = storage_create_compelete_data_name(KCM_CERTIFICATE_ITEM, 01156 data_source_type, 01157 STORAGE_BACKUP_ACRONYM, 01158 &cert_name_info, 01159 chain_context->chain_name, 01160 chain_context->chain_name_len, 01161 kcm_complete_name); 01162 01163 //we don't check the result of storage_file_delete, as it is possible that not all certificates were saved to the storage 01164 if (kcm_status == KCM_STATUS_SUCCESS) { 01165 pal_SSTRemove (kcm_complete_name); 01166 } 01167 } 01168 01169 if (chain_context->current_cert_index == 0) { 01170 break; 01171 } 01172 01173 // 01174 chain_context->current_cert_index--; 01175 } while (true); 01176 } 01177 01178 kcm_status_e storage_cert_chain_close(kcm_cert_chain_handle kcm_chain_handle, kcm_data_source_type_e data_source_type) 01179 { 01180 kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle; 01181 kcm_status_e kcm_status = KCM_STATUS_SUCCESS; 01182 01183 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS(); 01184 01185 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"); 01186 01187 if (kcm_chain_handle == NULL) { 01188 goto Exit; // and return KCM_STATUS_SUCCESS 01189 } 01190 SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain"); 01191 01192 // Check if KCM initialized, if not initialize it 01193 if (!g_kcm_initialized) { 01194 kcm_status = kcm_init(); 01195 SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n"); 01196 } 01197 01198 if (chain_context->operation_type == KCM_CHAIN_OP_TYPE_CREATE && chain_context->current_cert_index < chain_context->num_of_certificates_in_chain) { 01199 // user added less certificates than num_of_certificates_in_chain, delete all and return error 01200 storage_cert_chain_files_delete(chain_context, data_source_type, KCM_CHAIN_OP_TYPE_CREATE); 01201 SA_PV_ERR_RECOVERABLE_GOTO_IF(true, (kcm_status = KCM_STATUS_CLOSE_INCOMPLETE_CHAIN), Exit, "Closing incomplete kcm chain"); 01202 } 01203 01204 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 01205 Exit: 01206 if (chain_context != NULL) { 01207 fcc_free(chain_context->chain_name); 01208 fcc_free(chain_context); 01209 } 01210 01211 return kcm_status; 01212 } 01213 01214 01215 01216 #endif
Generated on Mon Aug 29 2022 19:53:42 by
