Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
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 }
Generated on Tue Jul 12 2022 20:20:59 by
