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 #include <stdio.h>
13 #include <stdarg.h>
14
15
16 #ifndef NX_AZURE_DISABLE_IOT_SECURITY_MODULE
17 #include "nx_azure_iot_security_module.h"
18 #endif /* NX_AZURE_DISABLE_IOT_SECURITY_MODULE */
19
20 #include "nx_azure_iot.h"
21
22 #include "azure/core/internal/az_log_internal.h"
23
24 #ifndef NX_AZURE_IOT_WAIT_OPTION
25 #define NX_AZURE_IOT_WAIT_OPTION NX_WAIT_FOREVER
26 #endif /* NX_AZURE_IOT_WAIT_OPTION */
27
28 /* Convert number to upper hex. */
29 #define NX_AZURE_IOT_NUMBER_TO_UPPER_HEX(number) (CHAR)(number + (number < 10 ? '0' : 'A' - 10))
30
31 /* Define the prototypes for Azure RTOS IoT. */
32 NX_AZURE_IOT *_nx_azure_iot_created_ptr;
33
34 /* Define the callback for logging. */
35 static VOID(*_nx_azure_iot_log_callback)(az_log_classification classification, UCHAR *msg, UINT msg_len);
36
37 extern UINT _nxd_mqtt_client_publish_packet_send(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr,
38 USHORT packet_id, UINT QoS, ULONG wait_option);
39
nx_azure_iot_event_process(VOID * nx_azure_iot,ULONG common_events,ULONG module_own_events)40 static VOID nx_azure_iot_event_process(VOID *nx_azure_iot, ULONG common_events, ULONG module_own_events)
41 {
42
43 NX_AZURE_IOT *nx_azure_iot_ptr = (NX_AZURE_IOT *)nx_azure_iot;
44
45 /* Process DPS events. */
46 if (nx_azure_iot_ptr -> nx_azure_iot_provisioning_client_event_process)
47 {
48 nx_azure_iot_ptr -> nx_azure_iot_provisioning_client_event_process(nx_azure_iot_ptr, common_events,
49 module_own_events);
50 }
51 }
52
nx_azure_iot_publish_packet_header_add(NX_PACKET * packet_ptr,UINT topic_len,UINT qos)53 static UINT nx_azure_iot_publish_packet_header_add(NX_PACKET* packet_ptr, UINT topic_len, UINT qos)
54 {
55 UCHAR *buffer_ptr;
56 UINT length;
57
58 /* Check if packet has enough space to write MQTT header. */
59 if (NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET >
60 (packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start))
61 {
62 return(NX_AZURE_IOT_INVALID_PACKET);
63 }
64
65 /* Start to fill MQTT header. */
66 buffer_ptr = packet_ptr -> nx_packet_prepend_ptr - NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET;
67
68 /* Set flags. */
69 buffer_ptr[0] = (UCHAR)(MQTT_CONTROL_PACKET_TYPE_PUBLISH << 4);
70 if (qos == NX_AZURE_IOT_MQTT_QOS_1)
71 {
72 buffer_ptr[0] |= MQTT_PUBLISH_QOS_LEVEL_1;
73 }
74
75 /* Set topic length. */
76 buffer_ptr[5] = (UCHAR)(topic_len >> 8);
77 buffer_ptr[6] = (UCHAR)(topic_len & 0xFF);
78
79 /* Set total length.
80 * 2 bytes for topic length.
81 * 2 bytes for packet id.
82 * data_size for payload.
83 *
84 * packet already contains topic length, packet id (optional) and data payload
85 */
86 length = packet_ptr -> nx_packet_length + 2;
87
88 /* Total length is encoded in fixed four bytes format. */
89 buffer_ptr[1] = (UCHAR)((length & 0x7F) | 0x80);
90 length >>= 7;
91 buffer_ptr[2] = (UCHAR)((length & 0x7F) | 0x80);
92 length >>= 7;
93 buffer_ptr[3] = (UCHAR)((length & 0x7F) | 0x80);
94 length >>= 7;
95 buffer_ptr[4] = (UCHAR)(length & 0x7F);
96
97 /* Update packet. */
98 packet_ptr -> nx_packet_prepend_ptr = buffer_ptr;
99 packet_ptr -> nx_packet_length += NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET;
100
101 return(NX_AZURE_IOT_SUCCESS);
102 }
103
nx_azure_iot_log(UCHAR * type_ptr,UINT type_len,UCHAR * msg_ptr,UINT msg_len,...)104 UINT nx_azure_iot_log(UCHAR *type_ptr, UINT type_len, UCHAR *msg_ptr, UINT msg_len, ...)
105 {
106 va_list ap;
107 UCHAR buffer[10] = { 0 };
108 az_span span;
109 az_span num_span;
110
111 span = az_span_create(type_ptr, (INT)type_len);
112 _az_LOG_WRITE(AZ_LOG_IOT_AZURERTOS, span);
113
114 if (msg_len >= 2 && (msg_ptr[msg_len - 2] == '%') &&
115 ((msg_ptr[msg_len - 1] == 'd') || (msg_ptr[msg_len - 1] == 's')))
116 {
117 span = az_span_create((UCHAR *)msg_ptr, (INT)(msg_len - 2));
118 _az_LOG_WRITE(AZ_LOG_IOT_AZURERTOS, span);
119
120 va_start(ap, msg_len);
121
122 /* Handles %d */
123 if (msg_ptr[msg_len - 1] == 'd')
124 {
125 num_span = az_span_create(buffer, sizeof(buffer));
126 if (!az_result_failed(az_span_u32toa(num_span, va_arg(ap, UINT), &span)))
127 {
128 num_span = az_span_slice(num_span, 0, (INT)sizeof(buffer) - az_span_size(span));
129 _az_LOG_WRITE(AZ_LOG_IOT_AZURERTOS, num_span);
130 }
131 }
132
133 /* Handles %s */
134 if (msg_ptr[msg_len - 1] == 's')
135 {
136 msg_ptr = va_arg(ap, UCHAR*);
137 msg_len = va_arg(ap, UINT);
138 span = az_span_create((UCHAR *)msg_ptr, (INT)msg_len);
139 _az_LOG_WRITE(AZ_LOG_IOT_AZURERTOS, span);
140 }
141
142 va_end(ap);
143 }
144 else
145 {
146 span = az_span_create((UCHAR *)msg_ptr, (INT)msg_len);
147 _az_LOG_WRITE(AZ_LOG_IOT_AZURERTOS, span);
148 }
149
150 _az_LOG_WRITE(AZ_LOG_IOT_AZURERTOS, AZ_SPAN_FROM_STR("\r\n"));
151
152 return(NX_AZURE_IOT_SUCCESS);
153 }
154
nx_azure_iot_log_listener(az_log_classification classification,az_span message)155 static VOID nx_azure_iot_log_listener(az_log_classification classification, az_span message)
156 {
157 NX_PARAMETER_NOT_USED(classification);
158
159 if (_nx_azure_iot_log_callback != NX_NULL)
160 {
161 _nx_azure_iot_log_callback(classification, az_span_ptr(message), (UINT)az_span_size(message));
162 }
163 }
164
nx_azure_iot_log_init(VOID (* log_callback)(az_log_classification classification,UCHAR * msg,UINT msg_len))165 VOID nx_azure_iot_log_init(VOID(*log_callback)(az_log_classification classification, UCHAR *msg, UINT msg_len))
166 {
167 _nx_azure_iot_log_callback = log_callback;
168 az_log_set_message_callback(nx_azure_iot_log_listener);
169 }
170
nx_azure_iot_resource_search(NXD_MQTT_CLIENT * client_ptr)171 NX_AZURE_IOT_RESOURCE *nx_azure_iot_resource_search(NXD_MQTT_CLIENT *client_ptr)
172 {
173 NX_AZURE_IOT_RESOURCE *resource_ptr;
174
175 /* Check if created Azure RTOS IoT. */
176 if ((_nx_azure_iot_created_ptr == NX_NULL) || (client_ptr == NX_NULL))
177 {
178 return(NX_NULL);
179 }
180
181 /* Loop to find the resource associated with current MQTT client. */
182 for (resource_ptr = _nx_azure_iot_created_ptr -> nx_azure_iot_resource_list_header;
183 resource_ptr; resource_ptr = resource_ptr -> resource_next)
184 {
185
186 if (&(resource_ptr -> resource_mqtt) == client_ptr)
187 {
188 return(resource_ptr);
189 }
190 }
191
192 return(NX_NULL);
193 }
194
nx_azure_iot_resource_add(NX_AZURE_IOT * nx_azure_iot_ptr,NX_AZURE_IOT_RESOURCE * resource_ptr)195 UINT nx_azure_iot_resource_add(NX_AZURE_IOT *nx_azure_iot_ptr, NX_AZURE_IOT_RESOURCE *resource_ptr)
196 {
197
198 resource_ptr -> resource_next = nx_azure_iot_ptr -> nx_azure_iot_resource_list_header;
199 nx_azure_iot_ptr -> nx_azure_iot_resource_list_header = resource_ptr;
200
201 return(NX_AZURE_IOT_SUCCESS);
202 }
203
nx_azure_iot_resource_remove(NX_AZURE_IOT * nx_azure_iot_ptr,NX_AZURE_IOT_RESOURCE * resource_ptr)204 UINT nx_azure_iot_resource_remove(NX_AZURE_IOT *nx_azure_iot_ptr, NX_AZURE_IOT_RESOURCE *resource_ptr)
205 {
206
207 NX_AZURE_IOT_RESOURCE *resource_previous;
208
209 if (nx_azure_iot_ptr -> nx_azure_iot_resource_list_header == NX_NULL)
210 {
211 return(NX_AZURE_IOT_NOT_FOUND);
212 }
213
214 if (nx_azure_iot_ptr -> nx_azure_iot_resource_list_header == resource_ptr)
215 {
216 nx_azure_iot_ptr -> nx_azure_iot_resource_list_header = nx_azure_iot_ptr -> nx_azure_iot_resource_list_header -> resource_next;
217 return(NX_AZURE_IOT_SUCCESS);
218 }
219
220 for (resource_previous = nx_azure_iot_ptr -> nx_azure_iot_resource_list_header;
221 resource_previous -> resource_next;
222 resource_previous = resource_previous -> resource_next)
223 {
224 if (resource_previous -> resource_next == resource_ptr)
225 {
226 resource_previous -> resource_next = resource_previous -> resource_next -> resource_next;
227 return(NX_AZURE_IOT_SUCCESS);
228 }
229 }
230
231 return(NX_AZURE_IOT_NOT_FOUND);
232 }
233
nx_azure_iot_create(NX_AZURE_IOT * nx_azure_iot_ptr,const UCHAR * name_ptr,NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,NX_DNS * dns_ptr,VOID * stack_memory_ptr,UINT stack_memory_size,UINT priority,UINT (* unix_time_callback)(ULONG * unix_time))234 UINT nx_azure_iot_create(NX_AZURE_IOT *nx_azure_iot_ptr, const UCHAR *name_ptr,
235 NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr,
236 VOID *stack_memory_ptr, UINT stack_memory_size,
237 UINT priority, UINT (*unix_time_callback)(ULONG *unix_time))
238 {
239 UINT status;
240
241 if ((nx_azure_iot_ptr == NX_NULL) || (ip_ptr == NX_NULL) ||
242 (pool_ptr == NX_NULL) || (dns_ptr == NX_NULL))
243 {
244 LogError(LogLiteralArgs("IoT create fail: INVALID POINTER"));
245 return(NX_AZURE_IOT_INVALID_PARAMETER);
246 }
247
248 nx_azure_iot_ptr -> nx_azure_iot_name = name_ptr;
249 nx_azure_iot_ptr -> nx_azure_iot_ip_ptr = ip_ptr;
250 nx_azure_iot_ptr -> nx_azure_iot_dns_ptr = dns_ptr;
251 nx_azure_iot_ptr -> nx_azure_iot_pool_ptr = pool_ptr;
252 nx_azure_iot_ptr -> nx_azure_iot_unix_time_get = unix_time_callback;
253
254 status = nx_cloud_create(&nx_azure_iot_ptr -> nx_azure_iot_cloud, (CHAR *)name_ptr, stack_memory_ptr,
255 stack_memory_size, priority);
256 if (status)
257 {
258 LogError(LogLiteralArgs("IoT create fail status: %d"), status);
259 return(status);
260 }
261
262 /* Register SDK module on cloud helper. */
263 status = nx_cloud_module_register(&(nx_azure_iot_ptr -> nx_azure_iot_cloud), &(nx_azure_iot_ptr -> nx_azure_iot_cloud_module),
264 "Azure SDK Module", NX_CLOUD_MODULE_AZURE_SDK_EVENT | NX_CLOUD_COMMON_PERIODIC_EVENT,
265 nx_azure_iot_event_process, nx_azure_iot_ptr);
266 if (status)
267 {
268 LogError(LogLiteralArgs("IoT module register fail status: %d"), status);
269 return(status);
270 }
271
272 /* Set the mutex. */
273 nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr = &(nx_azure_iot_ptr -> nx_azure_iot_cloud.nx_cloud_mutex);
274
275 /* Set created IoT pointer. */
276 _nx_azure_iot_created_ptr = nx_azure_iot_ptr;
277
278 #ifndef NX_AZURE_DISABLE_IOT_SECURITY_MODULE
279 /* Enable Azure IoT Security Module. */
280 status = nx_azure_iot_security_module_enable(nx_azure_iot_ptr);
281 if (status)
282 {
283 LogError(LogLiteralArgs("IoT failed to enable IoT Security Module, status: %d"), status);
284 nx_azure_iot_delete(nx_azure_iot_ptr);
285 return(status);
286 }
287 #endif /* NX_AZURE_DISABLE_IOT_SECURITY_MODULE */
288
289 return(NX_AZURE_IOT_SUCCESS);
290 }
291
nx_azure_iot_delete(NX_AZURE_IOT * nx_azure_iot_ptr)292 UINT nx_azure_iot_delete(NX_AZURE_IOT *nx_azure_iot_ptr)
293 {
294 UINT status;
295
296 if (nx_azure_iot_ptr == NX_NULL)
297 {
298 LogError(LogLiteralArgs("IoT delete fail: INVALID POINTER"));
299 return(NX_AZURE_IOT_INVALID_PARAMETER);
300 }
301
302 if (nx_azure_iot_ptr -> nx_azure_iot_resource_list_header)
303 {
304 LogError(LogLiteralArgs("IoT delete fail: Resource NOT DELETED"));
305 return(NX_AZURE_IOT_DELETE_ERROR);
306 }
307
308 #ifndef NX_AZURE_DISABLE_IOT_SECURITY_MODULE
309 /* Disable IoT Security Module. */
310 status = nx_azure_iot_security_module_disable(nx_azure_iot_ptr);
311 if (status != NX_AZURE_IOT_SUCCESS)
312 {
313 LogError(LogLiteralArgs("IoT failed to disable IoT Security Module, status: %d"), status);
314 return(status);
315 }
316 #endif /* NX_AZURE_DISABLE_IOT_SECURITY_MODULE */
317
318 /* Deregister SDK module on cloud helper. */
319 nx_cloud_module_deregister(&(nx_azure_iot_ptr -> nx_azure_iot_cloud), &(nx_azure_iot_ptr -> nx_azure_iot_cloud_module));
320
321 /* Delete cloud. */
322 status = nx_cloud_delete(&nx_azure_iot_ptr -> nx_azure_iot_cloud);
323 if (status)
324 {
325 LogError(LogLiteralArgs("IoT delete fail status: %d"), status);
326 return(status);
327 }
328
329 _nx_azure_iot_created_ptr = NX_NULL;
330
331 return(NX_AZURE_IOT_SUCCESS);
332 }
333
nx_azure_iot_buffer_allocate(NX_AZURE_IOT * nx_azure_iot_ptr,UCHAR ** buffer_pptr,UINT * buffer_size,VOID ** buffer_context)334 UINT nx_azure_iot_buffer_allocate(NX_AZURE_IOT *nx_azure_iot_ptr, UCHAR **buffer_pptr,
335 UINT *buffer_size, VOID **buffer_context)
336 {
337 NX_PACKET *packet_ptr;
338 UINT status;
339
340 status = nx_packet_allocate(nx_azure_iot_ptr -> nx_azure_iot_pool_ptr,
341 &packet_ptr, 0, NX_AZURE_IOT_WAIT_OPTION);
342 if (status)
343 {
344 return(status);
345 }
346
347 *buffer_pptr = packet_ptr -> nx_packet_data_start;
348 *buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start);
349 *buffer_context = (VOID *)packet_ptr;
350 return(NX_AZURE_IOT_SUCCESS);
351 }
352
nx_azure_iot_buffer_free(VOID * buffer_context)353 UINT nx_azure_iot_buffer_free(VOID *buffer_context)
354 {
355 NX_PACKET *packet_ptr = (NX_PACKET *)buffer_context;
356
357 return(nx_packet_release(packet_ptr));
358 }
359
nx_azure_iot_publish_packet_get(NX_AZURE_IOT * nx_azure_iot_ptr,NXD_MQTT_CLIENT * client_ptr,NX_PACKET ** packet_pptr,UINT wait_option)360 UINT nx_azure_iot_publish_packet_get(NX_AZURE_IOT *nx_azure_iot_ptr, NXD_MQTT_CLIENT *client_ptr,
361 NX_PACKET **packet_pptr, UINT wait_option)
362 {
363 UINT status;
364
365 status = nx_secure_tls_packet_allocate(&(client_ptr -> nxd_mqtt_tls_session),
366 nx_azure_iot_ptr -> nx_azure_iot_pool_ptr,
367 packet_pptr, wait_option);
368 if (status)
369 {
370 LogError(LogLiteralArgs("Create publish packet failed"));
371 return(status);
372 }
373
374 /* Preserve room for fixed MQTT header. */
375 (*packet_pptr) -> nx_packet_prepend_ptr += NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET;
376
377 return(NX_AZURE_IOT_SUCCESS);
378 }
379
nx_azure_iot_publish_mqtt_packet(NXD_MQTT_CLIENT * client_ptr,NX_PACKET * packet_ptr,UINT topic_len,UCHAR * packet_id,UINT qos,UINT wait_option)380 UINT nx_azure_iot_publish_mqtt_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr,
381 UINT topic_len, UCHAR *packet_id, UINT qos, UINT wait_option)
382 {
383 UINT status;
384 USHORT id = 0;
385
386 status = nx_azure_iot_publish_packet_header_add(packet_ptr, topic_len, qos);
387 if (status)
388 {
389 LogError(LogLiteralArgs("failed to add mqtt header"));
390 return(status);
391 }
392
393 if (qos != 0)
394 {
395 id = (USHORT)((packet_id[0] << 8) | packet_id[1]);
396 }
397
398 /* Note, mutex will be released by this function. */
399 status = _nxd_mqtt_client_publish_packet_send(client_ptr, packet_ptr,
400 id, qos, wait_option);
401 if (status)
402 {
403 LogError(LogLiteralArgs("Mqtt client send fail: PUBLISH FAIL status: %d"), status);
404 return(status);
405 }
406
407 return(NX_AZURE_IOT_SUCCESS);
408 }
409
nx_azure_iot_mqtt_packet_id_get(NXD_MQTT_CLIENT * client_ptr,UCHAR * packet_id)410 UINT nx_azure_iot_mqtt_packet_id_get(NXD_MQTT_CLIENT *client_ptr, UCHAR *packet_id)
411 {
412 UINT status;
413
414 /* Get packet id under mutex */
415 status = tx_mutex_get(client_ptr -> nxd_mqtt_client_mutex_ptr, NX_WAIT_FOREVER);
416 if (status)
417 {
418 return(status);
419 }
420
421 /* Do nothing if the client is not connected. */
422 if (client_ptr -> nxd_mqtt_client_state != NXD_MQTT_CLIENT_STATE_CONNECTED)
423 {
424 LogError(LogLiteralArgs("MQTT NOT CONNECTED"));
425 return(NX_AZURE_IOT_DISCONNECTED);
426 }
427
428 /* Internal API assuming it to be 2 Byte buffer */
429 packet_id[0] = (UCHAR)(client_ptr -> nxd_mqtt_client_packet_identifier >> 8);
430 packet_id[1] = (UCHAR)(client_ptr -> nxd_mqtt_client_packet_identifier & 0xFF);
431
432 /* Update packet id. */
433 client_ptr -> nxd_mqtt_client_packet_identifier = (client_ptr -> nxd_mqtt_client_packet_identifier + 1) & 0xFFFF;
434
435 /* Prevent packet identifier from being zero. MQTT-2.3.1-1. */
436 if(client_ptr -> nxd_mqtt_client_packet_identifier == 0)
437 {
438 client_ptr -> nxd_mqtt_client_packet_identifier = 1;
439 }
440
441 tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr);
442
443 return(NX_AZURE_IOT_SUCCESS);
444 }
445
nx_azure_iot_mqtt_packet_adjust(NX_PACKET * packet_ptr)446 VOID nx_azure_iot_mqtt_packet_adjust(NX_PACKET *packet_ptr)
447 {
448 UINT size;
449 UINT copy_size;
450 NX_PACKET *current_packet_ptr;
451
452 /* Adjust the packet to make sure,
453 * 1. nx_packet_prepend_ptr does not pointer to nx_packet_data_start.
454 * 2. The first packet is full if it is chained with multiple packets. */
455
456 if (packet_ptr -> nx_packet_prepend_ptr != packet_ptr -> nx_packet_data_start)
457 {
458
459 /* Move data to the nx_packet_data_start. */
460 size = (UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr);
461 memmove(packet_ptr -> nx_packet_data_start, packet_ptr -> nx_packet_prepend_ptr, size); /* Use case of memmove is verified. */
462 packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start;
463 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_data_start + size;
464 }
465
466 if (packet_ptr -> nx_packet_next == NX_NULL)
467 {
468
469 /* All data are in the first packet. */
470 return;
471 }
472
473 /* Move data in the chained packet into first one until it is full. */
474 for (current_packet_ptr = packet_ptr -> nx_packet_next;
475 current_packet_ptr;
476 current_packet_ptr = packet_ptr -> nx_packet_next)
477 {
478
479 /* Calculate remaining buffer size in the first packet. */
480 size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_append_ptr);
481
482 /* Calculate copy size from current packet. */
483 copy_size = (UINT)(current_packet_ptr -> nx_packet_append_ptr - current_packet_ptr -> nx_packet_prepend_ptr);
484
485 if (size >= copy_size)
486 {
487
488 /* Copy all data from current packet. */
489 memcpy((VOID *)packet_ptr -> nx_packet_append_ptr, (VOID *)current_packet_ptr -> nx_packet_prepend_ptr, copy_size); /* Use case of memcpy is verified. */
490 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_append_ptr + copy_size;
491 }
492 else
493 {
494
495 /* Copy partial data from current packet. */
496 memcpy(packet_ptr -> nx_packet_append_ptr, current_packet_ptr -> nx_packet_prepend_ptr, size); /* Use case of memcpy is verified. */
497 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_data_end;
498
499 /* Move data in current packet to nx_packet_data_start. */
500 memmove((VOID *)current_packet_ptr -> nx_packet_data_start, /* Use case of memmove is verified. */
501 (VOID *)(current_packet_ptr -> nx_packet_prepend_ptr + size),
502 (copy_size - size));
503 current_packet_ptr -> nx_packet_prepend_ptr = current_packet_ptr -> nx_packet_data_start;
504 current_packet_ptr -> nx_packet_append_ptr = current_packet_ptr -> nx_packet_data_start + (copy_size - size);
505
506 /* First packet is full. */
507 break;
508 }
509
510 /* Remove current packet from packet chain. */
511 packet_ptr -> nx_packet_next = current_packet_ptr -> nx_packet_next;
512
513 /* Release current packet. */
514 current_packet_ptr -> nx_packet_next = NX_NULL;
515 nx_packet_release(current_packet_ptr);
516 }
517 }
518
nx_azure_iot_certificate_verify(NX_SECURE_TLS_SESSION * session,NX_SECURE_X509_CERT * certificate)519 static ULONG nx_azure_iot_certificate_verify(NX_SECURE_TLS_SESSION *session, NX_SECURE_X509_CERT* certificate)
520 {
521 NX_AZURE_IOT_RESOURCE *resource_ptr;
522 UINT old_threshold;
523 UINT status = NX_AZURE_IOT_SUCCESS;
524
525 /* Disable preemption. */
526 tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
527
528 /* Check if created Azure RTOS IoT. */
529 if (_nx_azure_iot_created_ptr == NX_NULL)
530 {
531
532 /* Restore preemption. */
533 tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
534 return(NX_AZURE_IOT_NOT_INITIALIZED);
535 }
536
537 /* Get mutex */
538 status = tx_mutex_get(_nx_azure_iot_created_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER);
539
540 /* Restore preemption. */
541 tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
542 if (status)
543 {
544 return(status);
545 }
546
547 /* Loop to find the resource associated with current TLS session. */
548 for (resource_ptr = _nx_azure_iot_created_ptr -> nx_azure_iot_resource_list_header;
549 resource_ptr; resource_ptr = resource_ptr -> resource_next)
550 {
551
552 if (&(resource_ptr -> resource_mqtt.nxd_mqtt_tls_session) == session)
553 {
554 break;
555 }
556 }
557
558 if (resource_ptr)
559 {
560
561 /* Check DNS entry string. */
562 status = nx_secure_x509_common_name_dns_check(certificate,
563 resource_ptr -> resource_hostname,
564 resource_ptr -> resource_hostname_length);
565 if (status)
566 {
567 LogError(LogLiteralArgs("Error in certificate verification: DNS name did not match CN"));
568 }
569 }
570 else
571 {
572
573 /* TLS session not match. */
574 status = NX_AZURE_IOT_NOT_FOUND;
575 }
576
577 /* Release mutex. */
578 tx_mutex_put(_nx_azure_iot_created_ptr -> nx_azure_iot_mutex_ptr);
579
580 return(status);
581 }
582
583 #ifndef NX_AZURE_IOT_DISABLE_CERTIFICATE_DATE
nx_azure_iot_tls_time_function(VOID)584 static ULONG nx_azure_iot_tls_time_function(VOID)
585 {
586 ULONG unix_time = 0;
587 UINT old_threshold;
588
589 /* Disable preemption. */
590 tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
591
592 if (nx_azure_iot_unix_time_get(_nx_azure_iot_created_ptr, &unix_time))
593 {
594
595 /* Unable to get Unix time. */
596 LogError(LogLiteralArgs("Unable to get Unix time"));
597 unix_time = 0;
598 }
599
600 /* Restore preemption. */
601 tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
602 return(unix_time);
603 }
604 #endif /* NX_AZURE_IOT_DISABLE_CERTIFICATE_DATE */
605
nx_azure_iot_mqtt_tls_setup(NXD_MQTT_CLIENT * client_ptr,NX_SECURE_TLS_SESSION * tls_session,NX_SECURE_X509_CERT * certificate,NX_SECURE_X509_CERT * trusted_certificate)606 UINT nx_azure_iot_mqtt_tls_setup(NXD_MQTT_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session,
607 NX_SECURE_X509_CERT *certificate,
608 NX_SECURE_X509_CERT *trusted_certificate)
609 {
610 UINT status;
611 UINT i;
612 NX_AZURE_IOT_RESOURCE *resource_ptr;
613
614 NX_PARAMETER_NOT_USED(certificate);
615 NX_PARAMETER_NOT_USED(trusted_certificate);
616
617 /* Obtain the mutex. */
618 tx_mutex_get(client_ptr -> nxd_mqtt_client_mutex_ptr, TX_WAIT_FOREVER);
619
620 resource_ptr = nx_azure_iot_resource_search(client_ptr);
621
622 /* Release the mutex. */
623 tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr);
624
625 if (resource_ptr == NX_NULL)
626 {
627 LogError(LogLiteralArgs("Failed to find associated resource"));
628 return(NX_AZURE_IOT_INVALID_PARAMETER);
629 }
630
631 /* Create TLS session. */
632 status = _nx_secure_tls_session_create_ext(tls_session,
633 resource_ptr -> resource_crypto_array,
634 resource_ptr -> resource_crypto_array_size,
635 resource_ptr -> resource_cipher_map,
636 resource_ptr -> resource_cipher_map_size,
637 resource_ptr -> resource_metadata_ptr,
638 resource_ptr -> resource_metadata_size);
639 if (status)
640 {
641 LogError(LogLiteralArgs("Failed to create TLS session status: %d"), status);
642 return(status);
643 }
644
645 for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates); i++)
646 {
647 if (resource_ptr -> resource_trusted_certificates[i])
648 {
649 status = nx_secure_tls_trusted_certificate_add(tls_session, resource_ptr -> resource_trusted_certificates[i]);
650 if (status)
651 {
652 LogError(LogLiteralArgs("Failed to add trusted CA certificate to session status: %d"), status);
653 return(status);
654 }
655 }
656 }
657
658 for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates); i++)
659 {
660 if (resource_ptr -> resource_device_certificates[i])
661 {
662 status = nx_secure_tls_local_certificate_add(tls_session, resource_ptr -> resource_device_certificates[i]);
663 if (status)
664 {
665 LogError(LogLiteralArgs("Failed to add device certificate to session status: %d"), status);
666 return(status);
667 }
668 }
669 }
670
671 status = nx_secure_tls_session_packet_buffer_set(tls_session,
672 resource_ptr -> resource_tls_packet_buffer,
673 sizeof(resource_ptr -> resource_tls_packet_buffer));
674 if (status)
675 {
676 LogError(LogLiteralArgs("Failed to set the session packet buffer: status: %d"), status);
677 return(status);
678 }
679
680 /* Setup the callback invoked when TLS has a certificate it wants to verify so we can
681 do additional checks not done automatically by TLS. */
682 status = nx_secure_tls_session_certificate_callback_set(tls_session,
683 nx_azure_iot_certificate_verify);
684 if (status)
685 {
686 LogError(LogLiteralArgs("Failed to set the session certificate callback: status: %d"), status);
687 return(status);
688 }
689
690 #ifndef NX_AZURE_IOT_DISABLE_CERTIFICATE_DATE
691 /* Setup the callback function used by checking certificate valid date. */
692 nx_secure_tls_session_time_function_set(tls_session, nx_azure_iot_tls_time_function);
693 #endif /* NX_AZURE_IOT_DISABLE_CERTIFICATE_DATE */
694
695 return(NX_AZURE_IOT_SUCCESS);
696 }
697
nx_azure_iot_unix_time_get(NX_AZURE_IOT * nx_azure_iot_ptr,ULONG * unix_time)698 UINT nx_azure_iot_unix_time_get(NX_AZURE_IOT *nx_azure_iot_ptr, ULONG *unix_time)
699 {
700
701 if ((nx_azure_iot_ptr == NX_NULL) ||
702 (nx_azure_iot_ptr -> nx_azure_iot_unix_time_get == NX_NULL) ||
703 (unix_time == NX_NULL))
704 {
705 LogError(LogLiteralArgs("Unix time callback not set"));
706 return(NX_AZURE_IOT_INVALID_PARAMETER);
707 }
708
709 return(nx_azure_iot_ptr -> nx_azure_iot_unix_time_get(unix_time));
710 }
711
712 /* HMAC-SHA256(master key, message ) */
nx_azure_iot_hmac_sha256_calculate(NX_AZURE_IOT_RESOURCE * resource_ptr,UCHAR * key,UINT key_size,const UCHAR * message,UINT message_size,UCHAR * output)713 static UINT nx_azure_iot_hmac_sha256_calculate(NX_AZURE_IOT_RESOURCE *resource_ptr, UCHAR *key, UINT key_size,
714 const UCHAR *message, UINT message_size, UCHAR *output)
715 {
716 UINT i;
717 UINT status;
718 VOID *handler;
719 UCHAR *metadata_ptr = resource_ptr -> resource_metadata_ptr;
720 UINT metadata_size = resource_ptr -> resource_metadata_size;
721 const NX_CRYPTO_METHOD *hmac_sha_256_crypto_method = NX_NULL;
722
723
724 /* Find hmac sha256 crypto method. */
725 for(i = 0; i < resource_ptr -> resource_crypto_array_size; i++)
726 {
727 if(resource_ptr -> resource_crypto_array[i] -> nx_crypto_algorithm == NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_256)
728 {
729 hmac_sha_256_crypto_method = resource_ptr -> resource_crypto_array[i];
730 break;
731 }
732 }
733
734 /* Check if find the crypto method. */
735 if (hmac_sha_256_crypto_method == NX_NULL)
736 {
737 return(NX_AZURE_IOT_NO_AVAILABLE_CIPHER);
738 }
739
740 /* Initialize. */
741 status = hmac_sha_256_crypto_method -> nx_crypto_init((NX_CRYPTO_METHOD *)hmac_sha_256_crypto_method,
742 key, (key_size << 3),
743 &handler,
744 metadata_ptr,
745 metadata_size);
746 if (status)
747 {
748 return(status);
749 }
750
751 /* Authenticate. */
752 status = hmac_sha_256_crypto_method -> nx_crypto_operation(NX_CRYPTO_AUTHENTICATE,
753 handler,
754 (NX_CRYPTO_METHOD *)hmac_sha_256_crypto_method,
755 key,
756 (key_size << 3),
757 (VOID *)message,
758 message_size,
759 NX_CRYPTO_NULL,
760 output,
761 32,
762 metadata_ptr,
763 metadata_size,
764 NX_CRYPTO_NULL,
765 NX_CRYPTO_NULL);
766 if (status)
767 {
768 return(status);
769 }
770
771 /* Cleanup. */
772 status = hmac_sha_256_crypto_method -> nx_crypto_cleanup(metadata_ptr);
773
774 return(status);
775 }
776
nx_azure_iot_base64_hmac_sha256_calculate(NX_AZURE_IOT_RESOURCE * resource_ptr,const UCHAR * key_ptr,UINT key_size,const UCHAR * message_ptr,UINT message_size,UCHAR * buffer_ptr,UINT buffer_len,UCHAR ** output_pptr,UINT * output_len_ptr)777 UINT nx_azure_iot_base64_hmac_sha256_calculate(NX_AZURE_IOT_RESOURCE *resource_ptr,
778 const UCHAR *key_ptr, UINT key_size,
779 const UCHAR *message_ptr, UINT message_size,
780 UCHAR *buffer_ptr, UINT buffer_len,
781 UCHAR **output_pptr, UINT *output_len_ptr)
782 {
783 UINT status;
784 UCHAR *hash_buf;
785 UINT hash_buf_size = 33;
786 UCHAR *encoded_hash_buf;
787 UINT encoded_hash_buf_size = 48;
788 UINT encoded_hash_size;
789 UINT binary_key_buf_size;
790
791 binary_key_buf_size = buffer_len;
792 status = _nx_utility_base64_decode((UCHAR *)key_ptr, key_size,
793 buffer_ptr, binary_key_buf_size, &binary_key_buf_size);
794 if (status)
795 {
796 LogError(LogLiteralArgs("Failed to base64 decode"));
797 return(status);
798 }
799
800 buffer_len -= binary_key_buf_size;
801 if ((hash_buf_size + encoded_hash_buf_size) > buffer_len)
802 {
803 LogError(LogLiteralArgs("Failed to not enough memory"));
804 return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE);
805 }
806
807 hash_buf = buffer_ptr + binary_key_buf_size;
808 status = nx_azure_iot_hmac_sha256_calculate(resource_ptr, buffer_ptr, binary_key_buf_size,
809 message_ptr, (UINT)message_size, hash_buf);
810 if (status)
811 {
812 LogError(LogLiteralArgs("Failed to get hash256"));
813 return(status);
814 }
815
816 buffer_len -= hash_buf_size;
817 encoded_hash_buf = hash_buf + hash_buf_size;
818
819 /* Additional space is required by encoder. */
820 hash_buf[hash_buf_size - 1] = 0;
821 status = _nx_utility_base64_encode(hash_buf, hash_buf_size - 1,
822 encoded_hash_buf, encoded_hash_buf_size, &encoded_hash_size);
823 if (status)
824 {
825 LogError(LogLiteralArgs("Failed to base64 encode"));
826 return(status);
827 }
828
829 *output_pptr = encoded_hash_buf;
830 *output_len_ptr = encoded_hash_size;
831
832 return(NX_AZURE_IOT_SUCCESS);
833 }
834