Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IoTHubDeviceClient_CreateFromDeviceAuth() using symmetric key attestation issue #2612

Closed
pavel808 opened this issue Apr 22, 2024 · 2 comments
Assignees
Labels

Comments

@pavel808
Copy link

I am using the Azure IoT C SDK on Debian. I provision devices on my IoT Hub via a symmetric key enrolment group from my code. Provisioning works fine and I can see my devices on the hub.

The problem I have is that I can't create a device handle for any device in my code using the function IoTHubDeviceClient_CreateFromDeviceAuth(). From studying the documentation, my code must be linked against the library built from the custom_hsm_example.

I've modified the custom_hsm_example as follows, removing any certificate-related stuff. For the SYMMETRIC_KEY, i'm putting the symmetric primary key copied from the portal, and REGISTRATION_NAME is the name of my enrolment group ( i'm not sure if this is correct ? ) :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "hsm_client_data.h"

// This sample is provided for sample only.  Please do not use this in production
// For more information please see the devdoc using_custom_hsm.md
//static const char* const COMMON_NAME = "custom-hsm-example";
//static const char* const CERTIFICATE = "-----BEGIN CERTIFICATE-----""\n"
//"BASE64 Encoded certificate Here""\n"
//"-----END CERTIFICATE-----";
//static const char* const PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----""\n"
//"BASE64 Encoded certificate Here""\n"
//"-----END PRIVATE KEY-----";

// Provided for sample only
static const char* const SYMMETRIC_KEY = "FdN/YUSebXlTmhx3KnY90DrgWgEBXhbtE62xyPcvixw8P19oWtD65jXmb6x+WT0aW9blRNo0U1svkoWziKsb+w==";
static const char* const REGISTRATION_NAME = "symm-device-group";

// Provided for sample only, canned values
//static const unsigned char EK[] = { 0x45, 0x6e, 0x64, 0x6f, 0x72, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x0d, 0x0a };
//static const size_t EK_LEN = sizeof(EK)/sizeof(EK[0]);
//static const unsigned char SRK[] = { 0x53, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x0d, 0x0a };
//static const size_t SRK_LEN = sizeof(SRK) / sizeof(SRK[0]);
//static const unsigned char ENCRYPTED_DATA[] = { 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0d, 0x0a };

typedef struct CUSTOM_HSM_SAMPLE_INFO_TAG
{
    const char* certificate;
    const char* common_name;
    const char* key;
    const unsigned char* endorsement_key;
    size_t ek_length;
    const unsigned char* storage_root_key;
    size_t srk_len;
    const char* symm_key;
    const char* registration_name;
} CUSTOM_HSM_SAMPLE_INFO;

int hsm_client_x509_init(void)
{
    return 0;
}

void hsm_client_x509_deinit(void)
{
}

int hsm_client_tpm_init(void)
{
    return 0;
}

void hsm_client_tpm_deinit(void)
{
}

HSM_CLIENT_HANDLE custom_hsm_create(void)
{
    HSM_CLIENT_HANDLE result;
    CUSTOM_HSM_SAMPLE_INFO* hsm_info = malloc(sizeof(CUSTOM_HSM_SAMPLE_INFO));
    if (hsm_info == NULL)
    {
        (void)printf("Failed allocating hsm info\r\n");
        result = NULL;
    }
    else
    {
        // TODO: initialize any variables here
        hsm_info->certificate = NULL;
        hsm_info->key = NULL;
        hsm_info->common_name = NULL;
        hsm_info->endorsement_key = NULL;
        hsm_info->ek_length = 0;
        hsm_info->storage_root_key = NULL;
        hsm_info->srk_len = 0;
        hsm_info->symm_key = SYMMETRIC_KEY;
        hsm_info->registration_name = REGISTRATION_NAME;
        result = hsm_info;
    }
    return result;
}

void custom_hsm_destroy(HSM_CLIENT_HANDLE handle)
{
    if (handle != NULL)
    {
        CUSTOM_HSM_SAMPLE_INFO* hsm_info = (CUSTOM_HSM_SAMPLE_INFO*)handle;
        // Free anything that has been allocated in this module
        free(hsm_info);
    }
}

char* custom_hsm_symm_key(HSM_CLIENT_HANDLE handle)
{
    char* result;
    if (handle == NULL)
    {
        (void)printf("Invalid handle value specified\r\n");
        result = NULL;
    }
    else
    {
        // TODO: Malloc the symmetric key for the iothub
        // The SDK will call free() this value
        CUSTOM_HSM_SAMPLE_INFO* hsm_info = (CUSTOM_HSM_SAMPLE_INFO*)handle;
        size_t len = strlen(hsm_info->symm_key);
        if ((result = (char*)malloc(len + 1)) == NULL)
        {
            (void)printf("Failure allocating certificate\r\n");
            result = NULL;
        }
        else
        {
            strcpy(result, hsm_info->symm_key);
        }
    }
    return result;
}

char* custom_hsm_get_registration_name(HSM_CLIENT_HANDLE handle)
{
    char* result;
    if (handle == NULL)
    {
        (void)printf("Invalid handle value specified\r\n");
        result = NULL;
    }
    else
    {
        // TODO: Malloc the registration name for the iothub
        // The SDK will call free() this value
        CUSTOM_HSM_SAMPLE_INFO* hsm_info = (CUSTOM_HSM_SAMPLE_INFO*)handle;
        size_t len = strlen(hsm_info->registration_name);
        if ((result = (char*)malloc(len + 1)) == NULL)
        {
            (void)printf("Failure allocating certificate\r\n");
            result = NULL;
        }
        else
        {
            strcpy(result, hsm_info->registration_name);
        }
    }
    return result;
}


static const HSM_CLIENT_KEY_INTERFACE symm_key_interface =
{
    custom_hsm_create,
    custom_hsm_destroy,
    custom_hsm_symm_key,
    custom_hsm_get_registration_name
};


const HSM_CLIENT_KEY_INTERFACE* hsm_client_key_interface(void)
{
    return &symm_key_interface;
}

On calling IoTHubDeviceClient_CreateFromDeviceAuth("test-hub.azure-devices.net", "test-device", protocol) from my application, I get the following failure as below. The provisioning is successful, but fails on creating the device handle. Would anyone be able to assist with solving this?

Provisioning API Version: 1.13.0

Registering Device

Provisioning Status: PROV_DEVICE_REG_STATUS_CONNECTED
Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING

Registration Information received from service: test-hub.azure-devices.net, deviceId: test-device
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/provisioning_client/adapters/hsm_client_key.c Func:hsm_client_set_key_info Line:99 Invalid parameter specified handle: 0x55e6ccdeccb0, reg_name: (nil), symm_key: (nil)
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/provisioning_client/src/iothub_auth_client.c Func:iothub_device_auth_create Line:232 Invalid x509 secure device interface was specified
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/iothub_client/src/iothub_client_authorization.c Func:IoTHubClient_Auth_CreateFromDeviceAuth Line:184 Failed allocating IOTHUB_AUTHORIZATION_DATA
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/iothub_client/src/iothub_client_core_ll.c Func:initialize_iothub_client Line:875 Failed create authorization module
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/iothub_client/src/iothub_client_core_ll.c Func:IoTHubClientCore_LL_CreateFromDeviceAuth Line:1324 initialize iothub client
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/iothub_client/src/iothub_client_core.c Func:create_iothub_instance Line:1115 Failure creating iothub handle
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/provisioning_client/adapters/hsm_client_key.c Func:hsm_client_set_key_info Line:99 Invalid parameter specified handle: 0x55e6ccdece70, reg_name: (nil), symm_key: (nil)
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/provisioning_client/src/iothub_auth_client.c Func:iothub_device_auth_create Line:232 Invalid x509 secure device interface was specified
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/iothub_client/src/iothub_client_authorization.c Func:IoTHubClient_Auth_CreateFromDeviceAuth Line:184 Failed allocating IOTHUB_AUTHORIZATION_DATA
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/iothub_client/src/iothub_client_core_ll.c Func:initialize_iothub_client Line:875 Failed create authorization module
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/iothub_client/src/iothub_client_core_ll.c Func:IoTHubClientCore_LL_CreateFromDeviceAuth Line:1324 initialize iothub client
Error: Time:Mon Apr 22 14:44:33 2024 File:/home/azure-iot-sdk-c/iothub_client/src/iothub_client_core.c Func:create_iothub_instance Line:1115 Failure creating iothub handle
test-hub.azure-devices.netPress enter key to exit:
@ewertons ewertons self-assigned this May 13, 2024
@ewertons
Copy link
Contributor

Hey @mulligan252 , I just revisited the provisioning_client/samples/prov_dev_client_ll_sample to make sure everything was working as it should, and it worked with no issues. No custom hsm necessary.

Here is my output:

ewertons@9c8d746a8b75:/home/ewertons/code/s1/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_ll_sample$ ./prov_dev_client_ll_sample
Provisioning API Version: 1.13.0
Iothub API Version: 1.13.0
Provisioning Status: PROV_DEVICE_REG_STATUS_CONNECTED
Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING
Registration Information received from service: myiothub.azure-devices.net!
Creating IoTHub Device handle
Sending 1 messages to IoTHub every 2 seconds for 2 messages (Send any message to stop)
IoTHubClient_LL_SendEventAsync accepted message [1] for transmission to IoT Hub.
IoTHubClient_LL_SendEventAsync accepted message [2] for transmission to IoT Hub.
Press any enter to continue:

ewertons@9c8d746a8b75:/home/ewertons/code/s1/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_ll_sample$

Note that in sample prov_dev_client_ll_sample if you are using symmetric key enrollment group, you must make the following changes:

diff --git a/provisioning_client/samples/prov_dev_client_ll_sample/prov_dev_client_ll_sample.c b/provisioning_client/samples/prov_dev_client_ll_sample/prov_dev_client_ll_sample.c
index 805bc22bc..329f8a22b 100644
--- a/provisioning_client/samples/prov_dev_client_ll_sample/prov_dev_client_ll_sample.c
+++ b/provisioning_client/samples/prov_dev_client_ll_sample/prov_dev_client_ll_sample.c
@@ -65,7 +65,7 @@ MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(PROV_DEVICE_RESULT, PROV_DEVICE_RESULT_VA
 MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(PROV_DEVICE_REG_STATUS, PROV_DEVICE_REG_STATUS_VALUES);

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

 static bool g_use_proxy = false;
 static const char* PROXY_ADDRESS = "127.0.0.1";
@@ -155,8 +155,8 @@ int main(void)
 {
     SECURE_DEVICE_TYPE hsm_type;
     //hsm_type = SECURE_DEVICE_TYPE_TPM;
-    hsm_type = SECURE_DEVICE_TYPE_X509;
-    //hsm_type = SECURE_DEVICE_TYPE_SYMMETRIC_KEY;
+    // hsm_type = SECURE_DEVICE_TYPE_X509;
+    hsm_type = SECURE_DEVICE_TYPE_SYMMETRIC_KEY;

     bool traceOn = false;

@@ -165,7 +165,7 @@ int main(void)
     // Set the symmetric key if using they auth type
     // If using DPS with an enrollment group, this must the the derived device key from the DPS Primary Key
     // https://docs.microsoft.com/azure/iot-dps/concepts-symmetric-key-attestation?tabs=azure-cli#group-enrollments
-    //prov_dev_set_symmetric_key_info("<symm_registration_id>", "<symmetric_Key>");
+    prov_dev_set_symmetric_key_info("00-11-22-33-44-55-66", "chfrq9t+YzF6/K/oYMW5Ii6m5dxmZDMVR3OyM8fI7jE=");

     PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION prov_transport;
     HTTP_PROXY_OPTIONS http_proxy;

In that last line (when it calls prov_dev_set_symmetric_key_info), you must create a derived symmetric key for your device out of the enrollment group symmetric key, as described in this guide: https://learn.microsoft.com/en-us/azure/iot-dps/concepts-symmetric-key-attestation?tabs=azure-cli#group-enrollments

It literally says to:

  1. Get the symmetric key of your enrollment group (aka EG) (e.g., the primary key of your EG like for example "dcepKhNSSe0PiCOzVI410A4ZjZShvvO/V/c3toc4OP9j+EDStyElidGgwp+EDE/xcfC7YBDPO8ZQPJnx/wnsRZ==")
  2. Generate a registration id for your device (an unique id, like a device ID you come up with or the device's NIC MAC address; e.g., 00-11-22-33-44-55-66)
  3. Run this command to generate the derived symmetric key (using Azure CLI with IoT Hub module):
    az iot dps enrollment-group compute-device-key --key dcepKhNSSe0PiCOzVI410A4ZjZShvvO/V/c3toc4OP9j+EDStyElidGgwp+EDE/xcfC7YBDPO8ZQPJnx/wnsRZ== --registration-id 00-11-22-33-44-55-66

The result should be something like: "chfrq9t+YzF6/K/oYMW5Ii6m5dxmZDMVR3OyM8fI7jE="

Then fill these info in the prov_dev_client_ll_sample as shown in the diff above (using your own registration ID and derived key).
And compile and run the sample.
The sample provisions your device and connects to the IoT Hub using the provisioning data.

@ewertons
Copy link
Contributor

Hi @mulligan252 ,
we will close this issue given the last update above, but please feel free to reopen it if you would like to follow up.
Thanks,
Azure IoT SDKs Team

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants