1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Secure Component */
16 /** */
17 /** Datagram Transport Layer Security (DTLS) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SECURE_SOURCE_CODE
23
24 #include "nx_secure_dtls.h"
25
26
27 #ifdef NX_SECURE_ENABLE_DTLS
28
29
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _nx_secure_dtls_server_handshake PORTABLE C */
35 /* 6.3.0 */
36 /* AUTHOR */
37 /* */
38 /* Timothy Stapko, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* This function runs the DTLS Server mode state machine. It processes */
43 /* an incoming handshake record and takes appropriate action to */
44 /* advance the DTLS Server handshake. */
45 /* */
46 /* INPUT */
47 /* */
48 /* dtls_session TLS control block */
49 /* packet_buffer Pointer into record buffer */
50 /* data_length Length of data */
51 /* wait_option Controls timeout actions */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* status Completion status */
56 /* */
57 /* CALLS */
58 /* */
59 /* _nx_secure_dtls_allocate_handshake_packet */
60 /* Allocate DTLS handshake packet*/
61 /* _nx_secure_dtls_packet_allocate Allocate internal DTLS packet */
62 /* _nx_secure_dtls_process_clienthello Process ClientHello */
63 /* _nx_secure_dtls_process_handshake_header */
64 /* Process handshake header */
65 /* _nx_secure_dtls_retransmit_queue_flush */
66 /* Flush retransmit queue */
67 /* _nx_secure_dtls_send_handshake_record Send DTLS handshake record */
68 /* _nx_secure_dtls_send_helloverifyrequest */
69 /* Send DTLS HelloVerifyRequest */
70 /* _nx_secure_dtls_send_record Send DTLS records */
71 /* _nx_secure_dtls_send_serverhello Send DTLS ServerHello */
72 /* _nx_secure_tls_generate_keys Generate session keys */
73 /* _nx_secure_tls_handshake_hash_init Initialize Finished hash */
74 /* _nx_secure_tls_handshake_hash_update Update Finished hash */
75 /* _nx_secure_tls_process_client_key_exchange */
76 /* Process key exchange */
77 /* _nx_secure_tls_process_finished Process Finished message */
78 /* _nx_secure_tls_send_certificate Send TLS certificate */
79 /* _nx_secure_tls_send_changecipherspec Send ChangeCipherSpec */
80 /* _nx_secure_tls_send_finished Send Finished message */
81 /* _nx_secure_tls_send_server_key_exchange */
82 /* Send ServerKeyExchange */
83 /* _nx_secure_tls_session_keys_set Set session keys */
84 /* _nx_secure_tls_process_remote_certificate */
85 /* Process remote certificate */
86 /* _nx_secure_tls_process_certificate_verify */
87 /* Process certificate verify */
88 /* _nx_secure_tls_send_certificate_request */
89 /* Send certificate request */
90 /* tx_mutex_get Get protection mutex */
91 /* tx_mutex_put Put protection mutex */
92 /* [nx_secure_dtls_receive_notify] Notify aaplication of packet */
93 /* receive */
94 /* */
95 /* CALLED BY */
96 /* */
97 /* _nx_secure_dtls_process_record Process DTLS record data */
98 /* */
99 /* RELEASE HISTORY */
100 /* */
101 /* DATE NAME DESCRIPTION */
102 /* */
103 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
104 /* 09-30-2020 Timothy Stapko Modified comment(s), */
105 /* verified memcpy use cases, */
106 /* verified memmove use cases, */
107 /* fixed renegotiation bug, */
108 /* fixed certificate buffer */
109 /* allocation, */
110 /* resulting in version 6.1 */
111 /* 12-31-2020 Timothy Stapko Modified comment(s), */
112 /* improved buffer length */
113 /* verification, */
114 /* resulting in version 6.1.3 */
115 /* 01-31-2022 Timothy Stapko Modified comment(s), */
116 /* fixed out-of-order handling,*/
117 /* resulting in version 6.1.10 */
118 /* 07-29-2022 Yuxin Zhou Modified comment(s), */
119 /* removed duplicated alert, */
120 /* resulting in version 6.1.12 */
121 /* 10-31-2023 Tiejun Zhou Modified comment(s), and */
122 /* released packet on failure, */
123 /* resulting in version 6.3.0 */
124 /* */
125 /**************************************************************************/
_nx_secure_dtls_server_handshake(NX_SECURE_DTLS_SESSION * dtls_session,UCHAR * packet_buffer,UINT data_length,ULONG wait_option)126 UINT _nx_secure_dtls_server_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer,
127 UINT data_length, ULONG wait_option)
128 {
129 #ifndef NX_SECURE_TLS_SERVER_DISABLED
130 UINT status;
131 USHORT message_type;
132 UINT header_bytes;
133 UINT message_length;
134 UINT message_seq;
135 UINT fragment_offset;
136 UINT fragment_length;
137 NX_PACKET *send_packet;
138 NX_PACKET_POOL *packet_pool;
139 UCHAR *packet_start;
140 NX_SECURE_TLS_SESSION *tls_session;
141 UCHAR *fragment_buffer;
142
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 /* Save a pointer to the start of our packet for the hash that happens below. */
151 packet_start = packet_buffer;
152
153
154
155 /* Get a reference to TLS state. */
156 tls_session = &dtls_session -> nx_secure_dtls_tls_session;
157
158 /* Use the TLS packet buffer for fragment processing. */
159 fragment_buffer = tls_session->nx_secure_tls_packet_buffer;
160
161 header_bytes = data_length;
162
163 /* First, process the handshake message to get our state and any data therein. */
164 status = _nx_secure_dtls_process_handshake_header(packet_buffer, &message_type, &header_bytes,
165 &message_length, &message_seq, &fragment_offset, &fragment_length);
166
167 if (status == NX_SUCCESS)
168 {
169 /* For now, if we see a repeated message sequence, assume an unnecessary retransmission and ignore. */
170 /* Don't ignore sequence 0 - it's a new handshake request! */
171 if (message_seq < dtls_session -> nx_secure_dtls_remote_handshake_sequence)
172 {
173 /* Re-transmitted message. */
174 return(NX_CONTINUE);
175 }
176
177 /* When we receive a message fragment, subtract it from the current fragment length. */
178 if ((header_bytes + fragment_length) > data_length)
179 {
180 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
181 }
182
183 /* Check the fragment_length with the lenght of packet buffer. */
184 if ((header_bytes + fragment_length) > data_length)
185 {
186 return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
187 }
188
189 /* Check available area of buffer. */
190 if ((fragment_offset + fragment_length) > tls_session -> nx_secure_tls_packet_buffer_size ||
191 (header_bytes + message_length) > tls_session -> nx_secure_tls_packet_buffer_size)
192 {
193 return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
194 }
195
196 /* If this message sequence isn't what we expect, continue reading packets. */
197 if(message_seq != dtls_session -> nx_secure_dtls_expected_handshake_sequence)
198 {
199 return(NX_SECURE_TLS_OUT_OF_ORDER_MESSAGE);
200 }
201
202 /* If we have a new sequence number, we have a new record (may be fragmented). Unless
203 the sequence number is 0, which means it is the first record. */
204 if (message_seq > dtls_session -> nx_secure_dtls_remote_handshake_sequence || (message_seq == 0 && fragment_offset == 0))
205 {
206 /* New record starting, reset the fragment length and handshake sequence number. */
207 dtls_session -> nx_secure_dtls_remote_handshake_sequence = message_seq;
208 dtls_session -> nx_secure_dtls_fragment_length = message_length;
209 }
210
211 if (fragment_length > dtls_session -> nx_secure_dtls_fragment_length)
212 {
213 return(NX_SECURE_TLS_INVALID_PACKET);
214 }
215
216 /* When we receive a message fragment, subtract it from the current fragment length. */
217 dtls_session -> nx_secure_dtls_fragment_length -= fragment_length;
218
219 /* Copy the fragment data (minus the header) into the reassembly buffer. */
220 NX_SECURE_MEMCPY(&fragment_buffer[fragment_offset], &packet_buffer[header_bytes], fragment_length); /* Use case of memcpy is verified. */
221
222 /* If we still have fragments to add, just return success. */
223 if (dtls_session -> nx_secure_dtls_fragment_length > 0)
224 {
225 return(NX_SUCCESS);
226 }
227 else
228 {
229 /* At beginning of handshake, reset the expected sequence number. */
230 if (message_seq == 0)
231 {
232 dtls_session -> nx_secure_dtls_expected_handshake_sequence = 0;
233 }
234
235 /* If the recontructed message has a sequence number not equal to the expected, it's
236 a retransmission or out-of-order message we need to ignore. */
237 if (message_seq != dtls_session -> nx_secure_dtls_expected_handshake_sequence)
238 {
239 return(NX_CONTINUE);
240 }
241
242 /* Our next expected handshake message sequence number is 1 greater than this one. */
243 dtls_session -> nx_secure_dtls_expected_handshake_sequence = message_seq + 1;
244
245 /* Put the header into the packet buffer, adjusting the fields to create a seam-less
246 * DTLS record. */
247 NX_SECURE_MEMMOVE(&fragment_buffer[header_bytes], fragment_buffer, message_length); /* Use case of memmove is verified. */
248
249 /* Reconstruct the header in the fragment buffer so we can hash the
250 reconstructed record as if it were never fragmented. */
251
252 /* Type. */
253 fragment_buffer[0] = (UCHAR)message_type;
254
255 /* Length. */
256 fragment_buffer[1] = (UCHAR)(message_length >> 16);
257 fragment_buffer[2] = (UCHAR)(message_length >> 8);
258 fragment_buffer[3] = (UCHAR)(message_length);
259
260 /* Sequence. */
261 fragment_buffer[4] = (UCHAR)(message_seq >> 8);
262 fragment_buffer[5] = (UCHAR)(message_seq);
263
264 /* Fragment offset is now 0. */
265 fragment_buffer[6] = 0;
266 fragment_buffer[7] = 0;
267 fragment_buffer[8] = 0;
268
269 /* Fragment length is now == message length. */
270 fragment_buffer[9] = (UCHAR)(message_length >> 16);
271 fragment_buffer[10] = (UCHAR)(message_length >> 8);
272 fragment_buffer[11] = (UCHAR)(message_length);
273
274 /* We have a reassembled DTLS record, use that for the handshake. */
275 packet_buffer = fragment_buffer + header_bytes;
276 packet_start = fragment_buffer;
277 }
278 }
279
280 if (status != NX_SECURE_TLS_SUCCESS)
281 {
282 return(status);
283 }
284
285 /* Get reference to the packet pool so we can allocate a packet for all send operations. */
286 packet_pool = tls_session -> nx_secure_tls_packet_pool;
287
288 /* We need to hash all of the handshake messages that we receive and send. If this message is a ClientHello,
289 then we need to initialize the hashes (TLS 1.1 uses both MD5 and SHA-1). The final hash is generated
290 in the "Finished" message. */
291 if (message_type == NX_SECURE_TLS_CLIENT_HELLO)
292 {
293 /* Initialize the handshake hashes used for the Finished message. */
294 _nx_secure_tls_handshake_hash_init(tls_session);
295 }
296
297 /* Process the message itself information from the header. */
298 switch (message_type)
299 {
300 case NX_SECURE_TLS_CLIENT_HELLO:
301 /* Client is establishing a TLS session with our server. */
302 status = _nx_secure_dtls_process_clienthello(dtls_session, packet_buffer, message_length);
303
304 /* This is the end of a flight, clear out the transmit queue. */
305 _nx_secure_dtls_retransmit_queue_flush(dtls_session);
306 break;
307 #ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY
308 case NX_SECURE_TLS_CERTIFICATE_MSG:
309 /* Client sent certificate message (in response to a request from us. Process it now. */
310 status = _nx_secure_tls_process_remote_certificate(tls_session, packet_buffer, message_length, message_length);
311 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE;
312 break;
313 case NX_SECURE_TLS_CERTIFICATE_VERIFY:
314 /* Client has responded to a certificate request with a CertificateVerify message. */
315 status = _nx_secure_tls_process_certificate_verify(tls_session, packet_buffer, message_length);
316
317 if(status == NX_SUCCESS)
318 {
319 /* If remote certificate verification was a success, we have received credentials
320 from the remote host and may now pass Finished message processing once received. */
321 tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE;
322 }
323
324 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY;
325 break;
326 #endif /* NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY */
327 case NX_SECURE_TLS_CLIENT_KEY_EXCHANGE:
328 /* Received a client key exchange message, meaning it is time to generate keys if we can. */
329 status = _nx_secure_tls_process_client_key_exchange(tls_session, packet_buffer, message_length, NX_SECURE_DTLS);
330 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE;
331
332 if (status == NX_SECURE_TLS_SUCCESS)
333 {
334 /* Generate our key material from the data collected thus far and put it all into our
335 socket structure. */
336 status = _nx_secure_tls_generate_keys(tls_session);
337 }
338 break;
339 case NX_SECURE_TLS_FINISHED:
340 /* Final handshake message from the client, process it (verify the client handshake hash). */
341 status = _nx_secure_tls_process_finished(tls_session, packet_buffer, message_length);
342 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE;
343
344 /* This is the end of a flight, clear out the transmit queue. */
345 _nx_secure_dtls_retransmit_queue_flush(dtls_session);
346 break;
347 case NX_SECURE_TLS_HELLO_VERIFY_REQUEST:
348 case NX_SECURE_TLS_HELLO_REQUEST:
349 case NX_SECURE_TLS_SERVER_HELLO:
350 case NX_SECURE_TLS_SERVER_KEY_EXCHANGE:
351 case NX_SECURE_TLS_CERTIFICATE_REQUEST:
352 case NX_SECURE_TLS_SERVER_HELLO_DONE:
353 case NX_SECURE_TLS_CERTIFICATE_URL:
354 case NX_SECURE_TLS_CERTIFICATE_STATUS:
355 default:
356 /* The message received was not a valid TLS server handshake message, send alert and return. */
357 status = NX_SECURE_TLS_UNEXPECTED_MESSAGE;
358 break;
359 }
360
361 /* Check for errors in processing messages. */
362 if (status != NX_SECURE_TLS_SUCCESS)
363 {
364
365 return(status);
366 }
367
368 /* Hash this handshake message. We do not hash HelloRequest messages, but since only the server will send them,
369 we do not worry about them here because these are only messages received from the client at this point.
370 Hashes include the handshake layer header but not the record layer header. */
371 _nx_secure_tls_handshake_hash_update(tls_session, packet_start, (UINT)(message_length + header_bytes));
372
373 /* Now take any actions based on state set in the message processing. */
374 switch (tls_session -> nx_secure_tls_server_state)
375 {
376 case NX_SECURE_TLS_SERVER_STATE_ALERT_SENT:
377 /* This means an error was encountered at some point in processing a valid message. At this point
378 the alert was sent, so just return a status indicating as much. */
379 return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
380 break;
381 case NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_VERIFY:
382 /* We have received and processed a client hello. Now respond to the client appropriately. */
383 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
384
385 if (status != NX_SUCCESS)
386 {
387 break;
388 }
389
390 _nx_secure_dtls_send_helloverifyrequest(dtls_session, send_packet);
391 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_HELLO_VERIFY_REQUEST, wait_option, 1);
392
393 if (status != NX_SUCCESS)
394 {
395 break;
396 }
397
398 if (!dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_local_session_active)
399 {
400
401 /* Ignore the protocol version in a ClientHello without cookies. */
402 dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_protocol_version = 0;
403 }
404
405 break;
406 case NX_SECURE_TLS_SERVER_STATE_SEND_HELLO:
407 /* We have received and processed a client hello. Now respond to the client appropriately. */
408 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
409
410 if (status != NX_SUCCESS)
411 {
412 break;
413 }
414
415 _nx_secure_dtls_send_serverhello(dtls_session, send_packet);
416 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO, wait_option, 1);
417
418 if (status != NX_SUCCESS)
419 {
420 break;
421 }
422
423 /* For PSK and ECJPAKE ciphersuites, don't send the certificate message. */
424 if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm != NX_CRYPTO_KEY_EXCHANGE_PSK &&
425 tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm != NX_CRYPTO_KEY_EXCHANGE_ECJPAKE)
426 {
427 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
428
429 if (status != NX_SUCCESS)
430 {
431 break;
432 }
433
434 _nx_secure_tls_send_certificate(tls_session, send_packet, wait_option);
435 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_MSG, wait_option, 1);
436 if (status != NX_SUCCESS)
437 {
438 break;
439 }
440 }
441
442 #if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE)
443 if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK ||
444 tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE ||
445 tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE)
446 {
447 /* PSK or ECJPAKE ciphersuites use the ServerKeyExchange message to send cryptographic information. */
448 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
449
450 if (status != NX_SUCCESS)
451 {
452 break;
453 }
454
455 /* This is a PSK or ECJPAKE ciphersuite so we always send a ServerKeyExchange message. */
456 status = _nx_secure_tls_send_server_key_exchange(tls_session, send_packet);
457 if (status != NX_SUCCESS)
458 {
459 break;
460 }
461
462 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_SERVER_KEY_EXCHANGE, wait_option, 1);
463 if (status != NX_SUCCESS)
464 {
465 break;
466 }
467 }
468 #endif
469
470 #ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY
471 /* Application has requested that we request and verify the remote Client certificate. */
472 if (tls_session -> nx_secure_tls_verify_client_certificate)
473 {
474 /* Allocate a packet for our certificate request message. */
475 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
476
477 if (status != NX_SUCCESS)
478 {
479 break;
480 }
481
482 /* Populate our packet with the desired message (CertificateRequest). */
483 status = _nx_secure_tls_send_certificate_request(tls_session, send_packet);
484 NX_ASSERT(status == NX_SUCCESS);
485
486 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_REQUEST, wait_option, 1);
487 if (status != NX_SUCCESS)
488 {
489 break;
490 }
491 }
492 else
493 #endif
494 {
495 /* Server is not expecting credentials, so indicate that we have received the client's credentials
496 to pass Finished processing. */
497 tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE;
498 }
499
500 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
501
502 if (status != NX_SUCCESS)
503 {
504 break;
505 }
506
507 /* Server hello done message is 0 bytes, but it still has a TLS header so don't modify the length here. */
508 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO_DONE, wait_option, 1);
509
510 if (status != NX_SUCCESS)
511 {
512 break;
513 }
514
515
516 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HELLO_SENT;
517
518 break;
519 case NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE:
520 /* We processed the certificate above, do nothing. */
521 break;
522 case NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY:
523 /* We processed the certificate above, do nothing. */
524 break;
525 case NX_SECURE_TLS_SERVER_STATE_HELLO_SENT:
526 /* We sent a serverhellodone message, but we haven't received the next client message - this
527 is likely an error. */
528 break;
529 case NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE:
530 break;
531 case NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE:
532 /* Release the protection before suspending on nx_packet_allocate. */
533 tx_mutex_put(&_nx_secure_tls_protection);
534
535 /* We have received everything we need to complete the handshake and keys have been
536 * generated above. Now end the handshake with a ChangeCipherSpec (indicating following
537 * messages are encrypted) and the encrypted Finished message. */
538
539 status = _nx_secure_dtls_packet_allocate(dtls_session, packet_pool, &send_packet, wait_option);
540
541 /* Get the protection after nx_packet_allocate. */
542 tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
543
544 if (status != NX_SUCCESS)
545 {
546 break;
547 }
548
549 _nx_secure_tls_send_changecipherspec(tls_session, send_packet);
550
551 /* ChangeCipherSpec is NOT a handshake message, so send as a normal TLS record. */
552 status = _nx_secure_dtls_send_record(dtls_session, send_packet, NX_SECURE_TLS_CHANGE_CIPHER_SPEC, wait_option);
553
554 if (status != NX_SUCCESS)
555 {
556
557 /* Release packet on send error. */
558 nx_secure_tls_packet_release(send_packet);
559 break;
560 }
561
562 /* The local session is now active since we sent the changecipherspec message.
563 NOTE: Do not set this flag until after the changecipherspec message has been passed to the send record
564 routine - this flag causes encryption and hashing to happen on records. ChangeCipherSpec should be the last
565 un-encrypted/un-hashed record sent. */
566 tls_session -> nx_secure_tls_local_session_active = 1;
567
568 /* For DTLS, reset sequence number and advance epoch right after CCS message is sent. */
569 NX_SECURE_MEMSET(tls_session -> nx_secure_tls_local_sequence_number, 0, sizeof(tls_session -> nx_secure_tls_local_sequence_number));
570
571 status = _nx_secure_tls_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_LOCAL);
572
573 if (status != NX_SUCCESS)
574 {
575 break;
576 }
577
578 /* Advance the DTLS epoch - all messages after the ChangeCipherSpec are in a new epoch. */
579 dtls_session -> nx_secure_dtls_local_epoch = (USHORT)(dtls_session -> nx_secure_dtls_local_epoch + 1);
580
581 /* We processed the incoming finished message above, so now we can send our own finished message. */
582 status = _nx_secure_dtls_allocate_handshake_packet(dtls_session, packet_pool, &send_packet, wait_option);
583 if (status != NX_SUCCESS)
584 {
585 break;
586 }
587
588 _nx_secure_tls_send_finished(tls_session, send_packet);
589 status = _nx_secure_dtls_send_handshake_record(dtls_session, send_packet, NX_SECURE_TLS_FINISHED, wait_option, 1);
590
591
592 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED;
593
594 /* Check if application data is received before state change to NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED. */
595 if (dtls_session -> nx_secure_dtls_receive_queue_head)
596 {
597
598 /* Notify application. */
599 dtls_session -> nx_secure_dtls_server_parent -> nx_secure_dtls_receive_notify(dtls_session);
600 }
601
602 break;
603 case NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED:
604 /* Handshake is complete. */
605 break;
606 default:
607 status = NX_SECURE_TLS_INVALID_STATE;
608 }
609
610
611 return(status);
612 #else /* TLS Server disabled. */
613
614 /* We don't use the parameters since this is an error case. */
615 NX_PARAMETER_NOT_USED(packet_buffer);
616 NX_PARAMETER_NOT_USED(wait_option);
617
618 /* If TLS Server is disabled and we are in the server state machine, something is wrong... */
619 dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_ERROR;
620 return(NX_SECURE_TLS_INVALID_STATE);
621 #endif
622 }
623 #endif /* NX_SECURE_ENABLE_DTLS */
624
625