Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
fcc_bundle_handler.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 #ifndef USE_TINY_CBOR 00017 #include "fcc_bundle_handler.h" 00018 #include "cn-cbor.h" 00019 #include "pv_error_handling.h" 00020 #include "factory_configurator_client.h" 00021 #include "fcc_bundle_utils.h" 00022 #include "fcc_output_info_handler.h" 00023 #include "fcc_malloc.h" 00024 #include "fcc_sotp.h" 00025 #include "general_utils.h" 00026 #include "fcc_time_profiling.h" 00027 #include "fcc_utils.h" 00028 #include "fcc_bundle_fields.h" 00029 00030 /** 00031 * Defines for cbor layer 00032 */ 00033 #ifdef USE_CBOR_CONTEXT 00034 #define CONTEXT_NULL , NULL 00035 #define CONTEXT_NULL_COMMA NULL, 00036 #else 00037 #define CONTEXT_NULL 00038 #define CONTEXT_NULL_COMMA 00039 #endif 00040 00041 /** 00042 * Definition of size and value of current protocol scheme version 00043 */ 00044 #define FCC_SIZE_OF_VERSION_FIELD 5 00045 const char fcc_bundle_scheme_version[] = "0.0.1"; 00046 extern bool g_is_session_finished; 00047 00048 // FIXME: temporary. Will be removed when migration to tinycbor is complete 00049 void g_csr_buf_free(); 00050 00051 /** 00052 * Types of configuration parameter groups 00053 */ 00054 typedef enum { 00055 FCC_KEY_GROUP_TYPE, //!< Key group type 00056 FCC_CERTIFICATE_GROUP_TYPE, //!< Certificate group type 00057 FCC_CONFIG_PARAM_GROUP_TYPE, //!< Configuration parameter group type 00058 FCC_CERTIFICATE_CHAIN_GROUP_TYPE, //!< Certificate chain group type 00059 FCC_SCHEME_VERSION_TYPE, //!< Scheme version group type 00060 FCC_ENTROPY_TYPE, //!< Entropy group type 00061 FCC_ROT_TYPE, //!< Root of trust group type 00062 FCC_VERIFY_DEVICE_IS_READY_TYPE, //!< Verify device readiness type 00063 FCC_FACTORY_DISABLE_TYPE, //!< Disable FCC flow type 00064 FCC_IS_ALIVE_SESSION_GROUP_TYPE, //!< Indicates current message status - last message or not 00065 FCC_FCU_SESSION_ID_GROUP_TYPE, //!< Session ID sent by the FCU 00066 FCC_CSR_REQUESTS_GROUP_TYPE, //!< CSR requests type 00067 FCC_MAX_CONFIG_PARAM_GROUP_TYPE //!< Max group type 00068 } fcc_bundle_param_group_type_e; 00069 00070 /** 00071 * Group lookup record, correlating group's type and name 00072 */ 00073 typedef struct fcc_bundle_group_lookup_record_ { 00074 fcc_bundle_param_group_type_e group_type; 00075 const char *group_name; 00076 } fcc_bundle_group_lookup_record_s; 00077 /** 00078 * Group lookup table, correlating for each group its type and name. 00079 * Order is important - it is the order that fcc_bundle_handler() reads the cbor fields. 00080 * FCC_ENTROPY_TYPE and FCC_ROT_TYPE Must be processed first and second respectively. 00081 */ 00082 static const fcc_bundle_group_lookup_record_s fcc_groups_lookup_table[FCC_MAX_CONFIG_PARAM_GROUP_TYPE] = { 00083 { FCC_SCHEME_VERSION_TYPE, FCC_BUNDLE_SCHEME_GROUP_NAME }, 00084 { FCC_ENTROPY_TYPE, FCC_ENTROPY_NAME }, 00085 { FCC_ROT_TYPE, FCC_ROT_NAME }, 00086 { FCC_IS_ALIVE_SESSION_GROUP_TYPE, FCC_KEEP_ALIVE_SESSION_GROUP_NAME }, 00087 { FCC_KEY_GROUP_TYPE, FCC_KEY_GROUP_NAME }, 00088 { FCC_CERTIFICATE_GROUP_TYPE, FCC_CERTIFICATE_GROUP_NAME }, 00089 { FCC_CONFIG_PARAM_GROUP_TYPE, FCC_CONFIG_PARAM_GROUP_NAME }, 00090 { FCC_CERTIFICATE_CHAIN_GROUP_TYPE, FCC_CERTIFICATE_CHAIN_GROUP_NAME }, 00091 { FCC_VERIFY_DEVICE_IS_READY_TYPE, FCC_VERIFY_DEVICE_IS_READY_GROUP_NAME }, 00092 { FCC_FACTORY_DISABLE_TYPE, FCC_FACTORY_DISABLE_GROUP_NAME }, 00093 { FCC_FCU_SESSION_ID_GROUP_TYPE, FCC_FCU_SESSION_ID_GROUP_TYPE_NAME }, 00094 { FCC_CSR_REQUESTS_GROUP_TYPE, FCC_CSR_REQUESTS_GROUP_NAME } 00095 }; 00096 00097 00098 00099 00100 /* Response cbor blob structure 00101 00102 { "SchemeVersion": "0.0.1", 00103 "FCUSessionID": uint32_t, 00104 "Csrs": [ {"Name": "__", "Format":"_","Data":"__"}, 00105 {"Name": "__", "Format":"_","Data":"__"}], 00106 "WarningInfo": "string of warnings", 00107 "ReturnStatus": uint32_t, 00108 "InfoMessage": "detailed error string"} 00109 */ 00110 /** Prepare a response message 00111 * 00112 * The function prepare response buffer according to result of bundle buffer processing. 00113 * In case of failure, the function prepare buffer with status,scheme version and error logs, 00114 * in case of success - only the status and scheme version. 00115 * 00116 * @param bundle_response_out[in/out] The pointer to response buffer. 00117 * @param bundle_response_size_out[out/out] The size of response buffer. 00118 * @param fcc_status[in] The result of bundle buffer processing. 00119 * 00120 * @return 00121 * true for success, false otherwise. 00122 */ 00123 static bool prepare_reponse_message(uint8_t **bundle_response_out, size_t *bundle_response_size_out, fcc_status_e fcc_status, cn_cbor *encoder, const uint8_t *session_id, size_t session_id_len) 00124 { 00125 bool status = false; 00126 cn_cbor_errback err; 00127 cn_cbor *cbor_struct_cb = NULL; 00128 int size_of_cbor_buffer = 0; 00129 int size_of_out_buffer = 0; 00130 uint8_t *out_buffer = NULL; 00131 char *error_string_info = NULL; 00132 char *warning_string_info = NULL; 00133 const char success_message[] = { "The Factory process succeeded\n" }; 00134 *bundle_response_out = NULL; 00135 00136 SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS(); 00137 00138 // If error has occurred during bundle processing - create a new encoder (all that was encoded is not needed) 00139 // If no error occurred - the encoder will already have the scheme version and the FCU session ID inside an open map - therefore, in case of an error, we add them to a new map 00140 if (fcc_status != FCC_STATUS_SUCCESS) { 00141 // Free the old encoder and create a new one 00142 if (encoder) { 00143 cn_cbor_free(encoder CBOR_CONTEXT_PARAM); 00144 } 00145 encoder = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &err); 00146 SA_PV_ERR_RECOVERABLE_RETURN_IF((encoder == NULL), false, "Failed to create cbor map"); 00147 00148 /** 00149 * Create cbor with scheme version 00150 */ 00151 cbor_struct_cb = NULL; 00152 cbor_struct_cb = cn_cbor_text_create((const uint8_t *)fcc_bundle_scheme_version, sizeof(fcc_bundle_scheme_version) CBOR_CONTEXT_PARAM, &err); 00153 SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create scheme_version_cb "); 00154 00155 //Put the cbor scheme version in cbor map with string key "SchemeVersion" 00156 status = cn_cbor_mapput_string(encoder, FCC_BUNDLE_SCHEME_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err); 00157 SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed to put return status to cbor map"); 00158 00159 //Put the cbor session ID in cbor map with string key "SID" 00160 if(session_id != NULL) { 00161 cbor_struct_cb = cn_cbor_text_create(session_id, (int)session_id_len CBOR_CONTEXT_PARAM, &err); 00162 SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "CBOR error"); 00163 00164 status = cn_cbor_mapput_string(encoder, FCC_FCU_SESSION_ID_GROUP_TYPE_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err); 00165 SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed to put return session ID"); 00166 } 00167 } 00168 00169 00170 /** 00171 * Create cbor with return status 00172 */ 00173 cbor_struct_cb = cn_cbor_int_create(fcc_status CBOR_CONTEXT_PARAM, &err); 00174 SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create return_status_cb "); 00175 00176 //Put the cbor return status in cbor map with string key "ReturnStatus" 00177 status = cn_cbor_mapput_string(encoder, FCC_RETURN_STATUS_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err); 00178 SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put return status to cbor map"); 00179 00180 00181 /** 00182 * Create cbor with error info 00183 */ 00184 cbor_struct_cb = NULL; 00185 if (fcc_status == FCC_STATUS_SUCCESS) { 00186 cbor_struct_cb = cn_cbor_text_create((const uint8_t*)success_message, (int)strlen(success_message) CBOR_CONTEXT_PARAM, &err); 00187 } else { 00188 error_string_info = fcc_get_output_error_info(); 00189 if (error_string_info == NULL) { 00190 cbor_struct_cb = cn_cbor_text_create((const uint8_t*)g_fcc_general_status_error_str, (int)strlen(g_fcc_general_status_error_str) CBOR_CONTEXT_PARAM, &err); 00191 } else { 00192 cbor_struct_cb = cn_cbor_text_create((const uint8_t*)error_string_info, (int)strlen(error_string_info) CBOR_CONTEXT_PARAM, &err); 00193 } 00194 } 00195 SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create cbor_struct_cb "); 00196 00197 //Put the cbor info message in cbor map with string key "infoMessage" 00198 status = cn_cbor_mapput_string(encoder, FCC_ERROR_INFO_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err); 00199 SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put cbor_struct_cb to cbor map"); 00200 00201 /** 00202 * Create cbor with warning info 00203 */ 00204 cbor_struct_cb = NULL; 00205 status = fcc_get_warning_status(); 00206 warning_string_info = fcc_get_output_warning_info(); 00207 SA_PV_ERR_RECOVERABLE_GOTO_IF(status == true && warning_string_info == NULL, status = false, exit, "Failed to get created warnings"); 00208 if (warning_string_info != NULL) { 00209 cbor_struct_cb = cn_cbor_text_create((const uint8_t *)warning_string_info, (int)strlen(warning_string_info) CBOR_CONTEXT_PARAM, &err); 00210 SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create warning_message_cb "); 00211 00212 //Put the cbor info message in cbor map with string key "WarningInfo" 00213 status = cn_cbor_mapput_string(encoder, FCC_WARNING_INFO_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err); 00214 SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put warning_message_cb to cbor map"); 00215 } 00216 00217 status = true; 00218 //Get size of encoded cbor buffer 00219 size_of_cbor_buffer = cn_cbor_get_encoded_size(encoder, &err); 00220 SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_cbor_buffer == -1), status = false, exit, "Failed to get cbor buffer size"); 00221 00222 //Allocate out buffer 00223 out_buffer = fcc_malloc((size_t)size_of_cbor_buffer); 00224 SA_PV_ERR_RECOVERABLE_GOTO_IF((out_buffer == NULL), status = false, exit, "Failed to allocate memory for out buffer"); 00225 00226 //Write cbor blob to output buffer 00227 size_of_out_buffer = cn_cbor_encoder_write(encoder, out_buffer, size_of_cbor_buffer, &err); 00228 SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_out_buffer == -1), status = false, exit_without_out_buffer, "Failed to write cbor buffer to output buffer"); 00229 SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_out_buffer != size_of_cbor_buffer), status = false, exit_without_out_buffer, "Wrong written size for outbut buffer"); 00230 00231 //Update pointer and size of output buffer 00232 *bundle_response_out = out_buffer; 00233 *bundle_response_size_out = (size_t)size_of_out_buffer; 00234 goto exit; 00235 00236 exit_without_out_buffer: 00237 fcc_free(out_buffer); 00238 00239 // Nullify pointer so that the user cannot accidentally double free it. 00240 *bundle_response_out = NULL; 00241 exit: 00242 // FIXME: Free the CSRs buffer after the writing to the encoder buffer. Not needed after migration to tinycbor 00243 g_csr_buf_free(); 00244 fcc_free(warning_string_info); 00245 if (encoder != NULL) { 00246 cn_cbor_free(encoder CBOR_CONTEXT_PARAM); 00247 } 00248 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00249 return status; 00250 } 00251 00252 00253 /** Checks bundle scheme version 00254 * 00255 * @param cbor_blob[in] The pointer to main cbor blob. 00256 * @param encoder[in] Pointer to an encoder that points to the beginning of the CBOR response encoder 00257 * 00258 * FIXME: When we migrate to tinycbor encoder should be pointer to the encoder so that after encoding, the encoder will point to the next available spot in the response CBOR 00259 * @return 00260 * true for success, false otherwise. 00261 */ 00262 static bool check_scheme_version(cn_cbor *cbor_blob, cn_cbor *encoder) 00263 { 00264 cn_cbor *cbor = NULL; 00265 bool status; 00266 int result; 00267 00268 SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_blob == NULL), false, "Invalid cbor_blob"); 00269 00270 cbor = cn_cbor_mapget_string(cbor_blob, FCC_BUNDLE_SCHEME_GROUP_NAME); 00271 SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor == NULL), false, "Failed to find scheme version group"); 00272 00273 result = is_memory_equal(cbor->v.bytes, (size_t)(cbor->length), fcc_bundle_scheme_version, (size_t)strlen(fcc_bundle_scheme_version)); 00274 SA_PV_ERR_RECOVERABLE_RETURN_IF((!result), false, "Wrong scheme version"); 00275 00276 // append the scheme version key-value into the encoder 00277 cbor = cn_cbor_text_create((const uint8_t *)fcc_bundle_scheme_version, sizeof(fcc_bundle_scheme_version) CBOR_CONTEXT_PARAM, NULL); 00278 SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor == NULL), false, "Failed to create scheme_version_cb "); 00279 00280 status = cn_cbor_mapput_string(encoder, FCC_BUNDLE_SCHEME_GROUP_NAME, cbor, CBOR_CONTEXT_PARAM_COMMA NULL); 00281 SA_PV_ERR_RECOVERABLE_RETURN_IF((status == false), status, "CBOR error"); 00282 00283 return true; 00284 } 00285 00286 /** Checks the FCU session ID and encodes it into the encoder 00287 * 00288 * @param parser[in] Pointer to cbor containing the FCU session ID (the value of the KV pair where the key is FCC_FCU_SESSION_ID_GROUP_TYPE_NAME). 00289 * @param encoder[in] Pointer to an encoder that points to the beginning of the CBOR response encoder. 00290 * @param session_id[out] Pointer to a pointer that will point to the session ID in the incoming message. 00291 * @param session_id_len[out] The length of the session ID in the incoming message. 00292 * 00293 * FIXME: When we migrate to tinycbor encoder should be pointer to the encoder so that after encoding, the encoder will point to the next available spot in the response CBOR 00294 * @return 00295 * true for success, false otherwise. 00296 */ 00297 static bool fcc_bundle_process_session_id(cn_cbor *parser, cn_cbor *encoder, const uint8_t **session_id, size_t *session_id_len) 00298 { 00299 cn_cbor *cbor = NULL; 00300 bool status; 00301 00302 // Get the session ID from the message and make sure that it is either a text or bytes string 00303 SA_PV_ERR_RECOVERABLE_RETURN_IF((parser->type != CN_CBOR_TEXT), false, "Session ID of wrong type"); 00304 00305 // Output the values for use of the prepare_reponse_message() function in case of an error during the bundle handling process 00306 *session_id = (uint8_t *)parser->v.bytes; 00307 *session_id_len = (size_t)parser->length; 00308 00309 cbor = cn_cbor_text_create(*session_id, (int)*session_id_len CBOR_CONTEXT_PARAM, NULL); 00310 SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor == NULL), false, "CBOR error"); 00311 00312 // append the session id key-value into the encoder 00313 status = cn_cbor_mapput_string(encoder, FCC_FCU_SESSION_ID_GROUP_TYPE_NAME, cbor, CBOR_CONTEXT_PARAM_COMMA NULL); 00314 SA_PV_ERR_RECOVERABLE_RETURN_IF((status == false), false, "CBOR error"); 00315 00316 return true; 00317 } 00318 00319 00320 00321 /** The function parses group that indicates if current session will be closed after the processing of the message. 00322 * The function checks existence and value of the group and sets the result to global variable g_is_alive_sesssion. 00323 * 00324 * @param cbor_blob[in] The pointer to main cbor blob. 00325 * @return 00326 * true for success, false otherwise. 00327 */ 00328 static bool parse_keep_alive_session_group(cn_cbor *cbor_blob) 00329 { 00330 cn_cbor *is_alive_message = NULL; 00331 00332 is_alive_message = cn_cbor_mapget_string(cbor_blob, FCC_KEEP_ALIVE_SESSION_GROUP_NAME); 00333 //In case current group wasn't found - set g_is_not_last_message to false (for backward compatibility) 00334 if (is_alive_message == NULL) { 00335 g_is_session_finished = true; 00336 return true; 00337 } 00338 SA_PV_ERR_RECOVERABLE_RETURN_IF((is_alive_message->type != CN_CBOR_UINT || is_alive_message->v.uint > 1), false, "Wrong is alive session structure"); 00339 00340 // Session is finished if value is 0, and alive if value is 1 00341 g_is_session_finished = !(is_alive_message->v.uint); 00342 00343 return true; 00344 } 00345 00346 /* CBOR blob structure 00347 { "SchemeVersion": "0.0.1", 00348 "FCUSessionID": uint32_t, 00349 "IsNotLastMessage": 1 or 0, 00350 "Entropy": [byte array - 48 bytes], 00351 "Csrs": [ {"PrivKeyName":"__", 00352 "PubKeyName": "__", -optional 00353 "Extensions": [ 00354 {"TrustLevel": uint32_t }, 00355 { 00356 "KeyUsage": [uint32_t,uint32_t,unit32_t ], 00357 }, 00358 { 00359 "ExtendedKeyUsage": [byte array], 00360 }] 00361 "Subject": "C=__,ST=__ ,L=__, O=__,OU=__,CN=__,", 00362 }, 00363 { ... }, 00364 { ... } 00365 ], 00366 "ROT": "byte array", 00367 "Certificates": [ {"Name": "__", "Format":" _","Data":"__", "ACL" : "__"}, 00368 {..}, 00369 {"Name": "__", "Format":" _","Data":"__", "ACL" : "__"}], 00370 "Keys": [ {"Name": "__", "Type":"__", "Format":"__", "Data":"**","ACL" : "__"}, 00371 {"Name": "__", "Type":"__", "Format":"__", "Data":"**","ACL": "__"}, 00372 ... 00373 {"Name": "__", "Type":"__", "Format":"__", "Data":"**","ACL": "__"}], 00374 "ConfigParams": [ {"Name": "__", "Data":"__", "ACL" : "__"}, 00375 {"Name": "__", "Format":"__", "Data":"__", "ACL": "__"}, 00376 ..., 00377 {"Name": "__", "Format":"__", "Data":"__", "ACL": "__"}], 00378 "CertificateChains": [ {"Name": "mbed.CertificateChain", 00379 "DataArray":[h'3081870.....',h'308187020100...',h'308187020....'], 00380 "Format":"Der", 00381 "ACL":"_____"}, 00382 {"Name": "mbed.LwM2MCertificateChain", 00383 "DataArray":[h'308187...',h'30818702...',h'308187020...',h'308187020...',h'308187020...'], 00384 "Format":"Der", 00385 "ACL":"_____"}], 00386 "Verify":1, 00387 "Disable":1} 00388 */ 00389 fcc_status_e fcc_bundle_handler(const uint8_t *encoded_blob, size_t encoded_blob_size, uint8_t **bundle_response_out, size_t *bundle_response_size_out) 00390 { 00391 bool status = false; 00392 bool is_fcc_factory_disabled; 00393 fcc_status_e fcc_status = FCC_STATUS_SUCCESS; 00394 cn_cbor *main_list_cb = NULL; 00395 cn_cbor *group_value_cb = NULL; 00396 cn_cbor *response_cbor = NULL; 00397 cn_cbor_errback err; 00398 size_t group_index; 00399 fcc_bundle_param_group_type_e group_type; 00400 size_t num_of_groups_in_message = 0; 00401 const uint8_t *session_id = NULL; 00402 size_t session_id_len = 0; 00403 bool fcc_verify_status = true; // the default value of verify status is true 00404 bool fcc_disable_status = false;// the default value of disable status is false 00405 00406 00407 FCC_SET_START_TIMER(fcc_bundle_timer); 00408 00409 SA_PV_LOG_INFO_FUNC_ENTER("encoded_blob_size = %" PRIu32 "", (uint32_t)encoded_blob_size); 00410 00411 // Set *bundle_response_out to NULL before fcc_is_factory_disabled call so that in case factory is disabled - return FCC_STATUS_FACTORY_DISABLED_ERROR and nullify *bundle_response_out 00412 if (bundle_response_out != NULL) { 00413 // Set to NULL so that the user does not accidentally free a non NULL pointer after the function returns. 00414 *bundle_response_out = NULL; 00415 } 00416 00417 // Check if factory flow is disabled, if yes, do not proceed 00418 fcc_status = fcc_is_factory_disabled(&is_fcc_factory_disabled); 00419 SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed for fcc_is_factory_disabled"); 00420 SA_PV_ERR_RECOVERABLE_RETURN_IF((is_fcc_factory_disabled), FCC_STATUS_FACTORY_DISABLED_ERROR, "FCC is disabled, service not available"); 00421 00422 // Check params 00423 SA_PV_ERR_RECOVERABLE_RETURN_IF((bundle_response_out == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid bundle_response_out"); 00424 00425 SA_PV_ERR_RECOVERABLE_RETURN_IF((bundle_response_size_out == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid bundle_response_size_out"); 00426 SA_PV_ERR_RECOVERABLE_GOTO_IF((encoded_blob == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Invalid encoded_blob"); 00427 SA_PV_ERR_RECOVERABLE_GOTO_IF((encoded_blob_size == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Invalid encoded_blob_size"); 00428 00429 /*Initialize fcc_output_info_s structure , in case of error during store process the 00430 function will exit without fcc_verify_device_configured_4mbed_cloud where we perform additional fcc_clean_output_info_handler*/ 00431 fcc_clean_output_info_handler(); 00432 00433 // Create the CBOR encoder, an empty map 00434 response_cbor = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &err); 00435 SA_PV_ERR_RECOVERABLE_GOTO_IF((response_cbor == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, exit, "Failed to instatiate cbor structure"); 00436 00437 /* Decode CBOR message 00438 Check the size of the CBOR structure */ 00439 main_list_cb = cn_cbor_decode(encoded_blob, encoded_blob_size CBOR_CONTEXT_PARAM, &err); 00440 SA_PV_ERR_RECOVERABLE_GOTO_IF((main_list_cb == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "cn_cbor_decode failed (%" PRIu32 ")", (uint32_t)err.err); 00441 SA_PV_ERR_RECOVERABLE_GOTO_IF((main_list_cb->type != CN_CBOR_MAP), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "Wrong CBOR structure type"); 00442 SA_PV_ERR_RECOVERABLE_GOTO_IF((main_list_cb->length <= 0 || main_list_cb->length > FCC_MAX_CONFIG_PARAM_GROUP_TYPE *FCC_CBOR_MAP_LENGTH), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "Wrong CBOR structure size"); 00443 00444 /* Check scheme version*/ 00445 status = check_scheme_version(main_list_cb, response_cbor); 00446 SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), fcc_status = FCC_STATUS_BUNDLE_INVALID_SCHEME, free_cbor_list_and_out, "check_scheme_version failed"); 00447 00448 /* Parse and save is message status */ 00449 status = parse_keep_alive_session_group(main_list_cb); 00450 SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), fcc_status = FCC_STATUS_BUNDLE_INVALID_KEEP_ALIVE_SESSION_STATUS, free_cbor_list_and_out, "parse_keep_alive_session_group failed"); 00451 00452 //Go over parameter groups 00453 for (group_index = 0; group_index < FCC_MAX_CONFIG_PARAM_GROUP_TYPE; group_index++) { 00454 //Get content of current group (value of map, when key of map is name of group and value is list of params of current group) 00455 SA_PV_LOG_INFO(" fcc_groups_lookup_table[group_index].group_name is %s", fcc_groups_lookup_table[group_index].group_name); 00456 group_value_cb = cn_cbor_mapget_string(main_list_cb, fcc_groups_lookup_table[group_index].group_name); 00457 00458 if (group_value_cb != NULL) { 00459 //Get type of group 00460 group_type = fcc_groups_lookup_table[group_index].group_type; 00461 num_of_groups_in_message++; 00462 00463 switch (group_type) { 00464 case FCC_SCHEME_VERSION_TYPE: 00465 break; 00466 case FCC_ENTROPY_TYPE: // Entropy for random generator 00467 fcc_status = fcc_bundle_process_sotp_buffer(group_value_cb, SOTP_TYPE_RANDOM_SEED); 00468 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_sotp_buffer failed for entropy"); 00469 break; 00470 case FCC_ROT_TYPE: // Key for ESFS 00471 fcc_status = fcc_bundle_process_sotp_buffer(group_value_cb, SOTP_TYPE_ROT); 00472 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_sotp_buffer failed for ROT"); 00473 break; 00474 case FCC_IS_ALIVE_SESSION_GROUP_TYPE: 00475 break; 00476 case FCC_KEY_GROUP_TYPE: 00477 FCC_SET_START_TIMER(fcc_gen_timer); 00478 fcc_status = fcc_bundle_process_keys(group_value_cb); 00479 FCC_END_TIMER("Total keys process", 0 ,fcc_gen_timer); 00480 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_keys failed"); 00481 break; 00482 case FCC_CERTIFICATE_GROUP_TYPE: 00483 FCC_SET_START_TIMER(fcc_gen_timer); 00484 fcc_status = fcc_bundle_process_certificates(group_value_cb); 00485 FCC_END_TIMER("Total certificates process", 0, fcc_gen_timer); 00486 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_certificates failed"); 00487 break; 00488 case FCC_CONFIG_PARAM_GROUP_TYPE: 00489 FCC_SET_START_TIMER(fcc_gen_timer); 00490 fcc_status = fcc_bundle_process_config_params(group_value_cb); 00491 FCC_END_TIMER("Total config params process", 0, fcc_gen_timer); 00492 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_config_params failed"); 00493 break; 00494 case FCC_CERTIFICATE_CHAIN_GROUP_TYPE: 00495 FCC_SET_START_TIMER(fcc_gen_timer); 00496 fcc_status = fcc_bundle_process_certificate_chains(group_value_cb); 00497 FCC_END_TIMER("Total certificate chains process", 0, fcc_gen_timer); 00498 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_certificate_chains failed"); 00499 break; 00500 case FCC_VERIFY_DEVICE_IS_READY_TYPE: //Check if device need to be verified 00501 fcc_status = bundle_process_status_field(group_value_cb, (char*)FCC_VERIFY_DEVICE_IS_READY_GROUP_NAME, strlen((char*)FCC_VERIFY_DEVICE_IS_READY_GROUP_NAME), &fcc_verify_status); 00502 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "process_device_verify failed"); 00503 break; 00504 case FCC_FACTORY_DISABLE_TYPE://Check if device need to be disabled for factory 00505 fcc_status = bundle_process_status_field(group_value_cb, (char*)FCC_FACTORY_DISABLE_GROUP_NAME, strlen((char*)FCC_FACTORY_DISABLE_GROUP_NAME), &fcc_disable_status); 00506 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_factory_disable failed"); 00507 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_disable_status == true && g_is_session_finished == false), fcc_status = FCC_STATUS_BUNDLE_INVALID_KEEP_ALIVE_SESSION_STATUS, free_cbor_list_and_out, "can not disable fcc for intermidiate message"); 00508 break; 00509 case FCC_FCU_SESSION_ID_GROUP_TYPE: 00510 status = fcc_bundle_process_session_id(group_value_cb, response_cbor, &session_id, &session_id_len); 00511 SA_PV_ERR_RECOVERABLE_GOTO_IF((!status), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "fcc_bundle_process_session_id failed"); 00512 break; 00513 case FCC_CSR_REQUESTS_GROUP_TYPE: 00514 SA_PV_ERR_RECOVERABLE_GOTO_IF((session_id == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "Session ID is required when providing CSR requests"); 00515 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_verify_status || fcc_disable_status), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "Verify and Disable flags must not exist with CSR requests"); 00516 fcc_status = fcc_bundle_process_csrs(group_value_cb, response_cbor); 00517 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_csrs failed"); 00518 break; 00519 default: 00520 fcc_status = FCC_STATUS_BUNDLE_UNSUPPORTED_GROUP; 00521 SA_PV_LOG_ERR("Wrong group type"); 00522 goto free_cbor_list_and_out; 00523 } 00524 } 00525 } 00526 00527 SA_PV_ERR_RECOVERABLE_GOTO_IF((num_of_groups_in_message == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, free_cbor_list_and_out, "No groups in message"); 00528 SA_PV_ERR_RECOVERABLE_GOTO_IF(((size_t)(main_list_cb->length/FCC_CBOR_MAP_LENGTH)!= num_of_groups_in_message), fcc_status = FCC_STATUS_BUNDLE_INVALID_GROUP, free_cbor_list_and_out, "One ore more names of groups are invalid"); 00529 00530 // If not keep alive 00531 if (g_is_session_finished) { 00532 // Note that FCC_STATUS_CA_ERROR is being return only in case where the CA already exists 00533 // in SOTP, if in the future more error conditions will be attached to FCC_STATUS_CA_ERROR error code 00534 // then the logic here MUST be change. 00535 // Only if this is the last message - set the certificate ID 00536 fcc_status = fcc_trust_ca_cert_id_set(); 00537 SA_PV_ERR_RECOVERABLE_GOTO_IF(((fcc_status != FCC_STATUS_SUCCESS) && (fcc_status != FCC_STATUS_CA_ERROR)), (fcc_status = fcc_status), free_cbor_list_and_out, "CA store error %u", fcc_status); 00538 00539 } 00540 00541 if (fcc_verify_status == true) { 00542 // device VERIFY group does NOT exist in the CBOR message and device is NOT disabled. 00543 // Perform device verification to keep backward compatibility. 00544 00545 00546 FCC_SET_START_TIMER(fcc_gen_timer); 00547 fcc_status = fcc_verify_device_configured_4mbed_cloud(); 00548 FCC_END_TIMER("Total verify device", 0, fcc_gen_timer); 00549 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_verify_device_configured_4mbed_cloud failed"); 00550 } 00551 00552 if (fcc_disable_status == true) { 00553 fcc_status = fcc_bundle_factory_disable(); 00554 SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_factory_disable failed"); 00555 } 00556 00557 free_cbor_list_and_out: 00558 cn_cbor_free(main_list_cb CBOR_CONTEXT_PARAM); 00559 exit: 00560 //Prepare bundle response message 00561 status = prepare_reponse_message(bundle_response_out, bundle_response_size_out, fcc_status, response_cbor, session_id, session_id_len); 00562 SA_PV_ERR_RECOVERABLE_RETURN_IF((status != true), FCC_STATUS_BUNDLE_RESPONSE_ERROR, "Failed to prepare out response"); 00563 SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS(); 00564 FCC_END_TIMER("Total fcc_bundle_handler device", 0, fcc_bundle_timer); 00565 00566 return fcc_status; 00567 } 00568 #endif
Generated on Tue Jul 12 2022 19:12:12 by 1.7.2