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.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 Tue Jul 12 2022 20:21:03 by
