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 #include <stdio.h>
12 
13 #include "nx_api.h"
14 #include "nx_azure_iot_hub_client.h"
15 #include "nx_azure_iot_cert.h"
16 #include "nx_azure_iot_ciphersuites.h"
17 
18 
19 #define DEMO_DHCP_DISABLE
20 #define DEMO_IPV4_ADDRESS         IP_ADDRESS(192, 168, 100, 33)
21 #define DEMO_IPV4_MASK            0xFFFFFF00UL
22 #define DEMO_GATEWAY_ADDRESS      IP_ADDRESS(192, 168, 100, 1)
23 #define DEMO_DNS_SERVER_ADDRESS   IP_ADDRESS(192, 168, 100, 1)
24 #define NETWORK_DRIVER            _nx_ram_network_driver
25 
26 /* Include main.c in the test case since we need to disable DHCP in this test. */
27 #include "main.c"
28 
29 
30 #define STRING_UNSIGNED_ARGS(s) (UCHAR *)s, strlen(s)
31 
32 #ifndef DEMO_CLOUD_STACK_SIZE
33 #define DEMO_CLOUD_STACK_SIZE   2048
34 #endif /* DEMO_CLOUD_STACK_SIZE */
35 
36 #ifndef DEMO_CLOUD_THREAD_PRIORITY
37 #define DEMO_CLOUD_THREAD_PRIORITY  (4)
38 #endif /* DEMO_CLOUD_THREAD_PRIORITY */
39 
40 UINT __wrap__nxde_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr);
41 UINT __wrap__nxde_mqtt_client_receive_notify_set(NXD_MQTT_CLIENT *client_ptr,
42                                                  VOID (*receive_notify)(NXD_MQTT_CLIENT *client_ptr,
43                                                                         UINT message_count));
44 
45 static NX_AZURE_IOT iot;
46 static NX_AZURE_IOT_HUB_CLIENT iot_client;
47 static NX_AZURE_IOT_HUB_CLIENT iot_clients[3];
48 static NX_SECURE_X509_CERT root_ca_cert;
49 static UCHAR metadata_buffer[NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE];
50 static ULONG demo_cloud_thread_stack[DEMO_CLOUD_STACK_SIZE / sizeof(ULONG)];
51 extern int g_argc;
52 extern char **g_argv;
53 extern NX_AZURE_IOT *_nx_azure_iot_created_ptr;
54 
demo_entry(NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,NX_DNS * dns_ptr,UINT (* unix_time_callback)(ULONG * unix_time))55 VOID demo_entry(NX_IP* ip_ptr, NX_PACKET_POOL* pool_ptr, NX_DNS* dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
56 {
57 CHAR *host_name = "host_name";
58 CHAR *device_id = "device_id";
59 CHAR *module_id = "module_id";
60 CHAR *symmetric_key = "symmetric_key";
61 UINT i;
62 
63     /* Initialize root certificate.  */
64     assert_int_equal(nx_secure_x509_certificate_initialize(&root_ca_cert, (UCHAR *)_nx_azure_iot_root_cert, (USHORT)_nx_azure_iot_root_cert_size,
65                                                            NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE),
66                      NX_AZURE_IOT_SUCCESS);
67 
68     /*********** Test nx_azure_iot_create() ***********/
69     /* FAIL: NX_AZURE_IOT pointer is null. */
70     assert_int_not_equal(nx_azure_iot_create(NX_NULL, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr, (UCHAR *)demo_cloud_thread_stack,
71                                              sizeof(demo_cloud_thread_stack), DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
72                          NX_AZURE_IOT_SUCCESS);
73 
74     /* FAIL: NX_IP pointer is null. */
75     assert_int_not_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT", NX_NULL, pool_ptr, dns_ptr, (UCHAR *)demo_cloud_thread_stack,
76                                              sizeof(demo_cloud_thread_stack), DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
77                          NX_AZURE_IOT_SUCCESS);
78 
79     /* FAIL: NX_PACKET_POOL pointer is null. */
80     assert_int_not_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT", ip_ptr, NX_NULL, dns_ptr, (UCHAR *)demo_cloud_thread_stack,
81                                              sizeof(demo_cloud_thread_stack), DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
82                          NX_AZURE_IOT_SUCCESS);
83 
84     /* FAIL: NX_DNS pointer is null. */
85     assert_int_not_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, NX_NULL, (UCHAR *)demo_cloud_thread_stack,
86                                              sizeof(demo_cloud_thread_stack), DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
87                          NX_AZURE_IOT_SUCCESS);
88 
89     /* FAIL: stack pointer is null. */
90     assert_int_not_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr, NX_NULL,
91                                              sizeof(demo_cloud_thread_stack), DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
92                          NX_AZURE_IOT_SUCCESS);
93 
94     /* FAIL: stack size is 0. */
95     assert_int_not_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr, (UCHAR *)demo_cloud_thread_stack,
96                                              0, DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
97                          NX_AZURE_IOT_SUCCESS);
98 
99     /* SUCCESS: all parameters are valid. */
100     assert_int_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr, (UCHAR *)demo_cloud_thread_stack,
101                                          sizeof(demo_cloud_thread_stack), DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
102                      NX_AZURE_IOT_SUCCESS);
103 
104     /*********** Test nx_azure_iot_delete() ***********/
105     /* FAIL: NX_AZURE_IOT pointer is null. */
106     assert_int_not_equal(nx_azure_iot_delete(NX_NULL), NX_AZURE_IOT_SUCCESS);
107 
108     /* FAIL: nx_cloud_delete fail. */
109     /* Manually set nx_cloud_modules_count to none zero. */
110     iot.nx_azure_iot_cloud.nx_cloud_modules_count++;
111     assert_int_not_equal(nx_azure_iot_delete(&iot), NX_AZURE_IOT_SUCCESS);
112     iot.nx_azure_iot_cloud.nx_cloud_modules_count--;
113 
114     /* SUCCESS: iot is created. */
115     assert_int_equal(nx_azure_iot_delete(&iot), NX_AZURE_IOT_SUCCESS);
116 
117 
118     /*********** Test nx_azure_iot_hub_client_initialize() ***********/
119     assert_int_equal(nx_azure_iot_create(&iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr, (UCHAR *)demo_cloud_thread_stack,
120                                          sizeof(demo_cloud_thread_stack), DEMO_CLOUD_THREAD_PRIORITY, unix_time_callback),
121                      NX_AZURE_IOT_SUCCESS);
122 
123     /* FAIL: NX_AZURE_IOT pointer is null. */
124     assert_int_not_equal(nx_azure_iot_hub_client_initialize(&iot_client, NX_NULL,
125                                                             STRING_UNSIGNED_ARGS(host_name),
126                                                             STRING_UNSIGNED_ARGS(device_id),
127                                                             STRING_UNSIGNED_ARGS(module_id),
128                                                             _nx_azure_iot_tls_supported_crypto,
129                                                             _nx_azure_iot_tls_supported_crypto_size,
130                                                             _nx_azure_iot_tls_ciphersuite_map,
131                                                             _nx_azure_iot_tls_ciphersuite_map_size,
132                                                             metadata_buffer, sizeof(metadata_buffer),
133                                                             &root_ca_cert),
134                          NX_AZURE_IOT_SUCCESS);
135 
136     /* FAIL: NX_AZURE_IOT_HUB_CLIENT pointer is null. */
137     assert_int_not_equal(nx_azure_iot_hub_client_initialize(NX_NULL, &iot,
138                                                             STRING_UNSIGNED_ARGS(host_name),
139                                                             STRING_UNSIGNED_ARGS(device_id),
140                                                             STRING_UNSIGNED_ARGS(module_id),
141                                                             _nx_azure_iot_tls_supported_crypto,
142                                                             _nx_azure_iot_tls_supported_crypto_size,
143                                                             _nx_azure_iot_tls_ciphersuite_map,
144                                                             _nx_azure_iot_tls_ciphersuite_map_size,
145                                                             metadata_buffer, sizeof(metadata_buffer),
146                                                             &root_ca_cert),
147                          NX_AZURE_IOT_SUCCESS);
148 
149     /* FAIL: host_name pointer is null. */
150     assert_int_not_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
151                                                             NX_NULL, 0,
152                                                             STRING_UNSIGNED_ARGS(device_id),
153                                                             STRING_UNSIGNED_ARGS(module_id),
154                                                             _nx_azure_iot_tls_supported_crypto,
155                                                             _nx_azure_iot_tls_supported_crypto_size,
156                                                             _nx_azure_iot_tls_ciphersuite_map,
157                                                             _nx_azure_iot_tls_ciphersuite_map_size,
158                                                             metadata_buffer, sizeof(metadata_buffer),
159                                                             &root_ca_cert),
160                          NX_AZURE_IOT_SUCCESS);
161 
162     /* FAIL: device_id pointer is null. */
163     assert_int_not_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
164                                                             STRING_UNSIGNED_ARGS(host_name),
165                                                             NX_NULL, 0,
166                                                             STRING_UNSIGNED_ARGS(module_id),
167                                                             _nx_azure_iot_tls_supported_crypto,
168                                                             _nx_azure_iot_tls_supported_crypto_size,
169                                                             _nx_azure_iot_tls_ciphersuite_map,
170                                                             _nx_azure_iot_tls_ciphersuite_map_size,
171                                                             metadata_buffer, sizeof(metadata_buffer),
172                                                             &root_ca_cert),
173                          NX_AZURE_IOT_SUCCESS);
174 
175     /* FAIL: host_name_length is 0. */
176     assert_int_not_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
177                                                             "", 0,
178                                                             STRING_UNSIGNED_ARGS(device_id),
179                                                             STRING_UNSIGNED_ARGS(module_id),
180                                                             _nx_azure_iot_tls_supported_crypto,
181                                                             _nx_azure_iot_tls_supported_crypto_size,
182                                                             _nx_azure_iot_tls_ciphersuite_map,
183                                                             _nx_azure_iot_tls_ciphersuite_map_size,
184                                                             metadata_buffer, sizeof(metadata_buffer),
185                                                             &root_ca_cert),
186                          NX_AZURE_IOT_SUCCESS);
187 
188     /* FAIL: device_id_length is 0. */
189     assert_int_not_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
190                                                             STRING_UNSIGNED_ARGS(host_name),
191                                                             "", 0,
192                                                             STRING_UNSIGNED_ARGS(module_id),
193                                                             _nx_azure_iot_tls_supported_crypto,
194                                                             _nx_azure_iot_tls_supported_crypto_size,
195                                                             _nx_azure_iot_tls_ciphersuite_map,
196                                                             _nx_azure_iot_tls_ciphersuite_map_size,
197                                                             metadata_buffer, sizeof(metadata_buffer),
198                                                             &root_ca_cert),
199                          NX_AZURE_IOT_SUCCESS);
200 
201     /* FAIL: invalidate cloud_id manually. */
202     iot.nx_azure_iot_cloud.nx_cloud_id = 0;
203     assert_int_not_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
204                                                             STRING_UNSIGNED_ARGS(host_name),
205                                                             STRING_UNSIGNED_ARGS(device_id),
206                                                             STRING_UNSIGNED_ARGS(module_id),
207                                                             _nx_azure_iot_tls_supported_crypto,
208                                                             _nx_azure_iot_tls_supported_crypto_size,
209                                                             _nx_azure_iot_tls_ciphersuite_map,
210                                                             _nx_azure_iot_tls_ciphersuite_map_size,
211                                                             metadata_buffer, sizeof(metadata_buffer),
212                                                             &root_ca_cert),
213                          NX_AZURE_IOT_SUCCESS);
214     iot.nx_azure_iot_cloud.nx_cloud_id = NX_CLOUD_ID;
215 
216     /* FAIL: nxd_mqtt_client_receive_notify_set will fail by hijacked function. */
217     will_return(__wrap__nxde_mqtt_client_receive_notify_set, NXD_MQTT_INVALID_PARAMETER);
218     will_return(__wrap__nxde_mqtt_client_delete, NXD_MQTT_SUCCESS);
219     assert_int_not_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
220                                                             STRING_UNSIGNED_ARGS(host_name),
221                                                             STRING_UNSIGNED_ARGS(device_id),
222                                                             STRING_UNSIGNED_ARGS(module_id),
223                                                             _nx_azure_iot_tls_supported_crypto,
224                                                             _nx_azure_iot_tls_supported_crypto_size,
225                                                             _nx_azure_iot_tls_ciphersuite_map,
226                                                             _nx_azure_iot_tls_ciphersuite_map_size,
227                                                             metadata_buffer, sizeof(metadata_buffer),
228                                                             &root_ca_cert),
229                          NX_AZURE_IOT_SUCCESS);
230 
231     /* SUCCESS: all parameters are valid. */
232     will_return_always(__wrap__nxde_mqtt_client_receive_notify_set, NXD_MQTT_SUCCESS);
233     will_return(__wrap__nxde_mqtt_client_delete, NXD_MQTT_SUCCESS);
234     assert_int_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
235                                                         STRING_UNSIGNED_ARGS(host_name),
236                                                         STRING_UNSIGNED_ARGS(device_id),
237                                                         STRING_UNSIGNED_ARGS(module_id),
238                                                         _nx_azure_iot_tls_supported_crypto,
239                                                         _nx_azure_iot_tls_supported_crypto_size,
240                                                         _nx_azure_iot_tls_ciphersuite_map,
241                                                         _nx_azure_iot_tls_ciphersuite_map_size,
242                                                         metadata_buffer, sizeof(metadata_buffer),
243                                                         &root_ca_cert),
244                      NX_AZURE_IOT_SUCCESS);
245     assert_int_equal(nx_azure_iot_hub_client_deinitialize(&iot_client),
246                      NX_AZURE_IOT_SUCCESS);
247 
248     /* SUCCESS: all parameters are valid and module_id pointer is null. */
249     assert_int_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
250                                                         STRING_UNSIGNED_ARGS(host_name),
251                                                         STRING_UNSIGNED_ARGS(device_id),
252                                                         NX_NULL, 0,
253                                                         _nx_azure_iot_tls_supported_crypto,
254                                                         _nx_azure_iot_tls_supported_crypto_size,
255                                                         _nx_azure_iot_tls_ciphersuite_map,
256                                                         _nx_azure_iot_tls_ciphersuite_map_size,
257                                                         metadata_buffer, sizeof(metadata_buffer),
258                                                         &root_ca_cert),
259                      NX_AZURE_IOT_SUCCESS);
260     will_return(__wrap__nxde_mqtt_client_delete, NXD_MQTT_SUCCESS);
261     assert_int_equal(nx_azure_iot_hub_client_deinitialize(&iot_client),
262                      NX_AZURE_IOT_SUCCESS);
263 
264     /* SUCCESS: all parameters are valid and module_id pointer is null. */
265     assert_int_equal(nx_azure_iot_hub_client_initialize(&iot_client, &iot,
266                                                         STRING_UNSIGNED_ARGS(host_name),
267                                                         STRING_UNSIGNED_ARGS(device_id),
268                                                         NX_NULL, 0,
269                                                         _nx_azure_iot_tls_supported_crypto,
270                                                         _nx_azure_iot_tls_supported_crypto_size,
271                                                         _nx_azure_iot_tls_ciphersuite_map,
272                                                         _nx_azure_iot_tls_ciphersuite_map_size,
273                                                         metadata_buffer, sizeof(metadata_buffer),
274                                                         &root_ca_cert),
275                      NX_AZURE_IOT_SUCCESS);
276 
277 
278     /*********** Test nx_azure_iot_hub_client_deinitialize() ***********/
279     /* FAIL: NX_AZURE_IOT_HUB_CLIENT pointer is null. */
280     assert_int_not_equal(nx_azure_iot_hub_client_deinitialize(NX_NULL),
281                          NX_AZURE_IOT_SUCCESS);
282 
283     /* FAIL: iot_client is not deleted yet. */
284     assert_int_not_equal(nx_azure_iot_delete(&iot), NX_AZURE_IOT_SUCCESS);
285 
286     /* FAIL: nxd_mqtt_client_delete will fail by hijacked function. */
287     will_return(__wrap__nxde_mqtt_client_delete, NXD_MQTT_INVALID_PARAMETER);
288     assert_int_not_equal(nx_azure_iot_hub_client_deinitialize(&iot_client),
289                          NX_AZURE_IOT_SUCCESS);
290 
291     /* SUCCESS: iot_client is created. */
292     will_return_always(__wrap__nxde_mqtt_client_delete, NXD_MQTT_SUCCESS);
293     assert_int_equal(nx_azure_iot_hub_client_deinitialize(&iot_client),
294                      NX_AZURE_IOT_SUCCESS);
295 
296     /* FAIL: iot_client is already deleted. */
297     assert_int_not_equal(nx_azure_iot_hub_client_deinitialize(&iot_client),
298                          NX_AZURE_IOT_SUCCESS);
299 
300 
301     /*********** Test multiple nx_azure_iot_hub_client_initialize()/deinitialize() ***********/
302     for (i = 0; i < sizeof(iot_clients) / sizeof(NX_AZURE_IOT_HUB_CLIENT); i++)
303     {
304         assert_int_equal(nx_azure_iot_hub_client_initialize(&iot_clients[i], &iot,
305                                                             STRING_UNSIGNED_ARGS(host_name),
306                                                             STRING_UNSIGNED_ARGS(device_id),
307                                                             NX_NULL, 0,
308                                                             _nx_azure_iot_tls_supported_crypto,
309                                                             _nx_azure_iot_tls_supported_crypto_size,
310                                                             _nx_azure_iot_tls_ciphersuite_map,
311                                                             _nx_azure_iot_tls_ciphersuite_map_size,
312                                                             metadata_buffer, sizeof(metadata_buffer),
313                                                             &root_ca_cert),
314                          NX_AZURE_IOT_SUCCESS);
315     }
316 
317     /* Manually remove the header of nx_azure_iot_hub_client_list_header. */
318     /* FAIL: this one removed from nx_azure_iot_hub_client_list_header. */
319     _nx_azure_iot_created_ptr -> nx_azure_iot_resource_list_header = _nx_azure_iot_created_ptr -> nx_azure_iot_resource_list_header -> resource_next;
320     assert_int_not_equal(nx_azure_iot_hub_client_deinitialize(&iot_clients[sizeof(iot_clients) / sizeof(NX_AZURE_IOT_HUB_CLIENT) - 1]),
321                          NX_AZURE_IOT_SUCCESS);
322 
323     for (i = 0; i < sizeof(iot_clients) / sizeof(NX_AZURE_IOT_HUB_CLIENT) - 1; i++)
324     {
325         assert_int_equal(nx_azure_iot_hub_client_deinitialize(&iot_clients[i]),
326                          NX_AZURE_IOT_SUCCESS);
327     }
328 
329 
330     /* SUCCESS: iot is created. */
331     assert_int_equal(nx_azure_iot_delete(&iot), NX_AZURE_IOT_SUCCESS);
332 
333     /* Check if all the packet are released */
334     assert_int_equal(pool_ptr -> nx_packet_pool_available, pool_ptr -> nx_packet_pool_total);
335 }
336 
337 UINT __real__nxde_mqtt_client_receive_notify_set(NXD_MQTT_CLIENT *client_ptr,
338                                                  VOID (*receive_notify)(NXD_MQTT_CLIENT *client_ptr,
339                                                                         UINT message_count));
__wrap__nxde_mqtt_client_receive_notify_set(NXD_MQTT_CLIENT * client_ptr,VOID (* receive_notify)(NXD_MQTT_CLIENT * client_ptr,UINT message_count))340 UINT __wrap__nxde_mqtt_client_receive_notify_set(NXD_MQTT_CLIENT *client_ptr,
341                                                  VOID (*receive_notify)(NXD_MQTT_CLIENT *client_ptr,
342                                                                         UINT message_count))
343 {
344     if ((UINT)mock() != NXD_MQTT_SUCCESS)
345     {
346         printf("HIJACKED: %s\n", __func__);
347         return(NXD_MQTT_INVALID_PARAMETER);
348     }
349     return(__real__nxde_mqtt_client_receive_notify_set(client_ptr, receive_notify));
350 }
351 
352 UINT __real__nxde_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr);
__wrap__nxde_mqtt_client_delete(NXD_MQTT_CLIENT * client_ptr)353 UINT __wrap__nxde_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr)
354 {
355     if ((UINT)mock() != NXD_MQTT_SUCCESS)
356     {
357         printf("HIJACKED: %s\n", __func__);
358         return(NXD_MQTT_INVALID_PARAMETER);
359     }
360     return(__real__nxde_mqtt_client_delete(client_ptr));
361 }
362