Simulated product dispenser

Dependencies:   HTS221

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

Embed: (wiki syntax)

« Back to documentation index

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