You may know already about the Azure IoT Device Provisioning service, if not, head to https://docs.microsoft.com/en-us/azure/iot-dps/ for more information.
The idea behind DPS is short and simple: Imagine, you’re the manufacturer of an IoT device and you want enable your device to “just work” once it’s delivered to your customer. So the customer unpacks the device, plugs in Ethernet and the device lights up, starts talking to the cloud, receives device configuration information. So far, so easy, you think, in production, let’s just provision an Azure IoT hub device connection string or a x.509 certificate and that’s all.
So why would you need DPS? Let’s say your device has been configured at the factory, but it’s been sitting on a shelf for years. And then it gets exported to a country where you never thought you would sell devices to, back in the days when you created your service. That’s when you decided that you would use a x.509 certificate and a single iot hub. But now, a couple of years later, you have 10 iot hubs in different geographies and the initial certificates you installed in the device have expired since you set their validity to 3 years. This is where DPS comes in. Your device can now go to the global DPS endpoint and ask: “is there a new configuration for me?”. DPS now looks through its database to find a matching configuration. If it does, it encrypts it in a way that only this particular device can decrypt the information and sends it back to the device. The device then decrypts the configuration information using its built-in hardware security module and in it, it finds the configuration for an iot hub. It then connects with the obtained credentials, receives additional configuration information such as OS and application update instructions and suddenly works. Your customer is delighted and you are too since you now have another device talking to your backend service.
So why wouldn’t you do this all the time? Well, there is one important prerequisite for using DPS: You need to add a device-individual public/private key pair to the device at production time and you need to record the public key in a secure way at this time (or install a certificate used for group registration to be precise). Doing so isn’t very hard (e.g. if your devices have a built-in TPM 2.0, you can just use the built-in “EK” of the TPM for this) but the HSM adds BOM cost and reading out the information adds time in the manufacturing process.
Now imagine, you have a very simple device such as the teXXmo IoT Button (http://www.iot-button.eu/) which does not have a HSM, but needs an Azure IoT Hub device connection string. You can now go back to the initial approach and provision every device with an individual connection string at production. But maybe you don’t want to give your manufacturer full access to your production IoT hub when provisioning devices, but you still need an automated way to generate these connection strings.
This is where my simple Quick Device Registration Service sample comes handy. (Or did somebody say Quick & Dirty Registration Service?) Instead of handing over the keys to the castle (i.e. the iot hub owner connection string) you install this service as an Azure function and provide your manufacturer with the access codes to this service and he can produce device-individual iot hub connection strings while producing devices. The sample client included in the solution calls the service with a given device serial number and gets back the iot hub connection string for this device. The service also checks that no serial number is used twice and that each serial number is valid. (In the sample, it just checks if a serial number is divisible by 7, but you can test in whatever way you can imagine, e.g. CRCs, min/max etc.) Once the manufacturer has obtained the device connection string, he can write it into the device. Once the device is connected to the Internet, it has all information necessary to talk to your Azure IoT Hub.
But there is another usage for this. Imagine you want to use IoT hub in a software-only product, let’s say a digital signage solution that is “just” an application that an end user can install on an existing PC. Or it’s a driver package that comes with your device, and the device is a PC peripheral that does not talk to the cloud directly. In both cases, there is no factory provisioning possible. And while there may be a device-individual identity (e.g. a device serial number) you may not have any space to store (let alone secure) a per-device secret. But you still want to use IoT hub since it’s such a neat way to get information from your device, send information from the cloud to the individual devices and manage your devices using the device twin.
So you add code to your application or driver stack that calls the registration service during installation. The code reads out the serial number information (or even asks the user to enter it?) and then calls the service to obtain the device-individual connection string. It then stores the string locally (let’s say in a configuration file on disk or in the Windows registry) and then uses it to connect to an IoT Hub.
But here, a word of warning is required: If you implement such a solution, the credentials used to call your registration service need to be in your client application or driver stack. So, if there is information, it can be found using reverse engineering. Still, this is better than leaving the IOT hub owner credentials in the client application or, even worse, leaving behind a signing key that would be able to create valid group registration certificates for DPS. Nevertheless, you should implement some protection against reverse engineering and monitor your registration service carefully to identify potential attackers that may have found the credentials and try to compromise your service.
If you need a secure solution, use DPS (and a hardware security module!) If you can’t, then have a look at https://github.com/holgerkenn/qdrs and see if it fits your need.
Hope this helps,