Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers storage.c Source File

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