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 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Secure Component                                                 */
16 /**                                                                       */
17 /**    Datagram Transport Layer Security (DTLS)                           */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_SECURE_SOURCE_CODE
23 
24 #include "nx_secure_dtls.h"
25 #ifdef NX_SECURE_ENABLE_DTLS
26 #include "nx_packet.h"
27 #include "nx_udp.h"
28 
29 /**************************************************************************/
30 /*                                                                        */
31 /*  FUNCTION                                               RELEASE        */
32 /*                                                                        */
33 /*    _nx_secure_dtls_client_handshake                    PORTABLE C      */
34 /*                                                           6.1.12       */
35 /*  AUTHOR                                                                */
36 /*                                                                        */
37 /*    Timothy Stapko, Microsoft Corporation                               */
38 /*                                                                        */
39 /*  DESCRIPTION                                                           */
40 /*                                                                        */
41 /*    This function runs the DTLS Client mode state machine. It processes */
42 /*    an incoming handshake record and takes appropriate action to        */
43 /*    advance the DTLS Client handshake.                                  */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    dtls_session                          DTLS control block            */
48 /*    packet_buffer                         Pointer into record buffer    */
49 /*    data_length                           Length of data                */
50 /*    wait_option                           Controls timeout actions      */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    status                                Completion status             */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _nx_secure_dtls_allocate_handshake_packet                           */
59 /*                                          Allocate DTLS handshake packet*/
60 /*    _nx_secure_dtls_packet_allocate       Allocate internal DTLS packet */
61 /*    _nx_secure_dtls_process_handshake_header                            */
62 /*                                          Process handshake header      */
63 /*    _nx_secure_dtls_process_helloverifyrequest                          */
64 /*                                          Process HelloVerifyRequest    */
65 /*    _nx_secure_dtls_retransmit_queue_flush                              */
66 /*                                          Flush retransmit queue        */
67 /*    _nx_secure_dtls_send_clienthello      Send ClientHello              */
68 /*    _nx_secure_dtls_send_handshake_record Send DTLS handshake record    */
69 /*    _nx_secure_dtls_send_record           Send DTLS records             */
70 /*    _nx_secure_tls_generate_keys          Generate session keys         */
71 /*    _nx_secure_tls_generate_premaster_secret                            */
72 /*                                          Generate premaster secret     */
73 /*    _nx_secure_tls_handshake_hash_update  Update Finished hash          */
74 /*    _nx_secure_tls_process_certificate_request                          */
75 /*                                          Process certificate request   */
76 /*    _nx_secure_tls_process_finished       Process Finished message      */
77 /*    _nx_secure_tls_process_remote_certificate                           */
78 /*                                          Process remote certificate    */
79 /*    _nx_secure_tls_process_server_key_exchange                          */
80 /*                                          Process ServerKeyExchange     */
81 /*    _nx_secure_tls_process_serverhello    Process ServerHello           */
82 /*    _nx_secure_tls_send_certificate       Send DTLS certificate         */
83 /*    _nx_secure_tls_send_certificate_verify                              */
84 /*                                          Send certificate verify       */
85 /*    _nx_secure_tls_send_changecipherspec  Send ChangeCipherSpec         */
86 /*    _nx_secure_tls_send_client_key_exchange                             */
87 /*                                          Send ClientKeyExchange        */
88 /*    _nx_secure_tls_send_finished          Send Finished message         */
89 /*    _nx_secure_tls_session_keys_set       Set session keys              */
90 /*    nx_secure_tls_packet_release          Release packet                */
91 /*    tx_mutex_get                          Get protection mutex          */
92 /*    tx_mutex_put                          Put protection mutex          */
93 /*                                                                        */
94 /*  CALLED BY                                                             */
95 /*                                                                        */
96 /*    _nx_secure_dtls_process_record        Process DTLS record data      */
97 /*                                                                        */
98 /*  RELEASE HISTORY                                                       */
99 /*                                                                        */
100 /*    DATE              NAME                      DESCRIPTION             */
101 /*                                                                        */
102 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
103 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
104 /*                                            verified memcpy use cases,  */
105 /*                                            verified memmove use cases, */
106 /*                                            released packet securely,   */
107 /*                                            fixed certificate buffer    */
108 /*                                            allocation,                 */
109 /*                                            resulting in version 6.1    */
110 /*  12-31-2020     Timothy Stapko           Modified comment(s),          */
111 /*                                            improved buffer length      */
112 /*                                            verification, added null    */
113 /*                                            pointer checking,           */
114 /*                                            resulting in version 6.1.3  */
115 /*  01-31-2022     Timothy Stapko           Modified comment(s),          */
116 /*                                            fixed out-of-order handling,*/
117 /*                                            resulting in version 6.1.10 */
118 /*  07-29-2022     Yuxin Zhou               Modified comment(s),          */
119 /*                                            removed duplicated alert,   */
120 /*                                            resulting in version 6.1.12 */
121 /*                                                                        */
122 /**************************************************************************/
_nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION * dtls_session,UCHAR * packet_buffer,UINT data_length,ULONG wait_option)123 UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer,
124                                       UINT data_length, ULONG wait_option)
125 {
126 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
127 UINT                   status;
128 USHORT                 message_type = NX_SECURE_TLS_INVALID_MESSAGE;
129 UINT                   header_bytes;
130 UINT                   message_length;
131 UCHAR                 *data_start = NX_NULL;
132 NX_PACKET             *send_packet = NX_NULL;
133 NX_PACKET_POOL        *packet_pool;
134 UINT                   message_seq;
135 UINT                   fragment_offset;
136 UINT                   fragment_length;
137 UCHAR                 *fragment_buffer;
138 NX_SECURE_TLS_SESSION *tls_session;
139 
140     /* Basic state machine for handshake:
141      * 1. We have received a handshake message, now process the header.
142      * 2. Then process the message itself and populate the TLS socket structure.
143      * 3. Follow up with whatever actions are needed.
144      */
145 
146     /* Get a reference to the internal TLS state for ease of use. */
147     tls_session = &dtls_session -> nx_secure_dtls_tls_session;
148 
149     /* Use the TLS packet buffer for fragment processing. */
150     fragment_buffer = tls_session->nx_secure_tls_packet_buffer;
151 
152     while (data_length > 0)
153     {
154         header_bytes = data_length;
155 
156         /* First, process the handshake message to get our state and any data therein. */
157         status = _nx_secure_dtls_process_handshake_header(packet_buffer, &message_type, &header_bytes,
158                                                           &message_length, &message_seq, &fragment_offset, &fragment_length);
159 
160         if (status == NX_SUCCESS)
161         {
162 
163             /* Out-of-order plus fragmentation:
164              * - If message sequence > current message sequence
165              *     - New message
166              * - If message_sequence <= current message sequence
167              *    - If fragment_length < message length, we have a fragment
168              *    - Once fragment is reassembled, check message sequence for repeats
169              */
170 
171             /* If we see a repeated message sequence, assume an unnecessary retransmission and ignore. */
172             if (message_seq < dtls_session -> nx_secure_dtls_remote_handshake_sequence)
173             {
174                 /* Re-transmitted message. */
175                 return(NX_SUCCESS);
176             }
177 
178             /* Check the fragment_length with the lenght of packet buffer. */
179             if ((header_bytes + fragment_length) > data_length)
180             {
181                 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
182             }
183 
184             /* Check available area of buffer. */
185             if ((fragment_offset + fragment_length) > tls_session -> nx_secure_tls_packet_buffer_size ||
186                 (header_bytes + message_length) > tls_session -> nx_secure_tls_packet_buffer_size)
187             {
188                 return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
189             }
190 
191             /* If this message sequence isn't what we expect, continue reading packets. */
192             if(message_seq != dtls_session -> nx_secure_dtls_expected_handshake_sequence)
193             {
194                 return(NX_SECURE_TLS_OUT_OF_ORDER_MESSAGE);
195             }
196 
197             /* If we have a new sequence number, we have a new record (may be fragmented). Unless
198                the sequence number is 0, which means it is the first record. */
199             if (message_seq > dtls_session -> nx_secure_dtls_remote_handshake_sequence || (message_seq == 0 && fragment_offset == 0))
200             {
201                 /* New record starting, reset the fragment length and handshake sequence number. */
202                 dtls_session -> nx_secure_dtls_remote_handshake_sequence = message_seq;
203                 dtls_session -> nx_secure_dtls_fragment_length = message_length;
204             }
205 
206             if (fragment_length > dtls_session -> nx_secure_dtls_fragment_length)
207             {
208                 return(NX_SECURE_TLS_INVALID_PACKET);
209             }
210 
211             /* When we receive a message fragment, subtract it from the current fragment length. */
212             dtls_session -> nx_secure_dtls_fragment_length -= fragment_length;
213 
214             /* Copy the fragment data (minus the header) into the reassembly buffer. */
215             NX_SECURE_MEMCPY(&fragment_buffer[fragment_offset], &packet_buffer[header_bytes], fragment_length); /* Use case of memcpy is verified. */
216 
217             /* If we still have fragments to add, just return success. */
218             if (dtls_session -> nx_secure_dtls_fragment_length > 0)
219             {
220                 return(NX_SUCCESS);
221             }
222             else
223             {
224                 /* At beginning of handshake, reset the expected sequence number. */
225                 if (message_seq == 0)
226                 {
227                     dtls_session -> nx_secure_dtls_expected_handshake_sequence = 0;
228                 }
229 
230                 /* If the recontructed message has a sequence not equal to the expected, it's
231                    a retransmission we need to ignore. */
232                 if (message_seq != dtls_session -> nx_secure_dtls_expected_handshake_sequence)
233                 {
234                     return(NX_SUCCESS);
235                 }
236 
237                 /* Our next expected handshake message sequence number is 1 greater than this one. */
238                 dtls_session -> nx_secure_dtls_expected_handshake_sequence = message_seq + 1;
239 
240                 /* Put the header into the packet buffer, adjusting the fields to create a seam-less
241                  * DTLS record. */
242                 NX_SECURE_MEMMOVE(&fragment_buffer[header_bytes], fragment_buffer, message_length); /* Use case of memmove is verified. */
243 
244                 /* Reconstruct the header in the fragment buffer so we can hash the
245                    reconstructed record as if it were never fragmented. */
246 
247                 /* Type. */
248                 fragment_buffer[0] = (UCHAR)message_type;
249 
250                 /* Length. */
251                 fragment_buffer[1] = (UCHAR)(message_length >> 16);
252                 fragment_buffer[2] = (UCHAR)(message_length >> 8);
253                 fragment_buffer[3] = (UCHAR)(message_length);
254 
255                 /* Sequence. */
256                 fragment_buffer[4] = (UCHAR)(message_seq  >> 8);
257                 fragment_buffer[5] = (UCHAR)(message_seq);
258 
259                 /* Fragment offset is now 0. */
260                 fragment_buffer[6] = 0;
261                 fragment_buffer[7] = 0;
262                 fragment_buffer[8] = 0;
263 
264                 /* Fragment length is now == message length. */
265                 fragment_buffer[9] = (UCHAR)(message_length >> 16);
266                 fragment_buffer[10] = (UCHAR)(message_length >> 8);
267                 fragment_buffer[11] = (UCHAR)(message_length);
268 
269                 /* We have a reassembled DTLS record, use that for the handshake. */
270                 data_start = fragment_buffer;
271             }
272         }
273 
274         if (status != NX_SECURE_TLS_SUCCESS)
275         {
276             return(status);
277         }
278 
279         /* Allocate a packet for all send operations.  */
280         packet_pool = tls_session -> nx_secure_tls_packet_pool;
281 
282         /* Hash this handshake message. We do not hash HelloRequest messages.
283            Hashes include the handshake layer header but not the record layer header. */
284         if (message_type != NX_SECURE_TLS_HELLO_REQUEST && message_type != NX_SECURE_TLS_FINISHED &&
285             message_type != NX_SECURE_TLS_HELLO_VERIFY_REQUEST)
286         {
287             _nx_secure_tls_handshake_hash_update(tls_session, data_start, message_length + header_bytes);
288         }
289 
290         /* Reduce total length by the size of this fragment. */
291         data_length -= (fragment_length + header_bytes);
292         data_start += header_bytes;
293 
294         /* Process the message itself information from the header. */
295         switch (message_type)
296         {
297         case NX_SECURE_TLS_HELLO_VERIFY_REQUEST:
298             /* Initial DTLS message from server, contains a cookie for later transmissions. */
299             status = _nx_secure_dtls_process_helloverifyrequest(dtls_session, data_start, message_length);
300 
301             if (status)
302             {
303 
304                 /* This is the end of a flight, clear out the transmit queue. */
305                 _nx_secure_dtls_retransmit_queue_flush(dtls_session);
306             }
307             break;
308         case NX_SECURE_TLS_SERVER_HELLO:
309             /* Server has responded to our ClientHello. */
310             status = _nx_secure_tls_process_serverhello(tls_session, data_start, message_length);
311             break;
312         case NX_SECURE_TLS_CERTIFICATE_MSG:
313             /* Server has sent its certificate message. */
314             status = _nx_secure_tls_process_remote_certificate(tls_session, data_start, message_length, message_length);
315             break;
316         case NX_SECURE_TLS_SERVER_HELLO_DONE:
317             /* Server has responded to our ClientHello. */
318             /* A ServerHelloDone does not contain any data - it simply changes state. */
319             tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_SERVERHELLO_DONE;
320 
321             /* This is the end of a flight, clear out the transmit queue. */
322             _nx_secure_dtls_retransmit_queue_flush(dtls_session);
323             break;
324         case NX_SECURE_TLS_SERVER_KEY_EXCHANGE:
325             /* Server has sent a key exchange message, used for certain ciphersuites (DH and PSK mainly). */
326             status = _nx_secure_tls_process_server_key_exchange(tls_session, data_start, message_length);
327             break;
328         case NX_SECURE_TLS_CERTIFICATE_REQUEST:
329             /* Server has requested we provide a client certificate. */
330             status = _nx_secure_tls_process_certificate_request(tls_session, data_start, message_length);
331             break;
332         case NX_SECURE_TLS_FINISHED:
333             /* Final handshake message from the server, process it (verify the server handshake hash). */
334             status = _nx_secure_tls_process_finished(tls_session, data_start, message_length);
335 
336             /* This is the end of a flight, clear out the transmit queue. */
337             _nx_secure_dtls_retransmit_queue_flush(dtls_session);
338             break;
339         case NX_SECURE_TLS_HELLO_REQUEST:
340             /* Server has requested we restart the session. If we are in the middle of a handshake already
341              * (session is not active) then ignore. If we are in an active session, we can choose to
342              * send a ClientHello (start the handshake again) or send a no_renegotiation alert. */
343 
344             /* A HelloRequest does not contain any data - it simply changes state. */
345             tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_HELLO_REQUEST;
346             break;
347         case NX_SECURE_TLS_CERTIFICATE_VERIFY:
348         case NX_SECURE_TLS_CLIENT_KEY_EXCHANGE:
349         case NX_SECURE_TLS_CLIENT_HELLO:
350         case NX_SECURE_TLS_INVALID_MESSAGE:
351         case NX_SECURE_TLS_CERTIFICATE_URL:
352         case NX_SECURE_TLS_CERTIFICATE_STATUS:
353         default:
354             /* The message received was not a valid TLS server handshake message, send alert and return. */
355             status = NX_SECURE_TLS_UNEXPECTED_MESSAGE;
356             break;
357         }
358 
359         /* Check for errors in processing messages. */
360         if (status != NX_SECURE_TLS_SUCCESS)
361         {
362 
363             return(status);
364         }
365 
366         /* Now take any actions based on state set in the message processing. */
367         switch (tls_session -> nx_secure_tls_client_state)
368         {
369         case NX_SECURE_TLS_CLIENT_STATE_IDLE:
370             /* Client isn't doing anything right now. */
371             break;
372         case NX_SECURE_TLS_CLIENT_STATE_ERROR:
373         case NX_SECURE_TLS_CLIENT_STATE_ALERT_SENT:
374             /* This means an error was encountered at some point in processing a valid message. At this point
375                the alert was sent, so just return a status indicating as much. */
376             return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
377             break;
378         case NX_SECURE_TLS_CLIENT_STATE_HELLO_REQUEST:
379             /* Server sent a hello request, indicating it wants to restart the handshake process with a new ClientHello. */
380             if (tls_session -> nx_secure_tls_local_session_active)
381             {
382                 /* Respond to the HelloRequest with a "no_renegotiation" alert since we don't want to restart the handshake. */
383                 status = NX_SECURE_TLS_NO_RENEGOTIATION_ERROR;
384             }
385             /* If we are still in a handshake (session is not active) then ignore the message. */
386             break;
387         case NX_SECURE_TLS_CLIENT_STATE_HELLO_VERIFY:
388 
389             /* Get ClientHello packet from header of transmit queue. */
390             send_packet = dtls_session -> nx_secure_dtls_transmit_sent_head;
391             if ((send_packet == NX_NULL) || (send_packet -> nx_packet_queue_next != ((NX_PACKET *)NX_DRIVER_TX_DONE)))
392             {
393 
394                 /* Invalid packet. */
395                 status = NX_INVALID_PACKET;
396                 break;
397             }
398 
399             /* Clear the transmit queue. */
400             dtls_session -> nx_secure_dtls_transmit_sent_head = NX_NULL;
401             dtls_session -> nx_secure_dtls_transmit_sent_tail = NX_NULL;
402             dtls_session -> nx_secure_dtls_transmit_sent_count = 0;
403 
404             /* Reset the packet. */
405             send_packet -> nx_packet_prepend_ptr += sizeof(NX_UDP_HEADER);
406             send_packet -> nx_packet_length -= sizeof(NX_UDP_HEADER);
407             send_packet -> nx_packet_union_next.nx_packet_tcp_queue_next = (NX_PACKET *)NX_PACKET_ALLOCATED;
408 
409             _nx_secure_dtls_send_clienthello(dtls_session, send_packet);
410 
411             status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_CLIENT_HELLO, wait_option, 1);
412             break;
413         case NX_SECURE_TLS_CLIENT_STATE_SERVERHELLO:
414             /* We processed a serverhello above. Don't do anything right now. */
415             break;
416         case NX_SECURE_TLS_CLIENT_STATE_SERVER_CERTIFICATE:
417             /* Processed a server certificate above. Here, we extract the public key and do any verification
418                we want - the TLS implementation will verify certificate authenticity by checking the issuer
419                signature, but any other verification will be done by the caller via a callback. */
420             break;
421         case NX_SECURE_TLS_CLIENT_STATE_SERVER_KEY_EXCHANGE:
422             break;
423         case NX_SECURE_TLS_CLIENT_STATE_CERTIFICATE_REQUEST:
424             /* Set flag to send CertificateVerify once we have received ServerHelloDone. */
425             tls_session -> nx_secure_tls_client_certificate_requested = 1;
426             break;
427         case NX_SECURE_TLS_CLIENT_STATE_SERVERHELLO_DONE:
428             /* We received a ServerHelloDone, meaning we now have all the information we need to generate
429                our key material. First check if the server requested our client certificate. */
430 
431             if (tls_session -> nx_secure_tls_client_certificate_requested)
432             {
433 
434                 /* The server has requested a client certificate. Provide that certificate to the server here. */
435                 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
436 
437                 if (status != NX_SUCCESS)
438                 {
439                     break;
440                 }
441 
442                 _nx_secure_tls_send_certificate(tls_session, send_packet, wait_option);
443 
444                 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_MSG, wait_option, 1);
445 
446                 if (status != NX_SUCCESS)
447                 {
448                     break;
449                 }
450             }
451 
452             /* Now, generate the pre-master secret that is used to generate keys for our session. */
453             status = _nx_secure_tls_generate_premaster_secret(tls_session, NX_SECURE_DTLS);
454             if (status != NX_SUCCESS)
455             {
456                 break;
457             }
458 
459             /* We have received and processed a ServerHelloDone. Now respond to the client appropriately. */
460             status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
461 
462             if (status != NX_SUCCESS)
463             {
464                 break;
465             }
466 
467             /* Generate and send the ClientKeyExchange message. */
468             _nx_secure_tls_send_client_key_exchange(tls_session, send_packet);
469             status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_CLIENT_KEY_EXCHANGE, wait_option, 1);
470 
471             if (status != NX_SUCCESS)
472             {
473                 break;
474             }
475 
476             /* After sending ClientKeyExchange, we need to send a CertificateVerify message if the
477                server has requested a certificate. */
478             if (tls_session -> nx_secure_tls_client_certificate_requested)
479             {
480                 /* We can now clear the flag since this is the last specific certificate message sent. */
481                 tls_session -> nx_secure_tls_client_certificate_requested = 0;
482 
483                 /* Allocate packet for CertificateVerify. */
484                 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
485 
486                 if (status != NX_SUCCESS)
487                 {
488                     break;
489                 }
490 
491                 _nx_secure_tls_send_certificate_verify(tls_session, send_packet);
492 
493                 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_VERIFY, wait_option, 1);
494 
495                 if (status != NX_SUCCESS)
496                 {
497                     break;
498                 }
499             }
500 
501             /* Generate our key material from the data collected thus far and put it all into our
502                socket structure. Don't call generate keys before sending the client_key_exchange message
503                since it needs the pre-master secret and this call clears it out (for security). */
504             status = _nx_secure_tls_generate_keys(tls_session);
505 
506             if (status != NX_SUCCESS)
507             {
508                 break;
509             }
510 
511             /* Release the protection before suspending on nx_packet_allocate. */
512             tx_mutex_put(&_nx_secure_tls_protection);
513 
514             /* We have received everything we need to complete the handshake. Keys have been
515              * generated above. Now end the handshake with a ChangeCipherSpec (indicating following
516              * messages are encrypted) and the encrypted Finished message. */
517             status = _nx_secure_dtls_packet_allocate(dtls_session, packet_pool, &send_packet, wait_option);
518 
519             /* Get the protection after nx_packet_allocate. */
520             tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
521 
522             if (status != NX_SUCCESS)
523             {
524                 break;
525             }
526 
527             /* ChangeCipherSpec is NOT a handshake message, so send as a normal TLS record. */
528             _nx_secure_tls_send_changecipherspec(tls_session, send_packet);
529             status = _nx_secure_dtls_send_record(dtls_session, send_packet, NX_SECURE_TLS_CHANGE_CIPHER_SPEC, wait_option);
530 
531             if (status != NX_SUCCESS)
532             {
533                 /* Release packet on send error. */
534                 nx_secure_tls_packet_release(send_packet);
535                 break;
536             }
537             /* The local session is now active since we sent the changecipherspec message.
538                NOTE: Do not set this flag until after the changecipherspec message has been passed to the send record
539                routine - this flag causes encryption and hashing to happen on records. ChangeCipherSpec should be the last
540                un-encrypted/un-hashed record sent. */
541 
542             /* For DTLS, reset sequence number and advance epoch right after CCS message is sent. */
543             NX_SECURE_MEMSET(tls_session -> nx_secure_tls_local_sequence_number, 0, sizeof(tls_session -> nx_secure_tls_local_sequence_number));
544 
545             status = _nx_secure_tls_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_LOCAL);
546 
547             if (status != NX_SUCCESS)
548             {
549                 break;
550             }
551 
552             /* Advance the DTLS epoch - all messages after the ChangeCipherSpec are in a new epoch. */
553             dtls_session -> nx_secure_dtls_local_epoch = (USHORT)(dtls_session -> nx_secure_dtls_local_epoch + 1);
554 
555             /* We can now send our finished message, which will be encrypted using the chosen ciphersuite. */
556             status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
557 
558             if (status != NX_SUCCESS)
559             {
560                 break;
561             }
562 
563             /* Generate and send the finished message, which completes the handshake. */
564             _nx_secure_tls_send_finished(tls_session, send_packet);
565             status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_FINISHED, wait_option, 1);
566 
567             break;
568         case NX_SECURE_TLS_CLIENT_STATE_HANDSHAKE_FINISHED:
569             /* We processed a server finished message, completing the handshake. Verify all is good and if so,
570                continue to the encrypted session. */
571             break;
572         default:
573             status = NX_SECURE_TLS_INVALID_STATE;
574         }
575 
576         /* If we have an error at this point, we have experienced a problem in sending
577            handshake messages, which is some type of internal issue. */
578         if (status != NX_SUCCESS)
579         {
580 
581             return(status);
582         }
583 
584         /* Advance the buffer pointer past the fragment. */
585         packet_buffer += (fragment_length + header_bytes);
586     } /* End while. */
587     return(NX_SUCCESS);
588 #else /* TLS Client disabled. */
589 
590     /* We don't use the parameters since this is an error case. */
591     NX_PARAMETER_NOT_USED(packet_buffer);
592     NX_PARAMETER_NOT_USED(wait_option);
593     NX_PARAMETER_NOT_USED(data_length);
594 
595     /* If TLS Client is disabled and we are in the client state machine, something is wrong... */
596     dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_ERROR;
597     return(NX_SECURE_TLS_INVALID_STATE);
598 #endif
599 }
600 #endif /* NX_SECURE_ENABLE_DTLS */
601 
602