Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
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
Generated on Tue Jul 12 2022 19:12:12 by 1.7.2