Set up a device to provision using the Azure IoT Hub Device Provisioning Service

In the previous tutorial, you learned how to set up the Azure IoT Hub Device Provisioning Service to automatically provision your devices to your IoT hub. This tutorial shows you how to set up your device during the manufacturing process, enabling it to be auto-provisioned with IoT Hub. Your device is provisioned based on its Attestation mechanism, upon first boot and connection to the provisioning service. This tutorial covers the following tasks:

  • Build platform-specific Device Provisioning Services Client SDK
  • Extract the security artifacts
  • Create the device registration software

This tutorial expects that you have already created your Device Provisioning Service instance and an IoT hub, using the instructions in the previous Set up cloud resources tutorial.

This tutorial uses the Azure IoT SDKs and libraries for C repository, which contains the Device Provisioning Service Client SDK for C. The SDK currently provides TPM and X.509 support for devices running on Windows or Ubuntu implementations. This tutorial is based on use of a Windows development client, which also assumes basic proficiency with Visual Studio 2017.

If you're unfamiliar with the process of auto-provisioning, be sure to review Auto-provisioning concepts before continuing.

If you don't have an Azure subscription, create a free account before you begin.

Prerequisites

Build a platform-specific version of the SDK

The Device Provisioning Service Client SDK helps you implement your device registration software. But before you can use it, you need to build a version of the SDK specific to your development client platform and attestation mechanism. In this tutorial, you build an SDK that uses Visual Studio 2017 on a Windows development platform, for a supported type of attestation:

  1. Download the version 3.11.4 of the CMake build system. Verify the downloaded binary using the corresponding cryptographic hash value. The following example used Windows PowerShell to verify the cryptographic hash for version 3.11.4 of the x64 MSI distribution:

    PS C:\Downloads> $hash = get-filehash .\cmake-3.11.4-win64-x64.msi
    PS C:\Downloads> $hash.Hash -eq "56e3605b8e49cd446f3487da88fcc38cb9c3e9e99a20f5d4bd63e54b7a35f869"
    True
    

    The following hash values for version 3.11.4 were listed on the CMake site at the time of this writing:

    6dab016a6b82082b8bcd0f4d1e53418d6372015dd983d29367b9153f1a376435  cmake-3.11.4-Linux-x86_64.tar.gz
    72b3b82b6d2c2f3a375c0d2799c01819df8669dc55694c8b8daaf6232e873725  cmake-3.11.4-win32-x86.msi
    56e3605b8e49cd446f3487da88fcc38cb9c3e9e99a20f5d4bd63e54b7a35f869  cmake-3.11.4-win64-x64.msi
    

    It is important that the Visual Studio prerequisites (Visual Studio and the 'Desktop development with C++' workload) are installed on your machine, before starting the CMake installation. Once the prerequisites are in place, and the download is verified, install the CMake build system.

  2. Open a command prompt or Git Bash shell. Execute the following command to clone the Azure IoT C SDK GitHub repository:

    git clone https://github.com/Azure/azure-iot-sdk-c.git --recursive
    

    The size of this repository is currently around 220 MB. You should expect this operation to take several minutes to complete.

  3. Create a cmake subdirectory in the root directory of the git repository, and navigate to that folder.

    cd azure-iot-sdk-c
    mkdir cmake
    cd cmake
    
  4. Build the SDK for your development platform based on the attestation mechanisms you will be using. Use one of the following commands (also note the two trailing period characters for each command). Upon completion, CMake builds out the /cmake subdirectory with content specific to your device:

    • For devices that use the TPM simulator for attestation:

      cmake -Duse_prov_client:BOOL=ON -Duse_tpm_simulator:BOOL=ON ..
      
    • For any other device (physical TPM/HSM/X.509, or a simulated X.509 certificate):

      cmake -Duse_prov_client:BOOL=ON ..
      

Now you're ready to use the SDK to build your device registration code.

Extract the security artifacts

