Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers key_config_manager.c Source File

key_config_manager.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 #include <stdbool.h>
00017 #include "key_config_manager.h"
00018 #include "storage.h"
00019 #include "pv_error_handling.h"
00020 #include "cs_der_certs.h"
00021 #include "cs_der_keys_and_csrs.h"
00022 #include "fcc_malloc.h"
00023 #include "pal.h"
00024 #include "cs_utils.h"
00025 
00026 typedef enum {
00027     KCM_PRIVATE_KEY_DATA,
00028     KCM_PUBLIC_KEY_DATA,
00029     KCM_SYMMETRIC_KEY_DATA,
00030     KCM_CERTIFICATE_DATA,
00031     KCM_CONFIG_DATA,
00032 } kcm_data_type;
00033 
00034 static bool kcm_initialized = false;
00035 
00036 // The func create new name by adding kcm prefix
00037 static kcm_status_e  kcm_create_complete_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)
00038 {
00039     size_t prefix_length = 0;
00040     size_t total_length = 0;
00041 
00042     SA_PV_LOG_TRACE_FUNC_ENTER("name len=%" PRIu32 "", (uint32_t)kcm_name_len);
00043 
00044     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_buffer_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_buffer_out parameter");
00045     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_buffer_size_allocated_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_buffer_size_allocated_out parameter");
00046 
00047     // Check that name is not too long. This is done only in this function since all KCM APIs using file names go through here.
00048     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);
00049 
00050     prefix_length = strlen(prefix);
00051     total_length = kcm_name_len + prefix_length;
00052 
00053     // This Should never happen. This means that the total larger than permitted was used.
00054     SA_PV_ERR_RECOVERABLE_RETURN_IF((total_length > STORAGE_FILENAME_MAX_SIZE), KCM_STATUS_INVALID_PARAMETER, "KCM file name too long");
00055 
00056     *kcm_buffer_out = (uint8_t *)fcc_malloc(total_length);
00057     SA_PV_ERR_RECOVERABLE_RETURN_IF((*kcm_buffer_out == NULL), KCM_STATUS_OUT_OF_MEMORY, "Failed allocating kcm_buffer_out");
00058 
00059     /* Append prefix and name to allocated buffer */
00060     memcpy(*kcm_buffer_out, (uint8_t *)prefix, prefix_length);
00061     memcpy(*kcm_buffer_out + prefix_length, kcm_name, kcm_name_len);
00062 
00063     *kcm_buffer_size_allocated_out = total_length;
00064 
00065     SA_PV_LOG_TRACE_FUNC_EXIT("kcm_buffer_size_allocated_out=  %" PRIu32 "", (uint32_t)*kcm_buffer_size_allocated_out);
00066     return KCM_STATUS_SUCCESS;
00067 }
00068 
00069 
00070 static kcm_status_e  kcm_item_name_get_prefix(kcm_item_type_e kcm_item_type, const char** prefix)
00071 {
00072     kcm_status_e  status = KCM_STATUS_SUCCESS;
00073 
00074     switch (kcm_item_type) {
00075         case KCM_PRIVATE_KEY_ITEM:
00076             *prefix = KCM_FILE_PREFIX_PRIVATE_KEY;
00077             break;
00078         case KCM_PUBLIC_KEY_ITEM:
00079             *prefix = KCM_FILE_PREFIX_PUBLIC_KEY;
00080             break;
00081         case KCM_SYMMETRIC_KEY_ITEM:
00082             *prefix = KCM_FILE_PREFIX_SYMMETRIC_KEY;
00083             break;
00084         case KCM_CERTIFICATE_ITEM:
00085             *prefix = KCM_FILE_PREFIX_CERTIFICATE;
00086             break;
00087         case KCM_CONFIG_ITEM:
00088             *prefix = KCM_FILE_PREFIX_CONFIG_PARAM;
00089             break;
00090         default:
00091             status = KCM_STATUS_INVALID_PARAMETER;
00092             break;
00093     }
00094     return status;
00095 }
00096 
00097 kcm_status_e  kcm_init(void)
00098 {
00099     kcm_status_e  status = KCM_STATUS_SUCCESS;
00100 
00101     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00102 
00103     if (!kcm_initialized) {
00104         palStatus_t pal_status;
00105 
00106         //Initialize PAL
00107         pal_status = pal_init();
00108         SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), KCM_STATUS_ERROR, "Failed initializing PAL (%" PRIu32 ")", pal_status);
00109 
00110         //Initialize back-end storage
00111         status = storage_init();
00112         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "Failed initializing storage\n");
00113 
00114         // Mark as "initialized"
00115         kcm_initialized = true;
00116     }
00117 
00118     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00119 
00120     return status;
00121 }
00122 
00123 kcm_status_e  kcm_finalize(void)
00124 {
00125     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00126 
00127     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00128 
00129     if (kcm_initialized) {
00130 
00131         kcm_status = storage_finalize();
00132         if (kcm_status != KCM_STATUS_SUCCESS) {
00133             SA_PV_LOG_ERR("Failed finalizing storage\n");
00134         }
00135 
00136         //Finalize PAL
00137         pal_destroy();
00138 
00139         // Mark as "not initialized"
00140         kcm_initialized = false;
00141     }
00142 
00143     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00144 
00145     return kcm_status;
00146 }
00147 
00148 kcm_status_e  kcm_item_store(const uint8_t * kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, bool kcm_item_is_factory, const uint8_t * kcm_item_data, size_t kcm_item_data_size, const kcm_security_desc_s security_desc)
00149 {
00150     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00151     kcm_ctx_s ctx;
00152     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00153     size_t kcm_complete_name_size;
00154     const char *prefix;
00155     bool kcm_item_is_encrypted = true; //encrypt by default
00156 
00157     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
00158     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
00159     SA_PV_LOG_INFO_FUNC_ENTER("item name =  %.*s len=%" PRIu32 ", data size=%" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len, (uint32_t)kcm_item_data_size);
00160 
00161     // Check if KCM initialized, if not initialize it
00162     if (!kcm_initialized) {
00163         kcm_status = kcm_init();
00164         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00165     }
00166 
00167 
00168     // Validate function parameters
00169     SA_PV_ERR_RECOVERABLE_RETURN_IF(((kcm_item_data == NULL) && (kcm_item_data_size > 0)), KCM_STATUS_INVALID_PARAMETER, "Provided kcm_item_data NULL and kcm_item_data_size greater than 0");
00170 
00171     //temporary check that security descriptor is NULL
00172     SA_PV_ERR_RECOVERABLE_RETURN_IF((security_desc != NULL), KCM_STATUS_INVALID_PARAMETER, "Security descriptor is not NULL!");
00173     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type != KCM_CONFIG_ITEM && kcm_item_data_size == 0), KCM_STATUS_ITEM_IS_EMPTY, "The data of current item is empty!");
00174 
00175     switch (kcm_item_type) {
00176         case KCM_PRIVATE_KEY_ITEM:
00177             kcm_status = cs_der_priv_key_verify(kcm_item_data, kcm_item_data_size);
00178             SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Private key validation failed");
00179             break;
00180         case KCM_PUBLIC_KEY_ITEM:
00181             kcm_status = cs_der_public_key_verify(kcm_item_data, kcm_item_data_size);
00182             SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Public key validation failed");
00183             kcm_item_is_encrypted = false; //do not encrypt public key
00184             break;
00185         case KCM_SYMMETRIC_KEY_ITEM:
00186             //currently possible to write a symmetric key of size 0 since we do not check format
00187             break;
00188         case KCM_CERTIFICATE_ITEM:
00189             kcm_status = cs_check_der_x509_format(kcm_item_data, kcm_item_data_size);
00190             SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Certificate validation failed");
00191             kcm_item_is_encrypted = false; //do not encrypt certificates
00192             break;
00193         case KCM_CONFIG_ITEM:
00194             break;
00195         default:
00196             SA_PV_ERR_RECOVERABLE_RETURN_IF((true), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
00197     }
00198 
00199     kcm_status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
00200     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_item_name_get_prefix");
00201 
00202     kcm_status = kcm_create_complete_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
00203     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
00204 
00205     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);
00206     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed writing file to storage");
00207 
00208 Exit:
00209     fcc_free(kcm_complete_name);
00210     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00211 
00212     return kcm_status;
00213 }
00214 
00215 kcm_status_e  kcm_item_get_data_size(const uint8_t *kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, size_t *kcm_item_data_size_out)
00216 {
00217     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00218     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00219     size_t kcm_complete_name_size;
00220     kcm_ctx_s ctx;
00221     size_t kcm_data_size = 0;
00222     const char *prefix;
00223 
00224     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
00225     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
00226     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);
00227 
00228     // Check if KCM initialized, if not initialize it
00229     if (!kcm_initialized) {
00230         kcm_status = kcm_init();
00231         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00232     }
00233 
00234     // Validate function parameters
00235     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
00236     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Kcm size out pointer is NULL");
00237 
00238     kcm_status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
00239     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_item_name_get_prefix");
00240 
00241     kcm_status = kcm_create_complete_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
00242     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
00243 
00244     kcm_status = storage_file_size_get(&ctx, kcm_complete_name, kcm_complete_name_size, &kcm_data_size);
00245     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00246         goto Exit;
00247     }
00248     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Failed getting file size");
00249 
00250     *kcm_item_data_size_out = kcm_data_size;
00251     SA_PV_LOG_INFO_FUNC_EXIT("kcm data size = %" PRIu32 "", (uint32_t)*kcm_item_data_size_out);
00252 
00253 Exit:
00254     fcc_free(kcm_complete_name);
00255 
00256     return kcm_status;
00257 }
00258 
00259 
00260 kcm_status_e  kcm_item_get_data(const uint8_t * kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, uint8_t * kcm_item_data_out, size_t kcm_item_data_max_size, size_t * kcm_item_data_act_size_out)
00261 {
00262     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00263     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00264     size_t kcm_complete_name_size;
00265     kcm_ctx_s ctx;
00266     const char *prefix;
00267     size_t meta_data_size;
00268     uint16_t chain_len_to_read;
00269 
00270     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
00271     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
00272     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);
00273 
00274     // Check if KCM initialized, if not initialize it
00275     if (!kcm_initialized) {
00276         kcm_status = kcm_init();
00277         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00278     }
00279 
00280     // Validate function parameters
00281     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
00282     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_data_act_size_out");
00283     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");
00284 
00285     kcm_status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
00286     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_item_name_get_prefix");
00287 
00288     kcm_status = kcm_create_complete_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
00289     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
00290 
00291     kcm_status = storage_file_open(&ctx, kcm_complete_name, kcm_complete_name_size);
00292     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00293         goto Exit;
00294     }
00295     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Failed to open the given file");
00296 
00297     if (kcm_item_type == KCM_CERTIFICATE_ITEM) {
00298         // check if there is meta data
00299         kcm_status = storage_file_get_meta_data_size(&ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, &meta_data_size);
00300         if (kcm_status == KCM_STATUS_SUCCESS) {
00301             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);
00302             if (kcm_status == KCM_STATUS_SUCCESS && chain_len_to_read > 1) {
00303                 SA_PV_LOG_WARN("Warning: Reading certificate chain using single certificate API");
00304             }
00305         }
00306     }
00307 
00308     kcm_status = storage_file_read_with_ctx(&ctx, kcm_item_data_out, kcm_item_data_max_size, kcm_item_data_act_size_out);
00309     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed reading file from storage (%d)", kcm_status);
00310 
00311     SA_PV_LOG_INFO_FUNC_EXIT("kcm data size = %" PRIu32 "", (uint32_t)*kcm_item_data_act_size_out);
00312 Exit:
00313     if (kcm_status != KCM_STATUS_ITEM_NOT_FOUND) {
00314         storage_file_close(&ctx);
00315     }
00316     fcc_free(kcm_complete_name);
00317 
00318     return kcm_status;
00319 }
00320 
00321 
00322 kcm_status_e  kcm_item_delete(const uint8_t * kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type)
00323 {
00324     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00325     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00326     size_t kcm_complete_name_size;
00327     kcm_ctx_s ctx; // FIXME - Currently not implemented
00328     const char *prefix;
00329 
00330     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
00331     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
00332     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);
00333 
00334     // Check if KCM initialized, if not initialize it
00335     if (!kcm_initialized) {
00336         kcm_status = kcm_init();
00337         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00338     }
00339 
00340     // Validate function parameters
00341     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
00342 
00343     kcm_status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
00344     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_item_name_get_prefix");
00345 
00346     kcm_status = kcm_create_complete_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
00347     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
00348 
00349     kcm_status = storage_file_delete(&ctx, kcm_complete_name, kcm_complete_name_size);
00350     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed deleting kcm data");
00351 
00352 Exit:
00353     fcc_free(kcm_complete_name);
00354     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00355 
00356     return kcm_status;
00357 }
00358 
00359 kcm_status_e  kcm_factory_reset(void)
00360 {
00361     kcm_status_e  status = KCM_STATUS_SUCCESS;
00362 
00363     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00364 
00365     // Check if KCM initialized, if not initialize it
00366     if (!kcm_initialized) {
00367         status = kcm_init();
00368         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "KCM initialization failed\n");
00369     }
00370 
00371     status = storage_factory_reset();
00372     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed perform factory reset");
00373 
00374 Exit:
00375     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00376     return status;
00377 }
00378 
00379 // Internal function to update file name prefix according to chain index
00380 void kcm_cert_chain_update_name_prefix(uint8_t *complete_file_name, uint32_t index)
00381 {
00382     if (index == 0) {
00383         memcpy(complete_file_name, KCM_FILE_PREFIX_CERT_CHAIN_0, strlen(KCM_FILE_PREFIX_CERT_CHAIN_0));
00384         return;
00385     }
00386     memcpy(complete_file_name, KCM_FILE_PREFIX_CERT_CHAIN_X, strlen(KCM_FILE_PREFIX_CERT_CHAIN_X));
00387     complete_file_name[KCM_FILE_PREFIX_CERT_CHAIN_X_OFFSET] = (uint8_t)('0' + (uint8_t)index);
00388 }
00389 
00390 static void kcm_cert_chain_files_delete(kcm_cert_chain_context_int_s *chain_context)
00391 {
00392     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00393 
00394     do {
00395         kcm_cert_chain_update_name_prefix(chain_context->chain_name, chain_context->current_cert_index);
00396         storage_file_delete(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len);
00397         if (chain_context->current_cert_index == 0) {
00398             break;
00399         }
00400         chain_context->current_cert_index--;
00401     } while (true);
00402 
00403     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00404 }
00405 
00406 kcm_status_e  kcm_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)
00407 {
00408     kcm_cert_chain_context_int_s *chain_context = NULL;
00409     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00410     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00411     size_t kcm_complete_name_size;
00412     kcm_meta_data_list_s kcm_meta_data;
00413     uint16_t chain_len_to_write = (uint16_t)kcm_chain_len;
00414 
00415     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name");
00416     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name len");
00417     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);
00418 
00419     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid handle");
00420     *kcm_chain_handle = NULL;
00421 
00422     // Check if KCM initialized, if not initialize it
00423     if (!kcm_initialized) {
00424         kcm_status = kcm_init();
00425         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00426     }
00427 
00428     // Validate function parameters
00429     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_len == 0 || kcm_chain_len > KCM_MAX_NUMBER_OF_CERTIFICATES_IN_CHAIN), KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Invalid chain len");
00430 
00431     kcm_status = kcm_create_complete_name(kcm_chain_name, kcm_chain_name_len, KCM_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size);
00432     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
00433 
00434     // allocate the context
00435     chain_context = (kcm_cert_chain_context_int_s*)fcc_malloc(sizeof(kcm_cert_chain_context_int_s));
00436     memset(chain_context, 0, sizeof(kcm_cert_chain_context_int_s));
00437 
00438     // Prepare one meta data item for saving kcm_chain_len as meta data of the first file
00439     kcm_meta_data.meta_data[0].type = KCM_CERT_CHAIN_LEN_MD_TYPE;
00440     kcm_meta_data.meta_data[0].data_size = sizeof(chain_len_to_write);
00441     kcm_meta_data.meta_data[0].data = (uint8_t*)&chain_len_to_write;
00442     kcm_meta_data.meta_data_count = 1;
00443 
00444     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);
00445     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed creating kcm chain file");
00446 
00447     chain_context->operation_type = KCM_CHAIN_OP_TYPE_CREATE;
00448     chain_context->chain_name = kcm_complete_name;
00449     chain_context->chain_name_len = kcm_complete_name_size;
00450     chain_context->num_of_certificates_in_chain = kcm_chain_len;
00451     chain_context->current_cert_index = 0;
00452     chain_context->chain_is_factory = kcm_chain_is_factory;
00453 
00454 Exit:
00455     if (kcm_status != KCM_STATUS_SUCCESS) {
00456         fcc_free(kcm_complete_name);
00457         fcc_free(chain_context);
00458         *kcm_chain_handle = NULL;
00459     } else {
00460         // set the handle only if success
00461         *kcm_chain_handle = (kcm_cert_chain_handle)chain_context;
00462     }
00463 
00464 
00465     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00466 
00467     return kcm_status;
00468 }
00469 
00470 
00471 kcm_status_e  kcm_cert_chain_open(kcm_cert_chain_handle *kcm_chain_handle, const uint8_t *kcm_chain_name, size_t kcm_chain_name_len, size_t *kcm_chain_len_out)
00472 {
00473     kcm_cert_chain_context_int_s *chain_context = NULL;
00474     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00475     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00476     size_t kcm_complete_name_size;
00477     size_t meta_data_size;
00478     uint16_t chain_len_to_read;
00479 
00480     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name");
00481     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name len");
00482     SA_PV_LOG_INFO_FUNC_ENTER("chain name =  %.*s", (int)kcm_chain_name_len, kcm_chain_name);
00483 
00484     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid handle");
00485     *kcm_chain_handle = NULL;
00486 
00487     // Check if KCM initialized, if not initialize it
00488     if (!kcm_initialized) {
00489         kcm_status = kcm_init();
00490         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00491     }
00492 
00493     // Validate function parameters
00494     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_len_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain len out");
00495 
00496     kcm_status = kcm_create_complete_name(kcm_chain_name, kcm_chain_name_len, KCM_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size);
00497     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
00498 
00499     // allocate the context
00500     chain_context = (kcm_cert_chain_context_int_s*)fcc_malloc(sizeof(kcm_cert_chain_context_int_s));
00501     memset(chain_context, 0, sizeof(kcm_cert_chain_context_int_s));
00502 
00503     kcm_status = storage_file_open(&chain_context->current_kcm_ctx, kcm_complete_name, kcm_complete_name_size);
00504     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00505         // skip the error log msg
00506         goto Exit;
00507     }
00508     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed opening kcm chain file");
00509 
00510     kcm_status = storage_file_get_meta_data_size(&chain_context->current_kcm_ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, &meta_data_size);
00511     if (kcm_status == KCM_STATUS_META_DATA_NOT_FOUND) {
00512         // treat single cert as chain with size 1
00513         chain_len_to_read = 1;
00514         kcm_status = KCM_STATUS_SUCCESS;
00515     } else {
00516         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed getting kcm meta data size");
00517         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");
00518 
00519         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);
00520         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed reading file's metadata");
00521         // Test if the read len is legitimate number
00522         SA_PV_ERR_RECOVERABLE_GOTO_IF((chain_len_to_read == 0 || chain_len_to_read > KCM_MAX_NUMBER_OF_CERTIFICATES_IN_CHAIN), (kcm_status = KCM_STATUS_CORRUPTED_CHAIN_FILE), Exit, "Illegitimate chain len in file's metadata");
00523     }
00524 
00525     chain_context->operation_type = KCM_CHAIN_OP_TYPE_OPEN;
00526     chain_context->chain_name = kcm_complete_name;
00527     chain_context->chain_name_len = kcm_complete_name_size;
00528     chain_context->num_of_certificates_in_chain = (size_t)chain_len_to_read;
00529     chain_context->current_cert_index = 0;
00530 
00531 Exit:
00532     if (kcm_status != KCM_STATUS_SUCCESS) {
00533         storage_file_close(&chain_context->current_kcm_ctx);
00534         fcc_free(kcm_complete_name);
00535         fcc_free(chain_context);
00536         *kcm_chain_handle = NULL;
00537     } else {
00538         *kcm_chain_len_out = chain_context->num_of_certificates_in_chain;
00539         // set the handle only if success
00540         *kcm_chain_handle = (kcm_cert_chain_handle)chain_context;
00541     }
00542 
00543     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00544 
00545     return kcm_status;
00546 }
00547 
00548 /*
00549 * If not first certificate in chain:
00550 *     1. Validate previously added certificate with the public key inside kcm_cert_data
00551 *     2. Set the chain_context->prev_cert_params to be the params of the current certificate so it can be validated with next call to this function.
00552 *     3. Store the current certificate
00553 *     4. Update the index of the chain handle iterator for next use of this function
00554 * If is first certificate in chain:
00555 *    File already open - skip step 1 (no previous cert available). Note in this case the file should already be open so no need to reopen it
00556 */
00557 kcm_status_e  kcm_cert_chain_add_next(kcm_cert_chain_handle kcm_chain_handle, const uint8_t *kcm_cert_data, size_t kcm_cert_data_size)
00558 {
00559     kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
00560     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00561     palX509Handle_t cert;
00562 
00563     SA_PV_LOG_INFO_FUNC_ENTER("cert_data_size =%" PRIu32 "", (uint32_t)kcm_cert_data_size);
00564 
00565     // Check if KCM initialized, if not initialize it
00566     if (!kcm_initialized) {
00567         kcm_status = kcm_init();
00568         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00569     }
00570 
00571     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle");
00572     SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm context");
00573     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");
00574     SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_CREATE), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type");
00575     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");
00576 
00577     // Parse the X509 and make sure it is of correct structure
00578     kcm_status = cs_create_handle_from_der_x509_cert(kcm_cert_data, kcm_cert_data_size, &cert);
00579     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to parsing cert");
00580 
00581     if (chain_context->current_cert_index > 0) {
00582         // If not first certificate - validate based on params of previous certificate
00583         kcm_status = cs_x509_cert_verify_signature(cert, chain_context->prev_cert_params.htbs,
00584                                                    chain_context->prev_cert_params.htbs_actual_size,
00585                                                    chain_context->prev_cert_params.signature,
00586                                                    chain_context->prev_cert_params.signature_actual_size);
00587         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status == KCM_CRYPTO_STATUS_VERIFY_SIGNATURE_FAILED), (kcm_status = KCM_STATUS_CERTIFICATE_CHAIN_VERIFICATION_FAILED), Clean_X509, "Failed verifying child signature");
00588         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Clean_X509, "Failed verifying child signature");
00589         // only on the first certificate, the file is open
00590         // update file name by changing last char suffix and create the file
00591         kcm_cert_chain_update_name_prefix(chain_context->chain_name, chain_context->current_cert_index);
00592         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);
00593         if (kcm_status == KCM_STATUS_FILE_EXIST) {
00594             // trying to recover by deleting the existing file
00595             SA_PV_LOG_INFO("Certificate chain file for index %" PRIu32 " already exists. File will be overwritten.", (uint32_t)chain_context->current_cert_index);
00596 
00597             kcm_status = storage_file_delete(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len);
00598             SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Clean_X509, "Failed to delete existing kcm chain file");
00599 
00600             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);
00601         }
00602         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Clean_X509, "Failed creating kcm chain file");
00603     }
00604 
00605     // Save params only if certificate is not last in chain 
00606     if(chain_context->current_cert_index < chain_context->num_of_certificates_in_chain - 1) {
00607         // Get params needed for validation by the signer
00608         // These will be used to validate this certificate in the chain when parsing the next one
00609         kcm_status = cs_child_cert_params_get(cert, &chain_context->prev_cert_params);
00610         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed to retrieve child cert params");
00611     }
00612     kcm_status = storage_file_write_with_ctx(&chain_context->current_kcm_ctx, kcm_cert_data, kcm_cert_data_size);
00613     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed writing kcm chain file");
00614 
00615     kcm_status = storage_file_close(&chain_context->current_kcm_ctx);
00616     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed closing kcm chain file");
00617 
00618     // file written, increase current_cert_index
00619     chain_context->current_cert_index++;
00620 
00621 
00622 Exit:
00623     if (kcm_status != KCM_STATUS_SUCCESS) {
00624         if (chain_context->current_cert_index > 0) {
00625             storage_file_close(&chain_context->current_kcm_ctx);
00626         }
00627     }
00628 
00629 Clean_X509:
00630     cs_close_handle_x509_cert(&cert);
00631     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00632     return kcm_status;
00633 }
00634 
00635 
00636 kcm_status_e  kcm_cert_chain_delete(const uint8_t *kcm_chain_name, size_t kcm_chain_name_len)
00637 {
00638     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00639     kcm_status_e  first_status_err = KCM_STATUS_SUCCESS;
00640     kcm_cert_chain_handle kcm_chain_handle;
00641     kcm_cert_chain_context_int_s *chain_context;
00642     size_t kcm_chain_len = 0;
00643     uint8_t *kcm_complete_name = NULL; // Filename including prefix
00644     size_t kcm_complete_name_size;
00645     kcm_ctx_s kcm_ctx;
00646 
00647     // Validate function parameters
00648     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_chain_name");
00649     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_chain_name_len");
00650     SA_PV_LOG_INFO_FUNC_ENTER("chain name =  %.*s", (int)kcm_chain_name_len, kcm_chain_name);
00651 
00652     // Check if KCM initialized, if not initialize it
00653     if (!kcm_initialized) {
00654         kcm_status = kcm_init();
00655         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00656     }
00657 
00658     // open the first file and read the kcm_chain_len from meta data
00659     kcm_status = kcm_cert_chain_open(&kcm_chain_handle, kcm_chain_name, kcm_chain_name_len, &kcm_chain_len);
00660     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00661         return kcm_status;
00662     } else if (kcm_status != KCM_STATUS_SUCCESS) {
00663         kcm_status = kcm_create_complete_name(kcm_chain_name, kcm_chain_name_len, KCM_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size);
00664         if (kcm_status == KCM_STATUS_SUCCESS) {
00665             kcm_status = storage_file_delete(&kcm_ctx, kcm_complete_name, kcm_complete_name_size);
00666             fcc_free(kcm_complete_name);
00667         }
00668         first_status_err = kcm_status;
00669         goto Exit;
00670     }
00671 
00672     chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
00673 
00674     if (kcm_status == KCM_STATUS_SUCCESS) {
00675         // close the file before calling delete
00676         storage_file_close(&chain_context->current_kcm_ctx);
00677     }
00678 
00679     for (; chain_context->current_cert_index < kcm_chain_len; chain_context->current_cert_index++) {
00680         kcm_cert_chain_update_name_prefix(chain_context->chain_name, chain_context->current_cert_index);
00681         kcm_status = storage_file_delete(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len);
00682         // if there was an error, return the first one that occur
00683         if (kcm_status != KCM_STATUS_SUCCESS && first_status_err == KCM_STATUS_SUCCESS) {
00684             first_status_err = kcm_status;
00685         }
00686     }
00687 
00688     // close the chain to release the context
00689     kcm_cert_chain_close(kcm_chain_handle);
00690 
00691 Exit:
00692     SA_PV_ERR_RECOVERABLE_RETURN_IF((first_status_err != KCM_STATUS_SUCCESS), first_status_err, "Delete chain but with errors");
00693 
00694     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00695 
00696     return first_status_err;
00697 }
00698 
00699 
00700 kcm_status_e  kcm_cert_chain_get_next_size(kcm_cert_chain_handle kcm_chain_handle, size_t *kcm_cert_data_size)
00701 {
00702     kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
00703     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00704 
00705     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00706 
00707     // Check if KCM initialized, if not initialize it
00708     if (!kcm_initialized) {
00709         kcm_status = kcm_init();
00710         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00711     }
00712 
00713     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle");
00714     SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain");
00715     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data_size");
00716     SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_OPEN), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type");
00717     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");
00718 
00719     if (chain_context->current_cert_index > 0) {
00720         // only on the first certificate, the file is open
00721         // update file name by changing last char suffix and open the file
00722         kcm_cert_chain_update_name_prefix(chain_context->chain_name, chain_context->current_cert_index);
00723         kcm_status = storage_file_open(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len);
00724         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed opening kcm chain file");
00725     }
00726 
00727     kcm_status = storage_file_size_get_with_ctx(&chain_context->current_kcm_ctx, kcm_cert_data_size);
00728     if (kcm_status != KCM_STATUS_SUCCESS) {
00729         if (chain_context->current_cert_index > 0) {
00730             // close the file only if was open in that function
00731             storage_file_close(&chain_context->current_kcm_ctx);
00732         }
00733         SA_PV_ERR_RECOVERABLE_RETURN(kcm_status, "Failed getting kcm chain file size");
00734     }
00735 
00736     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00737 
00738     return kcm_status;
00739 }
00740 
00741 
00742 kcm_status_e  kcm_cert_chain_get_next_data(kcm_cert_chain_handle kcm_chain_handle, uint8_t *kcm_cert_data, size_t kcm_max_cert_data_size, size_t *kcm_actual_cert_data_size)
00743 {
00744     kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
00745     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00746     size_t expected_data_size = 0;
00747 
00748     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00749 
00750     // Check if KCM initialized, if not initialize it
00751     if (!kcm_initialized) {
00752         kcm_status = kcm_init();
00753         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00754     }
00755 
00756     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle");
00757     SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain");
00758     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data");
00759     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_max_cert_data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_max_cert_data_size");
00760     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_actual_cert_data_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_actual_cert_data_size");
00761     SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_OPEN), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type");
00762     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");
00763 
00764     if (chain_context->current_kcm_ctx.is_file_size_checked == false) {
00765         // if user skip call to kcm_cert_chain_get_next_size
00766         kcm_status = kcm_cert_chain_get_next_size((kcm_cert_chain_handle*)chain_context, &expected_data_size);
00767         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed getting kcm chain file size");
00768     } else {
00769         expected_data_size = chain_context->current_kcm_ctx.file_size;
00770     }
00771     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_max_cert_data_size < expected_data_size), KCM_STATUS_INSUFFICIENT_BUFFER, "Certificate data buffer too small");
00772 
00773     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);
00774     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed read kcm chain file");
00775 
00776     kcm_status = storage_file_close(&chain_context->current_kcm_ctx);
00777     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed closing kcm chain file");
00778 
00779     // file read, increase current_cert_index
00780     chain_context->current_cert_index++;
00781 
00782     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00783 
00784     return kcm_status;
00785 
00786 }
00787 
00788 
00789 kcm_status_e  kcm_cert_chain_close(kcm_cert_chain_handle kcm_chain_handle)
00790 {
00791     kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
00792     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00793 
00794     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00795 
00796     if (kcm_chain_handle == NULL) {
00797         goto Exit; // and return KCM_STATUS_SUCCESS
00798     }
00799 
00800     SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain");
00801 
00802     if (chain_context->current_cert_index == 0 ||
00803         (chain_context->operation_type == KCM_CHAIN_OP_TYPE_OPEN &&
00804         chain_context->current_cert_index < chain_context->num_of_certificates_in_chain &&
00805         chain_context->current_kcm_ctx.is_file_size_checked)) {
00806         // close open file (after create/open or between get_next_size to get_next_data)
00807         // if is_file_size_checked is true, the file had open before
00808         kcm_status = storage_file_close(&chain_context->current_kcm_ctx);
00809         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed closing kcm chain file");
00810     }
00811 
00812     if (chain_context->operation_type == KCM_CHAIN_OP_TYPE_CREATE &&
00813         chain_context->current_cert_index < chain_context->num_of_certificates_in_chain) {
00814         // user added less certificates than num_of_certificates_in_chain, delete all and return error
00815         kcm_cert_chain_files_delete(chain_context);
00816         SA_PV_ERR_RECOVERABLE_GOTO_IF(true, (kcm_status = KCM_STATUS_CLOSE_INCOMPLETE_CHAIN), Exit, "Closing incomplete kcm chain");
00817     }
00818 
00819 Exit:
00820     if (chain_context != NULL) {
00821         fcc_free(chain_context->chain_name);
00822         fcc_free(chain_context);
00823     }
00824 
00825     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00826 
00827     return kcm_status;
00828 
00829 }
00830 
00831 
00832 kcm_status_e  kcm_key_pair_generate_and_store(
00833     const kcm_crypto_key_scheme_e    key_scheme,
00834     const uint8_t                    *private_key_name,
00835     size_t                            private_key_name_len,
00836     const uint8_t                    *public_key_name,
00837     size_t                            public_key_name_len,
00838     bool                              kcm_item_is_factory,
00839     const kcm_security_desc_s        *kcm_params)
00840 
00841 {
00842     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00843     size_t actual_kcm_priv_key_size = 0;
00844     size_t actual_kcm_pub_key_size = 0;
00845     uint8_t priv_key_buffer[KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE];
00846     uint8_t pub_key_buffer[KCM_EC_SECP256R1_MAX_PUB_KEY_DER_SIZE];
00847     bool pub_key_exists = false;
00848 
00849     // Check if KCM initialized, if not initialize it
00850     if (!kcm_initialized) {
00851         kcm_status = kcm_init();
00852         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00853     }
00854 
00855     //temporary check that kcm_params is NULL                                                                                                   
00856     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_params != NULL), KCM_STATUS_INVALID_PARAMETER, "kcm_params is not NULL!");
00857 
00858     //check input params
00859     SA_PV_ERR_RECOVERABLE_RETURN_IF((key_scheme != KCM_SCHEME_EC_SECP256R1), KCM_STATUS_INVALID_PARAMETER, "Invalid key_scheme");
00860     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name");
00861     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name_len");
00862     SA_PV_ERR_RECOVERABLE_RETURN_IF(((public_key_name != NULL) && (public_key_name_len == 0)), KCM_STATUS_INVALID_PARAMETER, "public_key_name is not NULL, but its size is 0");
00863     SA_PV_ERR_RECOVERABLE_RETURN_IF(((public_key_name == NULL) && (public_key_name_len != 0)), KCM_STATUS_INVALID_PARAMETER, "public_key_name is NULL, but its size is not 0");
00864 
00865     SA_PV_LOG_INFO_FUNC_ENTER("priv_key_name = %.*s priv_key_len = %" PRIu32 ", pub_key_name = %.*s pub_key_len = %" PRIu32,
00866         (int)private_key_name_len, (char*)private_key_name, (uint32_t)private_key_name_len, (int)public_key_name_len, (char*)public_key_name, (uint32_t)public_key_name_len);
00867 
00868     pub_key_exists = ((public_key_name != NULL) && (public_key_name_len != 0));
00869 
00870     //check private key existence
00871     kcm_status = kcm_item_get_data_size(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM,
00872                                         &actual_kcm_priv_key_size);
00873     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "private key already exists");
00874     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check private key existence");
00875 
00876     //fetch public key if exists
00877     if (pub_key_exists) {
00878         kcm_status = kcm_item_get_data_size(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM,
00879                                             &actual_kcm_pub_key_size);
00880         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "public key already exists");
00881         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check public key existence");
00882     }
00883 
00884     //generate key pair
00885     kcm_status = cs_key_pair_generate(key_scheme, priv_key_buffer, sizeof(priv_key_buffer), &actual_kcm_priv_key_size, pub_key_buffer, sizeof(pub_key_buffer), &actual_kcm_pub_key_size);
00886     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to generate key pair");
00887 
00888     //store private key
00889     kcm_status = kcm_item_store(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM, kcm_item_is_factory, priv_key_buffer, actual_kcm_priv_key_size, NULL);
00890     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store private key");
00891 
00892     //store public key if exists
00893     if (pub_key_exists) {
00894         kcm_status = kcm_item_store(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM, kcm_item_is_factory, pub_key_buffer, actual_kcm_pub_key_size, NULL);
00895         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store public key");
00896     }
00897 
00898     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00899 
00900     return kcm_status;
00901 }
00902 
00903 
00904 kcm_status_e  kcm_csr_generate(
00905     const uint8_t            *private_key_name,
00906     size_t                   private_key_name_len,
00907     const kcm_csr_params_s   *csr_params,
00908     uint8_t                  *csr_buff_out,
00909     size_t                   csr_buff_max_size,
00910     size_t                   *csr_buff_act_size)
00911 {
00912 
00913     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00914     size_t prv_key_size, actual_prv_key_size = 0;
00915     uint8_t priv_key_buffer[KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE];
00916 
00917     // Check if KCM initialized, if not initialize it
00918     if (!kcm_initialized) {
00919         kcm_status = kcm_init();
00920         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00921     }
00922 
00923     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name");
00924     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name_len");
00925     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_params");
00926     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->subject == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid subject name");
00927     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->md_type == KCM_MD_NONE), KCM_STATUS_INVALID_PARAMETER, "Invalid md type");
00928     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_out");
00929     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_max_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_max_size");
00930     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_act_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_act_size");
00931 
00932     SA_PV_LOG_INFO_FUNC_ENTER("priv_key_name = %.*s priv_key_len = %" PRIu32", csr_buff_max_size = %" PRIu32,
00933         (int)private_key_name_len, (char*)private_key_name, (uint32_t)private_key_name_len, (uint32_t)csr_buff_max_size);
00934 
00935     //fetch private key size
00936     kcm_status = kcm_item_get_data_size(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM,
00937                                         &prv_key_size);
00938     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to get private key data size");
00939     SA_PV_ERR_RECOVERABLE_RETURN_IF((prv_key_size == 0), kcm_status, "Size of private key is 0");
00940 
00941     //fetch private key
00942     kcm_status = kcm_item_get_data(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM, priv_key_buffer,
00943                                    prv_key_size, &actual_prv_key_size);
00944     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to get private key");
00945     SA_PV_ERR_RECOVERABLE_RETURN_IF((actual_prv_key_size == 0), kcm_status = KCM_STATUS_ITEM_IS_EMPTY, "Size of private key is 0");
00946 
00947     //generate csr
00948     kcm_status = cs_csr_generate(priv_key_buffer, actual_prv_key_size, csr_params, csr_buff_out, csr_buff_max_size, csr_buff_act_size);
00949     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to generate CSR");
00950 
00951     SA_PV_LOG_INFO_FUNC_EXIT("csr_buff_act_size = %" PRIu32 "", (uint32_t)*csr_buff_act_size);
00952 
00953     return kcm_status;
00954 
00955 }
00956 
00957 
00958 kcm_status_e  kcm_generate_keys_and_csr(
00959     kcm_crypto_key_scheme_e   key_scheme,
00960     const uint8_t             *private_key_name,
00961     size_t                    private_key_name_len,
00962     const uint8_t             *public_key_name,
00963     size_t                    public_key_name_len,
00964     bool                      kcm_item_is_factory,
00965     const kcm_csr_params_s    *csr_params,
00966     uint8_t                   *csr_buff_out,
00967     size_t                    csr_buff_max_size,
00968     size_t                    *csr_buff_act_size_out,
00969     const kcm_security_desc_s *kcm_params)
00970 {
00971 
00972     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00973     size_t actual_kcm_key_size = 0;
00974     size_t priv_key_act_size_out = 0;
00975     size_t pub_key_act_size_out = 0;
00976     uint8_t priv_key_buffer[KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE];
00977     uint8_t pub_key_buffer[KCM_EC_SECP256R1_MAX_PUB_KEY_DER_SIZE];
00978     bool pub_key_exists = false;
00979 
00980     // Check if KCM initialized, if not initialize it
00981     if (!kcm_initialized) {
00982         kcm_status = kcm_init();
00983         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00984     }
00985 
00986     //temporary check that kcm_params is NULL                                                                                                   
00987     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_params != NULL), KCM_STATUS_INVALID_PARAMETER, "kcm_params is not NULL!");
00988 
00989     //check input params
00990     SA_PV_ERR_RECOVERABLE_RETURN_IF((key_scheme != KCM_SCHEME_EC_SECP256R1), KCM_STATUS_INVALID_PARAMETER, "Invalid key_scheme");
00991     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name");
00992     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name_len");
00993     SA_PV_ERR_RECOVERABLE_RETURN_IF(((public_key_name != NULL) && (public_key_name_len == 0)), KCM_STATUS_INVALID_PARAMETER, "public_key_name is not NULL, but its size is 0");
00994     SA_PV_ERR_RECOVERABLE_RETURN_IF(((public_key_name == NULL) && (public_key_name_len != 0)), KCM_STATUS_INVALID_PARAMETER, "public_key_name is NULL, but its size is not 0");
00995     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_params");
00996     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->subject == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid subject name");
00997     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->md_type == KCM_MD_NONE), KCM_STATUS_INVALID_PARAMETER, "Invalid md type");
00998     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_out");
00999     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_max_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_max_size");
01000     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_act_size");
01001 
01002     SA_PV_LOG_INFO_FUNC_ENTER("priv_key_name = %.*s priv_key_len = %" PRIu32 ", pub_key_name = %.*s pub_key_len = %" PRIu32,
01003         (int)private_key_name_len, (char*)private_key_name, (uint32_t)private_key_name_len, (int)public_key_name_len, (char*)public_key_name, (uint32_t)public_key_name_len);
01004 
01005     pub_key_exists = ((public_key_name != NULL) && (public_key_name_len != 0));
01006 
01007     //check private key existence
01008     kcm_status = kcm_item_get_data_size(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM,
01009                                         &actual_kcm_key_size);
01010     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "private key already exists");
01011     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check private key existence");
01012 
01013     //check public key existence
01014     if (pub_key_exists) {
01015         kcm_status = kcm_item_get_data_size(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM,
01016                                             &actual_kcm_key_size);
01017         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "public key already exists");
01018         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check public key existence");
01019     }
01020 
01021     //generat keys and csr
01022     kcm_status = cs_generate_keys_and_csr(key_scheme, csr_params, priv_key_buffer, sizeof(priv_key_buffer), &priv_key_act_size_out, pub_key_buffer, sizeof(pub_key_buffer), &pub_key_act_size_out, csr_buff_out, csr_buff_max_size, csr_buff_act_size_out);
01023     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to generate keys and csr");
01024 
01025     //store private key
01026     kcm_status = kcm_item_store(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM, kcm_item_is_factory, priv_key_buffer, sizeof(priv_key_buffer), NULL);
01027     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store private key");
01028 
01029     //store public key
01030     if (pub_key_exists) {
01031         kcm_status = kcm_item_store(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM, kcm_item_is_factory, pub_key_buffer, sizeof(pub_key_buffer), NULL);
01032         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store public key");
01033     }
01034 
01035 
01036     SA_PV_LOG_INFO_FUNC_EXIT("csr_buff_act_size_out = %" PRIu32 "", (uint32_t)*csr_buff_act_size_out);
01037     return kcm_status;
01038 
01039 }
01040 
01041 kcm_status_e  kcm_certificate_verify_with_private_key(
01042     const uint8_t * kcm_cert_data,
01043     size_t kcm_cert_data_size,
01044     const uint8_t * kcm_priv_key_name,
01045     size_t kcm_priv_key_name_len)
01046 {
01047 
01048     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
01049     size_t priv_key_data_size = 0;
01050     uint8_t *priv_key_data = NULL;
01051     size_t act_priv_key_data_size = 0;
01052     palX509Handle_t x509_cert;
01053 
01054     // Check if KCM initialized, if not initialize it
01055     if (!kcm_initialized) {
01056         kcm_status = kcm_init();
01057         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
01058     }
01059 
01060     //check input params
01061     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data");
01062     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data_size");
01063     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_priv_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_priv_key_name");
01064     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_priv_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_priv_key_name_len");
01065     SA_PV_LOG_INFO_FUNC_ENTER("priv key name =  %.*s, cert size=%" PRIu32 "", (int)kcm_priv_key_name_len, (char*)kcm_priv_key_name,(uint32_t)kcm_cert_data_size);
01066 
01067     //Get private key size
01068     kcm_status = kcm_item_get_data_size(kcm_priv_key_name,
01069         kcm_priv_key_name_len,
01070         KCM_PRIVATE_KEY_ITEM,
01071         &priv_key_data_size);
01072     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS || priv_key_data_size == 0), kcm_status, "Failed to get kcm private key size");
01073 
01074     //Allocate memory and get private key data
01075     priv_key_data = fcc_malloc(priv_key_data_size);
01076     SA_PV_ERR_RECOVERABLE_RETURN_IF((priv_key_data == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, "Failed to allocate buffer for private key data");
01077 
01078     //Get private key data
01079     kcm_status = kcm_item_get_data(kcm_priv_key_name,
01080         kcm_priv_key_name_len,
01081         KCM_PRIVATE_KEY_ITEM,
01082         priv_key_data,
01083         priv_key_data_size,
01084         &act_priv_key_data_size);
01085     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS || act_priv_key_data_size != priv_key_data_size), (kcm_status = kcm_status), Exit, "Failed to get private key data");
01086 
01087     //Create certificate handle
01088     kcm_status = cs_create_handle_from_der_x509_cert(kcm_cert_data, kcm_cert_data_size, &x509_cert);
01089     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed to create certificate handle");
01090 
01091     //Check current certificate against given private key
01092     kcm_status = cs_check_certifcate_public_key(x509_cert, priv_key_data, priv_key_data_size);
01093     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = KCM_STATUS_SELF_GENERATED_CERTIFICATE_VERIFICATION_ERROR), Exit, "Certificate verification failed against private key");
01094 
01095     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
01096 Exit:
01097 
01098     fcc_free(priv_key_data);
01099     cs_close_handle_x509_cert(&x509_cert);
01100     return kcm_status;
01101 
01102 }
01103 
01104