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