Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 122 additions & 17 deletions examples/Azure_IoT_Adu_ESP32/Azure_IoT_Adu_ESP32.ino
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,14 @@
#define ADU_DEVICE_SHA_SIZE 32
#define ADU_SHA_PARTITION_READ_BUFFER_SIZE 32
#define HTTP_DOWNLOAD_CHUNK 4096
#define ADU_PNP_ACCEPT_CODE 200
#define ADU_PNP_REJECT_CODE 406

// ADU Feature Values
static az_iot_adu_client adu_client;
static az_iot_adu_client_update_request adu_update_request;
static az_iot_adu_client_update_manifest adu_update_manifest;
static char adu_new_version[16];
static bool process_update_request = false;
static bool send_init_state = true;
static bool did_update = false;
static char adu_scratch_buffer[10000];
static char adu_manifest_unescape_buffer[2000];
Expand All @@ -83,12 +82,7 @@ static char partition_read_buffer[ADU_SHA_PARTITION_READ_BUFFER_SIZE];
static int chunked_data_index;

static az_span pnp_components[] = { AZ_SPAN_FROM_STR(AZ_IOT_ADU_CLIENT_PROPERTIES_COMPONENT_NAME) };
az_iot_adu_client_device_properties adu_device_information
= { .manufacturer = AZ_SPAN_LITERAL_FROM_STR(ADU_DEVICE_MANUFACTURER),
.model = AZ_SPAN_LITERAL_FROM_STR(ADU_DEVICE_MODEL),
.adu_version = AZ_SPAN_LITERAL_FROM_STR(AZ_IOT_ADU_CLIENT_AGENT_VERSION),
.delivery_optimization_agent_version = AZ_SPAN_EMPTY,
.update_id = AZ_SPAN_LITERAL_FROM_STR(ADU_UPDATE_ID) };
static az_iot_adu_client_device_properties adu_device_information;

// Utility macros and defines
#define sizeofarray(a) (sizeof(a) / sizeof(a[0]))
Expand Down Expand Up @@ -142,6 +136,90 @@ static AzIoTSasToken sasToken(
AZ_SPAN_FROM_BUFFER(mqtt_password));
#endif // IOT_CONFIG_USE_X509_CERT

