leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
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 #ifndef MBED_CONF_MBED_CLOUD_CLIENT_DISABLE_CERTIFICATE_ENROLLMENT
00026 #include "certificate_enrollment.h"
00027 #endif  // MBED_CONF_MBED_CLOUD_CLIENT_DISABLE_CERTIFICATE_ENROLLMENT
00028 
00029 
00030 bool g_kcm_initialized = false;
00031 
00032 kcm_status_e  kcm_init(void)
00033 {
00034     kcm_status_e  status = KCM_STATUS_SUCCESS;
00035 
00036     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00037 
00038     if (!g_kcm_initialized) {
00039         palStatus_t pal_status;
00040 
00041         //Initialize PAL
00042         pal_status = pal_init();
00043         SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), KCM_STATUS_ERROR, "Failed initializing PAL (%" PRIu32 ")", pal_status);
00044 
00045         /*
00046          * Do not initialize the time module inside pal_init since pal_initTime() uses storage functions.
00047          * At KCM init it is guaranteed that any entropy and RoT that should be injected - is already injected.
00048          */
00049         pal_status = pal_initTime();
00050         SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), KCM_STATUS_ERROR, "Failed PAL time module (%" PRIu32 ")", pal_status);
00051 
00052         //Initialize back-end storage
00053         status = storage_init();
00054         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "Failed initializing storage\n");
00055         // Mark as "initialized"
00056         g_kcm_initialized = true;
00057 
00058 #ifndef MBED_CONF_MBED_CLOUD_CLIENT_DISABLE_CERTIFICATE_ENROLLMENT
00059         //Check status of renewal process and restore backup items if needed
00060         ce_check_and_restore_backup_status();
00061 #endif // MBED_CONF_MBED_CLOUD_CLIENT_DISABLE_CERTIFICATE_ENROLLMENT
00062     }
00063 
00064     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00065 
00066     return status;
00067 }
00068 
00069 kcm_status_e  kcm_finalize(void)
00070 {
00071     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00072 
00073     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00074 
00075     if (g_kcm_initialized) {
00076 
00077         kcm_status = storage_finalize();
00078         if (kcm_status != KCM_STATUS_SUCCESS) {
00079             SA_PV_LOG_ERR("Failed finalizing storage\n");
00080         }
00081 
00082         //Finalize PAL
00083         pal_destroy();
00084 
00085         // Mark as "not initialized"
00086         g_kcm_initialized = false;
00087     }
00088 
00089     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00090 
00091     return kcm_status;
00092 }
00093 
00094 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)
00095 {
00096     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00097 
00098     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00099 
00100     // Check if KCM initialized, if not initialize it
00101     if (!g_kcm_initialized) {
00102         kcm_status = kcm_init();
00103         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00104     }
00105 
00106     // Validate function parameters
00107     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");
00108 
00109     //temporary check that security descriptor is NULL
00110     SA_PV_ERR_RECOVERABLE_RETURN_IF((security_desc != NULL), KCM_STATUS_INVALID_PARAMETER, "Security descriptor is not NULL!");
00111     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!");
00112 
00113     switch (kcm_item_type) {
00114         case KCM_PRIVATE_KEY_ITEM:
00115             kcm_status = cs_der_priv_key_verify(kcm_item_data, kcm_item_data_size);
00116             SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Private key validation failed");
00117             break;
00118         case KCM_PUBLIC_KEY_ITEM:
00119             kcm_status = cs_der_public_key_verify(kcm_item_data, kcm_item_data_size);
00120             SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Public key validation failed");
00121             break;
00122         case KCM_SYMMETRIC_KEY_ITEM:
00123             //currently possible to write a symmetric key of size 0 since we do not check format
00124             break;
00125         case KCM_CERTIFICATE_ITEM:
00126             kcm_status = cs_check_der_x509_format(kcm_item_data, kcm_item_data_size);
00127             SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Certificate validation failed");
00128             break;
00129         case KCM_CONFIG_ITEM:
00130             break;
00131         default:
00132             SA_PV_ERR_RECOVERABLE_RETURN_IF((true), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
00133     }
00134 
00135     kcm_status = storage_data_write(kcm_item_name, kcm_item_name_len, kcm_item_type, kcm_item_is_factory, KCM_ORIGINAL_ITEM, kcm_item_data, kcm_item_data_size);
00136     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_data_write");
00137 
00138     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00139     return kcm_status;
00140 }
00141 
00142 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)
00143 {
00144     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00145 
00146     kcm_status = storage_data_size_read(kcm_item_name, kcm_item_name_len, kcm_item_type, KCM_ORIGINAL_ITEM, kcm_item_data_size_out);
00147     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00148         return kcm_status;
00149     }
00150     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_data_size_read");
00151 
00152     return kcm_status;
00153 }
00154 
00155 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)
00156 {
00157     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00158 
00159     kcm_status =  storage_data_read(kcm_item_name, kcm_item_name_len, kcm_item_type, KCM_ORIGINAL_ITEM, kcm_item_data_out, kcm_item_data_max_size, kcm_item_data_act_size_out);
00160     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00161         return kcm_status;
00162     }
00163     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_data_read");
00164 
00165     return kcm_status;
00166 }
00167 
00168 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)
00169 {
00170     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00171 
00172     kcm_status = storage_data_delete(kcm_item_name, kcm_item_name_len, kcm_item_type, KCM_ORIGINAL_ITEM);
00173     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_data_delete");
00174 
00175     return kcm_status;
00176 }
00177 
00178 kcm_status_e  kcm_factory_reset(void)
00179 {
00180     kcm_status_e  status = KCM_STATUS_SUCCESS;
00181 
00182     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00183 
00184     // Check if KCM initialized, if not initialize it
00185     if (!g_kcm_initialized) {
00186         status = kcm_init();
00187         SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "KCM initialization failed\n");
00188     }
00189 
00190     status = storage_factory_reset();
00191     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed perform factory reset");
00192 
00193 Exit:
00194     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00195     return status;
00196 }
00197 
00198 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)
00199 {
00200     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00201 
00202     //Call internal storage_cert_chain_create
00203     kcm_status = storage_cert_chain_create(kcm_chain_handle, kcm_chain_name, kcm_chain_name_len, kcm_chain_len, kcm_chain_is_factory, KCM_ORIGINAL_ITEM);
00204     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_cert_chain_create");
00205 
00206     return kcm_status;
00207 }
00208 
00209 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)
00210 {
00211     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00212 
00213     //Call internal storage_cert_chain_open
00214     kcm_status = storage_cert_chain_open(kcm_chain_handle, kcm_chain_name, kcm_chain_name_len, KCM_ORIGINAL_ITEM, kcm_chain_len_out);
00215     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00216         return kcm_status;
00217     }
00218     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_cert_chain_open");
00219 
00220     return kcm_status;
00221 }
00222 /*
00223 * If not first certificate in chain:
00224 *     1. Validate previously added certificate with the public key inside kcm_cert_data
00225 *     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.
00226 *     3. Store the current certificate
00227 *     4. Update the index of the chain handle iterator for next use of this function
00228 * If is first certificate in chain:
00229 *    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
00230 */
00231 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)
00232 {
00233     kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
00234     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00235     palX509Handle_t cert;
00236 
00237     SA_PV_LOG_INFO_FUNC_ENTER("cert_data_size =%" PRIu32 "", (uint32_t)kcm_cert_data_size);
00238 
00239     // Check if KCM initialized, if not initialize it
00240     if (!g_kcm_initialized) {
00241         kcm_status = kcm_init();
00242         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00243     }
00244 
00245     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle");
00246     SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm context");
00247     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");
00248     SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_CREATE), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type");
00249     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");
00250 
00251     // Parse the X509 and make sure it is of correct structure
00252     kcm_status = cs_create_handle_from_der_x509_cert(kcm_cert_data, kcm_cert_data_size, &cert);
00253     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to parsing cert");
00254 
00255     if (chain_context->current_cert_index > 0) {
00256         // If not first certificate - validate based on params of previous certificate
00257         kcm_status = cs_x509_cert_verify_signature(cert, chain_context->prev_cert_params.htbs,
00258                                                    chain_context->prev_cert_params.htbs_actual_size,
00259                                                    chain_context->prev_cert_params.signature,
00260                                                    chain_context->prev_cert_params.signature_actual_size);
00261         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");
00262         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Clean_X509, "Failed verifying child signature");
00263     }
00264 
00265     // Save params only if certificate is not last in chain 
00266     if(chain_context->current_cert_index < chain_context->num_of_certificates_in_chain - 1) {
00267         // Get params needed for validation by the signer
00268         // These will be used to validate this certificate in the chain when parsing the next one
00269         kcm_status = cs_child_cert_params_get(cert, &chain_context->prev_cert_params);
00270         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Clean_X509, "Failed to retrieve child cert params");
00271     }
00272 
00273     //Call internal storage_chain_add_next
00274     kcm_status = storage_chain_add_next(kcm_chain_handle, kcm_cert_data, kcm_cert_data_size, KCM_ORIGINAL_ITEM);
00275     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Clean_X509, "Failed in storage_chain_add_next");
00276 
00277 Clean_X509:
00278     cs_close_handle_x509_cert(&cert);
00279     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00280     return kcm_status;
00281 }
00282 
00283 
00284 kcm_status_e  kcm_cert_chain_delete(const uint8_t *kcm_chain_name, size_t kcm_chain_name_len)
00285 {
00286     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00287 
00288     //Call internal storage_cert_chain_delete
00289     kcm_status = storage_cert_chain_delete(kcm_chain_name, kcm_chain_name_len, KCM_ORIGINAL_ITEM);
00290     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_cert_chain_delete");
00291 
00292     return kcm_status;
00293 }
00294 
00295 
00296 kcm_status_e  kcm_cert_chain_get_next_size(kcm_cert_chain_handle kcm_chain_handle, size_t *kcm_cert_data_size)
00297 {
00298     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00299 
00300     //Call internal storage_cert_chain_get_next_size
00301     kcm_status = storage_cert_chain_get_next_size(kcm_chain_handle, KCM_ORIGINAL_ITEM, kcm_cert_data_size );
00302     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_cert_chain_get_next_size");
00303 
00304     return kcm_status;
00305 }
00306 
00307 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)
00308 {
00309     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00310 
00311     //Call internal storage_cert_chain_get_next_data
00312     kcm_status = storage_cert_chain_get_next_data(kcm_chain_handle, kcm_cert_data, kcm_max_cert_data_size, KCM_ORIGINAL_ITEM, kcm_actual_cert_data_size);
00313     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_cert_chain_get_next_data");
00314 
00315     return kcm_status;
00316 }
00317 
00318 
00319 kcm_status_e  kcm_cert_chain_close(kcm_cert_chain_handle kcm_chain_handle)
00320 {
00321 
00322     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00323 
00324     //Call internal storage_cert_chain_close
00325     kcm_status = storage_cert_chain_close(kcm_chain_handle, KCM_ORIGINAL_ITEM);
00326     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during storage_cert_chain_close")
00327 
00328     return kcm_status;
00329 }
00330 
00331 kcm_status_e  kcm_key_pair_generate_and_store(
00332     const kcm_crypto_key_scheme_e    key_scheme,
00333     const uint8_t                    *private_key_name,
00334     size_t                            private_key_name_len,
00335     const uint8_t                    *public_key_name,
00336     size_t                            public_key_name_len,
00337     bool                              kcm_item_is_factory,
00338     const kcm_security_desc_s        *kcm_params)
00339 
00340 {
00341     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00342     size_t actual_kcm_priv_key_size = 0;
00343     size_t actual_kcm_pub_key_size = 0;
00344     uint8_t priv_key_buffer[KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE];
00345     uint8_t pub_key_buffer[KCM_EC_SECP256R1_MAX_PUB_KEY_DER_SIZE];
00346     bool pub_key_exists = false;
00347 
00348     // Check if KCM initialized, if not initialize it
00349     if (!g_kcm_initialized) {
00350         kcm_status = kcm_init();
00351         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00352     }
00353 
00354     //temporary check that kcm_params is NULL                                                                                                   
00355     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_params != NULL), KCM_STATUS_INVALID_PARAMETER, "kcm_params is not NULL!");
00356 
00357     //check input params
00358     SA_PV_ERR_RECOVERABLE_RETURN_IF((key_scheme != KCM_SCHEME_EC_SECP256R1), KCM_STATUS_INVALID_PARAMETER, "Invalid key_scheme");
00359     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name");
00360     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name_len");
00361     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");
00362     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");
00363 
00364     SA_PV_LOG_INFO_FUNC_ENTER("priv_key_name = %.*s priv_key_len = %" PRIu32 ", pub_key_name = %.*s pub_key_len = %" PRIu32,
00365         (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);
00366 
00367     pub_key_exists = ((public_key_name != NULL) && (public_key_name_len != 0));
00368 
00369     //check private key existence
00370     kcm_status = kcm_item_get_data_size(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM,
00371                                         &actual_kcm_priv_key_size);
00372     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "private key already exists");
00373     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check private key existence");
00374 
00375     //fetch public key if exists
00376     if (pub_key_exists) {
00377         kcm_status = kcm_item_get_data_size(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM,
00378                                             &actual_kcm_pub_key_size);
00379         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "public key already exists");
00380         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check public key existence");
00381     }
00382 
00383     //generate key pair
00384     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);
00385     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to generate key pair");
00386 
00387     //store private key
00388     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);
00389     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store private key");
00390 
00391     //store public key if exists
00392     if (pub_key_exists) {
00393         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);
00394         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store public key");
00395     }
00396 
00397     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00398 
00399     return kcm_status;
00400 }
00401 
00402 
00403 kcm_status_e  kcm_csr_generate(
00404     const uint8_t            *private_key_name,
00405     size_t                   private_key_name_len,
00406     const kcm_csr_params_s   *csr_params,
00407     uint8_t                  *csr_buff_out,
00408     size_t                   csr_buff_max_size,
00409     size_t                   *csr_buff_act_size)
00410 {
00411 
00412     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00413     size_t prv_key_size, actual_prv_key_size = 0;
00414     uint8_t priv_key_buffer[KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE];
00415 
00416     // Check if KCM initialized, if not initialize it
00417     if (!g_kcm_initialized) {
00418         kcm_status = kcm_init();
00419         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00420     }
00421 
00422     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name");
00423     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name_len");
00424     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_params");
00425     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->subject == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid subject name");
00426     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->md_type == KCM_MD_NONE), KCM_STATUS_INVALID_PARAMETER, "Invalid md type");
00427     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_out");
00428     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_max_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_max_size");
00429     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_act_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_act_size");
00430 
00431     SA_PV_LOG_INFO_FUNC_ENTER("priv_key_name = %.*s priv_key_len = %" PRIu32", csr_buff_max_size = %" PRIu32,
00432         (int)private_key_name_len, (char*)private_key_name, (uint32_t)private_key_name_len, (uint32_t)csr_buff_max_size);
00433 
00434     //fetch private key size
00435     kcm_status = kcm_item_get_data_size(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM,
00436                                         &prv_key_size);
00437     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to get private key data size");
00438     SA_PV_ERR_RECOVERABLE_RETURN_IF((prv_key_size == 0), kcm_status, "Size of private key is 0");
00439 
00440     //fetch private key
00441     kcm_status = kcm_item_get_data(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM, priv_key_buffer,
00442                                    prv_key_size, &actual_prv_key_size);
00443     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to get private key");
00444     SA_PV_ERR_RECOVERABLE_RETURN_IF((actual_prv_key_size == 0), kcm_status = KCM_STATUS_ITEM_IS_EMPTY, "Size of private key is 0");
00445 
00446     //generate csr
00447     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);
00448     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to generate CSR");
00449 
00450     SA_PV_LOG_INFO_FUNC_EXIT("csr_buff_act_size = %" PRIu32 "", (uint32_t)*csr_buff_act_size);
00451 
00452     return kcm_status;
00453 
00454 }
00455 
00456 
00457 kcm_status_e  kcm_generate_keys_and_csr(
00458     kcm_crypto_key_scheme_e   key_scheme,
00459     const uint8_t             *private_key_name,
00460     size_t                    private_key_name_len,
00461     const uint8_t             *public_key_name,
00462     size_t                    public_key_name_len,
00463     bool                      kcm_item_is_factory,
00464     const kcm_csr_params_s    *csr_params,
00465     uint8_t                   *csr_buff_out,
00466     size_t                    csr_buff_max_size,
00467     size_t                    *csr_buff_act_size_out,
00468     const kcm_security_desc_s *kcm_params)
00469 {
00470 
00471     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00472     size_t actual_kcm_key_size = 0;
00473     size_t priv_key_act_size_out = 0;
00474     size_t pub_key_act_size_out = 0;
00475     uint8_t priv_key_buffer[KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE];
00476     uint8_t pub_key_buffer[KCM_EC_SECP256R1_MAX_PUB_KEY_DER_SIZE];
00477     bool pub_key_exists = false;
00478 
00479     // Check if KCM initialized, if not initialize it
00480     if (!g_kcm_initialized) {
00481         kcm_status = kcm_init();
00482         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00483     }
00484 
00485     //temporary check that kcm_params is NULL                                                                                                   
00486     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_params != NULL), KCM_STATUS_INVALID_PARAMETER, "kcm_params is not NULL!");
00487 
00488     //check input params
00489     SA_PV_ERR_RECOVERABLE_RETURN_IF((key_scheme != KCM_SCHEME_EC_SECP256R1), KCM_STATUS_INVALID_PARAMETER, "Invalid key_scheme");
00490     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name");
00491     SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name_len");
00492     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");
00493     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");
00494     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_params");
00495     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->subject == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid subject name");
00496     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->md_type == KCM_MD_NONE), KCM_STATUS_INVALID_PARAMETER, "Invalid md type");
00497     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_out");
00498     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_max_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_max_size");
00499     SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_act_size");
00500 
00501     SA_PV_LOG_INFO_FUNC_ENTER("priv_key_name = %.*s priv_key_len = %" PRIu32 ", pub_key_name = %.*s pub_key_len = %" PRIu32,
00502         (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);
00503 
00504     pub_key_exists = ((public_key_name != NULL) && (public_key_name_len != 0));
00505 
00506     //check private key existence
00507     kcm_status = kcm_item_get_data_size(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM,
00508                                         &actual_kcm_key_size);
00509     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "private key already exists");
00510     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check private key existence");
00511 
00512     //check public key existence
00513     if (pub_key_exists) {
00514         kcm_status = kcm_item_get_data_size(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM,
00515                                             &actual_kcm_key_size);
00516         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "public key already exists");
00517         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check public key existence");
00518     }
00519 
00520     //generat keys and csr
00521     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);
00522     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to generate keys and csr");
00523 
00524     //store private key
00525     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);
00526     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store private key");
00527 
00528     //store public key
00529     if (pub_key_exists) {
00530         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);
00531         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store public key");
00532     }
00533 
00534 
00535     SA_PV_LOG_INFO_FUNC_EXIT("csr_buff_act_size_out = %" PRIu32 "", (uint32_t)*csr_buff_act_size_out);
00536     return kcm_status;
00537 
00538 }
00539 
00540 kcm_status_e  kcm_certificate_verify_with_private_key(
00541     const uint8_t * kcm_cert_data,
00542     size_t kcm_cert_data_size,
00543     const uint8_t * kcm_priv_key_name,
00544     size_t kcm_priv_key_name_len)
00545 {
00546 
00547     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00548     size_t priv_key_data_size = 0;
00549     uint8_t *priv_key_data = NULL;
00550     size_t act_priv_key_data_size = 0;
00551     palX509Handle_t x509_cert;
00552 
00553     // Check if KCM initialized, if not initialize it
00554     if (!g_kcm_initialized) {
00555         kcm_status = kcm_init();
00556         SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
00557     }
00558 
00559     //check input params
00560     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data");
00561     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data_size");
00562     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_priv_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_priv_key_name");
00563     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_priv_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_priv_key_name_len");
00564     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);
00565 
00566     //Get private key size
00567     kcm_status = kcm_item_get_data_size(kcm_priv_key_name,
00568         kcm_priv_key_name_len,
00569         KCM_PRIVATE_KEY_ITEM,
00570         &priv_key_data_size);
00571     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");
00572 
00573     //Allocate memory and get private key data
00574     priv_key_data = fcc_malloc(priv_key_data_size);
00575     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");
00576 
00577     //Get private key data
00578     kcm_status = kcm_item_get_data(kcm_priv_key_name,
00579         kcm_priv_key_name_len,
00580         KCM_PRIVATE_KEY_ITEM,
00581         priv_key_data,
00582         priv_key_data_size,
00583         &act_priv_key_data_size);
00584     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");
00585 
00586     //Create certificate handle
00587     kcm_status = cs_create_handle_from_der_x509_cert(kcm_cert_data, kcm_cert_data_size, &x509_cert);
00588     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed to create certificate handle");
00589 
00590     //Check current certificate against given private key
00591     kcm_status = cs_check_certifcate_public_key(x509_cert, priv_key_data, priv_key_data_size);
00592     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");
00593 
00594     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00595 Exit:
00596 
00597     fcc_free(priv_key_data);
00598     cs_close_handle_x509_cert(&x509_cert);
00599     return kcm_status;
00600 
00601 }
00602 
00603