1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Secure Component                                                 */
17 /**                                                                       */
18 /**    Transport Layer Security (TLS)                                     */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define NX_SECURE_SOURCE_CODE
24 
25 #include "nx_secure_tls.h"
26 
27 
28 /**************************************************************************/
29 /*                                                                        */
30 /*  FUNCTION                                               RELEASE        */
31 /*                                                                        */
32 /*    _nx_secure_tls_client_handshake                     PORTABLE C      */
33 /*                                                           6.2.1        */
34 /*  AUTHOR                                                                */
35 /*                                                                        */
36 /*    Timothy Stapko, Microsoft Corporation                               */
37 /*                                                                        */
38 /*  DESCRIPTION                                                           */
39 /*                                                                        */
40 /*    This function runs the TLS Client mode state machine. It processes  */
41 /*    an incoming handshake record and takes appropriate action to        */
42 /*    advance the TLS Client handshake.                                   */
43 /*                                                                        */
44 /*  INPUT                                                                 */
45 /*                                                                        */
46 /*    tls_session                           TLS control block             */
47 /*    packet_buffer                         Pointer into record buffer    */
48 /*    data_length                           Length of packet buffer       */
49 /*    wait_option                           Controls timeout actions      */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    status                                Completion status             */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    _nx_secure_tls_allocate_handshake_packet                            */
58 /*                                          Allocate TLS packet           */
59 /*    _nx_secure_tls_generate_keys          Generate session keys         */
60 /*    _nx_secure_tls_generate_premaster_secret                            */
61 /*                                          Generate premaster secret     */
62 /*    _nx_secure_tls_handshake_hash_update  Update Finished hash          */
63 /*    _nx_secure_tls_packet_allocate        Allocate internal TLS packet  */
64 /*    _nx_secure_tls_process_certificate_request                          */
65 /*                                          Process certificate request   */
66 /*    _nx_secure_tls_process_finished       Process Finished message      */
67 /*    _nx_secure_tls_process_handshake_header                             */
68 /*                                          Process handshake header      */
69 /*    _nx_secure_tls_process_remote_certificate                           */
70 /*                                          Process server certificate    */
71 /*    _nx_secure_tls_process_server_key_exchange                          */
72 /*                                          Process ServerKeyExchange     */
73 /*    _nx_secure_tls_process_serverhello    Process ServerHello           */
74 /*    _nx_secure_tls_remote_certificate_free_all                          */
75 /*                                          Free all remote certificates  */
76 /*    _nx_secure_tls_send_certificate       Send TLS certificate          */
77 /*    _nx_secure_tls_send_certificate_verify                              */
78 /*                                          Send certificate verify       */
79 /*    _nx_secure_tls_send_changecipherspec  Send ChangeCipherSpec         */
80 /*    _nx_secure_tls_send_client_key_exchange                             */
81 /*                                          Send ClientKeyExchange        */
82 /*    _nx_secure_tls_send_clienthello       Send ClientHello              */
83 /*    _nx_secure_tls_send_finished          Send Finished message         */
84 /*    _nx_secure_tls_send_handshake_record  Send TLS handshake record     */
85 /*    _nx_secure_tls_send_record            Send TLS records              */
86 /*    _nx_secure_tls_session_keys_set       Set session keys              */
87 /*    nx_secure_tls_packet_release          Release packet                */
88 /*    [nx_secure_tls_session_renegotiation_callback]                      */
89 /*                                          Renegotiation callback        */
90 /*    tx_mutex_get                          Get protection mutex          */
91 /*    tx_mutex_put                          Put protection mutex          */
92 /*                                                                        */
93 /*  CALLED BY                                                             */
94 /*                                                                        */
95 /*    _nx_secure_tls_process_record         Process TLS record data       */
96 /*                                                                        */
97 /*  RELEASE HISTORY                                                       */
98 /*                                                                        */
99 /*    DATE              NAME                      DESCRIPTION             */
100 /*                                                                        */
101 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
102 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
103 /*                                            released packet securely,   */
104 /*                                            fixed renegotiation bug,    */
105 /*                                            fixed certificate buffer    */
106 /*                                            allocation,                 */
107 /*                                            resulting in version 6.1    */
108 /*  12-31-2020     Timothy Stapko           Modified comment(s),          */
109 /*                                            improved buffer length      */
110 /*                                            verification,               */
111 /*                                            resulting in version 6.1.3  */
112 /*  02-02-2021     Timothy Stapko           Modified comment(s), added    */
113 /*                                            support for fragmented TLS  */
114 /*                                            Handshake messages,         */
115 /*                                            resulting in version 6.1.4  */
116 /*  03-02-2021     Timothy Stapko           Modified comment(s),          */
117 /*                                            fixed compiler warnings,    */
118 /*                                            resulting in version 6.1.5  */
119 /*  07-29-2022     Yuxin Zhou               Modified comment(s),          */
120 /*                                            removed duplicated alert,   */
121 /*                                            resulting in version 6.1.12 */
122 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
123 /*                                            fixed compiler errors when  */
124 /*                                            x509 is disabled,           */
125 /*                                            resulting in version 6.2.1  */
126 /*                                                                        */
127 /**************************************************************************/
_nx_secure_tls_client_handshake(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,UINT data_length,ULONG wait_option)128 UINT _nx_secure_tls_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer,
129                                      UINT data_length, ULONG wait_option)
130 {
131 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
132 UINT            status;
133 UINT            temp_status;
134 USHORT          message_type = NX_SECURE_TLS_INVALID_MESSAGE;
135 UINT            header_bytes;
136 UINT            message_length;
137 UINT            packet_buffer_length = data_length;
138 UCHAR          *packet_start;
139 NX_PACKET      *send_packet = NX_NULL;
140 NX_PACKET_POOL *packet_pool;
141 const NX_CRYPTO_METHOD
142                *method_ptr = NX_NULL;
143 
144     /* Basic state machine for handshake:
145      * 1. We have received a handshake message, now process the header.
146      * 2. Then process the message itself and populate the TLS socket structure.
147      * 3. Follow up with whatever actions are needed.
148      */
149 
150     /* Loop through multiple messages in a single record. This can happen if the remote host
151        packs multiple handshake messages into a single TLS record. */
152     while (data_length > 0)
153     {
154         /* Save a pointer to the actual packet data (before we do fragment reassembly, etc. below)
155          * so we can hash it. */
156         packet_start = packet_buffer;
157 
158         header_bytes = data_length;
159 
160         /* First, process the handshake message to get our state and any data therein. */
161         status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
162 
163         if (status != NX_SECURE_TLS_SUCCESS)
164         {
165             return(status);
166         }
167 
168         /* Check for fragmented message. */
169         if((message_length + header_bytes) > data_length)
170         {
171             /* Incomplete message! A single message is fragmented across several records. We need to obtain the next fragment. */
172             tls_session -> nx_secure_tls_handshake_record_expected_length = message_length + header_bytes;
173 
174             tls_session -> nx_secure_tls_handshake_record_fragment_state = NX_SECURE_TLS_HANDSHAKE_RECEIVED_FRAGMENT;
175 
176             return(NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED);
177         }
178 
179 
180         /* Advance the buffer pointer past the handshake header. */
181         packet_buffer += header_bytes;
182 
183         /* Allocate a packet for all send operations.  */
184         packet_pool = tls_session -> nx_secure_tls_packet_pool;
185 
186         /* Hash this handshake message. We do not hash HelloRequest messages.
187            Hashes include the handshake layer header but not the record layer header. */
188         if (message_type != NX_SECURE_TLS_HELLO_REQUEST && message_type != NX_SECURE_TLS_FINISHED &&
189             message_type != NX_SECURE_TLS_HELLO_VERIFY_REQUEST && message_type != NX_SECURE_TLS_SERVER_HELLO)
190         {
191             _nx_secure_tls_handshake_hash_update(tls_session, packet_start, message_length + header_bytes);
192         }
193 
194         /* Reduce total length by the size of this message. */
195         data_length -= (message_length + header_bytes);
196 
197         /* Process the message itself information from the header. */
198         status = NX_SECURE_TLS_HANDSHAKE_FAILURE;
199         switch (message_type)
200         {
201         case NX_SECURE_TLS_SERVER_HELLO:
202             /* Server has responded to our ClientHello. */
203             status = _nx_secure_tls_process_serverhello(tls_session, packet_buffer, message_length);
204             break;
205         case NX_SECURE_TLS_CERTIFICATE_MSG:
206             /* Server has sent its certificate message. */
207             status = _nx_secure_tls_process_remote_certificate(tls_session, packet_buffer, message_length, packet_buffer_length);
208             break;
209         case NX_SECURE_TLS_SERVER_HELLO_DONE:
210             /* Server has responded to our ClientHello. */
211             /* A ServerHelloDone does not contain any data - it simply changes state. */
212             tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_SERVERHELLO_DONE;
213             status = NX_SECURE_TLS_SUCCESS;
214             break;
215         case NX_SECURE_TLS_SERVER_KEY_EXCHANGE:
216             /* Server has sent a key exchange message, used for certain ciphersuites (DH and PSK mainly). */
217             status = _nx_secure_tls_process_server_key_exchange(tls_session, packet_buffer, message_length);
218             break;
219         case NX_SECURE_TLS_CERTIFICATE_REQUEST:
220             /* Server has requested we provide a client certificate. */
221             status = _nx_secure_tls_process_certificate_request(tls_session, packet_buffer, message_length);
222             break;
223         case NX_SECURE_TLS_FINISHED:
224             /* Final handshake message from the server, process it (verify the server handshake hash). */
225             status = _nx_secure_tls_process_finished(tls_session, packet_buffer, message_length);
226 
227             /* For client, cleanup hash handler after received the finished message from server. */
228             /* NOTE: we want to run all of the nx_crypto_cleanup calls regardless of the status of the finished processing above
229                      so use a secondary status to track their return status values. */
230 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
231             method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method;
232 
233             /* NOTE: we want to run all of the nx_crypto_cleanup calls regardless of the  */
234             if (method_ptr -> nx_crypto_cleanup != NX_NULL)
235             {
236                 temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata);
237                 if(temp_status != NX_CRYPTO_SUCCESS)
238                 {
239                     status = temp_status;
240                 }
241             }
242 
243 #endif /* (NX_SECURE_TLS_TLS_1_2_ENABLED) */
244 
245 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
246             method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
247             if (method_ptr != NX_NULL && method_ptr -> nx_crypto_cleanup != NX_NULL)
248             {
249                 temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata);
250                 if(temp_status != NX_CRYPTO_SUCCESS)
251                 {
252                     status = temp_status;
253                 }
254             }
255 
256             method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
257             if (method_ptr != NX_NULL && method_ptr -> nx_crypto_cleanup != NX_NULL)
258             {
259                 temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata);
260                 if(temp_status != NX_CRYPTO_SUCCESS)
261                 {
262                     status = temp_status;
263                 }
264             }
265 #endif /* (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) */
266 
267             break;
268         case NX_SECURE_TLS_HELLO_REQUEST:
269             /* Server has requested we restart the session. If we are in the middle of a handshake already
270              * (session is not active) then ignore. If we are in an active session, we can choose to
271              * send a ClientHello (start the handshake again) or send a no_renegotiation alert. */
272             if (tls_session -> nx_secure_tls_local_session_active)
273             {
274 #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
275                 /* A HelloRequest does not contain any data - it simply changes state. */
276                 tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_HELLO_REQUEST;
277 
278                 if (tls_session -> nx_secure_tls_renegotation_enabled && tls_session -> nx_secure_tls_secure_renegotiation)
279                 {
280                     tls_session -> nx_secure_tls_renegotiation_handshake = NX_TRUE;
281 
282 #ifndef NX_SECURE_DISABLE_X509
283 
284                     /* On a session resumption free all certificates for the new session.
285                      * SESSION RESUMPTION: if session resumption is enabled, don't free!!
286                      */
287                     status = _nx_secure_tls_remote_certificate_free_all(tls_session);
288 
289                     if (status != NX_SUCCESS)
290                     {
291                         return(status);
292                     }
293 #else
294                     status = NX_SECURE_TLS_SUCCESS;
295 #endif
296                 }
297                 else
298 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
299                 {
300                     /* Session renegotiation is disabled, so this is an error! */
301                     return(NX_SECURE_TLS_NO_RENEGOTIATION_ERROR);
302                 }
303             }
304 
305             break;
306         case NX_SECURE_TLS_HELLO_VERIFY_REQUEST:  /* DTLS ONLY! */
307         case NX_SECURE_TLS_CERTIFICATE_VERIFY:
308         case NX_SECURE_TLS_CLIENT_KEY_EXCHANGE:
309         case NX_SECURE_TLS_CLIENT_HELLO:
310         case NX_SECURE_TLS_INVALID_MESSAGE:
311         case NX_SECURE_TLS_CERTIFICATE_URL:
312         case NX_SECURE_TLS_CERTIFICATE_STATUS:
313         default:
314             /* The message received was not a valid TLS server handshake message, send alert and return. */
315             break;
316         }
317 
318         /* Check for errors in processing messages. */
319         if (status != NX_SECURE_TLS_SUCCESS)
320         {
321 
322             return(status);
323         }
324 
325         /* Now take any actions based on state set in the message processing. */
326         switch (tls_session -> nx_secure_tls_client_state)
327         {
328         case NX_SECURE_TLS_CLIENT_STATE_IDLE:
329         case NX_SECURE_TLS_CLIENT_STATE_RENEGOTIATING:
330             /* Client isn't doing anything right now. */
331             break;
332         case NX_SECURE_TLS_CLIENT_STATE_ERROR:
333         case NX_SECURE_TLS_CLIENT_STATE_ALERT_SENT:
334             /* This means an error was encountered at some point in processing a valid message. At this point
335                the alert was sent, so just return a status indicating as much. */
336             return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
337 #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
338         case NX_SECURE_TLS_CLIENT_STATE_HELLO_REQUEST:
339             /* Server sent a hello request, indicating it wants to restart the handshake process with a new ClientHello. */
340             if (tls_session -> nx_secure_tls_local_session_active)
341             {
342                 /* See if renegotiation is enabled. */
343                 if (tls_session -> nx_secure_tls_renegotation_enabled && tls_session -> nx_secure_tls_secure_renegotiation)
344                 {
345                     /* Invoke user callback to notify application of renegotiation request. */
346                     if (tls_session -> nx_secure_tls_session_renegotiation_callback != NX_NULL)
347                     {
348                         status = tls_session -> nx_secure_tls_session_renegotiation_callback(tls_session);
349 
350                         if (status != NX_SUCCESS)
351                         {
352                             return(status);
353                         }
354                     }
355 
356                     /* If we are currently in a session, we have a renegotiation handshake. */
357                     tls_session -> nx_secure_tls_renegotiation_handshake = NX_TRUE;
358 
359                     /* Allocate a handshake packet so we can send the ClientHello. */
360                     status = _nx_secure_tls_allocate_handshake_packet(tls_session, tls_session -> nx_secure_tls_packet_pool, &send_packet, wait_option);
361 
362                     if (status != NX_SUCCESS)
363                     {
364                         return(status);
365                     }
366 
367                     /* Populate our packet with clienthello data. */
368                     status = _nx_secure_tls_send_clienthello(tls_session, send_packet);
369 
370                     if (status != NX_SUCCESS)
371                     {
372                         return(status);
373                     }
374 
375                     /* Send the ClientHello to kick things off. */
376                     status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CLIENT_HELLO, wait_option);
377                 }
378                 else
379                 {
380                     /* Respond to the HelloRequest with a "no_renegotiation" alert since we don't want to restart the handshake. */
381                     status = NX_SECURE_TLS_NO_RENEGOTIATION_ERROR;
382                 }
383             }
384             /* If we are still in a handshake (session is not active) then ignore the message. */
385             break;
386 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
387         case NX_SECURE_TLS_CLIENT_STATE_SERVERHELLO:
388             /* We received a serverhello above. It is time to update the hash for the handshake. */
389 
390             if(tls_session->nx_secure_tls_key_material.nx_secure_tls_handshake_cache_length > 0)
391             {
392                 /* We have some cached messages from earlier in the handshake that we need to process. Generally
393                    this will just be the ClientHello. */
394                 status = _nx_secure_tls_handshake_hash_update(tls_session, tls_session->nx_secure_tls_key_material.nx_secure_tls_handshake_cache,
395                                                               tls_session->nx_secure_tls_key_material.nx_secure_tls_handshake_cache_length);
396                 if(status != NX_SUCCESS)
397                 {
398                     return(status);
399                 }
400 
401                 /* Indicate that all cached messages have been hashed. */
402                 tls_session->nx_secure_tls_key_material.nx_secure_tls_handshake_cache_length = 0;
403 
404                 _nx_secure_tls_handshake_hash_update(tls_session, packet_start, message_length + header_bytes);
405             }
406             break;
407         case NX_SECURE_TLS_CLIENT_STATE_SERVER_CERTIFICATE:
408             /* Processed a server certificate above. Here, we extract the public key and do any verification
409                we want - the TLS implementation will verify certificate authenticity by checking the issuer
410                signature, but any other verification will be done by the caller via a callback. */
411             break;
412         case NX_SECURE_TLS_CLIENT_STATE_SERVER_KEY_EXCHANGE:
413             break;
414         case NX_SECURE_TLS_CLIENT_STATE_CERTIFICATE_REQUEST:
415             /* Set flag to send CertificateVerify once we have received ServerHelloDone. */
416             tls_session -> nx_secure_tls_client_certificate_requested = 1;
417             break;
418         case NX_SECURE_TLS_CLIENT_STATE_SERVERHELLO_DONE:
419             /* We received a ServerHelloDone, meaning we now have all the information we need to generate
420                our key material. First check if the server requested our client certificate. */
421 
422             if (tls_session -> nx_secure_tls_client_certificate_requested)
423             {
424 
425                 /* The server has requested a client certificate. Provide that certificate to the server here. */
426                 status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
427 
428                 if (status != NX_SUCCESS)
429                 {
430                     break;
431                 }
432 
433                 status = _nx_secure_tls_send_certificate(tls_session, send_packet, wait_option);
434 
435                 if (status != NX_SUCCESS)
436                 {
437                     break;
438                 }
439 
440                 status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_MSG, wait_option);
441 
442                 if (status != NX_SUCCESS)
443                 {
444                     break;
445                 }
446             }
447 
448             /* Now, generate the pre-master secret that is used to generate keys for our session. */
449             status = _nx_secure_tls_generate_premaster_secret(tls_session, NX_SECURE_TLS);
450             if (status != NX_SUCCESS)
451             {
452                 break;
453             }
454 
455             /* We have received and processed a ServerHelloDone. Now respond to the client appropriately. */
456             status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
457 
458             if (status != NX_SUCCESS)
459             {
460                 break;
461             }
462 
463             /* Generate and send the ClientKeyExchange message. */
464             status = _nx_secure_tls_send_client_key_exchange(tls_session, send_packet);
465 
466             if (status != NX_SUCCESS)
467             {
468                 break;
469             }
470 
471             status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CLIENT_KEY_EXCHANGE, wait_option);
472 
473             if (status != NX_SUCCESS)
474             {
475                 break;
476             }
477 
478             /* After sending ClientKeyExchange, we need to send a CertificateVerify message if the
479                server has requested a certificate. If no certificate is available, this flag will
480                be cleared after the empty certificate message is sent. */
481             if (tls_session -> nx_secure_tls_client_certificate_requested)
482             {
483                 /* We can now clear the flag since this is the last specific certificate message sent. */
484                 tls_session -> nx_secure_tls_client_certificate_requested = 0;
485 
486                 /* Allocate packet for CertificateVerify. */
487                 status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
488 
489                 if (status != NX_SUCCESS)
490                 {
491                     break;
492                 }
493 
494                 status = _nx_secure_tls_send_certificate_verify(tls_session, send_packet);
495 
496                 if (status != NX_SUCCESS)
497                 {
498                     break;
499                 }
500 
501                 status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_VERIFY, wait_option);
502 
503                 if (status != NX_SUCCESS)
504                 {
505                     break;
506                 }
507             }
508 
509             /* Generate our key material from the data collected thus far and put it all into our
510                socket structure. Don't call generate keys before sending the client_key_exchange message
511                since it needs the pre-master secret and this call clears it out (for security). */
512             status = _nx_secure_tls_generate_keys(tls_session);
513 
514             if (status != NX_SUCCESS)
515             {
516                 break;
517             }
518 
519             /* Release the protection before suspending on nx_packet_allocate. */
520             tx_mutex_put(&_nx_secure_tls_protection);
521 
522             /* We have received everything we need to complete the handshake. Keys have been
523              * generated above. Now end the handshake with a ChangeCipherSpec (indicating following
524              * messages are encrypted) and the encrypted Finished message. */
525             status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option);
526 
527             /* Get the protection after nx_packet_allocate. */
528             tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
529 
530             if (status != NX_SUCCESS)
531             {
532                 break;
533             }
534 
535             /* ChangeCipherSpec is NOT a handshake message, so send as a normal TLS record. */
536             _nx_secure_tls_send_changecipherspec(tls_session, send_packet);
537 
538             status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_CHANGE_CIPHER_SPEC, wait_option);
539 
540             if (status != NX_SUCCESS)
541             {
542                 /* Release packet on send error. */
543                 nx_secure_tls_packet_release(send_packet);
544                 break;
545             }
546 
547             /* Reset the sequence number now that we are starting a new session. */
548             NX_SECURE_MEMSET(tls_session -> nx_secure_tls_local_sequence_number, 0, sizeof(tls_session -> nx_secure_tls_local_sequence_number));
549 
550             /* The local session is now active since we sent the changecipherspec message.
551                NOTE: Do not set the keys until after the changecipherspec message has been passed to the send record
552                routine - this call causes encryption and hashing to happen on records. ChangeCipherSpec should be the last
553                un-encrypted/un-hashed record sent. For a renegotiation handshake, CCS is the last message encrypted using
554                the original session keys. */
555 
556             /* Set our local session keys since we are sent a CCS message. */
557             _nx_secure_tls_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_LOCAL);
558 
559             /* We can now send our finished message, which will be encrypted using the chosen ciphersuite. */
560             status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
561 
562             if (status != NX_SUCCESS)
563             {
564                 break;
565             }
566 
567             /* Generate and send the finished message, which completes the handshake. */
568             _nx_secure_tls_send_finished(tls_session, send_packet);
569 
570             status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_FINISHED, wait_option);
571 
572             break;
573         case NX_SECURE_TLS_CLIENT_STATE_HANDSHAKE_FINISHED:
574             /* We processed a server finished message, completing the handshake. Verify all is good and if so,
575                continue to the encrypted session. */
576             break;
577         case NX_SECURE_TLS_CLIENT_STATE_HELLO_VERIFY: /* DTLS ONLY! */
578         default:
579             status = NX_SECURE_TLS_INVALID_STATE;
580         }
581 
582         /* If we have an error at this point, we have experienced a problem in sending
583            handshake messages, which is some type of internal issue. */
584         if (status != NX_SUCCESS)
585         {
586 
587             return(status);
588         }
589 
590         /* Advance the buffer pointer past the message. */
591         packet_buffer += message_length;
592     } /* End while. */
593     return(NX_SUCCESS);
594 #else /* TLS Client disabled. */
595 
596     /* We don't use the parameters since this is an error case. */
597     NX_PARAMETER_NOT_USED(packet_buffer);
598     NX_PARAMETER_NOT_USED(wait_option);
599     NX_PARAMETER_NOT_USED(data_length);
600 
601     /* If TLS Client is disabled and we are in the client state machine, something is wrong... */
602     tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_ERROR;
603     return(NX_SECURE_TLS_INVALID_STATE);
604 #endif
605 }
606 
607