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