leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers factory_configurator_client.c Source File

factory_configurator_client.c

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2018 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 "key_config_manager.h"
00019 #include "pv_error_handling.h"
00020 #include "fcc_verification.h"
00021 #include "storage.h"
00022 #include "fcc_defs.h"
00023 #include "fcc_malloc.h"
00024 #include "common_utils.h"
00025 #include "pal.h"
00026 #include "fcc_utils.h"
00027 
00028 /**
00029 * Device general info
00030 */
00031 const char g_fcc_use_bootstrap_parameter_name[] = "mbed.UseBootstrap";
00032 const char g_fcc_endpoint_parameter_name[] = "mbed.EndpointName";
00033 const char g_fcc_account_id_parameter_name[] = "mbed.AccountID";
00034 const char g_fcc_first_to_claim_parameter_name[] = "mbed.FirstToClaim";
00035 
00036 /**
00037 * Device meta data
00038 */
00039 const char g_fcc_manufacturer_parameter_name[] = "mbed.Manufacturer";
00040 const char g_fcc_model_number_parameter_name[] = "mbed.ModelNumber";
00041 const char g_fcc_device_type_parameter_name[] = "mbed.DeviceType";
00042 const char g_fcc_hardware_version_parameter_name[] = "mbed.HardwareVersion";
00043 const char g_fcc_memory_size_parameter_name[] = "mbed.MemoryTotalKB";
00044 const char g_fcc_device_serial_number_parameter_name[] = "mbed.SerialNumber";
00045 /**
00046 * Time Synchronization
00047 */
00048 const char g_fcc_current_time_parameter_name[] = "mbed.CurrentTime";
00049 const char g_fcc_device_time_zone_parameter_name[] = "mbed.Timezone";
00050 const char g_fcc_offset_from_utc_parameter_name[] = "mbed.UTCOffset";
00051 /**
00052 * Bootstrap configuration
00053 */
00054 const char g_fcc_bootstrap_server_ca_certificate_name[] = "mbed.BootstrapServerCACert";
00055 const char g_fcc_bootstrap_server_crl_name[] = "mbed.BootstrapServerCRL";
00056 const char g_fcc_bootstrap_server_uri_name[] = "mbed.BootstrapServerURI";
00057 const char g_fcc_bootstrap_device_certificate_name[] = "mbed.BootstrapDeviceCert";
00058 const char g_fcc_bootstrap_device_private_key_name[] = "mbed.BootstrapDevicePrivateKey";
00059 /**
00060 * LWm2m configuration
00061 */
00062 const char g_fcc_lwm2m_server_ca_certificate_name[] = "mbed.LwM2MServerCACert";
00063 const char g_fcc_lwm2m_server_crl_name[] = "mbed.LwM2MServerCRL";
00064 const char g_fcc_lwm2m_server_uri_name[] = "mbed.LwM2MServerURI";
00065 const char g_fcc_lwm2m_device_certificate_name[] = "mbed.LwM2MDeviceCert";
00066 const char g_fcc_lwm2m_device_private_key_name[] = "mbed.LwM2MDevicePrivateKey";
00067 /**
00068 * Firmware update
00069 */
00070 const char g_fcc_update_authentication_certificate_name[] = "mbed.UpdateAuthCert";
00071 const char g_fcc_class_id_name[] = "mbed.ClassId";
00072 const char g_fcc_vendor_id_name[] = "mbed.VendorId";
00073 
00074 static bool g_is_fcc_initialized = false;
00075 bool g_is_session_finished = true;
00076 
00077 fcc_status_e  fcc_init(void)
00078 {
00079     palStatus_t pal_status;
00080 
00081     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00082 
00083     if (g_is_fcc_initialized) {
00084         // No need for second initialization
00085         return FCC_STATUS_SUCCESS;
00086     }
00087     
00088     pal_status = pal_init();
00089     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_ERR_INIT_SOTP_FAILED ), FCC_STATUS_STORE_ERROR, "Failed initializing internal storage (%" PRIu32 ")", pal_status);
00090     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), FCC_STATUS_ERROR, "Failed initializing PAL (%" PRIu32 ")", pal_status);
00091     
00092     //Initialize output info handler
00093     fcc_init_output_info_handler();
00094 
00095     g_is_fcc_initialized = true;
00096 
00097     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00098 
00099     return FCC_STATUS_SUCCESS;
00100 }
00101 
00102 fcc_status_e  fcc_finalize(void)
00103 {
00104     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00105     kcm_status_e  kcm_status = KCM_STATUS_SUCCESS;
00106 
00107     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00108 
00109     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
00110 
00111     //FIXME: add relevant error handling - general task for all APIs.
00112     //It is okay to finalize KCM here since it's already initialized beforehand.
00113     kcm_status = kcm_finalize();
00114     if (kcm_status != KCM_STATUS_SUCCESS) {
00115         fcc_status = FCC_STATUS_ERROR;
00116         SA_PV_LOG_ERR("Failed finalizing KCM");
00117     }
00118 
00119     //Finalize output info handler
00120     fcc_clean_output_info_handler();
00121 
00122     //Finalize PAL
00123     pal_destroy();
00124 
00125     g_is_fcc_initialized = false;
00126     g_is_session_finished = true;
00127 
00128     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00129 
00130     return fcc_status;
00131 }
00132 
00133 fcc_status_e  fcc_storage_delete()
00134 {
00135     kcm_status_e  status = KCM_STATUS_SUCCESS;
00136 
00137     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00138 
00139 //when using SST don't check this since we want to delete storage before initialization
00140 #ifndef MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT
00141     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
00142 #endif
00143     status = storage_reset();
00144     SA_PV_ERR_RECOVERABLE_RETURN_IF((status == KCM_STATUS_ESFS_ERROR), FCC_STATUS_KCM_STORAGE_ERROR, "Failed in storage_reset. got ESFS error");
00145     SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), FCC_STATUS_ERROR, "Failed storage reset");
00146 
00147     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00148     return FCC_STATUS_SUCCESS;
00149 }
00150 
00151 fcc_output_info_s* fcc_get_error_and_warning_data(void)
00152 {
00153     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00154 
00155     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), NULL, "FCC not initialized");
00156 
00157     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00158 
00159     return get_output_info();
00160 }
00161 
00162 bool fcc_is_session_finished(void)
00163 {
00164     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00165 
00166     return g_is_session_finished;
00167 }
00168 
00169 fcc_status_e  fcc_verify_device_configured_4mbed_cloud(void)
00170 {
00171     fcc_status_e   fcc_status =  FCC_STATUS_SUCCESS;
00172     bool use_bootstrap = false;
00173     bool success = false;
00174 
00175     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00176 
00177     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
00178 
00179     /*Initialize fcc_output_info_s structure.
00180     In case output indo struct is not empty in the beginning of the verify process we will clean it.*/
00181     fcc_clean_output_info_handler();
00182 
00183     //Check entropy initialization
00184     success = fcc_is_entropy_initialized();
00185     SA_PV_ERR_RECOVERABLE_RETURN_IF((success != true), fcc_status = FCC_STATUS_ENTROPY_ERROR, "Entropy is not initialized");
00186 
00187     //Check time synchronization
00188     fcc_status = fcc_check_time_synchronization();
00189     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check time synhronization");
00190 
00191     //Get bootstrap mode
00192     fcc_status = fcc_get_bootstrap_mode(&use_bootstrap);
00193     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to get bootstrap mode");
00194 
00195     // Check general info
00196     fcc_status = fcc_check_device_general_info();
00197     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check general info");
00198 
00199     //Check device meta-data
00200     fcc_status = fcc_check_device_meta_data();
00201     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check configuration parameters");
00202 
00203     //Check device security objects
00204     fcc_status = fcc_check_device_security_objects(use_bootstrap);
00205     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check device security objects");
00206 
00207     //Check firmware integrity
00208     fcc_status = fcc_check_firmware_update_integrity();
00209     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check device security objects");
00210 
00211     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00212 
00213     return fcc_status;
00214 }
00215 
00216 fcc_status_e  fcc_entropy_set(const uint8_t *buf, size_t buf_size)
00217 {
00218     palStatus_t pal_status;
00219     SA_PV_LOG_INFO_FUNC_ENTER("buf_size = %" PRIu32, (uint32_t)buf_size);
00220 
00221     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
00222     SA_PV_ERR_RECOVERABLE_RETURN_IF(buf_size != FCC_ENTROPY_SIZE, FCC_STATUS_INVALID_PARAMETER, "Size of entropy provided is %" PRIu32 ", Should be %" PRIu32 , (uint32_t)buf_size, (uint32_t)FCC_ENTROPY_SIZE);
00223 
00224     pal_status = pal_osEntropyInject(buf, buf_size); 
00225     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), fcc_convert_pal_to_fcc_status(pal_status), "Failed to set entropy, pal status =%" PRId32, pal_status);
00226 
00227     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00228     return FCC_STATUS_SUCCESS;
00229 }
00230 
00231 fcc_status_e  fcc_rot_set(const uint8_t *buf, size_t buf_size)
00232 {
00233     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00234     palStatus_t pal_status = PAL_SUCCESS;
00235 
00236     SA_PV_LOG_INFO_FUNC_ENTER("buf_size = %" PRIu32 , (uint32_t)buf_size);
00237 
00238     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
00239     SA_PV_ERR_RECOVERABLE_RETURN_IF((buf == NULL || buf_size != FCC_ROT_SIZE), FCC_STATUS_INVALID_PARAMETER, "Invalid params");
00240 
00241     pal_status = pal_osSetRoT((uint8_t*)buf, buf_size);
00242 
00243     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_ERR_ITEM_EXIST ), fcc_status  = FCC_STATUS_ROT_ERROR, "RoT already exist in storage");
00244     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_ERR_INVALID_ARGUMENT ), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Failed to set RoT");
00245     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), fcc_status = FCC_STATUS_ROT_ERROR, "Failed to set RoT");
00246 
00247     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00248     return fcc_status;
00249 }
00250 
00251 fcc_status_e  fcc_time_set(uint64_t time)
00252 {
00253     palStatus_t pal_status;
00254 
00255     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00256     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
00257 
00258     pal_status = pal_osSetStrongTime(time);
00259     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), FCC_STATUS_ERROR, "Failed to set new EPOCH time (pal_status = %" PRIu32 ")", pal_status);
00260 
00261     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00262     return FCC_STATUS_SUCCESS;
00263 }
00264 
00265 fcc_status_e  fcc_is_factory_disabled(bool *is_factory_disabled)
00266 {
00267 
00268     int64_t factory_disable_flag = 0;
00269     size_t data_actual_size_out = 0;
00270     palStatus_t pal_status = PAL_SUCCESS;
00271 
00272     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00273     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
00274     SA_PV_ERR_RECOVERABLE_RETURN_IF((is_factory_disabled == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid param is_factory_disabled");
00275 
00276     pal_status = storage_rbp_read(STORAGE_RBP_FACTORY_DONE_NAME, (uint8_t *)(&factory_disable_flag), sizeof(factory_disable_flag), &data_actual_size_out);
00277     SA_PV_LOG_INFO("pal_status:%" PRId32", factory_disable_flag:%" PRIuMAX "\n", pal_status, factory_disable_flag);
00278     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS && pal_status != PAL_ERR_ITEM_NOT_EXIST ), fcc_convert_pal_to_fcc_status(pal_status), "Failed for storage_rbp_read");
00279     SA_PV_ERR_RECOVERABLE_RETURN_IF(((factory_disable_flag != 0) && (factory_disable_flag != 1)), FCC_STATUS_FACTORY_DISABLED_ERROR, "Failed for storage_rbp_read");
00280 
00281     // If we get here - it must be either "0" or "1"
00282     *is_factory_disabled = (factory_disable_flag == 1) ? true : false;
00283     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00284     return FCC_STATUS_SUCCESS;
00285 }
00286 
00287 
00288 fcc_status_e  fcc_factory_disable(void)
00289 {
00290     palStatus_t pal_status = PAL_SUCCESS;
00291     int64_t factory_disable_flag = 1;
00292     size_t data_actual_size_out = 0;
00293 
00294     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00295 
00296     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
00297 
00298     pal_status = storage_rbp_write(STORAGE_RBP_FACTORY_DONE_NAME, (uint8_t *)(&factory_disable_flag), sizeof(factory_disable_flag), true);
00299     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_ERR_ITEM_EXIST ), FCC_STATUS_FACTORY_DISABLED_ERROR, "FCC already disabled in storage");
00300     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_ERR_INVALID_ARGUMENT ), FCC_STATUS_INVALID_PARAMETER, "Failed to set storage_rbp_write");
00301     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), fcc_convert_pal_to_fcc_status(pal_status), "Failed to set storage_rbp_write");
00302 
00303     //Check FACTORY_DONE written correctly
00304     pal_status = storage_rbp_read(STORAGE_RBP_FACTORY_DONE_NAME, (uint8_t *)(&factory_disable_flag), sizeof(factory_disable_flag), &data_actual_size_out);
00305     SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS || data_actual_size_out != sizeof(factory_disable_flag)), FCC_STATUS_FACTORY_DISABLED_ERROR, "Failed to set storage_rbp_write");
00306 
00307 
00308     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00309     return FCC_STATUS_SUCCESS;
00310 }
00311 
00312 
00313 fcc_status_e  fcc_trust_ca_cert_id_set(void)
00314 {
00315     fcc_status_e  fcc_status = FCC_STATUS_SUCCESS;
00316     palStatus_t pal_status = PAL_SUCCESS;
00317     fcc_status_e  output_info_fcc_status = FCC_STATUS_SUCCESS;
00318     uint8_t attribute_data[PAL_CERT_ID_SIZE] __attribute__((aligned(4))) = { 0 };
00319     size_t size_of_attribute_data = 0;
00320     bool use_bootstrap = false;
00321 
00322     SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
00323 
00324     SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
00325 
00326     fcc_status = fcc_get_bootstrap_mode(&use_bootstrap);
00327     SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to get bootstrap mode");
00328 
00329 
00330     //For now this API relevant only for bootstrap certificate.
00331     if (use_bootstrap == true) {
00332         fcc_status = fcc_get_certificate_attribute_by_name((const uint8_t*)g_fcc_bootstrap_server_ca_certificate_name,
00333             (size_t)(strlen(g_fcc_bootstrap_server_ca_certificate_name)),
00334             CS_CERT_ID_ATTR,
00335             attribute_data,
00336             sizeof(attribute_data),
00337             &size_of_attribute_data);
00338         SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get ca id");
00339  
00340         pal_status = storage_rbp_write(STORAGE_RBP_TRUSTED_TIME_SRV_ID_NAME, attribute_data, size_of_attribute_data, true);
00341         SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status == PAL_ERR_ITEM_EXIST ), (fcc_status = FCC_STATUS_CA_ERROR), exit, "CA already exist in storage");
00342         SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status == PAL_ERR_INVALID_ARGUMENT ), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Failed to set ca id");
00343         SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), fcc_status = fcc_convert_pal_to_fcc_status(pal_status), exit, "Failed to setca id");
00344     }
00345 
00346 exit:
00347     if (fcc_status != FCC_STATUS_SUCCESS) {
00348         output_info_fcc_status = fcc_store_error_info((const uint8_t*)g_fcc_bootstrap_server_ca_certificate_name, strlen(g_fcc_bootstrap_server_ca_certificate_name), fcc_status);
00349         SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
00350             fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
00351             "Failed to set ca identifier error  %d",
00352             fcc_status);
00353     }
00354 
00355     SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
00356     return fcc_status;
00357 }
00358 
00359 bool fcc_is_initialized()
00360 {
00361     return g_is_fcc_initialized;
00362 }