The next step is to extract the security artifacts for the attestation mechanism used by your device.

Physical devices

Depending on whether you built the SDK to use attestation for a physical TPM/HSM or using X.509 certificates, gathering the security artifacts is as follows:

  • For a TPM device, you need to determine the Endorsement Key associated with it from the TPM chip manufacturer. You can derive a unique Registration ID for your TPM device by hashing the endorsement key.

  • For an X.509 device, you need to obtain the certificates issued to your device(s). The provisioning service exposes two types of enrollment entries that control access for devices using the X.509 attestation mechanism. The certificates needed depend on the enrollment types you will be using.

    1. Individual enrollments: Enrollment for a specific single device. This type of enrollment entry requires end-entity, "leaf", certificates.
    2. Enrollment groups: This type of enrollment entry requires intermediate or root certificates. For more information, see Controlling device access to the provisioning service with X.509 certificates.

Simulated devices

Depending on whether you built the SDK to use attestation for a simulated device using TPM or X.509 certificates, gathering the security artifacts is as follows:

  • For a simulated TPM device:

    1. Open a Windows Command Prompt, navigate to the azure-iot-sdk-c subdirectory, and run the TPM simulator. It listens over a socket on ports 2321 and 2322. Do not close this command window; you will need to keep this simulator running until the end of the following Quickstart.

      From the azure-iot-sdk-c subdirectory, run the following command to start the simulator:

      .\provisioning_client\deps\utpm\tools\tpm_simulator\Simulator.exe
      

      Note

      If you use the Git Bash command prompt for this step, you'll need to change the backslashes to forward slashes, for example: ./provisioning_client/deps/utpm/tools/tpm_simulator/Simulator.exe.

    2. Using Visual Studio, open the solution generated in the cmake folder named azure_iot_sdks.sln, and build it using the "Build solution" command on the "Build" menu.

    3. In the Solution Explorer pane in Visual Studio, navigate to the folder Provision_Tools. Right-click the tpm_device_provision project and select Set as Startup Project.

    4. Run the solution using either of the "Start" commands on the "Debug" menu. The output window displays the TPM simulator's Registration ID and the Endorsement Key, needed for device enrollment and registration. Copy these values for use later. You can close this window (with Registration ID and Endorsement Key), but leave the TPM simulator window running that you started in step #1.

  • For a simulated X.509 device:

    1. Using Visual Studio, open the solution generated in the cmake folder named azure_iot_sdks.sln, and build it using the "Build solution" command on the "Build" menu.

    2. In the Solution Explorer pane in Visual Studio, navigate to the folder Provision_Tools. Right-click the dice_device_enrollment project and select Set as Startup Project.

    3. Run the solution using either of the "Start" commands on the "Debug" menu. In the output window, enter i for individual enrollment when prompted. The output window displays a locally generated X.509 certificate for your simulated device. Copy to clipboard the output starting from -----BEGIN CERTIFICATE----- and ending at the first -----END CERTIFICATE-----, making sure to include both of these lines as well. You only need the first certificate from the output window.

    4. Create a file named X509testcert.pem, open it in a text editor of your choice, and copy the clipboard contents to this file. Save the file as you will use it later for device enrollment. When your registration software runs, it uses the same certificate during auto-provisioning.

These security artifacts are required during enrollment your device to the Device Provisioning Service. The provisioning service waits for the device to boot and connect with it at any later point in time. When your device boots for the first time, the client SDK logic interacts with your chip (or simulator) to extract the security artifacts from the device, and verifies registration with your Device Provisioning service.

Create the device registration software

The last step is to write a registration application that uses the Device Provisioning Service client SDK to register the device with the IoT Hub service.

Note

