source/azure_iot.c (126 lines of code) (raw):
/* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License. */
/**
* @file azure_iot.c
*
* @brief Common Azure IoT code for FreeRTOS middleware.
*
*/
#include "azure_iot.h"
#include <string.h>
#include "azure_iot_private.h"
#include "azure_iot_result.h"
/* Azure SDK for Embedded C includes */
#include "azure/az_iot.h"
#include "azure/core/az_base64.h"
/* Using SHA256 hash - needs 32 bytes */
#define azureiotBASE64_HASH_BUFFER_SIZE ( 33 )
/*-----------------------------------------------------------*/
/**
*
* Set the log listener in the embedded SDK.
*
* */
static void prvAzureIoTLogListener( az_log_classification xClassification,
az_span xMessage )
{
( void ) xClassification;
/* In case logs are stripped out, suppress unused parameter error. */
( void ) xMessage;
AZLogInfo( ( "%.*s", ( int16_t ) az_span_size( xMessage ), az_span_ptr( xMessage ) ) );
}
/*-----------------------------------------------------------*/
AzureIoTResult_t AzureIoT_TranslateCoreError( az_result xCoreError )
{
AzureIoTResult_t xResult;
switch( xCoreError )
{
/* Core errors */
case AZ_OK:
xResult = eAzureIoTSuccess;
break;
case AZ_ERROR_IOT_TOPIC_NO_MATCH:
xResult = eAzureIoTErrorTopicNoMatch;
break;
case AZ_ERROR_IOT_END_OF_PROPERTIES:
xResult = eAzureIoTErrorEndOfProperties;
break;
case AZ_ERROR_ARG:
xResult = eAzureIoTErrorInvalidArgument;
break;
case AZ_ERROR_ITEM_NOT_FOUND:
xResult = eAzureIoTErrorItemNotFound;
break;
case AZ_ERROR_UNEXPECTED_CHAR:
xResult = eAzureIoTErrorUnexpectedChar;
break;
case AZ_ERROR_NOT_ENOUGH_SPACE:
xResult = eAzureIoTErrorOutOfMemory;
break;
/* JSON errors */
case AZ_ERROR_JSON_INVALID_STATE:
xResult = eAzureIoTErrorJSONInvalidState;
break;
case AZ_ERROR_JSON_NESTING_OVERFLOW:
xResult = eAzureIoTErrorJSONNestingOverflow;
break;
case AZ_ERROR_JSON_READER_DONE:
xResult = eAzureIoTErrorJSONReaderDone;
break;
/* Default */
default:
xResult = eAzureIoTErrorFailed;
}
return xResult;
}
/*-----------------------------------------------------------*/
AzureIoTResult_t AzureIoT_Init()
{
#ifdef AZLogInfo
az_log_set_message_callback( prvAzureIoTLogListener );
#else
( void ) prvAzureIoTLogListener;
#endif
return eAzureIoTSuccess;
}
/*-----------------------------------------------------------*/
void AzureIoT_Deinit()
{
}
/*-----------------------------------------------------------*/
AzureIoTResult_t AzureIoT_Base64HMACCalculate( AzureIoTGetHMACFunc_t xAzureIoTHMACFunction,
const uint8_t * pucKey,
uint32_t ulKeySize,
const uint8_t * pucMessage,
uint32_t ulMessageSize,
uint8_t * pucBuffer,
uint32_t ulBufferLength,
uint8_t * pucOutput,
uint32_t ulOutputSize,
uint32_t * pulOutputLength )
{
az_result xCoreResult;
uint8_t * pucHashBuf;
uint8_t * pucDecodedKeyBuf = pucBuffer;
uint32_t ulHashBufSize = azureiotBASE64_HASH_BUFFER_SIZE;
int32_t lDecodedKeyLength;
int32_t lEncodedLength;
az_span xEncodedKeySpan;
az_span xOutputDecodedKeySpan;
az_span xHashSpan;
az_span xOutputEncodedHashSpan;
if( ( xAzureIoTHMACFunction == NULL ) ||
( pucKey == NULL ) || ( ulKeySize == 0 ) ||
( pucMessage == NULL ) || ( ulMessageSize == 0 ) ||
( pucBuffer == NULL ) || ( ulBufferLength == 0 ) ||
( pucOutput == NULL ) || ( pulOutputLength == NULL ) )
{
AZLogError( ( "AzureIoT_Base64HMACCalculate failed: Invalid argument" ) );
return eAzureIoTErrorInvalidArgument;
}
xEncodedKeySpan = az_span_create( ( uint8_t * ) pucKey, ( int32_t ) ulKeySize );
xOutputDecodedKeySpan = az_span_create( ( uint8_t * ) pucDecodedKeyBuf, ( int32_t ) ulBufferLength );
if( az_result_failed( xCoreResult = az_base64_decode( xOutputDecodedKeySpan, xEncodedKeySpan, &lDecodedKeyLength ) ) )
{
AZLogError( ( "az_base64_decode failed: core error=0x%08x", ( uint16_t ) xCoreResult ) );
return eAzureIoTErrorFailed;
}
/* Decoded key is less than total decoded buffer size */
ulBufferLength -= ( uint32_t ) lDecodedKeyLength;
if( ulHashBufSize > ulBufferLength )
{
return eAzureIoTErrorOutOfMemory;
}
pucHashBuf = pucDecodedKeyBuf + lDecodedKeyLength;
memset( pucHashBuf, 0, ulHashBufSize );
if( xAzureIoTHMACFunction( pucDecodedKeyBuf, ( uint32_t ) lDecodedKeyLength,
pucMessage, ( uint32_t ) ulMessageSize,
pucHashBuf, ulHashBufSize, &ulHashBufSize ) )
{
return eAzureIoTErrorFailed;
}
xHashSpan = az_span_create( pucHashBuf, ( int32_t ) ulHashBufSize );
xOutputEncodedHashSpan = az_span_create( pucOutput, ( int32_t ) ulOutputSize );
if( az_result_failed( xCoreResult = az_base64_encode( xOutputEncodedHashSpan, xHashSpan, &lEncodedLength ) ) )
{
AZLogError( ( "az_base64_decode failed: core error=0x%08x", ( uint16_t ) xCoreResult ) );
return eAzureIoTErrorFailed;
}
*pulOutputLength = ( uint32_t ) lEncodedLength;
return eAzureIoTSuccess;
}
/*-----------------------------------------------------------*/