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