/* Azure Device Update root keys used to verify the signed deployment */
/* ADU.200702.R */
static uint8_t ucAzureIoTADURootKeyId200702[ 13 ] = "ADU.200702.R";
static uint8_t ucAzureIoTADURootKeyN200702[ 385 ]
=
{
0x00, 0xd5, 0x42, 0x2e, 0xaf, 0x11, 0x54, 0xa3, 0x50, 0x65, 0x87, 0xa2, 0x4d, 0x5b, 0xba,
0x1a, 0xfb, 0xa9, 0x32, 0xdf, 0xe9, 0x99, 0x5f, 0x05, 0x45, 0xc8, 0xaf, 0xbd, 0x35, 0x1d,
0x89, 0xe8, 0x27, 0x27, 0x58, 0xa3, 0xa8, 0xee, 0xc5, 0xc5, 0x1e, 0x4f, 0xf7, 0x92, 0xa6,
0x12, 0x06, 0x7d, 0x3d, 0x7d, 0xb0, 0x07, 0xf6, 0x2c, 0x7f, 0xde, 0x6d, 0x2a, 0xf5, 0xbc,
0x49, 0xbc, 0x15, 0xef, 0xf0, 0x81, 0xcb, 0x3f, 0x88, 0x4f, 0x27, 0x1d, 0x88, 0x71, 0x28,
0x60, 0x08, 0xb6, 0x19, 0xd2, 0xd2, 0x39, 0xd0, 0x05, 0x1f, 0x3c, 0x76, 0x86, 0x71, 0xbb,
0x59, 0x58, 0xbc, 0xb1, 0x88, 0x7b, 0xab, 0x56, 0x28, 0xbf, 0x31, 0x73, 0x44, 0x32, 0x10,
0xfd, 0x3d, 0xd3, 0x96, 0x5c, 0xff, 0x4e, 0x5c, 0xb3, 0x6b, 0xff, 0x8b, 0x84, 0x9b, 0x8b,
0x80, 0xb8, 0x49, 0xd0, 0x7d, 0xfa, 0xd6, 0x40, 0x58, 0x76, 0x4d, 0xc0, 0x72, 0x27, 0x75,
0xcb, 0x9a, 0x2f, 0x9b, 0xb4, 0x9f, 0x0f, 0x25, 0xf1, 0x1c, 0xc5, 0x1b, 0x0b, 0x5a, 0x30,
0x7d, 0x2f, 0xb8, 0xef, 0xa7, 0x26, 0x58, 0x53, 0xaf, 0xd5, 0x1d, 0x55, 0x01, 0x51, 0x0d,
0xe9, 0x1b, 0xa2, 0x0f, 0x3f, 0xd7, 0xe9, 0x1d, 0x20, 0x41, 0xa6, 0xe6, 0x14, 0x0a, 0xae,
0xfe, 0xf2, 0x1c, 0x2a, 0xd6, 0xe4, 0x04, 0x7b, 0xf6, 0x14, 0x7e, 0xec, 0x0f, 0x97, 0x83,
0xfa, 0x58, 0xfa, 0x81, 0x36, 0x21, 0xb9, 0xa3, 0x2b, 0xfa, 0xd9, 0x61, 0x0b, 0x1a, 0x94,
0xf7, 0xc1, 0xbe, 0x7f, 0x40, 0x14, 0x4a, 0xc9, 0xfa, 0x35, 0x7f, 0xef, 0x66, 0x70, 0x00,
0xb1, 0xfd, 0xdb, 0xd7, 0x61, 0x0d, 0x3b, 0x58, 0x74, 0x67, 0x94, 0x89, 0x75, 0x76, 0x96,
0x7c, 0x91, 0x87, 0xd2, 0x8e, 0x11, 0x97, 0xee, 0x7b, 0x87, 0x6c, 0x9a, 0x2f, 0x45, 0xd8,
0x65, 0x3f, 0x52, 0x70, 0x98, 0x2a, 0xcb, 0xc8, 0x04, 0x63, 0xf5, 0xc9, 0x47, 0xcf, 0x70,
0xf4, 0xed, 0x64, 0xa7, 0x74, 0xa5, 0x23, 0x8f, 0xb6, 0xed, 0xf7, 0x1c, 0xd3, 0xb0, 0x1c,
0x64, 0x57, 0x12, 0x5a, 0xa9, 0x81, 0x84, 0x1f, 0xa0, 0xe7, 0x50, 0x19, 0x96, 0xb4, 0x82,
0xb1, 0xac, 0x48, 0xe3, 0xe1, 0x32, 0x82, 0xcb, 0x40, 0x1f, 0xac, 0xc4, 0x59, 0xbc, 0x10,
0x34, 0x51, 0x82, 0xf9, 0x28, 0x8d, 0xa8, 0x1e, 0x9b, 0xf5, 0x79, 0x45, 0x75, 0xb2, 0xdc,
0x9a, 0x11, 0x43, 0x08, 0xbe, 0x61, 0xcc, 0x9a, 0xc4, 0xcb, 0x77, 0x36, 0xff, 0x83, 0xdd,
0xa8, 0x71, 0x4f, 0x51, 0x8e, 0x0e, 0x7b, 0x4d, 0xfa, 0x79, 0x98, 0x8d, 0xbe, 0xfc, 0x82,
0x7e, 0x40, 0x48, 0xa9, 0x12, 0x01, 0xa8, 0xd9, 0x7e, 0xf3, 0xa5, 0x1b, 0xf1, 0xfb, 0x90,
0x77, 0x3e, 0x40, 0x87, 0x18, 0xc9, 0xab, 0xd9, 0xf7, 0x79
};
static uint8_t ucAzureIoTADURootKeyE200702[ 3 ] = { 0x01, 0x00, 0x01 };

