Simulated product dispenser
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