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