/* ADU.200703.R */
static uint8_t ucAzureIoTADURootKeyId200703[ 13 ] = "ADU.200703.R";
static uint8_t ucAzureIoTADURootKeyN200703[ 385 ] =
{
0x00, 0xb2, 0xa3, 0xb2, 0x74, 0x16, 0xfa, 0xbb, 0x20, 0xf9, 0x52, 0x76, 0xe6, 0x27, 0x3e,
0x80, 0x41, 0xc6, 0xfe, 0xcf, 0x30, 0xf9, 0xc8, 0x96, 0xf5, 0x59, 0x0a, 0xaa, 0x81, 0xe7,
0x51, 0x83, 0x8a, 0xc4, 0xf5, 0x17, 0x3a, 0x2f, 0x2a, 0xe6, 0x57, 0xd4, 0x71, 0xce, 0x8a,
0x3d, 0xef, 0x9a, 0x55, 0x76, 0x3e, 0x99, 0xe2, 0xc2, 0xae, 0x4c, 0xee, 0x2d, 0xb8, 0x78,
0xf5, 0xa2, 0x4e, 0x28, 0xf2, 0x9c, 0x4e, 0x39, 0x65, 0xbc, 0xec, 0xe4, 0x0d, 0xe5, 0xe3,
0x38, 0xa8, 0x59, 0xab, 0x08, 0xa4, 0x1b, 0xb4, 0xf4, 0xa0, 0x52, 0xa3, 0x38, 0xb3, 0x46,
0x21, 0x13, 0xcc, 0x3c, 0x68, 0x06, 0xde, 0xfe, 0x00, 0xa6, 0x92, 0x6e, 0xde, 0x4c, 0x47,
0x10, 0xd6, 0x1c, 0x9c, 0x24, 0xf5, 0xcd, 0x70, 0xe1, 0xf5, 0x6a, 0x7c, 0x68, 0x13, 0x1d,
0xe1, 0xc5, 0xf6, 0xa8, 0x4f, 0x21, 0x9f, 0x86, 0x7c, 0x44, 0xc5, 0x8a, 0x99, 0x1c, 0xc5,
0xd3, 0x06, 0x9b, 0x5a, 0x71, 0x9d, 0x09, 0x1c, 0xc3, 0x64, 0x31, 0x6a, 0xc5, 0x17, 0x95,
0x1d, 0x5d, 0x2a, 0xf1, 0x55, 0xc7, 0x66, 0xd4, 0xe8, 0xf5, 0xd9, 0xa9, 0x5b, 0x8c, 0xa2,
0x6c, 0x62, 0x60, 0x05, 0x37, 0xd7, 0x32, 0xb0, 0x73, 0xcb, 0xf7, 0x4b, 0x36, 0x27, 0x24,
0x21, 0x8c, 0x38, 0x0a, 0xb8, 0x18, 0xfe, 0xf5, 0x15, 0x60, 0x35, 0x8b, 0x35, 0xef, 0x1e,
0x0f, 0x88, 0xa6, 0x13, 0x8d, 0x7b, 0x7d, 0xef, 0xb3, 0xe7, 0xb0, 0xc9, 0xa6, 0x1c, 0x70,
0x7b, 0xcc, 0xf2, 0x29, 0x8b, 0x87, 0xf7, 0xbd, 0x9d, 0xb6, 0x88, 0x6f, 0xac, 0x73, 0xff,
0x72, 0xf2, 0xef, 0x48, 0x27, 0x96, 0x72, 0x86, 0x06, 0xa2, 0x5c, 0xe3, 0x7d, 0xce, 0xb0,
0x9e, 0xe5, 0xc2, 0xd9, 0x4e, 0xc4, 0xf3, 0x7f, 0x78, 0x07, 0x4b, 0x65, 0x88, 0x45, 0x0c,
0x11, 0xe5, 0x96, 0x56, 0x34, 0x88, 0x2d, 0x16, 0x0e, 0x59, 0x42, 0xd2, 0xf7, 0xd9, 0xed,
0x1d, 0xed, 0xc9, 0x37, 0x77, 0x44, 0x7e, 0xe3, 0x84, 0x36, 0x9f, 0x58, 0x13, 0xef, 0x6f,
0xe4, 0xc3, 0x44, 0xd4, 0x77, 0x06, 0x8a, 0xcf, 0x5b, 0xc8, 0x80, 0x1c, 0xa2, 0x98, 0x65,
0x0b, 0x35, 0xdc, 0x73, 0xc8, 0x69, 0xd0, 0x5e, 0xe8, 0x25, 0x43, 0x9e, 0xf6, 0xd8, 0xab,
0x05, 0xaf, 0x51, 0x29, 0x23, 0x55, 0x40, 0x58, 0x10, 0xea, 0xb8, 0xe2, 0xcd, 0x5d, 0x79,
0xcc, 0xec, 0xdf, 0xb4, 0x5b, 0x98, 0xc7, 0xfa, 0xe3, 0xd2, 0x6c, 0x26, 0xce, 0x2e, 0x2c,
0x56, 0xe0, 0xcf, 0x8d, 0xee, 0xfd, 0x93, 0x12, 0x2f, 0x00, 0x49, 0x8d, 0x1c, 0x82, 0x38,
0x56, 0xa6, 0x5d, 0x79, 0x44, 0x4a, 0x1a, 0xf3, 0xdc, 0x16, 0x10, 0xb3, 0xc1, 0x2d, 0x27,
0x11, 0xfe, 0x1b, 0x98, 0x05, 0xe4, 0xa3, 0x60, 0x31, 0x99
};
static uint8_t ucAzureIoTADURootKeyE200703[ 3 ] = { 0x01, 0x00, 0x01 };

