Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fcc_bundle_handler.c Source File

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 #include "fcc_bundle_handler.h"
00017 #include "cn-cbor.h"
00018 #include "pv_error_handling.h"
00019 #include "factory_configurator_client.h"
00020 #include "fcc_bundle_utils.h"
00021 #include "fcc_output_info_handler.h"
00022 #include "fcc_malloc.h"
00023 #include "fcc_sotp.h"
00024 #include "general_utils.h"
00025 #include "fcc_time_profiling.h"
00026 #include "fcc_utils.h"
00027 
00028 /**
00029 * Defines for cbor layer
00030 */
00031 #ifdef USE_CBOR_CONTEXT
00032 #define CONTEXT_NULL , NULL
00033 #define CONTEXT_NULL_COMMA NULL,
00034 #else
00035 #define CONTEXT_NULL
00036 #define CONTEXT_NULL_COMMA
00037 #endif
00038 
00039 /**
00040 * Definition of size and value of current protocol scheme version
00041 */
00042 #define FCC_SIZE_OF_VERSION_FIELD 5
00043 const char fcc_bundle_scheme_version[] = "0.0.1";
00044 /**
00045 * Types of configuration parameter groups
00046 */
00047 typedef enum {
00048     FCC_KEY_GROUP_TYPE,                //!< Key group type
00049     FCC_CERTIFICATE_GROUP_TYPE,        //!< Certificate group type
00050     FCC_CSR_GROUP_TYPE,                //!< CSR group type
00051     FCC_CONFIG_PARAM_GROUP_TYPE,       //!< Configuration parameter group type
00052     FCC_CERTIFICATE_CHAIN_GROUP_TYPE,  //!< Certificate chain group type
00053     FCC_SCHEME_VERSION_TYPE,           //!< Scheme version group type
00054     FCC_ENTROPY_TYPE,                  //!< Entropy group type
00055     FCC_ROT_TYPE,                      //!< Root of trust group type
00056     FCC_VERIFY_DEVICE_IS_READY_TYPE,   //!< Verify device readiness type
00057     FCC_FACTORY_DISABLE_TYPE,             //!< Disable FCC flow type
00058     FCC_MAX_CONFIG_PARAM_GROUP_TYPE    //!< Max group type
00059 } fcc_bundle_param_group_type_e;
00060 /**
00061 * Group lookup record, correlating group's type and name
00062 */
00063 typedef struct fcc_bundle_group_lookup_record_ {
00064     fcc_bundle_param_group_type_e group_type;
00065     const char *group_name;
00066 } fcc_bundle_group_lookup_record_s;
00067 /**
00068 * Group lookup table, correlating for each group its type and name.
00069 * Order is important - it is the order that fcc_bundle_handler() reads the cbor fields.
00070 * FCC_ENTROPY_TYPE and FCC_ROT_TYPE Must be processed first and second respectively.
00071 */
00072 static const fcc_bundle_group_lookup_record_s fcc_groups_lookup_table[FCC_MAX_CONFIG_PARAM_GROUP_TYPE] = {
00073     { FCC_SCHEME_VERSION_TYPE,           FCC_BUNDLE_SCHEME_GROUP_NAME },
00074     { FCC_ENTROPY_TYPE,                  FCC_ENTROPY_NAME },
00075     { FCC_ROT_TYPE,                      FCC_ROT_NAME },
00076     { FCC_KEY_GROUP_TYPE,                FCC_KEY_GROUP_NAME },
00077     { FCC_CERTIFICATE_GROUP_TYPE,        FCC_CERTIFICATE_GROUP_NAME },
00078     { FCC_CSR_GROUP_TYPE,                FCC_CSR_GROUP_NAME },
00079     { FCC_CONFIG_PARAM_GROUP_TYPE,       FCC_CONFIG_PARAM_GROUP_NAME },
00080     { FCC_CERTIFICATE_CHAIN_GROUP_TYPE,  FCC_CERTIFICATE_CHAIN_GROUP_NAME },
00081     { FCC_VERIFY_DEVICE_IS_READY_TYPE,   FCC_VERIFY_DEVICE_IS_READY_GROUP_NAME },
00082     { FCC_FACTORY_DISABLE_TYPE,          FCC_FACTORY_DISABLE_GROUP_NAME },
00083 };
00084 
00085 /** Prepare a response message
00086 *
00087 * The function prepare response buffer according to result of bundle buffer processing.
00088 * In case of failure, the function prepare buffer with status,scheme version and error logs,
00089 * in case of success - only the status and scheme version.
00090 *
00091 * @param bundle_response_out[in/out]   The pointer to response buffer.
00092 * @param bundle_response_size_out[out/out]     The size of response buffer.
00093 * @param fcc_status[in]     The result of bundle buffer processing.
00094 * @return
00095 *     true for success, false otherwise.
00096 */
00097 static bool prepare_reponse_message(uint8_t **bundle_response_out, size_t *bundle_response_size_out, fcc_status_e  fcc_status)
00098 {
00099     bool status = false;
00100     cn_cbor_errback err;
00101     cn_cbor *cb_map = NULL;
00102     cn_cbor *cbor_struct_cb = NULL;
00103     int size_of_cbor_buffer = 0;
00104     int size_of_out_buffer = 0;
00105     uint8_t *out_buffer = NULL;
00106     char *error_string_info = NULL;
00107     char *warning_string_info = NULL;
00108     const char success_message[] = { "The Factory process succeeded\n" };
00109     *bundle_response_out = NULL;
00110 
00111     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00112 
00113     cb_map = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &err);
00114     SA_PV_ERR_RECOVERABLE_RETURN_IF((cb_map == NULL), false, "Failed to create cbor map");
00115 
00116     /**
00117     * Create cbor with return status
00118     */
00119     cbor_struct_cb = cn_cbor_int_create(fcc_status CBOR_CONTEXT_PARAM, &err);
00120     SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create return_status_cb ");
00121 
00122     //Put the cbor return status in cbor map with string key "ReturnStatus"
00123     status = cn_cbor_mapput_string(cb_map, FCC_RETURN_STATUS_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err);
00124     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put return status to cbor map");
00125 
00126     /**
00127     * Create cbor with scheme version
00128     */
00129     cbor_struct_cb = NULL;
00130     cbor_struct_cb = cn_cbor_data_create((const uint8_t *)fcc_bundle_scheme_version,sizeof(fcc_bundle_scheme_version) CBOR_CONTEXT_PARAM, &err);
00131     SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create scheme_version_cb ");
00132 
00133     //Put the cbor return status in cbor map with string key "SchemeVersion"
00134     status = cn_cbor_mapput_string(cb_map, FCC_BUNDLE_SCHEME_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err);
00135     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put return status to cbor map");
00136 
00137     /**
00138     * Create cbor with error info
00139     */
00140     cbor_struct_cb = NULL;
00141     if (fcc_status == FCC_STATUS_SUCCESS) {
00142         cbor_struct_cb = cn_cbor_data_create((const uint8_t*)success_message, (int)strlen(success_message) CBOR_CONTEXT_PARAM, &err);
00143     } else {
00144         error_string_info = fcc_get_output_error_info();
00145         if (error_string_info == NULL) {
00146             cbor_struct_cb = cn_cbor_data_create((const uint8_t*)g_fcc_general_status_error_str, (int)strlen(g_fcc_general_status_error_str) CBOR_CONTEXT_PARAM, &err);
00147         } else {
00148             cbor_struct_cb = cn_cbor_data_create((const uint8_t*)error_string_info, (int)strlen(error_string_info) CBOR_CONTEXT_PARAM, &err);
00149        }
00150     }
00151     SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create cbor_struct_cb ");
00152 
00153     //Put the cbor info message in cbor map with string key "infoMessage"
00154     status = cn_cbor_mapput_string(cb_map, FCC_ERROR_INFO_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err);
00155     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put cbor_struct_cb to cbor map");
00156 
00157     /**
00158     * Create cbor with warning info
00159     */
00160     cbor_struct_cb = NULL;
00161     status = fcc_get_warning_status();
00162     warning_string_info = fcc_get_output_warning_info();
00163     SA_PV_ERR_RECOVERABLE_GOTO_IF(status == true && warning_string_info == NULL, status = false, exit, "Failed to get created warnings");
00164     if (warning_string_info != NULL) {
00165         cbor_struct_cb = cn_cbor_data_create((const uint8_t *)warning_string_info, (int)strlen(warning_string_info) CBOR_CONTEXT_PARAM, &err);
00166         SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create warning_message_cb ");
00167 
00168         //Put the cbor info message in cbor map with string key "WarningInfo"
00169         status = cn_cbor_mapput_string(cb_map, FCC_WARNING_INFO_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err);
00170         SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put warning_message_cb to cbor map");
00171     } 
00172 
00173     status = true;
00174     //Get size of encoded cbor buffer
00175     size_of_cbor_buffer = cn_cbor_get_encoded_size(cb_map, &err);
00176     SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_cbor_buffer == -1), status = false, exit, "Failed to get cbor buffer size");
00177 
00178     //Allocate out buffer
00179     out_buffer = fcc_malloc((size_t)size_of_cbor_buffer);
00180     SA_PV_ERR_RECOVERABLE_GOTO_IF((out_buffer == NULL), status = false, exit, "Failed to allocate memory for out buffer");
00181 
00182     //Write cbor blob to output buffer
00183     size_of_out_buffer = cn_cbor_encoder_write(cb_map, out_buffer, size_of_cbor_buffer, &err);
00184     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");
00185     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");
00186 
00187     //Update pointer and size of output buffer
00188     *bundle_response_out = out_buffer;
00189     *bundle_response_size_out = (size_t)size_of_out_buffer;
00190     goto exit;
00191 
00192 exit_without_out_buffer:
00193     fcc_free(out_buffer);
00194 
00195     // Nullify pointer so that the user cannot accidentally double free it.
00196     *bundle_response_out = NULL;
00197 exit:
00198     fcc_free(warning_string_info);
00199     if (cb_map != NULL) {
00200         cn_cbor_free(cb_map CBOR_CONTEXT_PARAM);
00201     }
00202     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00203     return status;
00204 }
00205 
00206 /** Checks bundle scheme version
00207 *
00208 * @param cbor_blob[in]   The pointer to main cbor blob.
00209 * @return
00210 *     true for success, false otherwise.
00211 */
00212 static bool check_scheme_version(cn_cbor *cbor_blob)
00213 {
00214     cn_cbor *scheme_version_cb = NULL;
00215     int result;
00216 
00217     SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_blob == NULL), false, "Invalid cbor_blob");
00218 
00219     scheme_version_cb = cn_cbor_mapget_string(cbor_blob, FCC_BUNDLE_SCHEME_GROUP_NAME);
00220     SA_PV_ERR_RECOVERABLE_RETURN_IF((scheme_version_cb == NULL), false, "Failed to find scheme version group");
00221 
00222     result = is_memory_equal(scheme_version_cb->v.bytes, (size_t)(scheme_version_cb->length), fcc_bundle_scheme_version, (size_t)strlen(fcc_bundle_scheme_version));
00223     SA_PV_ERR_RECOVERABLE_RETURN_IF((!result), false, "Wrong scheme version");
00224 
00225     return true;
00226 }
00227 
00228 
00229 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)
00230 {
00231     bool status = false;
00232     bool is_fcc_factory_disabled;
00233     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00234     cn_cbor *main_list_cb = NULL;
00235     cn_cbor *group_value_cb = NULL;
00236     cn_cbor_errback err;
00237     size_t group_index;
00238     fcc_bundle_param_group_type_e group_type;
00239     size_t num_of_groups_in_message = 0;
00240     bool fcc_verify_status = true; // the default value of verify status is true
00241     bool fcc_disable_status = false;// the default value of dasable status is false
00242 
00243 
00244     FCC_SET_START_TIMER(fcc_bundle_timer);
00245 
00246     SA_PV_LOG_INFO_FUNC_ENTER("encoded_blob_size = %" PRIu32 "", (uint32_t)encoded_blob_size);
00247 
00248     // 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
00249     if (bundle_response_out != NULL) {
00250         // Set to NULL so that the user does not accidentally free a non NULL pointer after the function returns.
00251         *bundle_response_out = NULL;
00252     }
00253 
00254     // Check if factory flow is disabled, if yes, do not proceed
00255     fcc_status = fcc_is_factory_disabled(&is_fcc_factory_disabled);
00256     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed for fcc_is_factory_disabled");
00257     SA_PV_ERR_RECOVERABLE_RETURN_IF((is_fcc_factory_disabled), FCC_STATUS_FACTORY_DISABLED_ERROR, "FCC is disabled, service not available");
00258 
00259     // Check params
00260     SA_PV_ERR_RECOVERABLE_RETURN_IF((bundle_response_out == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid bundle_response_out");
00261     
00262 
00263     SA_PV_ERR_RECOVERABLE_RETURN_IF((bundle_response_size_out == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid bundle_response_size_out");
00264     SA_PV_ERR_RECOVERABLE_GOTO_IF((encoded_blob == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Invalid encoded_blob");
00265     SA_PV_ERR_RECOVERABLE_GOTO_IF((encoded_blob_size == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Invalid encoded_blob_size");
00266 
00267     /*Initialize fcc_output_info_s structure , in case of error during store process the
00268     function will exit without fcc_verify_device_configured_4mbed_cloud where we perform additional fcc_clean_output_info_handler*/
00269     fcc_clean_output_info_handler();
00270 
00271     /* Decode CBOR message
00272     Check the size of the CBOR structure */
00273     main_list_cb = cn_cbor_decode(encoded_blob, encoded_blob_size CBOR_CONTEXT_PARAM, &err);
00274     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);
00275     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");
00276     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");
00277 
00278     /* Check scheme version*/
00279     status = check_scheme_version(main_list_cb);
00280     SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), fcc_status = FCC_STATUS_BUNDLE_INVALID_SCHEME, free_cbor_list_and_out, "check_scheme_version failed");
00281 
00282     //Go over parameter groups
00283     for (group_index = 0; group_index < FCC_MAX_CONFIG_PARAM_GROUP_TYPE; group_index++) {
00284         //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)
00285         SA_PV_LOG_INFO(" fcc_groups_lookup_table[group_index].group_name is %s", fcc_groups_lookup_table[group_index].group_name);
00286         group_value_cb = cn_cbor_mapget_string(main_list_cb, fcc_groups_lookup_table[group_index].group_name);
00287 
00288         if (group_value_cb != NULL) {
00289             //Get type of group
00290             group_type = fcc_groups_lookup_table[group_index].group_type;
00291             num_of_groups_in_message++;
00292 
00293             switch (group_type) {
00294                 case FCC_SCHEME_VERSION_TYPE:
00295                     break;
00296                 case FCC_KEY_GROUP_TYPE:
00297                     FCC_SET_START_TIMER(fcc_gen_timer);
00298                     fcc_status = fcc_bundle_process_keys(group_value_cb);
00299                     FCC_END_TIMER("Total keys process", 0 ,fcc_gen_timer);
00300                     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");
00301                     break;
00302                 case FCC_CERTIFICATE_GROUP_TYPE:
00303                     FCC_SET_START_TIMER(fcc_gen_timer);
00304                     fcc_status = fcc_bundle_process_certificates(group_value_cb);
00305                     FCC_END_TIMER("Total certificates process", 0, fcc_gen_timer);
00306                     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");
00307                     break;
00308                 case FCC_CONFIG_PARAM_GROUP_TYPE:
00309                     FCC_SET_START_TIMER(fcc_gen_timer);
00310                     fcc_status = fcc_bundle_process_config_params(group_value_cb);
00311                     FCC_END_TIMER("Total config params process", 0, fcc_gen_timer);
00312                     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");
00313                     break;
00314                 case FCC_CERTIFICATE_CHAIN_GROUP_TYPE:
00315                     FCC_SET_START_TIMER(fcc_gen_timer);
00316                     fcc_status = fcc_bundle_process_certificate_chains(group_value_cb);
00317                     FCC_END_TIMER("Total certificate chains process", 0, fcc_gen_timer);
00318                     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");
00319                     break;
00320                 case FCC_ENTROPY_TYPE: // Entropy for random generator
00321                     fcc_status = fcc_bundle_process_sotp_buffer(group_value_cb, SOTP_TYPE_RANDOM_SEED);
00322                     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");
00323                     break;
00324                 case FCC_ROT_TYPE: // Key for ESFS
00325                     fcc_status = fcc_bundle_process_sotp_buffer(group_value_cb, SOTP_TYPE_ROT);
00326                     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");
00327                     break;
00328                 case FCC_VERIFY_DEVICE_IS_READY_TYPE: //Check if device need to be verified
00329                     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);
00330                     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "process_device_verify failed");
00331                     break;
00332                 case FCC_FACTORY_DISABLE_TYPE://Check if device need to be disabled for factory
00333                     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);
00334                     SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_factory_disable failed");
00335                     break;
00336                 default:
00337                     fcc_status = FCC_STATUS_BUNDLE_UNSUPPORTED_GROUP;
00338                     SA_PV_LOG_ERR("Wrong group type");
00339                     goto free_cbor_list_and_out;
00340             }
00341         }
00342     }
00343 
00344     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");
00345     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");
00346 
00347     // Note that FCC_STATUS_CA_ERROR is being return only in case where the CA is already exist
00348     // in SOTP, if in the future more error conditions will be attached to FCC_STATUS_CA_ERROR error code
00349     // then the logic here MUST be change.
00350     fcc_status = fcc_trust_ca_cert_id_set();
00351     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);
00352 
00353     if (fcc_verify_status == true) {
00354         // device VERIFY group does NOT exist in the CBOR message and device is NOT disabled.
00355         // Perform device verification to keep backward compatibility.
00356         FCC_SET_START_TIMER(fcc_gen_timer);
00357         fcc_status = fcc_verify_device_configured_4mbed_cloud();
00358         FCC_END_TIMER("Total verify device", 0, fcc_gen_timer);
00359         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");
00360     }
00361 
00362     if (fcc_disable_status == true) {
00363         fcc_status = fcc_bundle_factory_disable();
00364         SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_factory_disable failed");
00365     }
00366 
00367 free_cbor_list_and_out:
00368     cn_cbor_free(main_list_cb CBOR_CONTEXT_PARAM);
00369 
00370 exit:
00371     //Prepare bundle response message
00372     status = prepare_reponse_message(bundle_response_out, bundle_response_size_out, fcc_status);
00373     SA_PV_ERR_RECOVERABLE_RETURN_IF((status != true), FCC_STATUS_BUNDLE_RESPONSE_ERROR, "Failed to prepare out response");
00374     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00375     FCC_END_TIMER("Total fcc_bundle_handler device", 0, fcc_bundle_timer);
00376     return fcc_status;
00377 }