Writing a device application for provisioning without FCU
You can set up your device application to carry out the factory provisioning process without Factory Configurator Utility (FCU) using two modules that are part of Device Management Client:
- The factory configurator client (FCC) module exposes APIs for initiating and finalizing the factory flow, carrying out the injection process, and verifying that the device is ready to connect to Device Management.
- The key and configuration manager (KCM) module exposes APIs for storing, retrieving, deleting, and verifying items in the device's secure storage.
To provision a device, your device application must call FCC and KCM APIs to perform a series of operations in sequence:
- Initialize FCC.
- Configure the device.
- Store data on the device.
- Set the Bootstrap CA identification flag.
- Verify device configuration.
- Switch on the Factory Disable flag.
- Finalize FCC and KCM.
For details about FCC and KCM APIs, please see the FCC and KCM API documentation on the Pelion Device Management documentation site.
Initializing FCC
Use the fcc_init()
function to initialize FCC at the beginning of your application code.
#include "factory_configurator_client.h"
#include "fcc_status.h"
int main() {
fcc_status_e fcc_status;
fcc_status = fcc_init();
if(fcc_status != FCC_STATUS_SUCCESS) {
return 1;
}
...
}
Configuring the device
Use FCC to configure device parameters such as:
- Entropy (
fcc_entropy_set
) - Set the entropy if the device doesn't have a TRNG (True Random Number Generator) or its entropy source isn't strong enough. - Time (
fcc_time_set
).
// The entropy buffer must be generated by a platform with a strong entropy source
uint8_t entropy_buf[FCC_ENTROPY_SIZE] = {};
uint64_t epoch_time;
// Set entropy
fcc_status = fcc_entropy_set(entropy_buf, entropy_buf(buf));
if (fcc_status != FCC_STATUS_SUCCESS) {
return 1;
}
// Set device time
fcc_status = fcc_time_set(epoch_time);
if (fcc_status != FCC_STATUS_SUCCESS) {
return 1;
}
Storing data on the device
You must store all of the mandatory items listed in the provisioning information section on the device during the factory process.
The item names must match the table exactly. Use the KCM module to store keys, certificates, and configuration parameters.
kcm_status_e kcm_status;
// Storing the useBootstrap configuration parameter
kcm_status = kcm_item_store(g_fcc_use_bootstrap_parameter_name,
strlen(g_fcc_use_bootstrap_parameter_name),
KCM_CONFIG_ITEM,
true,
use_bootstrap_mode,
sizeof(use_bootstrap_mode),
NULL);
if (kcm_status != KCM_STATUS_SUCCESS) {
return 1;
}
// Additional storing operations
// such as bootstrap ca certificate and other mandatory and optional
// items listed in provisioning info section
Setting the Bootstrap CA identification flag
Call the fcc_trust_ca_cert_id_set
function to set and store the Bootstrap CA identification. Call this function only after you store the Bootstrap CA certificate on the device.
// Set bootstrap CA identification
fcc_status = fcc_trust_ca_cert_id_set();
if (fcc_status != FCC_STATUS_SUCCESS) {
return 1;
}
Verifying device configuration
Use the fcc_verify_device_configured_4mbed_cloud()
function to verify that the device is configured correctly for Device Management.
This function verifies that all mandatory items exist and validates that parameters are set correctly to connect to Device Management.
For the full list of validations, see the Provisioning Information section.
// Verify the device was configure correctly
fcc_status = fcc_verify_device_configured_4mbed_cloud();
if (fcc_status != FCC_STATUS_SUCCESS) {
return 1;
}
Errors and warnings in the verification process
The fcc_output_info_s
structure records all errors and warnings output by the fcc_verify_device_configured_4mbed_cloud()
function.
You can call the fcc_get_error_and_warning_data()
API to get all recorded warnings and errors.
If there are no warnings and errors, error_string_info
and head_of_warning_list
are NULL
, and size_of_warning_info_list
is 0
.
fcc_output_info_s *output_info = NULL;
fcc_warning_info_s *warning_list = NULL;
// Check the verify process results
output_info = fcc_get_error_and_warning_data();
if (output_info != NULL) {
// Handle errors and warnings as required
// Check if there is an error
if (output_info->error_string_info != NULL) {
// Handle output_info->error_string_info as required. For example, print it to the stdout
}
// Check if there are warnings
if (output_info->size_of_warning_info_list > 0) {
// Set warning_list to point on the head of the list
warning_list = output_info->head_of_warning_list;
// Iterate the list
while (warning_list != NULL) {
// Handle warning_list->warning_info_string as required. For example, print it to the stdout
// Move warning_list to point on the next warning in the list
warning_list = warning_list->next;
}
}
}
Switching on the Factory Disable flag
Call fcc_factory_disable()
to raise the factory disable flag and indicate that the factory process has completed.
// Raise factory disable flag
fcc_status = fcc_factory_disable();
if (fcc_status != FCC_STATUS_SUCCESS) {
return 1;
}
Finalizing FCC and KCM
Use the fcc_finalize()
function to finalize FCC, release resources, and conclude the workflow. This also finalizes the KCM module, so you don't need to finalize it manually.
// Finalization
fcc_status = fcc_finalize();
if (fcc_status != FCC_STATUS_SUCCESS) {
return 1;
}