For this step we will assume the use of a simulated device, accomplished by running an SDK sample registration application from your workstation. However, the same concepts apply if you are building a registration application for deployment to a physical device.

  1. In the Azure portal, select the Overview blade for your Device Provisioning service and copy the ID Scope value. The ID Scope is generated by the service and guarantees uniqueness. It is immutable and used to uniquely identify the registration IDs.

    Extract Device Provisioning Service endpoint information from the portal blade

  2. In the Visual Studio Solution Explorer on your machine, navigate to the folder Provision_Samples. Select the sample project named prov_dev_client_sample and open the source file prov_dev_client_sample.c.

  3. Assign the ID Scope value obtained in step #1, to the id_scope variable (removing the left/[ and right/] brackets):

    static const char* global_prov_uri = "global.azure-devices-provisioning.net";
    static const char* id_scope = "[ID Scope]";
    

    For reference, the global_prov_uri variable, which allows the IoT Hub client registration API IoTHubClient_LL_CreateFromDeviceAuth to connect with the designated Device Provisioning Service instance.

  4. In the main() function in the same file, comment/uncomment the hsm_type variable that matches the attestation mechanism being used by your device's registration software (TPM or X.509):

    hsm_type = SECURE_DEVICE_TYPE_TPM;
    //hsm_type = SECURE_DEVICE_TYPE_X509;
    
  5. Save your changes and rebuild the prov_dev_client_sample sample by selecting "Build solution" from the "Build" menu.

  6. Right-click the prov_dev_client_sample project under the Provision_Samples folder, and select Set as Startup Project. DO NOT run the sample application yet.

Important

Do not run/start the device yet! You need to finish the process by enrolling the device with the Device Provisioning Service first, before starting the device. The Next steps section below will guide you to the next article.

SDK APIs used during registration (for reference only)

For reference, the SDK provides the following APIs for your application to use during registration. These APIs help your device connect and register with the Device Provisioning Service when it boots up. In return, your device receives the information required to establish a connection to your IoT Hub instance:

// Creates a Provisioning Client for communications with the Device Provisioning Client Service.  
PROV_DEVICE_LL_HANDLE Prov_Device_LL_Create(const char* uri, const char* scope_id, PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION protocol)

// Disposes of resources allocated by the provisioning Client.
void Prov_Device_LL_Destroy(PROV_DEVICE_LL_HANDLE handle)

// Asynchronous call initiates the registration of a device.
PROV_DEVICE_RESULT Prov_Device_LL_Register_Device(PROV_DEVICE_LL_HANDLE handle, PROV_DEVICE_CLIENT_REGISTER_DEVICE_CALLBACK register_callback, void* user_context, PROV_DEVICE_CLIENT_REGISTER_STATUS_CALLBACK reg_status_cb, void* status_user_ctext)

// Api to be called by user when work (registering device) can be done
void Prov_Device_LL_DoWork(PROV_DEVICE_LL_HANDLE handle)

// API sets a runtime option identified by parameter optionName to a value pointed to by value
PROV_DEVICE_RESULT Prov_Device_LL_SetOption(PROV_DEVICE_LL_HANDLE handle, const char* optionName, const void* value)

You may also find that you need to refine your Device Provisioning Service client registration application, using a simulated device at first, and a test service setup. Once your application is working in the test environment, you can build it for your specific device and copy the executable to your device image.

Clean up resources

At this point, you might have the Device Provisioning and IoT Hub services running in the portal. If you wish to abandon the device provisioning setup, and/or delay completion of this tutorial series, we recommend shutting them down to avoid incurring unnecessary costs.

  1. From the left-hand menu in the Azure portal, click All resources and then select your Device Provisioning service. At the top of the All resources blade, click Delete.
  2. From the left-hand menu in the Azure portal, click All resources and then select your IoT hub. At the top of the All resources blade, click Delete.

Next steps

In this tutorial, you learned how to:

  • Build platform-specific Device Provisioning Service Client SDK
  • Extract the security artifacts
  • Create the device registration software

Advance to the next tutorial to learn how to provision the device to your IoT hub by enrolling it to the Azure IoT Hub Device Provisioning Service for auto-provisioning.