Mistake on this page? Email us

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:

  1. Initialize FCC.
  2. Configure the device.
  3. Store data on the device.
  4. Set the Bootstrap CA identification flag.
  5. Verify device configuration.
  6. Switch on the Factory Disable flag.
  7. 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;
    }