static SampleJWS::RootKey xADURootKeys[] =
{
{
// Minus one on id to not count NULL
.root_key_id = az_span_create(ucAzureIoTADURootKeyId200703, sizeof(ucAzureIoTADURootKeyId200703) - 1),
.root_key_n = AZ_SPAN_FROM_BUFFER(ucAzureIoTADURootKeyN200703),
.root_key_exponent = AZ_SPAN_FROM_BUFFER(ucAzureIoTADURootKeyE200703)
},
{
// Minus one on id to not count NULL
.root_key_id = az_span_create(ucAzureIoTADURootKeyId200702, sizeof(ucAzureIoTADURootKeyId200702) - 1),
.root_key_n = AZ_SPAN_FROM_BUFFER(ucAzureIoTADURootKeyN200702),
.root_key_exponent = AZ_SPAN_FROM_BUFFER(ucAzureIoTADURootKeyE200702)
}
};

static void connect_to_wifi()
{
Logger.Info("Connecting to WIFI SSID " + String(ssid));
Expand Down Expand Up @@ -360,7 +438,7 @@ static void request_all_properties(void)

// send_adu_device_reported_property writes a property payload reporting device
// state and then sends it to Azure IoT Hub.
static void send_adu_device_information_property(int32_t agent_state, az_iot_adu_client_workflow * workflow)
static void send_adu_device_information_property(az_iot_adu_client_agent_state agent_state, az_iot_adu_client_workflow * workflow)
{
az_result rc;

Expand Down Expand Up @@ -423,7 +501,7 @@ static void send_adu_device_information_property(int32_t agent_state, az_iot_adu
}

static void send_adu_accept_manifest_property(int32_t version_number,
int32_t response_code)
az_iot_adu_client_request_decision response_code)
{
az_result rc;

Expand Down Expand Up @@ -546,7 +624,7 @@ static void process_device_property_message(
}
else
{
if(adu_update_request.workflow.action != AZ_IOT_ADU_CLIENT_SERVICE_ACTION_CANCEL)
if(adu_update_request.workflow.action == AZ_IOT_ADU_CLIENT_SERVICE_ACTION_APPLY_DEPLOYMENT)
{
rc = az_json_string_unescape(adu_update_request.update_manifest, (char*)adu_manifest_unescape_buffer, sizeof(adu_manifest_unescape_buffer), &out_manifest_size);

Expand Down Expand Up @@ -580,6 +658,7 @@ static void process_device_property_message(
rc = SampleJWS::ManifestAuthenticate(
manifest_unescaped,
adu_update_request.update_manifest_signature,
&xADURootKeys[0], sizeof(xADURootKeys) / sizeof(xADURootKeys[0]),
AZ_SPAN_FROM_BUFFER(adu_verification_buffer));
if (az_result_failed(rc))
{
Expand All @@ -593,20 +672,30 @@ static void process_device_property_message(
if (is_update_already_applied())
{
Logger.Info("Update already applied");
send_adu_accept_manifest_property(version_number, ADU_PNP_REJECT_CODE);
send_adu_accept_manifest_property(version_number, AZ_IOT_ADU_CLIENT_REQUEST_DECISION_REJECT);
process_update_request = false;
}
else
{
Logger.Info("Sending manifest property accept");
send_adu_accept_manifest_property(version_number, ADU_PNP_ACCEPT_CODE);
send_adu_accept_manifest_property(version_number, AZ_IOT_ADU_CLIENT_REQUEST_DECISION_ACCEPT);

process_update_request = true;
}
}
else
else if (adu_update_request.workflow.action == AZ_IOT_ADU_CLIENT_SERVICE_ACTION_CANCEL)
{
Logger.Info("ADU action received: cancelled deployment");
send_adu_device_information_property(AZ_IOT_ADU_CLIENT_AGENT_STATE_IDLE, NULL);
process_update_request = false;
}
else
{
Logger.Error("Unknown workflow action received: " + String(adu_update_request.workflow.action));

send_adu_device_information_property(AZ_IOT_ADU_CLIENT_AGENT_STATE_FAILED, &adu_update_request.workflow);

process_update_request = false;
}
}
}
Expand Down Expand Up @@ -985,9 +1074,16 @@ static void send_telemetry()

// Arduino setup and loop main functions.

void setup() { establish_connection(); }
void setup() {
adu_device_information = az_iot_adu_client_device_properties_default();
adu_device_information.manufacturer = AZ_SPAN_FROM_STR(ADU_DEVICE_MANUFACTURER);
adu_device_information.model = AZ_SPAN_FROM_STR(ADU_DEVICE_MODEL);
adu_device_information.adu_version = AZ_SPAN_FROM_STR(AZ_IOT_ADU_CLIENT_AGENT_VERSION);
adu_device_information.delivery_optimization_agent_version = AZ_SPAN_EMPTY;
adu_device_information.update_id = AZ_SPAN_FROM_STR(ADU_UPDATE_ID);

bool send_init_state = true;
establish_connection();
}

void loop()
{
Expand Down Expand Up @@ -1034,9 +1130,10 @@ void loop()
{
Logger.Info("Cancellation request was received during download. "
"Aborting update.");
send_adu_device_information_property(AZ_IOT_ADU_CLIENT_AGENT_STATE_IDLE, NULL);
process_update_request = false;
}
else
else if (adu_update_request.workflow.action == AZ_IOT_ADU_CLIENT_SERVICE_ACTION_APPLY_DEPLOYMENT)
{
result = verify_image(
adu_update_manifest.files[0].hashes->hash_value,
Expand All @@ -1052,6 +1149,14 @@ void loop()
esp_restart();
}
}
else
{
Logger.Error("Unknown workflow action received: " + String(adu_update_request.workflow.action));

send_adu_device_information_property(AZ_IOT_ADU_CLIENT_AGENT_STATE_FAILED, &adu_update_request.workflow);

process_update_request = false;
}
}
}
}
Expand Down
33 changes: 22 additions & 11 deletions examples/Azure_IoT_Adu_ESP32/SampleAduJWS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,10 @@ static az_result base64_decode_jws_header_and_payload(jws_validation_context* ma
return AZ_OK;
}

static az_result validate_root_key(jws_validation_context* manifest_context)
static az_result validate_root_key(jws_validation_context* manifest_context,
SampleJWS::RootKey * root_keys,
uint32_t root_keys_length,
int32_t * adu_root_key_index)
{
az_result result;
az_json_reader json_reader;
Expand All @@ -656,16 +659,16 @@ static az_result validate_root_key(jws_validation_context* manifest_context)
return AZ_ERROR_ITEM_NOT_FOUND;
}

if (!az_span_is_content_equal(
az_span_create(
(uint8_t*)azure_iot_adu_root_key_id, sizeof(azure_iot_adu_root_key_id) - 1),
manifest_context->kid_span))
for( int i = 0; i < root_keys_length; i++ )
{
Logger.Error("[JWS] Using the wrong root key");
return AZ_ERROR_NOT_SUPPORTED;
if( az_span_is_content_equal( root_keys[ i ].root_key_id, manifest_context->kid_span ) )
{
*adu_root_key_index = i;
return AZ_OK;
}
}

return AZ_OK;
return AZ_ERROR_NOT_SUPPORTED;
}

static az_result verify_sha_match(jws_validation_context* manifest_context, az_span manifest_span)
Expand Down Expand Up @@ -748,11 +751,14 @@ static az_result verify_sha_match(jws_validation_context* manifest_context, az_s
az_result SampleJWS::ManifestAuthenticate(
az_span manifest_span,
az_span jws_span,
SampleJWS::RootKey * root_keys,
uint32_t root_keys_length,
az_span scratch_buffer_span)
{
az_result result;
az_json_reader json_reader;
jws_validation_context manifest_context = { 0 };
int32_t root_key_index;

/* Break up scratch buffer for reusable and persistent sections */
uint8_t* persistent_scratch_space_head = az_span_ptr(scratch_buffer_span);
Expand Down Expand Up @@ -850,7 +856,12 @@ az_result SampleJWS::ManifestAuthenticate(

/*------------------- Parse root key id ------------------------*/

validate_root_key(&manifest_context);
result = validate_root_key(&manifest_context, root_keys, root_keys_length, &root_key_index );
if (az_result_failed(result))
{
Logger.Error("[JWS] validate_root_key failed: result " + String(result, HEX));
return result;
}

/*------------------- Parse necessary pieces for signing key
* ------------------------*/
Expand Down Expand Up @@ -884,8 +895,8 @@ az_result SampleJWS::ManifestAuthenticate(
az_span_size(manifest_context.jwk_base64_encoded_header)
+ az_span_size(manifest_context.jwk_base64_encoded_payload) + 1),
manifest_context.jwk_signature,
az_span_create((uint8_t*)azure_iot_adu_root_key_n, sizeof(azure_iot_adu_root_key_n)),
az_span_create((uint8_t*)azure_iot_adu_root_key_e, sizeof(azure_iot_adu_root_key_e)),
root_keys[root_key_index].root_key_n,
root_keys[root_key_index].root_key_exponent,
manifest_context.scratch_calculation_buffer);

if (result != AZ_OK)
Expand Down
15 changes: 15 additions & 0 deletions examples/Azure_IoT_Adu_ESP32/SampleAduJWS.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,24 @@

namespace SampleJWS
{

/**
* @brief Holds the values of the root key used to verify the JWS signature.
*/
typedef struct RootKey
{
az_span root_key_id;
az_span root_key_n;
az_span root_key_exponent;
} RootKey;

/**
* @brief Authenticate the manifest from ADU.
*
* @param[in] manifest_span The escaped manifest from the ADU twin property.
* @param[in] jws_span The JWS used to authenticate \p manifest_span.
* @param[in] root_keys An array of root keys that may be used to verify the payload.
* @param[in] root_keys_length The number of root keys in \p root_keys.
* @param[in] scratch_buffer_span Scratch buffer space for calculations. It
* should be `jwsSCRATCH_BUFFER_SIZE` in length.
* @return az_result The return value of this function.
Expand All @@ -51,6 +64,8 @@ namespace SampleJWS
az_result ManifestAuthenticate(
az_span manifest_span,
az_span jws_span,
RootKey * root_keys,
uint32_t root_keys_length,
az_span scratch_buffer_span);
}; // namespace SampleJWS

Expand Down
4 changes: 2 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name=Azure SDK for C
version=1.1.0-beta.1
version=1.1.0-beta.2
author=Microsoft Corporation
maintainer=Microsoft Corporation <aziotarduino@microsoft.com>
sentence=Azure SDK for C library for Arduino.
paragraph=This is an Arduino port of the Azure SDK for C (1.4.0-beta.1). It allows you to use your Arduino device with Azure services like Azure IoT Hub and Azure Device Provisioning Service. See README.md for more details. Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.
paragraph=This is an Arduino port of the Azure SDK for C (1.4.0-beta.2). It allows you to use your Arduino device with Azure services like Azure IoT Hub and Azure Device Provisioning Service. See README.md for more details. Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.
category=Communication
url=https://github.com/Azure/azure-sdk-for-c-arduino/releases
architectures=*
Expand Down
2 changes: 1 addition & 1 deletion src/az_http_policy_logging.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static az_result _az_http_policy_logging_append_http_request_msg(
}
else
{
required_length = az_span_size(request->_internal.method) + request->_internal.url_length + 1;
required_length += az_span_size(request->_internal.method) + request->_internal.url_length + 1;
}

_az_RETURN_IF_NOT_ENOUGH_SIZE(*ref_log_msg, required_length);
Expand Down
Loading