Provision your IoT Edge device using a TPM

IoT Devices need a secure connection, the reason is obvious. It all starts with a secure connection between a device in the field and the Cloud platform.

Microsoft provides a secure connection for devices to the IoT Hub in three ways:

  • Symmetric keys
  • Certificates
  • Support for a Trusted Platform Module (TPM)

We are interested in how to get our connection secured using the TPM.

A TPM is “an international standard for a secure cryptoprocessor”. It can generate private keys and expose the public keys related to them. So it somewhat behaves like a set of certificates but now as a physical device.

If somebody tries to physically compromise the chip to retrieve a private key, it should break thus destroying the chip and its content. You can buy TPM chips (eg. for a Raspberry PI) but it’s better to have it already attached to your PC’s motherboard. The chip acts as an identity and you do not want to see it being unplugged.

My Advantech UNO 2372G has a TPM 2.0 chip already built in. The same goes for a few laptops I have. Keep in mind that older versions of this security chip (like the TPM 1.2) are not supported by Microsoft.

Symmetric keys and certificates are supported by the Azure IoT Hub. We need another service, the Azure Device Provisioning Service to provision a device using the TPM and get access to an IoT Hub of your choice.

How does it work?

The Device Provisioning Service acts as a broker between provisioned devices and one or more IoTHubs.

The following picture shows the ‘dance’ a registered device has to perform if it wants to contact an IoT Hub (example taken from the documentation):

  1. Device manufacturer adds the device registration information to the enrollment list in the Azure portal.
  2. Device contacts the provisioning service endpoint set at the factory. The device passes the identifying information to the provisioning service to prove its identity.
  3. The provisioning service validates the identity of the device by validating the registration ID and key against the enrollment list entry using either a nonce challenge (Trusted Platform Module) or standard X.509 verification (X.509).
  4. The provisioning service registers the device with an IoT hub and populates the device’s desired twin state.
  5. The IoT hub returns device ID information to the provisioning service.
  6. The provisioning service returns the IoT hub connection information to the device. The device can now start sending data directly to the IoT hub.
  7. The device connects to IoT hub.
  8. The device gets the desired state from its device twin in IoT hub.

Note: Keep in mind, this dance can only start after a device is registered at the DPS. There must be a trust relationship between the device (with a TPM) and Device Provisioning Service first.

Why should we use a TPM?

Every example starts with symmetric keys. Are symmetric keys not enough?

All three available ways to secure a device are great but only certificates and a TPM are recommended to be used in production. The problem with symmetric keys is that replacing those keys is hard, you need to change it on the device itself. And you need to transport the new key to the device (on a USB stick?) so you are a bit vulnerable then.

Using a TPM (and a DPS) helps in two ways:

  1. When the security token behind the secure connection with an IoT Hub expires, the device itself simple asks for a new token by connecting to the DPS. There is no need for extra work to be done.
  2. The DPS has knowledge about one or more IoTHubs. So depending on rules you have set, the DPS routes the device to the right IoT Hub. Imagine a device on a ship going around the world and always connects to the nearest IoTHub for the best connection (lowest lag). You can also program rules yourself using Azure Functions.

Note: If you want to make use of a DPS with Azure IoT Edge, only a TPM is supported at this moment (2018Q4).

How to register your IoT Edge device

So we need an IoT Edge device like a Raspberry Pi with a TPM on top of it or an industrial PC like the Advantech Uno 2372G with a TPM built in.

At this point, the IoT Edge documentation get’s a bit fussy. All examples I found until now are referring to the use of a TPM emulator, not an actual TPM.

In this blog, I will show you how you can register using a DPS.

But first, we learn a bit more about enrollment and registration of your device.

What is an enrollment and what is a registration?

Nicole Berdy wrote a nice blog about enrollment and registration.

Here is my summary:

  1. The DPS has a ‘secret’ ID Scope (you do not want to register your device in someone else his DPS)
  2. Your device needs a unique registration ID (you do not want to mix up devices)
  3. The TPM on your device can generate a ‘public’ Endorsement key for this combination of information
  4. With this key, you enroll your device at the DPS
  5. Once enrolled, you have to close the loop by registering the device using the enrollment in the DPS

So enrollment is simple, you just fill in the public secrets of your device into a Device provisioning service.

But after the enrollment, you need to register the device using the private secret key in the TPM. Yes, this is done without exposing the private key.

These steps seem a bit cryptic at this moment, the best way to learn more about this is just doing it!

Enroll your device using the TPM by hand

One possibility is filling in all the information in the Device Provisioning service.

If you are able to get an Endorsement key from an actual TPM, a TPM simulation or a key you just made up, you can do this:

Here is all the information we need when we enroll a device using a TPM:

  1. the unique Endorsement key from your (fictitious) TPM
  2. The unique Registration ID
  3. Are you registering an IoT Edge device?
  4. The rules behind selecting an IoT Hub
  5. Optionally, the Device ID of the device within the IoT Hub (which can diver from the Registration ID).

Press save to accept the enrollment.

Note: The device is not registered yet as we will see below!

Doing the same step again: Now enroll your device using the TPM by code

To make enrollment more convenient, Microsoft provides an API to enroll by code.

You can follow this tutorial to code an enrollment.

Note: in the tutorial, they just provide an Endorsement Key which is not bound to an actual device. This is how the emulator works.

Note: Pro mode: you could combine this with the code I offer below which shows how to get the endorsement key of a real TPM.

So fill in the Connection String, the Registration ID, and the Endorsement Key:

namespace DeviceProvisioningGenerator
    using System;
    using System.Threading.Tasks;
    using Microsoft.Azure.Devices.Provisioning.Service;
    using Microsoft.Azure.Devices.Shared;
    internal class Program
        private static string ProvisioningConnectionString =
        private const string RegistrationId =
        private const string TpmEndorsementKey =
            "[An endorsementkey]";
        private const ProvisioningStatus StatusProvisioning = ProvisioningStatus.Enabled;
        // Optionally, replace RegistrationId with a valid device name
        private const string OptionalDeviceId = RegistrationId; 
        private static void Main(string[] args)
            Console.WriteLine("\nHit <Enter> to exit ...");
        public static async Task RunSample()
            Console.WriteLine("Starting sample...");
            using (var provisioningServiceClient = 
                Console.WriteLine("\nCreating a new individualEnrollment...");
                var attestation = 
                    new TpmAttestation(TpmEndorsementKey);
                var individualEnrollment = 
                    new IndividualEnrollment(RegistrationId.ToLower(), attestation);
                // The following parameters are optional. Remove them if you don't need them.
                individualEnrollment.DeviceId = OptionalDeviceId;
                // Add this line if you deploy an IoT Edge device
                individualEnrollment.Capabilities = 
                    new DeviceCapabilities { IotEdge = true };
                individualEnrollment.ProvisioningStatus = StatusProvisioning;
                Console.WriteLine("\nAdding new individualEnrollment...");
                var individualEnrollmentResult = 
                    await provisioningServiceClient.
                Console.WriteLine("\nIndividualEnrollment created with success.");

If you run this code, you get output about the enrollment like this:

Check out the Azure portal for the individual enrollment:

As you can see, you still need to register the device.

And again, what about that endorsement key? How do I retrieve that from a TPM?

Registering your TPM using code

Documentation about accessing your TPM for endorsement and registering is scarce. I found this sample but:

“The sample is currently using SecurityProviderTpmSimulator which is not supported on Linux. To run against a real TPM2.0 device, replace this with SecurityProviderTpm.”

I want to use the TPM 2.0 version of this code and I wanted to get it working in Linux. So I fixed some parts of it and now it works great on both Linux and Windows 10 IoT Enterprise.

My TPM 2.0 version is open source.

Just clone the code, run it from the command line and pass Device Provisioning Service ID_Scope and RegistrationID as command-prompt arguments:

Usage: ProvisionTpm <IDScope> <RegistrationID> <SkipTest:Y|N>

Note: Run this ‘As Administrator’ or ‘SU’. If not you will see an error regarding commands being blocked.

In the original code, after the registration, there is a test which sends a message to the device. I made it optional in my version. It has little or no use for an IoT Edge device.

A full example of registering a device with real TPM2.0

Here is how I put everything together.

First, I created a resource group with an IoT Hub and a Device Provisioning Service.

I then linked the IoT Hub to the DPS so the DPS can refer devices to it:

After that, I checked the Scope ID of the DPS:

Now I only had to come up with a nice Registration Id and run the GitHub repository code to start the registration.

I opened a PowerShell window. I made sure it ran “As Administrator”.

And I provided both the Scope ID and the Registration ID:

Yes, now I have the Endorsement key of my TPM for this registration at this DPS.

Note: The application is still waiting for the actual individual enrollment.

So execute the enrollment at this point:

Once saved, we still have to complete the registration step. In the Enrollment, the device is still unassigned:

So let’s assign it by just pressing Enter in the PowerShell dialog:

The device with the TPM 2.0 is now assigned:

Finally, the registration is complete.

We can actually start installing the IoT Edge runtime on this device using the DPS registration.

If we follow this guide, all we have to do is this:

. {Invoke-WebRequest -useb} | Invoke-Expression; `
Install-SecurityDaemon -Dps -ContainerOs Windows -ScopeId 0ne0003CEA5 -RegistrationId uno2372gsv

This will install the IoT Edge runtime using the Device Provisioning Service.

As you can see, all the pieces of information provided, the ScopeID, the RegistrationID, and even the Endorsement Key are pretty harmless. A hacker has little or no use of these items. These are only interesting in combination with the TPM itself. This makes the usage of a TPM so powerful.


We are now able to actually start using IoT Edge secured by the TPM2.0 chip on your device. This opens new scenarios for appointing the right IoT Hub to your device based on location or load.

You could try to automate the step by bringing the two pieces of code together. But this means you expose the DPS connection string outside Azure.


More info:


Een reactie op “Provision your IoT Edge device using a TPM

Geef een reactie

Vul je gegevens in of klik op een icoon om in te loggen. logo

Je reageert onder je account. Log uit /  Bijwerken )

Google+ photo

Je reageert onder je Google+ account. Log uit /  Bijwerken )


Je reageert onder je Twitter account. Log uit /  Bijwerken )

Facebook foto

Je reageert onder je Facebook account. Log uit /  Bijwerken )

Verbinden met %s