1 /**************************************************************************/ 2 /* */ 3 /* Copyright (c) Microsoft Corporation. All rights reserved. */ 4 /* */ 5 /* This software is licensed under the Microsoft Software License */ 6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */ 7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ 8 /* and in the root directory of this software. */ 9 /* */ 10 /**************************************************************************/ 11 12 /** 13 * @file nx_azure_iot.h 14 * 15 */ 16 17 #ifndef NX_AZURE_IOT_H 18 #define NX_AZURE_IOT_H 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 #include "azure/core/az_log.h" 25 #include "azure/iot/az_iot_common.h" 26 #include "nx_api.h" 27 #include "nx_cloud.h" 28 #include "nxd_dns.h" 29 #include "nxd_mqtt_client.h" 30 31 #ifndef NXD_MQTT_CLOUD_ENABLE 32 #error "NXD_MQTT_CLOUD_ENABLE must be defined" 33 #endif /* NXD_MQTT_CLOUD_ENABLE */ 34 35 #ifndef NX_SECURE_ENABLE 36 #error "NX_SECURE_ENABLE must be defined" 37 #endif /* NX_SECURE_ENABLE */ 38 39 /* Defined, certificate date is not validated. By default, it is enabled. */ 40 /* 41 #define NX_AZURE_IOT_DISABLE_CERTIFICATE_DATE 42 */ 43 44 /* Define the LOG LEVEL. */ 45 #ifndef NX_AZURE_IOT_LOG_LEVEL 46 #define NX_AZURE_IOT_LOG_LEVEL 2 47 #endif /* NX_AZURE_IOT_LOG_LEVEL */ 48 49 /* Define maximum trusted certificates count. */ 50 #ifndef NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS 51 #define NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS 3 52 #endif /* NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS */ 53 54 /* Define maximum device certificates count. */ 55 #ifndef NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS 56 #define NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS 2 57 #endif /* NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS */ 58 59 #define NX_AZURE_IOT_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 60 61 /* Define the az iot log function. */ 62 #define LogError(...) 63 #define LogInfo(...) 64 #define LogDebug(...) 65 #define LogLiteralArgs(s) (UCHAR *)s, sizeof(s) - 1 66 67 /** 68 * Supports logging of AZ_LOG_IOT_AZURERTOS classification message. In the logged 69 * message, at-most one format specifier can be specifed at the end of message. 70 * Currently only two format specifier are supported: 71 * - %d for integer 72 * - %s for string, where first argument is length and second is pointer to string 73 */ 74 UINT nx_azure_iot_log(UCHAR *type_ptr, UINT type_len, UCHAR *msg_ptr, UINT msg_len, ...); 75 76 #if NX_AZURE_IOT_LOG_LEVEL > 0 77 #undef LogError 78 #define LogError(...) nx_azure_iot_log(LogLiteralArgs("[ERROR] "), __VA_ARGS__) 79 #endif /* NX_AZURE_IOT_LOG_LEVEL > 0 */ 80 #if NX_AZURE_IOT_LOG_LEVEL > 1 81 #undef LogInfo 82 #define LogInfo(...) nx_azure_iot_log(LogLiteralArgs("[INFO] "), __VA_ARGS__) 83 #endif /* NX_AZURE_IOT_LOG_LEVEL > 1 */ 84 #if NX_AZURE_IOT_LOG_LEVEL > 2 85 #undef LogDebug 86 #define LogDebug(...) nx_azure_iot_log(LogLiteralArgs("[DEBUG] "), __VA_ARGS__) 87 #endif /* NX_AZURE_IOT_LOG_LEVEL > 2 */ 88 89 #define NX_AZURE_IOT_MQTT_QOS_0 0 90 #define NX_AZURE_IOT_MQTT_QOS_1 1 91 92 /* Define AZ IoT SDK event flags. These events are processed by the Cloud thread. */ 93 94 /* Provisioning Client Connect event */ 95 #define NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_EVENT ((ULONG)0x00000001) 96 97 /* Provisioning Client Subscribe event */ 98 #define NX_AZURE_IOT_PROVISIONING_CLIENT_SUBSCRIBE_EVENT ((ULONG)0x00000002) 99 100 /* Provisioning Client Request event */ 101 #define NX_AZURE_IOT_PROVISIONING_CLIENT_REQUEST_EVENT ((ULONG)0x00000004) 102 103 /* Provisioning Client Response event */ 104 #define NX_AZURE_IOT_PROVISIONING_CLIENT_RESPONSE_EVENT ((ULONG)0x00000008) 105 106 /* Provisioning Client Disconnect event */ 107 #define NX_AZURE_IOT_PROVISIONING_CLIENT_DISCONNECT_EVENT ((ULONG)0x00000010) 108 109 /* API return values. */ 110 /**< The operation was successful. */ 111 #define NX_AZURE_IOT_SUCCESS 0x0 112 113 /**< The operation was unsuccessful. */ 114 #define NX_AZURE_IOT_FAILURE 0x20000 115 #define NX_AZURE_IOT_SDK_CORE_ERROR 0x20001 116 #define NX_AZURE_IOT_INVALID_PARAMETER 0x20002 117 #define NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE 0x20003 118 #define NX_AZURE_IOT_INVALID_PACKET 0x20004 119 #define NX_AZURE_IOT_NO_PACKET 0x20005 120 121 /**< If the item requested was not found */ 122 #define NX_AZURE_IOT_NOT_FOUND 0x20006 123 #define NX_AZURE_IOT_NOT_ENABLED 0x20007 124 #define NX_AZURE_IOT_NOT_INITIALIZED 0x20008 125 #define NX_AZURE_IOT_NOT_SUPPORTED 0x20009 126 #define NX_AZURE_IOT_ALREADY_CONNECTED 0x2000A 127 #define NX_AZURE_IOT_CONNECTING 0x2000B 128 #define NX_AZURE_IOT_DISCONNECTED 0x2000C 129 130 /**< The operation is pending. */ 131 #define NX_AZURE_IOT_PENDING 0x2000D 132 #define NX_AZURE_IOT_SERVER_RESPONSE_ERROR 0x2000E 133 #define NX_AZURE_IOT_TOPIC_TOO_LONG 0x2000F 134 #define NX_AZURE_IOT_MESSAGE_TOO_LONG 0x20010 135 #define NX_AZURE_IOT_NO_AVAILABLE_CIPHER 0x20011 136 #define NX_AZURE_IOT_WRONG_STATE 0x20012 137 #define NX_AZURE_IOT_DELETE_ERROR 0x20013 138 #define NX_AZURE_IOT_NO_SUBSCRIBE_ACK 0x20014 139 #define NX_AZURE_IOT_THROTTLED 0x20015 140 141 #define NX_AZURE_IOT_EMPTY_JSON 0x20016 142 #define NX_AZURE_IOT_SAS_TOKEN_EXPIRED 0x20017 143 #define NX_AZURE_IOT_NO_MORE_ENTRIES 0x20018 144 145 /* Resource type managed by AZ_IOT. */ 146 #define NX_AZURE_IOT_RESOURCE_IOT_HUB 0x1 147 #define NX_AZURE_IOT_RESOURCE_IOT_PROVISIONING 0x2 148 149 /* Define the packet buffer for THREADX TLS. */ 150 #ifndef NX_AZURE_IOT_TLS_PACKET_BUFFER_SIZE 151 #define NX_AZURE_IOT_TLS_PACKET_BUFFER_SIZE (1024 * 7) 152 #endif /* NX_AZURE_IOT_TLS_PACKET_BUFFER_SIZE */ 153 154 /* Define MQTT keep alive in seconds. 0 means the keep alive is disabled. 155 By default, keep alive is 4 minutes. */ 156 #ifndef NX_AZURE_IOT_MQTT_KEEP_ALIVE 157 #define NX_AZURE_IOT_MQTT_KEEP_ALIVE (60 * 4) 158 #endif /* NX_AZURE_IOT_MQTT_KEEP_ALIVE */ 159 160 /* MQTT Subscribe topic offset. */ 161 #define NX_AZURE_IOT_MQTT_SUBSCRIBE_TOPIC_OFFSET 6 162 163 /* MQTT Publish offset. */ 164 #define NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET 7 165 166 /** 167 * @brief Resource struct 168 * 169 */ 170 typedef struct NX_AZURE_IOT_RESOURCE_STRUCT 171 { 172 UINT resource_type; 173 VOID *resource_data_ptr; 174 NXD_MQTT_CLIENT resource_mqtt; 175 UCHAR *resource_mqtt_client_id; 176 UINT resource_mqtt_client_id_length; 177 UCHAR *resource_mqtt_user_name; 178 UINT resource_mqtt_user_name_length; 179 UCHAR *resource_mqtt_sas_token; 180 UINT resource_mqtt_sas_token_length; 181 VOID *resource_mqtt_buffer_context; 182 UINT resource_mqtt_buffer_size; 183 UCHAR resource_tls_packet_buffer[NX_AZURE_IOT_TLS_PACKET_BUFFER_SIZE]; 184 const NX_CRYPTO_METHOD **resource_crypto_array; 185 UINT resource_crypto_array_size; 186 const NX_CRYPTO_CIPHERSUITE **resource_cipher_map; 187 UINT resource_cipher_map_size; 188 UCHAR *resource_metadata_ptr; 189 UINT resource_metadata_size; 190 NX_SECURE_X509_CERT *resource_trusted_certificates[NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS]; 191 NX_SECURE_X509_CERT *resource_device_certificates[NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS]; 192 const UCHAR *resource_hostname; 193 UINT resource_hostname_length; 194 struct NX_AZURE_IOT_RESOURCE_STRUCT *resource_next; 195 196 } NX_AZURE_IOT_RESOURCE; 197 198 /** 199 * @brief Azure IoT Struct 200 * 201 */ 202 typedef struct NX_AZURE_IOT_STRUCT 203 { 204 const UCHAR *nx_azure_iot_name; 205 NX_IP *nx_azure_iot_ip_ptr; 206 NX_PACKET_POOL *nx_azure_iot_pool_ptr; 207 NX_DNS *nx_azure_iot_dns_ptr; 208 NX_CLOUD nx_azure_iot_cloud; 209 NX_CLOUD_MODULE nx_azure_iot_cloud_module; 210 TX_MUTEX *nx_azure_iot_mutex_ptr; 211 VOID (*nx_azure_iot_provisioning_client_event_process)( 212 struct NX_AZURE_IOT_STRUCT *nx_azure_iot_ptr, 213 ULONG common_events, ULONG module_own_events); 214 struct NX_AZURE_IOT_RESOURCE_STRUCT *nx_azure_iot_resource_list_header; 215 UINT (*nx_azure_iot_unix_time_get)(ULONG *unix_time); 216 } NX_AZURE_IOT; 217 218 typedef struct NX_AZURE_IOT_THREAD_STRUCT 219 { 220 TX_THREAD *thread_ptr; 221 struct NX_AZURE_IOT_THREAD_STRUCT *thread_next; 222 UINT thread_message_type; 223 UINT thread_expected_id; /* Used by device twin. */ 224 NX_PACKET *thread_received_message; 225 } NX_AZURE_IOT_THREAD; 226 227 /** 228 * @brief Create the Azure IoT subsystem 229 * 230 * @details This routine creates the Azure IoT subsystem. An internal thread is created to 231 * manage activities related to Azure IoT services. Only one NX_AZURE_IOT instance 232 * is needed to manage instances for Azure IoT hub, IoT Central, Device Provisioning 233 * Services (DPS), and Azure Security Center (ASC). 234 * 235 * @remarks This routine enables ASC by default. ASC provides a comprehensive security solution for 236 * Azure RTOS devices in which it collects network information and send it to the IoTHub. 237 * More details can be found https://docs.microsoft.com/en-us/azure/defender-for-iot/iot-security-azure-rtos. 238 * To disable ASC from your application, we provide both compile time and runtime option: 239 * - compile-time : NX_AZURE_DISABLE_IOT_SECURITY_MODULE in NetXDuo header file such as nx_port.h 240 * when building the middleware. 241 * - runtime : Call UINT nx_azure_iot_security_module_disable(NX_AZURE_IOT *nx_azure_iot_ptr) 242 * in your application code. 243 * 244 * @param[in] nx_azure_iot_ptr A pointer to a #NX_AZURE_IOT 245 * @param[in] name_ptr A pointer to a NULL-terminated string indicating the name of the Azure IoT instance. 246 * @param[in] ip_ptr A pointer to a `NX_IP`, which is the IP stack used to connect to Azure IoT Services. 247 * @param[in] pool_ptr A pointer to a `NX_PACKET_POOL`, which is the packet pool used by Azure IoT Services. 248 * @param[in] dns_ptr A pointer to a `NX_DNS`. 249 * @param[in] stack_memory_ptr A pointer to memory to be used as a stack space for the internal thread. 250 * @param[in] stack_memory_size Size of stack memory area. 251 * @param[in] priority Priority of the internal thread. 252 * @param[in] unix_time_callback Callback to fetch unix time from platform. 253 * @return A `UINT` with the result of the API. 254 * @retval #NX_AZURE_IOT_SUCCESS Successfully created the Azure IoT instance. 255 * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to create the Azure IoT instance due to invalid parameter. 256 * @retval NX_OPTION_ERROR Fail to create the Azure IoT instance due to invalid priority. 257 * @retval NX_PTR_ERROR Fail to create the Azure IoT instance due to invalid parameter. 258 * @retval NX_SIZE_ERROR Fail to create the Azure IoT instance due to insufficient size of stack memory. 259 */ 260 UINT nx_azure_iot_create(NX_AZURE_IOT *nx_azure_iot_ptr, const UCHAR *name_ptr, 261 NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, 262 VOID *stack_memory_ptr, UINT stack_memory_size, 263 UINT priority, UINT (*unix_time_callback)(ULONG *unix_time)); 264 265 /** 266 * @brief Shutdown and cleanup the Azure IoT subsystem. 267 * @details This routine stops all Azure services managed by this instance, and cleans up internal resources. 268 * 269 * @param[in] nx_azure_iot_ptr A pointer to a #NX_AZURE_IOT. 270 * @return A `UINT` with the result of the API. 271 * @retval #NX_AZURE_IOT_SUCCESS Successfully stopped Azure IoT services and cleaned up internal 272 * resources instance. 273 * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to delete the Azure IoT instance due to invalid parameter. 274 * @retval #NX_AZURE_IOT_DELETE_ERROR Fail to delete the Azure IoT instance due to resource is still in use. 275 */ 276 UINT nx_azure_iot_delete(NX_AZURE_IOT *nx_azure_iot_ptr); 277 278 /** 279 * @brief Get unixtime 280 * 281 * @param[in] nx_azure_iot_ptr A pointer to a #NX_AZURE_IOT. 282 * @param[out] unix_time Pointer to `ULONG` where unixtime is returned. 283 * @return A `UINT` with the result of the API. 284 * @retval #NX_AZURE_IOT_SUCCESS Successfully return unix time. 285 * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to get unix time due to invalid parameter. 286 */ 287 UINT nx_azure_iot_unix_time_get(NX_AZURE_IOT *nx_azure_iot_ptr, ULONG *unix_time); 288 289 /** 290 * @brief Initialize logging 291 * 292 * @details This routine initialized the logging with customer specific callback to output the logs for different 293 * classifications: 294 * - AZ_LOG_IOT_AZURERTOS, 295 * - AZ_LOG_MQTT_RECEIVED_TOPIC, 296 * - AZ_LOG_MQTT_RECEIVED_PAYLOAD, 297 * - AZ_LOG_IOT_RETRY, 298 * - AZ_LOG_IOT_SAS_TOKEN 299 * 300 * @param[in] log_callback A pointer to a callback. 301 * 302 */ 303 VOID nx_azure_iot_log_init(VOID(*log_callback)(az_log_classification classification, UCHAR *msg, UINT msg_len)); 304 305 /* Internal APIs. */ 306 UINT nx_azure_iot_buffer_allocate(NX_AZURE_IOT *nx_azure_iot_ptr, UCHAR **buffer_pptr, 307 UINT *buffer_size, VOID **buffer_context); 308 UINT nx_azure_iot_buffer_free(VOID *buffer_context); 309 UINT nx_azure_iot_resource_add(NX_AZURE_IOT *nx_azure_iot_ptr, NX_AZURE_IOT_RESOURCE *resource); 310 UINT nx_azure_iot_resource_remove(NX_AZURE_IOT *nx_azure_iot_ptr, NX_AZURE_IOT_RESOURCE *resource); 311 NX_AZURE_IOT_RESOURCE *nx_azure_iot_resource_search(NXD_MQTT_CLIENT *client_ptr); 312 UINT nx_azure_iot_publish_mqtt_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, 313 UINT topic_len, UCHAR *packet_id, UINT qos, UINT wait_option); 314 UINT nx_azure_iot_publish_packet_get(NX_AZURE_IOT *nx_azure_iot_ptr, NXD_MQTT_CLIENT *client_ptr, 315 NX_PACKET **packet_pptr, UINT wait_option); 316 UINT nx_azure_iot_mqtt_packet_id_get(NXD_MQTT_CLIENT *client_ptr, UCHAR *packet_id); 317 VOID nx_azure_iot_mqtt_packet_adjust(NX_PACKET *packet_ptr); 318 UINT nx_azure_iot_mqtt_tls_setup(NXD_MQTT_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session, 319 NX_SECURE_X509_CERT *certificate, 320 NX_SECURE_X509_CERT *trusted_certificate); 321 UINT nx_azure_iot_base64_hmac_sha256_calculate(NX_AZURE_IOT_RESOURCE *resource_ptr, 322 const UCHAR *key_ptr, UINT key_size, 323 const UCHAR *message_ptr, UINT message_size, 324 UCHAR *buffer_ptr, UINT buffer_len, 325 UCHAR **output_ptr, UINT *output_len_ptr); 326 327 #ifdef __cplusplus 328 } 329 #endif 330 #endif /* NX_AZURE_IOT_H */ 331