Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fcc_verification.c Source File

fcc_verification.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 
00017 #include "factory_configurator_client.h"
00018 #include "fcc_status.h"
00019 #include "fcc_verification.h"
00020 #include "key_config_manager.h"
00021 #include "pv_error_handling.h"
00022 #include "cs_der_certs.h"
00023 #include "cs_utils.h"
00024 #include "fcc_output_info_handler.h"
00025 #include "fcc_malloc.h"
00026 #include "time.h"
00027 #include "cs_der_keys_and_csrs.h"
00028 #include "cs_utils.h"
00029 #include "common_utils.h"
00030 #include "fcc_utils.h"
00031 #include "pv_macros.h"
00032 #include "storage.h"
00033 
00034 
00035 #define FCC_10_YEARS_IN_SECONDS 315360000//10*365*24*60*60
00036 
00037 /**
00038 * Group lookup table, correlating for each group its type and name
00039 */
00040 static const fcc_config_param_lookup_record_s fcc_config_param_lookup_table[FCC_MAX_CONFIG_PARAM_TYPE] = {
00041     { FCC_MANUFACTURER_NAME_CONFIG_PARAM_TYPE,     g_fcc_manufacturer_parameter_name },
00042     { FCC_MODEL_NUMBER_CONFIG_PARAM_TYPE,          g_fcc_model_number_parameter_name },
00043     { FCC_DEVICE_TYPE_CONFIG_PARAM_TYPE,           g_fcc_device_type_parameter_name },
00044     { FCC_HARDWARE_VERSION_CONFIG_PARAM_TYPE,      g_fcc_hardware_version_parameter_name },
00045     { FCC_MEMORY_TOTAL_SIZE_CONFIG_PARAM_TYPE,     g_fcc_memory_size_parameter_name },
00046     { FCC_DEVICE_SERIAL_NUMBER_CONFIG_PARAM_TYPE,  g_fcc_device_serial_number_parameter_name },
00047 };
00048 
00049 /*
00050 * The function checks that UTC offset value is inside defined range of valid offsets :-12:00 - +14:00
00051 */
00052 static bool check_utc_offset_data(char *utc_offset_data, size_t utc_data_size)
00053 {
00054     PV_DEBUG_USE(utc_data_size);
00055 
00056     uint8_t symbol_index = 0;
00057     uint8_t first_digit_of_hour = 1;
00058     uint8_t second_digit_of_hour = 2;
00059     uint8_t first_digit_of_minutes = 4;
00060     uint8_t second_digit_of_minutes = 5;
00061 
00062     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00063 
00064     /*
00065     The range of UTC offsets taken from https://en.wikipedia.org/wiki/List_of_UTC_time_offsets
00066     We check only that the offset is -xx:yy or +xx:yy and that the offset is in range of offsets : -12:00 - +14:00
00067     but we check only that UTC contain restricted symbols(-,+,:_) and numbers at xx or yy.
00068     */
00069     //The first char must be '+' or '-'
00070     if ((utc_offset_data[symbol_index] != '+') && (utc_offset_data[symbol_index] != '-')) {
00071         return false;
00072     }
00073 
00074     //The format of utc offset should be -xx:xx or +xx:xx
00075     if (utc_offset_data[3] != ':') {
00076         return false;
00077     }
00078 
00079     //Check that all numbers of hours and minutes are valid
00080     if (utc_offset_data[first_digit_of_hour] < '0' || utc_offset_data[first_digit_of_hour] > '9') {
00081         return false;
00082     }
00083     if (utc_offset_data[second_digit_of_hour] < '0' || utc_offset_data[second_digit_of_hour] > '9') {
00084         return false;
00085     }
00086     if (utc_offset_data[first_digit_of_minutes] < '0' || utc_offset_data[first_digit_of_minutes] > '9') {
00087         return false;
00088     }
00089     if (utc_offset_data[second_digit_of_minutes] < '0' || utc_offset_data[second_digit_of_minutes] > '9') {
00090         return false;
00091     }
00092 
00093     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00094     return true;
00095 }
00096 
00097 /** The function checks bootstrap server uri data contents.
00098 *
00099 * @param uri_data_buffer[in]             The bootstrap uri data.
00100 * @param size_of_uri_data_buffer[in]      The bootstrap uri data size.
00101 * @return
00102 *     fcc_status_e.
00103 */
00104 static fcc_status_e  fcc_check_uri_contents(bool use_bootstrap, uint8_t* uri_data_buffer, size_t size_of_uri_data_buffer)
00105 {
00106     const char uri_coap_prefix[] = "coap://";
00107     const char uri_coaps_prefix[] = "coaps://";
00108     const char uri_aid_1[] = "?aid=";
00109     const char uri_aid_2[] = "&aid=";
00110     bool has_uri_aid = false;
00111     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00112     char *uri_string = NULL;
00113     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00114     bool is_first_to_claim_mode = false;
00115     uint32_t first_to_claim = 0;
00116     size_t act_config_param_size = 0;
00117 
00118     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00119 
00120     // get first to claim
00121     kcm_status = kcm_item_get_data((const uint8_t*)g_fcc_first_to_claim_parameter_name,
00122                                    strlen(g_fcc_first_to_claim_parameter_name),
00123                                    KCM_CONFIG_ITEM,
00124                                    (uint8_t*)&first_to_claim,
00125                                    sizeof(uint32_t),
00126                                    &act_config_param_size);
00127     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS && kcm_status != KCM_STATUS_ITEM_NOT_FOUND), FCC_STATUS_KCM_ERROR, "Failed to get first to claim config parameter");
00128     if (kcm_status == KCM_STATUS_SUCCESS) {
00129         SA_PV_ERR_RECOVERABLE_RETURN_IF((act_config_param_size != sizeof(uint32_t)), FCC_STATUS_WRONG_ITEM_DATA_SIZE, "Size of first to claim mode parameter is wrong ");
00130         is_first_to_claim_mode = (first_to_claim == 1);
00131     }
00132 
00133     //Allocate buffer for uri string creation
00134     uri_string = fcc_malloc(size_of_uri_data_buffer + 1);
00135     SA_PV_ERR_RECOVERABLE_RETURN_IF((uri_string == NULL), FCC_STATUS_MEMORY_OUT, "Failed to allocate memory for URI string");
00136 
00137     //Copy data and create null terminated string
00138     memcpy(uri_string, uri_data_buffer, size_of_uri_data_buffer);
00139     (*(uri_string + size_of_uri_data_buffer)) = '\0';
00140 
00141     // Check that uri_string has correct prefix
00142     if (memcmp(uri_string, uri_coap_prefix, strlen(uri_coap_prefix)) != 0 && memcmp(uri_string, uri_coaps_prefix, strlen(uri_coaps_prefix)) != 0) {
00143         SA_PV_ERR_RECOVERABLE_GOTO_IF(true, fcc_status = FCC_STATUS_URI_WRONG_FORMAT, exit, "Wrong uri prefix");
00144     }
00145 
00146     // Check if uri_string contains uri_aid (indicate the uri contains AccountId)
00147     if ((strstr(uri_string, uri_aid_1) != NULL) || (strstr(uri_string, uri_aid_2) != NULL)) {
00148         has_uri_aid = true;
00149     }
00150 
00151     if (is_first_to_claim_mode == true) {
00152         SA_PV_ERR_RECOVERABLE_GOTO_IF(use_bootstrap == false, fcc_status = FCC_STATUS_FIRST_TO_CLAIM_NOT_ALLOWED, exit, "First to claim not allowed in lwm2m mode");
00153         SA_PV_ERR_RECOVERABLE_GOTO_IF(has_uri_aid == true, fcc_status = FCC_STATUS_FIRST_TO_CLAIM_NOT_ALLOWED, exit, "First to claim not allowed if account ID exist");
00154     } else {
00155         SA_PV_ERR_RECOVERABLE_GOTO_IF(has_uri_aid == false, fcc_status = FCC_STATUS_URI_WRONG_FORMAT, exit, "Wrong uri data");
00156     }
00157 
00158 exit:
00159     fcc_free(uri_string);
00160     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00161     return fcc_status;
00162 }
00163 
00164 /* The function verifies if current item exists and checks the result with is_should_be_present flag.
00165 *  In case of unsuitability of the flag and existence of the item, the function sets warning with relevant message.
00166 */
00167 static fcc_status_e  verify_existence_and_set_warning(const uint8_t *parameter_name, size_t size_of_parameter_name, kcm_item_type_e parameter_type, bool is_should_be_present)
00168 {
00169     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00170     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00171     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00172     size_t item_size = 0;
00173 
00174     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00175 
00176     //Check that second mode server uri is not present
00177     kcm_status = kcm_item_get_data_size(parameter_name,
00178                                         size_of_parameter_name,
00179                                         parameter_type,
00180                                         &item_size);
00181 
00182     if (kcm_status == KCM_STATUS_SUCCESS && is_should_be_present == false) {
00183         output_info_fcc_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_redundant_item_warning_str);
00184     }
00185     if (kcm_status != KCM_STATUS_SUCCESS &&  is_should_be_present == true) {
00186         output_info_fcc_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_item_not_set_warning_str);
00187     }
00188     SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00189                                     fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
00190                                     "Failed to create warning");
00191 
00192     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00193     return fcc_status;
00194 }
00195 /**This function verifies certificate expiration according to
00196 *
00197 * @param certificate_data[in]                  buffer of certificate.
00198 * @param size_of_certificate_data[in]          size of certificate data.
00199 * @param certificate_name[in]                  buffer of certificate name.
00200 * @param size_of_certificate_name[in]          size of certificate name buffer.
00201 *    @returns
00202 *        fcc_status_e status.
00203 */
00204 static fcc_status_e  verify_certificate_expiration(palX509Handle_t x509_cert, const uint8_t *certificate_name, size_t size_of_certificate_name)
00205 {
00206     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00207     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00208     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00209     size_t size_of_valid_from_attr = 0;
00210     size_t size_of_valid_until_attr = 0;
00211     uint64_t valid_from_attr = 0;
00212     uint64_t time = 0;
00213     uint64_t diff_time = 60; //seconds. This value used to reduce time adjustment 
00214     uint64_t valid_until_attr = 0;
00215 
00216     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00217 
00218     //Get "valid_from" certificate attribute
00219     kcm_status = cs_attr_get_data_x509_cert(x509_cert,
00220                                             CS_VALID_FROM_ATTRIBUTE_TYPE,
00221                                             (uint8_t*)&valid_from_attr,
00222                                             sizeof(uint64_t),
00223                                             &size_of_valid_from_attr);
00224     SA_PV_ERR_RECOVERABLE_GOTO_IF(kcm_status != KCM_STATUS_SUCCESS, fcc_status = FCC_STATUS_INVALID_CERT_ATTRIBUTE, exit, "Failed to get valid_from attribute");
00225 
00226     //Get "valid_until" certificate attribute
00227     kcm_status = cs_attr_get_data_x509_cert(x509_cert,
00228                                             CS_VALID_TO_ATTRIBUTE_TYPE,
00229                                             (uint8_t*)&valid_until_attr,
00230                                             sizeof(uint64_t),
00231                                             &size_of_valid_until_attr);
00232     SA_PV_ERR_RECOVERABLE_GOTO_IF(kcm_status != KCM_STATUS_SUCCESS, fcc_status = FCC_STATUS_INVALID_CERT_ATTRIBUTE, exit, "Failed to get valid_until attribute");
00233 
00234 
00235     //Check device time
00236     time = pal_osGetTime();
00237     if (time == 0) {
00238         output_info_fcc_status = fcc_store_warning_info((const uint8_t*)certificate_name, size_of_certificate_name, g_fcc_cert_time_validity_warning_str);
00239         SA_PV_LOG_ERR("time is (%" PRIuMAX ") ", (uint64_t)time);
00240         SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, exit, "Failed to create warning");
00241     } else {
00242         //Check that the certificate is not expired
00243         SA_PV_ERR_RECOVERABLE_GOTO_IF((time > (valid_until_attr)), fcc_status = FCC_STATUS_EXPIRED_CERTIFICATE, exit, "The certificate is expired. Device time is %" PRIuMAX ", cert time is %"PRIuMAX "", time, valid_until_attr);
00244 
00245         //Check that start of validity is less than current time
00246         if (time + diff_time < (valid_from_attr)) {
00247             SA_PV_LOG_ERR("valid_from_attr is (%" PRIuMAX ") ", (uint64_t)(valid_from_attr));
00248             SA_PV_LOG_ERR("time is (%" PRIuMAX ") ", (uint64_t)time);
00249             output_info_fcc_status = fcc_store_warning_info((const uint8_t*)certificate_name, size_of_certificate_name, g_fcc_cert_time_validity_warning_str);
00250             SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, exit, "Failed to create warning");
00251         }
00252 
00253         //Check that the certificate is valid at least for 10 years
00254         if ((valid_until_attr)-time < FCC_10_YEARS_IN_SECONDS) {
00255             output_info_fcc_status = fcc_store_warning_info((const uint8_t*)certificate_name, size_of_certificate_name, g_fcc_cert_validity_less_10_years_warning_str);
00256             SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, exit, "Failed to create warning");
00257         }
00258 
00259     }
00260 exit:
00261     if (fcc_status != FCC_STATUS_SUCCESS) {
00262         output_info_fcc_status = fcc_store_error_info((const uint8_t*)certificate_name, size_of_certificate_name, fcc_status);
00263         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR, "Failed to create output fcc_status error %d", fcc_status);
00264     }
00265     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00266     return fcc_status;
00267 }
00268 /**This function verifies lwm2m certificate ou attribute is equal to aid from server link.
00269 *
00270 * @param certificate_data[in]                  buffer of certificate.
00271 * @param size_of_certificate_data[in]          size of certificate data.
00272 *        fcc_status_e status.
00273 */
00274 static fcc_status_e  compare_ou_with_aid_server(palX509Handle_t x509_cert)
00275 {
00276     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00277     uint8_t *ou_attribute_data = NULL;
00278     size_t ou_attribute_size = 0;
00279     uint8_t *parameter_name = (uint8_t*)g_fcc_lwm2m_server_uri_name;
00280     size_t size_of_parameter_name = strlen(g_fcc_lwm2m_server_uri_name);
00281     uint8_t *server_uri_buffer = NULL;
00282     size_t item_size = 0;
00283     char *uri_string = NULL;
00284     char *aid_substring = NULL;
00285     int aid_substring_size = 0;
00286     int result = 0;
00287     int len_of_aid_sub_string = (int)strlen("&aid=");
00288 
00289     //Get OU certificate attribute
00290     fcc_status = fcc_get_certificate_attribute(x509_cert, CS_OU_ATTRIBUTE_TYPE, &ou_attribute_data, &ou_attribute_size);
00291     SA_PV_ERR_RECOVERABLE_RETURN_IF(fcc_status != FCC_STATUS_SUCCESS, fcc_status = fcc_status, "Failed to get size OU attribute");
00292 
00293     //Get aid data
00294     fcc_status = fcc_get_kcm_data(parameter_name, size_of_parameter_name, KCM_CONFIG_ITEM, &server_uri_buffer, &item_size);
00295     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get kcm data server url");
00296 
00297     uri_string = fcc_malloc(item_size + 1);
00298     SA_PV_ERR_RECOVERABLE_GOTO_IF((uri_string == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, exit, "Failed to get kcm data server url");
00299 
00300     memcpy(uri_string, server_uri_buffer, item_size);
00301     (*(uri_string + item_size)) = '\0';
00302 
00303     aid_substring = strstr(uri_string, "&aid=");
00304     if (aid_substring == NULL) {
00305         aid_substring = strstr(uri_string, "?aid=");
00306         SA_PV_ERR_RECOVERABLE_GOTO_IF((aid_substring == NULL), fcc_status = FCC_STATUS_URI_WRONG_FORMAT, exit, "URI format is wrong");
00307     }
00308 
00309     aid_substring_size = (int)strlen(aid_substring);
00310     aid_substring_size = aid_substring_size - len_of_aid_sub_string;
00311     SA_PV_ERR_RECOVERABLE_GOTO_IF((aid_substring_size < (int)ou_attribute_size - 1), fcc_status = FCC_STATUS_URI_WRONG_FORMAT, exit, "URI format is wrong");
00312 
00313     result = memcmp(&(aid_substring[len_of_aid_sub_string]), ou_attribute_data, ou_attribute_size);
00314     SA_PV_ERR_RECOVERABLE_GOTO_IF((result != 0), fcc_status = FCC_STATUS_INVALID_LWM2M_CN_ATTR, exit, "CN of LWM2M different from endpoint name");
00315 
00316 exit:
00317     fcc_free(ou_attribute_data);
00318     fcc_free(server_uri_buffer);
00319     fcc_free(uri_string);
00320     return fcc_status;
00321 }
00322 /**This function verifies  certificate's cn attribute is equal to endpoint name.
00323 *
00324 * @param certificate_data[in]                  buffer of certificate.
00325 * @param size_of_certificate_data[in]          size of certificate data.
00326 *        fcc_status_e status.
00327 */
00328 static fcc_status_e  compare_cn_with_endpoint(palX509Handle_t x509_cert)
00329 {
00330     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00331     //fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
00332     size_t size_of_cn_attr = 0;
00333     uint8_t *cn_attribute_data = NULL;
00334     size_t endpoint_name_size;
00335     uint8_t *endpoint_name_data = NULL;
00336     int result = 0;
00337 
00338     //Get  CN certificate attribute
00339     fcc_status = fcc_get_certificate_attribute(x509_cert, CS_CN_ATTRIBUTE_TYPE, &cn_attribute_data, &size_of_cn_attr);
00340     SA_PV_ERR_RECOVERABLE_RETURN_IF(fcc_status != FCC_STATUS_SUCCESS, fcc_status = fcc_status, "Failed to get size CN attribute");
00341 
00342     //Get attribute returns size of string including  "\0"
00343     size_of_cn_attr = size_of_cn_attr - 1;
00344 
00345     //Get endpoint name size
00346     fcc_status = fcc_get_kcm_data((const uint8_t*)g_fcc_endpoint_parameter_name, strlen(g_fcc_endpoint_parameter_name), KCM_CONFIG_ITEM, &endpoint_name_data, &endpoint_name_size);
00347     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get endpoint name");
00348     SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_cn_attr != endpoint_name_size), fcc_status = FCC_STATUS_INVALID_LWM2M_CN_ATTR, exit, "Wrong size of CN");
00349 
00350     result = memcmp(endpoint_name_data, cn_attribute_data, size_of_cn_attr);
00351     SA_PV_ERR_RECOVERABLE_GOTO_IF((result != 0), fcc_status = FCC_STATUS_INVALID_LWM2M_CN_ATTR, exit, "CN of the certificate is different from endpoint name");
00352 
00353 exit:
00354     fcc_free(cn_attribute_data);
00355     fcc_free(endpoint_name_data);
00356     return fcc_status;
00357 }
00358 /** The function checks validity of bootstrap server uri parameter
00359 *
00360 * The function checks the item's size, gets its data and checks it.
00361 *
00362 * @param bootrstrap_server_uri_name[in]             The bootstrap uri name.
00363 * @param size_of_bootrstrap_server_uri_name[in]     The size of bootstrap uri name.
00364 * @return
00365 *     fcc_status_e.
00366 */
00367 static fcc_status_e  verify_server_uri(bool use_bootstrap)
00368 {
00369 
00370     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00371     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00372     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00373     size_t item_size = 0;
00374     uint8_t *server_uri_buffer = NULL;
00375     uint8_t *parameter_name = NULL;
00376     size_t size_of_parameter_name = 0;
00377     uint8_t *second_mode_parameter_name = NULL;
00378     size_t size_of_second_mode_parameter_name = 0;
00379 
00380     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00381 
00382     //Set server uri parameter names of current and second mode according to bootstrap mode
00383     if (use_bootstrap == true) {
00384         parameter_name = (uint8_t*)g_fcc_bootstrap_server_uri_name;
00385         size_of_parameter_name = strlen(g_fcc_bootstrap_server_uri_name);
00386         second_mode_parameter_name = (uint8_t*)g_fcc_lwm2m_server_uri_name;
00387         size_of_second_mode_parameter_name = strlen(g_fcc_lwm2m_server_uri_name);
00388     } else {
00389         parameter_name = (uint8_t*)g_fcc_lwm2m_server_uri_name;
00390         size_of_parameter_name = strlen(g_fcc_lwm2m_server_uri_name);
00391         second_mode_parameter_name = (uint8_t*)g_fcc_bootstrap_server_uri_name;
00392         size_of_second_mode_parameter_name = strlen(g_fcc_bootstrap_server_uri_name);
00393     }
00394     fcc_status = fcc_get_kcm_data(parameter_name, size_of_parameter_name, KCM_CONFIG_ITEM, &server_uri_buffer, &item_size);
00395     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get kcm data server url");
00396 
00397     //Check that server uri of second mode is not present, if yes - set warning
00398     fcc_status = verify_existence_and_set_warning(second_mode_parameter_name, size_of_second_mode_parameter_name, KCM_CONFIG_ITEM, false);
00399     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to verify_existence_and_set_warning");
00400 
00401     //Check server uri data
00402     fcc_status = fcc_check_uri_contents(use_bootstrap, server_uri_buffer, item_size);
00403     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to check bootstrap uri data");
00404 
00405 exit:
00406     fcc_free(server_uri_buffer);
00407     //In case kcm or fcc error, record the error with parameter name
00408     if (kcm_status != KCM_STATUS_SUCCESS || fcc_status != FCC_STATUS_SUCCESS) {
00409         if (fcc_status == FCC_STATUS_FIRST_TO_CLAIM_NOT_ALLOWED && parameter_name == (uint8_t*)g_fcc_lwm2m_server_uri_name)
00410         {
00411             // In case that using lwm2m and first to claim on, change the parameter_name
00412             parameter_name = (uint8_t*)g_fcc_first_to_claim_parameter_name;
00413             size_of_parameter_name = strlen(g_fcc_first_to_claim_parameter_name);
00414         }
00415         output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
00416         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00417                                         fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
00418                                         "Failed to create output fcc_status error %d",
00419                                         fcc_status);
00420     }
00421     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00422     return fcc_status;
00423 }
00424 
00425 /* The function checks UTC offset.
00426 */
00427 static fcc_status_e  check_utc_offset(void)
00428 {
00429     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00430     fcc_status_e  fcc_output_status = FCC_STATUS_SUCCESS;
00431     uint8_t *parameter_name = (uint8_t*)g_fcc_offset_from_utc_parameter_name;
00432     size_t size_of_parameter_name = strlen(g_fcc_offset_from_utc_parameter_name);
00433     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00434     size_t item_size = 0;
00435 
00436     uint8_t *utc_offset_data = NULL;
00437     bool status = false;
00438 
00439     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00440 
00441     fcc_status = fcc_get_kcm_data(parameter_name, size_of_parameter_name, KCM_CONFIG_ITEM, &utc_offset_data, &item_size);
00442 
00443     //If the item is missing or empty, write warning
00444     if (fcc_status == FCC_STATUS_ITEM_NOT_EXIST || fcc_status == FCC_STATUS_EMPTY_ITEM) {
00445         fcc_output_status = fcc_store_warning_info(parameter_name, size_of_parameter_name, g_fcc_item_not_set_warning_str);
00446         SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_output_status != FCC_STATUS_SUCCESS),
00447                                       fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
00448                                       exit,
00449                                       "Failed to create output warning %s",
00450                                       g_fcc_item_not_set_warning_str);
00451         fcc_status = FCC_STATUS_SUCCESS;
00452     } else {
00453         //If get kcm data returned error, exit with error
00454         SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get utc data");
00455 
00456         status = check_utc_offset_data((char*)utc_offset_data, item_size);
00457         SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), fcc_status = FCC_STATUS_UTC_OFFSET_WRONG_FORMAT, exit, "Failed to check utc offset");
00458     }
00459 
00460 exit:
00461     fcc_free(utc_offset_data);
00462     if (fcc_status != FCC_STATUS_SUCCESS) {
00463         output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
00464         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00465                                         fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
00466                                         "Failed to create output fcc_status error  %d",
00467                                         fcc_status);
00468     }
00469     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00470     return fcc_status;
00471 }
00472 /**This function checks Root CA certificate.
00473 *
00474 * @param device_objects[in]         Structure with set of device security object data.
00475 * @param use_bootstrap[in]          Bootstrap mode.
00476 *    @returns
00477 *        fcc_status_e status.
00478 */
00479 static fcc_status_e  verify_root_ca_certificate(bool use_bootstrap)
00480 {
00481     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00482     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00483     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00484     size_t item_size = 0;
00485     uint8_t *parameter_name = NULL;
00486     size_t size_of_parameter_name = 0;
00487     uint8_t *second_mode_parameter_name = NULL;
00488     size_t size_of_second_mode_parameter_name = 0;
00489     uint8_t attribute_data[PAL_CERT_ID_SIZE] = { 0 };
00490     size_t size_of_attribute_data = 0;
00491     uint8_t data_out[FCC_CA_IDENTIFICATION_SIZE] = { 0 };
00492     size_t data_size_out = 0;
00493     int result = 0;
00494 
00495 
00496     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00497 
00498     //Set CA certificate names of current and second mode
00499     if (use_bootstrap == true) {
00500         //Set bootstrap root ca certificate name
00501         parameter_name = (uint8_t*)g_fcc_bootstrap_server_ca_certificate_name;
00502         size_of_parameter_name = strlen(g_fcc_bootstrap_server_ca_certificate_name);
00503         second_mode_parameter_name = (uint8_t*)g_fcc_lwm2m_server_ca_certificate_name;
00504         size_of_second_mode_parameter_name = strlen(g_fcc_lwm2m_server_ca_certificate_name);
00505     } else {
00506         //Set lwm2m root ca certificate name
00507         parameter_name = (uint8_t*)g_fcc_lwm2m_server_ca_certificate_name;
00508         size_of_parameter_name = strlen(g_fcc_lwm2m_server_ca_certificate_name);
00509         second_mode_parameter_name = (uint8_t*)g_fcc_bootstrap_server_ca_certificate_name;
00510         size_of_second_mode_parameter_name = strlen(g_fcc_bootstrap_server_ca_certificate_name);
00511     }
00512 
00513     //Check that ca certificate of current mode is present 
00514     kcm_status = kcm_item_get_data_size((const uint8_t*)parameter_name,
00515                                         size_of_parameter_name,
00516                                         KCM_CERTIFICATE_ITEM,
00517                                         &item_size);
00518     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_ITEM_NOT_EXIST, store_error_and_exit, "Failed to get size bootstrap root ca certificate size");
00519     SA_PV_ERR_RECOVERABLE_GOTO_IF((item_size == 0), fcc_status = FCC_STATUS_EMPTY_ITEM, store_error_and_exit, "Empty root CA certificate");
00520 
00521     //Check  that ca certificate of second mode is not present, if yes - set warning
00522     fcc_status = verify_existence_and_set_warning(second_mode_parameter_name, size_of_second_mode_parameter_name, KCM_CERTIFICATE_ITEM, false);
00523     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, store_error_and_exit, "Failed in verify_existence_and_set_warning");
00524 
00525     if (use_bootstrap == true) {
00526         fcc_status = fcc_get_certificate_attribute_by_name((const uint8_t*)parameter_name,
00527                                                            size_of_parameter_name,
00528                                                            CS_CERT_ID_ATTR,
00529                                                            attribute_data,
00530                                                            sizeof(attribute_data),
00531                                                            &size_of_attribute_data);
00532         SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, store_error_and_exit, "Failed to get ca id attribute");
00533 
00534         kcm_status = storage_fcc_rbp_read(STORAGE_RBP_TRUSTED_TIME_SRV_ID_NAME, data_out, size_of_attribute_data, &data_size_out);
00535         if (kcm_status != KCM_STATUS_SUCCESS || data_size_out != size_of_attribute_data) {
00536             output_info_fcc_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_ca_identifier_warning_str);
00537             SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, store_error_and_exit, "Failed to create warning");
00538         }
00539 
00540         if (fcc_status == FCC_STATUS_SUCCESS) {
00541             result = memcmp(data_out, attribute_data, data_size_out);
00542             if (result != 0) {
00543                 output_info_fcc_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_ca_identifier_warning_str);
00544                 SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, store_error_and_exit, "Failed to create warning");
00545             }
00546         }
00547         fcc_status = FCC_STATUS_SUCCESS;
00548     }
00549 
00550     //TBD : check of mbed crypto scheme IOTPREQ-1417
00551 store_error_and_exit:
00552     if (fcc_status != FCC_STATUS_SUCCESS) {
00553         output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
00554         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00555                                         fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
00556                                         "Failed to create output fcc_status error  %d",
00557                                         fcc_status);
00558     }
00559     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00560     return fcc_status;
00561 }
00562 
00563 /** Get a handle to the next X509 in the chain
00564 *   This is done by getting the size of the next X509, then reading the file into a dynamically allocated buffer, creating the X509 handle and freeing the buffer.
00565 *   Calling this function after ::kcm_cert_chain_open will output the X509 handle of the first certificate in the chain
00566 *
00567 *    @param[in]  kcm_chain_handle                  pointer to an open chain handle (use the ::kcm_cert_chain_open API).
00568 *    @param[out] x509_cert_handle_out              pointer to an X509 handle where the created handle will be placed.
00569 *
00570 *    @returns
00571 *        FCC_STATUS_SUCCESS in case of success or one of the `::fcc_status_e` errors otherwise.
00572 */
00573 static fcc_status_e  get_next_x509_in_chain(kcm_cert_chain_handle chain_handle, palX509Handle_t *x509_cert_handle_out)
00574 {
00575     uint8_t *cert_buff = NULL;
00576     size_t cert_buff_size = 0;
00577     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00578     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00579 
00580     kcm_status = kcm_cert_chain_get_next_size(chain_handle, &cert_buff_size);
00581     SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_convert_kcm_to_fcc_status(kcm_status), "Failed to get next size");
00582 
00583     cert_buff = fcc_malloc(cert_buff_size);
00584     SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_buff == NULL), FCC_STATUS_MEMORY_OUT, "Allocation failed");
00585 
00586     kcm_status = kcm_cert_chain_get_next_data(chain_handle, cert_buff, cert_buff_size, &cert_buff_size);
00587     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_status), Exit, "Failed to get next cert");
00588 
00589     kcm_status = cs_create_handle_from_der_x509_cert(cert_buff, cert_buff_size, x509_cert_handle_out);
00590     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_status), Exit, "Failed to get X509 handle");
00591 
00592 Exit:
00593     fcc_free(cert_buff);
00594     return fcc_status;
00595 }
00596 
00597 /**This function checks device private key.
00598 *
00599 * @param use_bootstrap[in]          Bootstrap mode.
00600 *    @returns
00601 *        fcc_status_e status.
00602 */
00603 static fcc_status_e  verify_device_certificate_and_private_key(bool use_bootstrap)
00604 {
00605     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00606     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00607     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00608     bool is_self_signed = false;
00609     uint8_t *parameter_name = NULL;
00610     size_t size_of_parameter_name = 0;
00611     uint8_t *second_mode_parameter_name = NULL;
00612     size_t size_of_second_mode_parameter_name = 0;
00613     uint8_t *private_key_data = NULL;
00614     size_t size_of_private_key_data = 0;
00615     kcm_cert_chain_context_int_s *cert_chain;
00616     kcm_cert_chain_handle chain_handle;
00617     size_t chain_len = 0;
00618     palX509Handle_t x509_cert_handle = NULLPTR;
00619     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00620 
00621     //Set device private key names of current and second modes
00622     if (use_bootstrap == true) {
00623         parameter_name = (uint8_t*)g_fcc_bootstrap_device_private_key_name;
00624         size_of_parameter_name = strlen(g_fcc_bootstrap_device_private_key_name);
00625         second_mode_parameter_name = (uint8_t*)g_fcc_lwm2m_device_private_key_name;
00626         size_of_second_mode_parameter_name = strlen(g_fcc_lwm2m_device_private_key_name);
00627     } else {
00628         parameter_name = (uint8_t*)g_fcc_lwm2m_device_private_key_name;
00629         size_of_parameter_name = strlen(g_fcc_lwm2m_device_private_key_name);
00630         second_mode_parameter_name = (uint8_t*)g_fcc_bootstrap_device_private_key_name;
00631         size_of_second_mode_parameter_name = strlen(g_fcc_bootstrap_device_private_key_name);
00632     }
00633 
00634     fcc_status = fcc_get_kcm_data(parameter_name, size_of_parameter_name, KCM_PRIVATE_KEY_ITEM, &private_key_data, &size_of_private_key_data);
00635     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, store_error_and_exit, "Failed to get device certificate");
00636 
00637     //Check that device private key of second mode is not present, if yes - set warning
00638     fcc_status = verify_existence_and_set_warning(second_mode_parameter_name, size_of_second_mode_parameter_name, KCM_PRIVATE_KEY_ITEM, false);
00639     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, store_error_and_exit, "Failed in verify_existence_and_set_warning");
00640 
00641 
00642     //Set parameter names of device certificate according to mode
00643     if (use_bootstrap == true) {
00644         //Set bootstrap root ca certificate name
00645         parameter_name = (uint8_t*)g_fcc_bootstrap_device_certificate_name;
00646         size_of_parameter_name = strlen(g_fcc_bootstrap_device_certificate_name);
00647         second_mode_parameter_name = (uint8_t*)g_fcc_lwm2m_device_certificate_name;
00648         size_of_second_mode_parameter_name = strlen(g_fcc_lwm2m_device_certificate_name);
00649     } else {
00650         //Set lwm2m device certificate name
00651         parameter_name = (uint8_t*)g_fcc_lwm2m_device_certificate_name;
00652         size_of_parameter_name = strlen(g_fcc_lwm2m_device_certificate_name);
00653         second_mode_parameter_name = (uint8_t*)g_fcc_bootstrap_device_certificate_name;
00654         size_of_second_mode_parameter_name = strlen(g_fcc_bootstrap_device_certificate_name);
00655     }
00656 
00657     // Open device certificate as chain. 
00658     kcm_status = kcm_cert_chain_open(&chain_handle, parameter_name, size_of_parameter_name, &chain_len);
00659     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_status), store_error_and_exit, "Failed to get device certificate descriptor");
00660     
00661     cert_chain = (kcm_cert_chain_context_int_s *)chain_handle;
00662 
00663     //Create device certificate handle
00664     fcc_status = get_next_x509_in_chain(chain_handle, &x509_cert_handle);
00665     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to get device certificate descriptor");
00666 
00667     //Check device certificate public key
00668     kcm_status = cs_check_certifcate_public_key(x509_cert_handle, private_key_data, size_of_private_key_data);
00669     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_CERTIFICATE_PUBLIC_KEY_CORRELATION_ERROR, close_chain, "Failed to check device certificate public key");
00670 
00671     //Check if the certificate of second mode exists, if yes - set warning
00672     fcc_status = verify_existence_and_set_warning(second_mode_parameter_name, size_of_second_mode_parameter_name, KCM_CERTIFICATE_ITEM, false);
00673     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to verify_existence_and_set_warning");
00674 
00675     //Compare device certificate's CN attribute with endpoint name
00676     fcc_status = compare_cn_with_endpoint(x509_cert_handle);
00677     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to compare_cn_with_endpoint");
00678 
00679     //In case LWM2M certificate check it's OU attribute with aid of server link
00680     if (strcmp((const char*)parameter_name, g_fcc_lwm2m_device_certificate_name) == 0) {
00681         fcc_status = compare_ou_with_aid_server(x509_cert_handle);
00682         SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to compare_ou_with_aid_server");
00683     }
00684 
00685     //Check that device certificate not self-signed
00686     kcm_status = cs_is_self_signed_x509_cert(x509_cert_handle, &is_self_signed);
00687     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_INVALID_CERTIFICATE, close_chain, "Failed to check if device certificate is self-signed");
00688     if (is_self_signed == true) {
00689         output_info_fcc_status = fcc_store_warning_info(parameter_name, size_of_parameter_name, g_fcc_self_signed_warning_str);
00690         SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00691                                       fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
00692                                       close_chain,
00693                                       "Failed to create warning %s",
00694                                       g_fcc_self_signed_warning_str);
00695     }
00696 
00697     //Verify expiration of first certificate in chain
00698     fcc_status = verify_certificate_expiration(x509_cert_handle, parameter_name, size_of_parameter_name);
00699     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to verify_certificate_validity");
00700 
00701     // Verify expiration of rest of chain
00702     while (cert_chain->current_cert_index < cert_chain->num_of_certificates_in_chain) {
00703 
00704         // Close handle of first X509 in chain
00705         cs_close_handle_x509_cert(&x509_cert_handle);
00706         
00707         // Acquire a handle to the next X509 in the chain
00708         fcc_status = get_next_x509_in_chain(chain_handle, &x509_cert_handle);
00709         SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to get device certificate descriptor");
00710 
00711         // Only verify the expiration date of the X509, not the signature (was checked before the store)
00712         fcc_status = verify_certificate_expiration(x509_cert_handle, KCM_FILE_BASENAME(cert_chain->chain_name, KCM_FILE_PREFIX_CERTIFICATE), KCM_FILE_BASENAME_LEN(cert_chain->chain_name_len, KCM_FILE_PREFIX_CERTIFICATE));
00713         SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to verify_certificate_validity");
00714     }
00715 
00716 
00717 close_chain:
00718     kcm_cert_chain_close(chain_handle);
00719 
00720 store_error_and_exit:
00721     fcc_free(private_key_data);
00722     cs_close_handle_x509_cert(&x509_cert_handle);
00723     if (fcc_status != FCC_STATUS_SUCCESS) {
00724         output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
00725         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00726                                         fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
00727                                         "Failed to create output fcc_status error  %d",
00728                                         fcc_status);
00729     }
00730 
00731     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00732     return fcc_status;
00733 }
00734 
00735 /* The function checks firmware integrity ca and firmware integrity certificates
00736 */
00737 static fcc_status_e  verify_firmware_update_certificate(void)
00738 {
00739     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00740     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00741     fcc_status_e  fcc_output_status = FCC_STATUS_SUCCESS;
00742     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00743     uint8_t *parameter_name = (uint8_t*)g_fcc_update_authentication_certificate_name;
00744     size_t size_of_parameter_name = strlen(g_fcc_update_authentication_certificate_name);
00745     palX509Handle_t x509_cert_handle = NULLPTR;
00746     kcm_cert_chain_context_int_s *cert_chain = NULL;
00747     kcm_cert_chain_handle chain_handle;
00748     size_t chain_len = 0;
00749 
00750     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00751 
00752     // Open device certificate as chain. 
00753     kcm_status = kcm_cert_chain_open(&chain_handle, parameter_name, size_of_parameter_name, &chain_len);
00754 
00755     // If item does not exist or is empty -set warning
00756     if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND ) {
00757         fcc_output_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_item_not_set_warning_str);
00758         SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_output_status != FCC_STATUS_SUCCESS),
00759                                       fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
00760                                       exit,
00761                                       "Failed to create output warning %s",
00762                                       g_fcc_item_not_set_warning_str);
00763         fcc_status = FCC_STATUS_SUCCESS;
00764     } else {
00765 
00766         //If get kcm data returned error, exit with error
00767         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_status), exit, "Failed to get update certificate data");
00768 
00769         cert_chain = (kcm_cert_chain_context_int_s *)chain_handle;
00770 
00771         // Verify expiration of all certificates in firmware chain
00772         // ADAM: Maybe change to function that gets verify_certificate_expiration as callback function (seems unnecessary for now...)
00773         while (cert_chain->current_cert_index < cert_chain->num_of_certificates_in_chain) {
00774 
00775             // Acquire a handle to the next X509 in the chain
00776             fcc_status = get_next_x509_in_chain(chain_handle, &x509_cert_handle);
00777             SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get device certificate descriptor");
00778 
00779             // Only verify the expiration date of the X509, not the signature (was checked before the store)
00780             fcc_status = verify_certificate_expiration(x509_cert_handle, parameter_name, strlen(g_fcc_update_authentication_certificate_name));
00781             SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to verify_certificate_validity");
00782 
00783             cs_close_handle_x509_cert(&x509_cert_handle);
00784 
00785             // Set handle to 0 so that cs_close_handle_x509_cert is not called upon exit
00786             x509_cert_handle = NULLPTR;
00787         }
00788         
00789     }
00790 
00791 exit:
00792     //Close the chain in case it was created
00793     if ( cert_chain != NULL) {
00794         kcm_cert_chain_close(chain_handle);
00795     }
00796     if (x509_cert_handle != NULLPTR) {
00797         cs_close_handle_x509_cert(&x509_cert_handle);
00798     }
00799     if (fcc_status != FCC_STATUS_SUCCESS) {
00800         output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
00801         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00802                                         fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
00803                                         "Failed to create output fcc_status error  %d",
00804                                         fcc_status);
00805     }
00806     return fcc_status;
00807 }
00808 
00809 // Check that fcc_firmware_id_name exists and is of correct uuid5 size
00810 /** Check that fcc_firmware_id_name exists and is of correct uuid5 size
00811 *
00812 * @param fcc_firmware_id_name[in]           Name of the file of the uuid (must be either g_fcc_class_id_name or g_fcc_vendor_id_name).
00813 *    @returns
00814 *        FCC_STATUS_SUCCESS If validated successfully, or if the item does not exist (warning is set).
00815 *        Otherwise will return an fcc_status_e error
00816 */
00817 
00818 static fcc_status_e  verify_firmware_uuid(const char *fcc_firmware_id_name)
00819 {
00820     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00821     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00822     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00823     size_t item_size = 0;
00824 
00825     SA_PV_LOG_TRACE_FUNC_ENTER("fcc_firmware_id_name = %s", fcc_firmware_id_name);
00826 
00827     // Check if class id exists - if not write warning
00828     kcm_status = kcm_item_get_data_size((const uint8_t*)fcc_firmware_id_name,
00829                                         strlen(fcc_firmware_id_name),
00830                                         KCM_CONFIG_ITEM,
00831                                         &item_size);
00832 
00833     if (kcm_status != KCM_STATUS_SUCCESS) {
00834         // If item not found, store warning
00835         if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
00836             fcc_status = fcc_store_warning_info((const uint8_t*)fcc_firmware_id_name, strlen(fcc_firmware_id_name), g_fcc_item_not_set_warning_str);
00837             SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS),
00838                 (fcc_status = FCC_STATUS_WARNING_CREATE_ERROR),
00839                                           Exit,
00840                                           "Failed to create output warning %s",
00841                                           g_fcc_item_not_set_warning_str);
00842 
00843         } else { // If any other KCM error - exit with generic KCM error
00844             fcc_status = FCC_STATUS_KCM_ERROR;
00845 
00846             // Go to Exit returning FCC_STATUS_KCM_ERROR and setting error buffer
00847             goto Exit;
00848         }
00849 
00850     } else {
00851         // If item exists assert item is correct size of UUID5 
00852         SA_PV_ERR_RECOVERABLE_GOTO_IF((item_size != FCC_UUID5_SIZE_IN_BYTES), (fcc_status = FCC_STATUS_WRONG_ITEM_DATA_SIZE), Exit, "Class ID of incorrect size - %" PRIu32, (uint32_t)item_size);
00853     }
00854 
00855 Exit:
00856     if (fcc_status != FCC_STATUS_SUCCESS) {
00857         output_info_fcc_status = fcc_store_error_info((uint8_t*)fcc_firmware_id_name, strlen(fcc_firmware_id_name), fcc_status);
00858         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00859                                         FCC_STATUS_OUTPUT_INFO_ERROR,
00860                                         "Failed to create output fcc_status error  %d",
00861                                         fcc_status);
00862     }
00863 
00864     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00865     return fcc_status;
00866 }
00867 
00868 //FIXME : once init entropy API will be ready,add fcc_is_entropy_initialized implementation
00869 bool fcc_is_entropy_initialized(void)
00870 {
00871     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00872 
00873     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00874 
00875     return true;
00876 }
00877 fcc_status_e  fcc_check_time_synchronization()
00878 {
00879 
00880     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00881     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00882     uint64_t time = 0;
00883     uint8_t *parameter_name = (uint8_t*)g_fcc_device_time_zone_parameter_name;
00884     size_t size_of_parameter_name = strlen(g_fcc_device_time_zone_parameter_name);
00885     size_t item_size = 0;
00886     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00887     /*
00888     Time zone defines -  https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
00889     */
00890     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00891 
00892     //Check device time
00893     time = pal_osGetTime();
00894     if (time == 0) {
00895         output_info_fcc_status = fcc_store_warning_info((const uint8_t*)g_fcc_current_time_parameter_name, strlen(g_fcc_current_time_parameter_name), g_fcc_item_not_set_warning_str);
00896         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, "Failed to create warning");
00897     }
00898 
00899     //Check device time zone
00900     kcm_status = kcm_item_get_data_size((const uint8_t*)parameter_name,
00901                                         size_of_parameter_name,
00902                                         KCM_CONFIG_ITEM,
00903                                         &item_size);
00904     //Store warning in case time zone is missing or empty
00905     if (kcm_status != KCM_STATUS_SUCCESS || item_size == 0) {
00906         output_info_fcc_status = fcc_store_warning_info(parameter_name, size_of_parameter_name, g_fcc_item_not_set_warning_str);
00907         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00908                                         fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
00909                                         "Failed to create output warning %s",
00910                                         g_fcc_item_not_set_warning_str);
00911     }
00912 
00913     //Check UTC offset
00914     fcc_status = check_utc_offset();
00915     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed in check_utc_offset");
00916 
00917     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00918     return fcc_status;
00919 }
00920 
00921 fcc_status_e  fcc_check_device_general_info()
00922 {
00923     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00924     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00925     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00926     size_t config_param_size = 0;
00927 
00928     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00929     //Check FCC_ENDPOINT_NAME_CONFIG_PARAM_NAME
00930     kcm_status = kcm_item_get_data_size((const uint8_t*)&g_fcc_endpoint_parameter_name,
00931                                         strlen(g_fcc_endpoint_parameter_name),
00932                                         KCM_CONFIG_ITEM,
00933                                         &config_param_size);
00934     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_ITEM_NOT_EXIST, exit, "Failed to get size of %s ", g_fcc_endpoint_parameter_name);
00935     SA_PV_ERR_RECOVERABLE_GOTO_IF((config_param_size == 0), fcc_status = FCC_STATUS_EMPTY_ITEM, exit, "Size of %s is 0 ", g_fcc_endpoint_parameter_name);
00936 
00937 exit:
00938     if (fcc_status != FCC_STATUS_SUCCESS) {
00939         output_info_fcc_status = fcc_store_error_info((const uint8_t*)g_fcc_endpoint_parameter_name, strlen(g_fcc_endpoint_parameter_name), fcc_status);
00940         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00941                                         fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
00942                                         "Failed to create output fcc_status error %d",
00943                                         fcc_status);
00944     }
00945     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00946     return fcc_status;
00947 }
00948 
00949 fcc_status_e  fcc_check_device_meta_data(void)
00950 {
00951     int config_param_index = 0;
00952     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00953     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00954     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00955     size_t config_param_size = 0;
00956     uint8_t *parameter_name = NULL;
00957     size_t size_of_parameter_name = 0;
00958 
00959     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00960 
00961     for (config_param_index = 0; config_param_index < FCC_MAX_CONFIG_PARAM_TYPE; config_param_index++) {
00962 
00963         //Set current configuration parameter to local variable
00964         parameter_name = (uint8_t*)fcc_config_param_lookup_table[config_param_index].config_param_name;
00965         size_of_parameter_name = strlen(fcc_config_param_lookup_table[config_param_index].config_param_name);
00966 
00967         //Check that current configuration parameter is present
00968         kcm_status = kcm_item_get_data_size((const uint8_t*)parameter_name,
00969                                             size_of_parameter_name,
00970                                             KCM_CONFIG_ITEM,
00971                                             &config_param_size);
00972         SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_ITEM_NOT_EXIST, exit, "Failed to get size of %s ", fcc_config_param_lookup_table[config_param_index].config_param_name);
00973     }
00974 
00975 exit:
00976     if (fcc_status != FCC_STATUS_SUCCESS) {
00977         output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
00978         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00979                                         fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
00980                                         "Failed to create output fcc_status error %d",
00981                                         fcc_status);
00982     }
00983     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
00984     return fcc_status;
00985 }
00986 
00987 fcc_status_e  fcc_get_bootstrap_mode(bool *use_bootstrap)
00988 {
00989     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00990     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00991     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00992     size_t config_param_size = sizeof(uint32_t);
00993     size_t act_config_param_size = 0;
00994     uint32_t bootstrap;
00995     uint8_t *parameter_name = (uint8_t*)g_fcc_use_bootstrap_parameter_name;
00996     size_t size_of_parameter_name = strlen(g_fcc_use_bootstrap_parameter_name);
00997 
00998     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
00999 
01000     //Get configuration parameter
01001     kcm_status = kcm_item_get_data((const uint8_t*)parameter_name,
01002                                    size_of_parameter_name,
01003                                    KCM_CONFIG_ITEM,
01004                                    (uint8_t*)&bootstrap,
01005                                    config_param_size,
01006                                    &act_config_param_size);
01007     SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_ITEM_NOT_EXIST, exit, "Failed to get data bootstrap mode parameter");
01008     SA_PV_ERR_RECOVERABLE_GOTO_IF((act_config_param_size != sizeof(uint32_t)), fcc_status = FCC_STATUS_WRONG_ITEM_DATA_SIZE, exit, "Size of bootstrap mode parameter is wrong ");
01009 
01010     if (bootstrap != 0 && bootstrap != 1) {
01011         SA_PV_ERR_RECOVERABLE_GOTO_IF((true), fcc_status = FCC_STATUS_BOOTSTRAP_MODE_ERROR, exit, "Invalid bootstrap mode");
01012     }
01013     if (bootstrap == 0) {
01014         *use_bootstrap = false;
01015         output_info_fcc_status = fcc_store_warning_info(parameter_name, size_of_parameter_name, g_fcc_bootstrap_mode_false_warning_str);
01016         SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
01017                                       fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
01018                                       exit,
01019                                       "Failed to create output warning %s",
01020                                       g_fcc_bootstrap_mode_false_warning_str);
01021     } else {
01022         *use_bootstrap = true;
01023     }
01024 
01025 exit:
01026     if (fcc_status != FCC_STATUS_SUCCESS) {
01027         output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
01028         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
01029                                         fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
01030                                         "Failed to create output fcc_status error  %d",
01031                                         fcc_status);
01032     }
01033     SA_PV_LOG_TRACE_FUNC_EXIT("use_bootstrap is %d", *use_bootstrap);
01034     return fcc_status;
01035 }
01036 
01037 fcc_status_e  fcc_check_device_security_objects(bool use_bootstrap)
01038 {
01039     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
01040 
01041     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
01042 
01043     fcc_status = verify_root_ca_certificate(use_bootstrap);
01044     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to verify root CA certificate");
01045 
01046     //Check bootstrap server URI
01047     fcc_status = verify_server_uri(use_bootstrap);
01048     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to verify server URI");
01049 
01050     //Check device certificate and private key
01051     fcc_status = verify_device_certificate_and_private_key(use_bootstrap);
01052     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to verify device certificate and private key");
01053 
01054     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
01055     return fcc_status;
01056 }
01057 
01058 
01059 fcc_status_e  fcc_check_firmware_update_integrity(void)
01060 {
01061     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
01062 
01063     SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
01064 
01065     fcc_status = verify_firmware_update_certificate();
01066     //fcc_status = verify_certificate(g_fcc_update_authentication_certificate_name);
01067     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to verify integrity CA certificate");
01068 
01069     fcc_status = verify_firmware_uuid(g_fcc_class_id_name);
01070     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Error verifying class ID");
01071 
01072     fcc_status = verify_firmware_uuid(g_fcc_vendor_id_name);
01073     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Error verifying vendor ID");
01074 
01075     SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
01076     return fcc_status;
01077 }