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