1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**
12  * @file nx_azure_iot_provisioning_client.h
13  *
14  * @brief Definition for the Azure Device Provisioning client.
15  * @remark The Device Provisioning MQTT protocol is described at
16  * https://docs.microsoft.com/en-us/azure/iot-dps/iot-dps-mqtt-support.
17  *
18  */
19 
20 #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_H
21 #define NX_AZURE_IOT_PROVISIONING_CLIENT_H
22 
23 #ifdef __cplusplus
24 extern   "C" {
25 #endif
26 
27 #include "azure/iot/az_iot_provisioning_client.h"
28 #include "nx_azure_iot.h"
29 #include "nx_api.h"
30 #include "nxd_mqtt_client.h"
31 
32 /* Define the MAX status size. */
33 #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_STATUS_ID_SIZE
34 #define NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_STATUS_ID_SIZE        30
35 #endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_STATUS_ID_SIZE */
36 
37 /* Define the MAX deviceID size. */
38 #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_ID_BUFFER_SIZE
39 #define NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_ID_BUFFER_SIZE        100
40 #endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_ID_BUFFER_SIZE */
41 
42 /* Define the MAX IoT Hub Endpoint size. */
43 #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_HUB_SIZE
44 #define NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_HUB_SIZE              100
45 #endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_HUB_SIZE */
46 
47 /* Define the MAX operation Id of provisioning service. */
48 #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_REQ_OP_ID_SIZE
49 #define NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_REQ_OP_ID_SIZE        100
50 #endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_MAX_REQ_OP_ID_SIZE */
51 
52 /* Set the default token expiry in secs.  */
53 #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_TOKEN_EXPIRY
54 #define NX_AZURE_IOT_PROVISIONING_CLIENT_TOKEN_EXPIRY              (3600)
55 #endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_TOKEN_EXPIRY */
56 
57 /* Set the default timeout for DNS query.  */
58 #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_DNS_TIMEOUT
59 #define NX_AZURE_IOT_PROVISIONING_CLIENT_DNS_TIMEOUT               (5 * NX_IP_PERIODIC_RATE)
60 #endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_DNS_TIMEOUT */
61 
62 typedef struct NX_AZURE_IOT_PROVISIONING_DEVICE_RESPONSE_STRUCT
63 {
64     az_iot_provisioning_client_register_response    register_response;
65     NX_PACKET                                      *packet_ptr;
66 } NX_AZURE_IOT_PROVISIONING_RESPONSE;
67 
68 typedef struct NX_AZURE_IOT_PROVISIONING_THREAD_STRUCT
69 {
70     TX_THREAD                                      *thread_ptr;
71     struct NX_AZURE_IOT_PROVISIONING_THREAD_STRUCT *thread_next;
72 } NX_AZURE_IOT_PROVISIONING_THREAD;
73 
74 /**
75  * @brief Azure IoT Provisining Client struct
76  *
77  */
78 typedef struct NX_AZURE_IOT_PROVISIONING_CLIENT_STRUCT
79 {
80     NX_AZURE_IOT                           *nx_azure_iot_ptr;
81 
82     UINT                                    nx_azure_iot_provisioning_client_state;
83     NX_AZURE_IOT_PROVISIONING_THREAD       *nx_azure_iot_provisioning_client_thread_suspended;
84 
85     UINT                                    nx_azure_iot_provisioning_client_req_timeout;
86     NX_PACKET                              *nx_azure_iot_provisioning_client_last_response;
87     UINT                                    nx_azure_iot_provisioning_client_request_id;
88     UINT                                    nx_azure_iot_provisioning_client_result;
89     NX_AZURE_IOT_PROVISIONING_RESPONSE      nx_azure_iot_provisioning_client_response;
90     VOID                                  (*nx_azure_iot_provisioning_client_on_complete_callback)(
91                                            struct NX_AZURE_IOT_PROVISIONING_CLIENT_STRUCT *prov_client_ptr,
92                                            UINT status);
93 
94     const UCHAR                            *nx_azure_iot_provisioning_client_endpoint;
95     UINT                                    nx_azure_iot_provisioning_client_endpoint_length;
96     const UCHAR                            *nx_azure_iot_provisioning_client_id_scope;
97     UINT                                    nx_azure_iot_provisioning_client_id_scope_length;
98     const UCHAR                            *nx_azure_iot_provisioning_client_registration_payload;
99     UINT                                    nx_azure_iot_provisioning_client_registration_payload_length;
100     const UCHAR                            *nx_azure_iot_provisioning_client_registration_id;
101     UINT                                    nx_azure_iot_provisioning_client_registration_id_length;
102     const UCHAR                            *nx_azure_iot_provisioning_client_symmetric_key;
103     UINT                                    nx_azure_iot_provisioning_client_symmetric_key_length;
104     UCHAR                                  *nx_azure_iot_provisioning_client_sas_token;
105     UINT                                    nx_azure_iot_provisioning_client_sas_token_buff_size;
106 
107     NX_AZURE_IOT_RESOURCE                   nx_azure_iot_provisioning_client_resource;
108     az_iot_provisioning_client              nx_azure_iot_provisioning_client_core;
109 } NX_AZURE_IOT_PROVISIONING_CLIENT;
110 
111 
112 /**
113  * @brief Initialize Azure IoT Provisioning instance
114  * @details This routine initializes the device to the IoT provisioning service.
115  *
116  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
117  * @param[in] nx_azure_iot_ptr A pointer to a #NX_AZURE_IOT.
118  * @param[in] endpoint A `UCHAR` pointer to IoT Provisioning endpoint. Must be `NULL` terminated.
119  * @param[in] endpoint_length Length of `endpoint`. Does not include the `NULL` terminator.
120  * @param[in] id_scope A `UCHAR` pointer to ID Scope.
121  * @param[in] id_scope_length Length of the `id_scope`. Does not include the `NULL` terminator.
122  * @param[in] registration_id A `UCHAR` pointer to registration ID.
123  * @param[in] registration_id_length Length of `registration_id`. Does not include the `NULL` terminator.
124  * @param[in] crypto_array A pointer to `NX_CRYPTO_METHOD`.
125  * @param[in] crypto_array_size Size of `crypto_array`.
126  * @param[in] cipher_map A pointer to `NX_CRYPTO_CIPHERSUITE`.
127  * @param[in] cipher_map_size Size of `cipher_map`.
128  * @param[in] metadata_memory A `UCHAR` pointer to metadata memory buffer.
129  * @param[in] memory_size Size of metadata buffer.
130  * @param[in] trusted_certificate A pointer to `NX_SECURE_X509_CERT`, which are the server side certs.
131  * @return A `UINT` with the result of the API.
132  *  @retval #NX_AZURE_IOT_SUCCESS Successfully initialized to Azure IoT Provisioning Client.
133  *  @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to initialize the Azure IoT Provisioning Client due to invalid parameter.
134  *  @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to initialize the Azure IoT Provisioning Client due to SDK core error.
135  *  @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to initialize the Azure IoT Provisioning Client due to buffer size is too small.
136  */
137 UINT nx_azure_iot_provisioning_client_initialize(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
138                                                  NX_AZURE_IOT *nx_azure_iot_ptr,
139                                                  const UCHAR *endpoint, UINT endpoint_length,
140                                                  const UCHAR *id_scope, UINT id_scope_length,
141                                                  const UCHAR *registration_id, UINT registration_id_length,
142                                                  const NX_CRYPTO_METHOD **crypto_array, UINT crypto_array_size,
143                                                  const NX_CRYPTO_CIPHERSUITE **cipher_map, UINT cipher_map_size,
144                                                  UCHAR *metadata_memory, UINT memory_size,
145                                                  NX_SECURE_X509_CERT *trusted_certificate);
146 
147 /**
148  * @brief Cleanup the Azure IoT Provisioning Client.
149  * @details This routine de-initializes the Azure IoT Provisioning Client.
150  *
151  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
152  * @return A `UINT` with the result of the API.
153  *  @retval #NX_AZURE_IOT_SUCCESS Successfully cleaned up AZ IoT Provisioning Client Instance.
154  *  @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to deinitialize the AZ IoT Provisioning Client Instance due to invalid parameter.
155  *  @retval #NX_AZURE_IOT_NOT_FOUND Fail to deinitialize the AZ IoT Provisioning Client Instance due to resource not found.
156  */
157 UINT nx_azure_iot_provisioning_client_deinitialize(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr);
158 
159 /**
160  * @brief Add more trusted certificate in the IoT Provisioning client if needed. It can be called multiple times to set certificate chain.
161  *
162  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
163  * @param[in] trusted_certificate A pointer to a `NX_SECURE_X509_CERT`, which is the trusted certificate.
164  * @return A `UINT` with the result of the API.
165  *  @retval #NX_AZURE_IOT_SUCCESS Successfully add trusted certificate to AZ IoT Provisioning Client Instance.
166  *  @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to add trusted certificate to AZ IoT Provisioning Client Instance due to invalid parameter.
167  *  @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to add trusted certificate due to NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS is too small.
168  */
169 UINT nx_azure_iot_provisioning_client_trusted_cert_add(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
170                                                        NX_SECURE_X509_CERT *trusted_certificate);
171 
172 /**
173  * @brief Set client certificate.
174  * @details This routine sets the device certificate. It can be called multiple times to set certificate chain.
175  *
176  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
177  * @param[in] x509_cert A pointer to a `NX_SECURE_X509_CERT` client cert.
178  * @return A `UINT` with the result of the API.
179  *  @retval #NX_AZURE_IOT_SUCCESS Successfully set device certs to AZ IoT Provisioning Client Instance.
180  *  @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set device certs to AZ IoT Provisioning Client Instance due to invalid parameter.
181  *  @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to set device certificate due to NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS is too small.
182  */
183 UINT nx_azure_iot_provisioning_client_device_cert_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
184                                                       NX_SECURE_X509_CERT *x509_cert);
185 
186 /**
187  * @brief Set symmetric key
188  * @details This routine sets symmetric key.
189  *
190  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
191  * @param[in] symmetric_key A UCHAR pointer to a symmetric key.
192  * @param[in] symmetric_key_length Length of symmetric key.
193  * @return A `UINT` with the result of the API.
194  *  @retval #NX_AZURE_IOT_SUCCESS Successfully set symmetric key to the IoT Provisioning client.
195  *  @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set symmetric key to AZ IoT Provisioning Client Instance due to invalid parameter.
196  */
197 UINT nx_azure_iot_provisioning_client_symmetric_key_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
198                                                         const UCHAR *symmetric_key, UINT symmetric_key_length);
199 
200 #ifdef NXD_MQTT_OVER_WEBSOCKET
201 /**
202  * @brief Enable using MQTT over WebSocket to register device to Azure IoT Provisioning service.
203  *
204  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
205  * @return A `UINT` with the result of the API.
206  *   @retval #NX_AZURE_IOT_SUCCESS Successful if MQTT over WebSocket is enabled.
207  *   @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to enable MQTT over WebSocket due to invalid parameter.
208  */
209 UINT nx_azure_iot_provisioning_client_websocket_enable(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr);
210 #endif /* NXD_MQTT_OVER_WEBSOCKET */
211 
212 /**
213  * @brief Register device to Azure IoT Provisioning service.
214  * @details This routine registers device to Azure IoT Provisioning service.
215  *
216  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
217  * @param[in] wait_option Number of ticks to block for device registration.
218  * @return A `UINT` with the result of the API.
219  *  @retval #NX_AZURE_IOT_SUCCESS Successfully register device to AZ IoT Provisioning.
220  *  @retval #NX_AZURE_IOT_PENDING Successfully started registration of device but not yet completed.
221  *  @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to register device to AZ IoT Provisioning due to invalid parameter.
222  *  @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to register device to AZ IoT Provisioning due to SDK core error.
223  *  @retval #NX_AZURE_IOT_SERVER_RESPONSE_ERROR Fail to register device to AZ IoT Provisioning due to error response from server.
224  *  @retval #NX_AZURE_IOT_DISCONNECTED Fail to register device to AZ IoT Provisioning due to disconnection.
225  *  @retval NX_DNS_QUERY_FAILED Fail to register device to AZ IoT Provisioning due to hostname can not be resolved.
226  *  @retval NX_NO_PACKET Fail to register device to AZ IoT Provisioning due to no available packet in pool.
227  *  @retval NX_INVALID_PARAMETERS Fail to register device to AZ IoT Provisioning due to invalid parameters.
228  *  @retval NX_SECURE_TLS_INSUFFICIENT_METADATA_SPACE Fail to register device to AZ IoT Provisioning due to insufficient metadata space.
229  *  @retval NX_SECURE_TLS_UNSUPPORTED_CIPHER Fail to register device to AZ IoT Provisioning due to unsupported cipher.
230  *  @retval NXD_MQTT_ALREADY_CONNECTED Fail to register device to AZ IoT Provisioning due to MQTT session is not disconnected.
231  *  @retval NXD_MQTT_CONNECT_FAILURE Fail to register device to AZ IoT Provisioning due to TCP/TLS connect error.
232  *  @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to register device to AZ IoT Provisioning due to MQTT connect error.
233  *  @retval NXD_MQTT_ERROR_SERVER_UNAVAILABLE Fail to register device to AZ IoT Provisioning due to server unavailable.
234  *  @retval NXD_MQTT_ERROR_NOT_AUTHORIZED Fail to register device to AZ IoT Provisioning due to authentication error.
235  */
236 UINT nx_azure_iot_provisioning_client_register(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, UINT wait_option);
237 
238 /**
239  * @brief Set registration completion callback
240  * @details This routine sets the callback for registration completion.
241  *
242  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
243  * @param[in] on_complete_callback Registration completion callback.
244  * @return A `UINT` with the result of the API.
245  *  @retval #NX_AZURE_IOT_SUCCESS Successful register completion callback.
246  *  @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to register completion callback due to invalid parameter.
247  */
248 UINT nx_azure_iot_provisioning_client_completion_callback_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
249                                                               VOID (*on_complete_callback)(
250                                                                     struct NX_AZURE_IOT_PROVISIONING_CLIENT_STRUCT *client_ptr,
251                                                                     UINT status));
252 
253 /**
254  * @brief Set registration payload
255  * @details This routine sets registration payload, which is JSON object.
256  *
257  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
258  * @param[in] payload_ptr A pointer to registration payload.
259  * @param[in] payload_length Length of `payload`. Does not include the `NULL` terminator.
260  * @return A `UINT` with the result of the API.
261  *  @retval #NX_AZURE_IOT_SUCCESS Successfully set registration payload to Azure IoT Provisioning Client.
262  *  @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set registration payload Azure IoT Provisioning Client due to invalid parameter.
263  */
264 UINT nx_azure_iot_provisioning_client_registration_payload_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
265                                                                const UCHAR *payload_ptr, UINT payload_length);
266 
267 /**
268  * @brief Get IoTHub device info into user supplied buffer.
269  * @details This routine gets the device id and puts it into a user supplied buffer.
270  *
271  * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT.
272  * @param[out] iothub_hostname Buffer pointer that will contain IoTHub hostname.
273  * @param[in/out] iothub_hostname_len Pointer to UINT that contains size of buffer supplied. On successful return,
274  *               it contains bytes copied to the buffer.
275  * @param[out] device_id Buffer pointer that will contain IoTHub deviceId.
276  * @param[in/out] device_id_len Pointer to UINT that contains size of buffer supplied, once successfully return it contains bytes copied to buffer.
277  * @return A `UINT` with the result of the API.
278  *  @retval #NX_AZURE_IOT_SUCCESS The device info is successfully retrieved to user supplied buffers.
279  *  @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to retrieve device info due to invalid parameter.
280  *  @retval #NX_AZURE_IOT_WRONG_STATE Fail to retrieve device info due to wrong state.
281  *  @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to retrieve device info due to buffer size is too small.
282  */
283 UINT nx_azure_iot_provisioning_client_iothub_device_info_get(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr,
284                                                              UCHAR *iothub_hostname, UINT *iothub_hostname_len,
285                                                              UCHAR *device_id, UINT *device_id_len);
286 
287 #ifdef __cplusplus
288 }
289 #endif
290 #endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_H */
291