Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers storage_esfs.c Source File

storage_esfs.c

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