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 /*                                                                        */
28 /*  FUNCTION                                               RELEASE        */
29 /*                                                                        */
30 /*    _nx_secure_dtls_session_end                         PORTABLE C      */
31 /*                                                           6.3.0        */
32 /*  AUTHOR                                                                */
33 /*                                                                        */
34 /*    Timothy Stapko, Microsoft Corporation                               */
35 /*                                                                        */
36 /*  DESCRIPTION                                                           */
37 /*                                                                        */
38 /*    This function ends an active DTLS session by sending the DTLS       */
39 /*    CloseNotify alert to the remote host, then waiting for the response */
40 /*    CloseNotify before returning.                                       */
41 /*                                                                        */
42 /*  INPUT                                                                 */
43 /*                                                                        */
44 /*    dtls_session                          DTLS session control block    */
45 /*    wait_option                           Indicates how long the caller */
46 /*                                          should wait for the response  */
47 /*                                                                        */
48 /*  OUTPUT                                                                */
49 /*                                                                        */
50 /*    status                                Completion status             */
51 /*                                                                        */
52 /*  CALLS                                                                 */
53 /*                                                                        */
54 /*    _nx_secure_dtls_packet_allocate       Allocate internal DTLS packet */
55 /*    _nx_secure_tls_send_alert             Generate the CloseNotify      */
56 /*    _nx_secure_dtls_send_record           Send the CloseNotify          */
57 /*    _nx_secure_dtls_session_reset         Clear out the session         */
58 /*    _nx_secure_dtls_session_receive       Receive DTLS data             */
59 /*    nx_secure_tls_packet_release          Release packet                */
60 /*    tx_mutex_get                          Get protection mutex          */
61 /*    tx_mutex_put                          Put protection mutex          */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    Application Code                                                    */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
72 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
73 /*                                            released packet securely,   */
74 /*                                            resulting in version 6.1    */
75 /*  01-31-2022     Timothy Stapko           Modified comment(s),          */
76 /*                                            fixed out-of-order handling,*/
77 /*                                            resulting in version 6.1.10 */
78 /*  10-31-2023     Tiejun Zhou              Modified comment(s),          */
79 /*                                            handled close notify packet,*/
80 /*                                            resulting in version 6.3.0  */
81 /*                                                                        */
82 /**************************************************************************/
_nx_secure_dtls_session_end(NX_SECURE_DTLS_SESSION * dtls_session,UINT wait_option)83 UINT  _nx_secure_dtls_session_end(NX_SECURE_DTLS_SESSION *dtls_session, UINT wait_option)
84 {
85 #ifdef NX_SECURE_ENABLE_DTLS
86 UINT                    status;
87 UINT                    error_status;
88 NX_PACKET              *send_packet;
89 NX_PACKET              *incoming_packet;
90 NX_PACKET              *tmp_ptr;
91 NX_SECURE_TLS_SESSION  *tls_session;
92 
93     /* Get reference to internal TLS state. */
94     tls_session = &dtls_session -> nx_secure_dtls_tls_session;
95 
96     /* Get the protection. */
97     tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
98 
99     /* Release packets in queue. */
100     while (tls_session -> nx_secure_record_queue_header)
101     {
102         tmp_ptr = tls_session -> nx_secure_record_queue_header;
103         tls_session -> nx_secure_record_queue_header = tmp_ptr -> nx_packet_queue_next;
104         tmp_ptr -> nx_packet_queue_next = NX_NULL;
105         nx_secure_tls_packet_release(tmp_ptr);
106     }
107     if (tls_session -> nx_secure_record_decrypted_packet)
108     {
109         nx_secure_tls_packet_release(tls_session -> nx_secure_record_decrypted_packet);
110         tls_session -> nx_secure_record_decrypted_packet = NX_NULL;
111     }
112 
113     /* If the remote session is already finished, don't try to send. */
114     if(!dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_remote_session_active)
115     {
116         /* Reset the TLS state so this socket can be reused. */
117         tx_mutex_put(&_nx_secure_tls_protection);
118         status = _nx_secure_dtls_session_reset(dtls_session);
119         return(status);
120     }
121 
122 
123     /* Release the protection before suspending on nx_packet_allocate. */
124     tx_mutex_put(&_nx_secure_tls_protection);
125 
126     /* Allocate a packet for our close-notify alert. */
127     status = _nx_secure_dtls_packet_allocate(dtls_session, tls_session -> nx_secure_tls_packet_pool, &send_packet, wait_option);
128 
129     /* Check for errors in allocating packet. */
130     if (status != NX_SUCCESS)
131     {
132         _nx_secure_dtls_session_reset(dtls_session);
133         return(status);
134     }
135 
136     /* Get the protection after nx_packet_allocate. */
137     tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
138 
139     /* A close-notify alert shuts down the TLS session cleanly. */
140     _nx_secure_tls_send_alert(tls_session, send_packet, NX_SECURE_TLS_ALERT_CLOSE_NOTIFY, NX_SECURE_TLS_ALERT_LEVEL_WARNING);
141 
142     /* Finally, send the alert record to the remote host. */
143     status = _nx_secure_dtls_send_record(dtls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option);
144 
145     if (status)
146     {
147         /* Failed to send, release the packet. */
148         nx_secure_tls_packet_release(send_packet);
149         _nx_secure_dtls_session_reset(dtls_session);
150         tx_mutex_put(&_nx_secure_tls_protection);
151         return(status);
152     }
153 
154     /* Release the protection. */
155     tx_mutex_put(&_nx_secure_tls_protection);
156 
157     /* See if we received the CloseNotify, or if we need to wait. */
158     if(tls_session -> nx_secure_tls_received_alert_level != NX_SECURE_TLS_ALERT_LEVEL_WARNING ||
159        tls_session -> nx_secure_tls_received_alert_value != NX_SECURE_TLS_ALERT_CLOSE_NOTIFY)
160     {
161         while (status == NX_SUCCESS)
162         {
163             /* Wait for the CloseNotify response. */
164 
165             status = _nx_secure_dtls_session_receive(dtls_session, &incoming_packet, wait_option);
166 
167             if (status == NX_SUCCESS)
168             {
169 
170                 /* Release the packet. */
171                 nx_secure_tls_packet_release(incoming_packet);
172             }
173         }
174     }
175 
176     /* Save error status for return below. */
177     error_status = status;
178 
179     /* Reset the TLS state so this socket can be reused. */
180     status = _nx_secure_dtls_session_reset(dtls_session);
181 
182     if(error_status != NX_SECURE_TLS_ALERT_RECEIVED && error_status != NX_SECURE_TLS_CLOSE_NOTIFY_RECEIVED)
183     {
184         status = error_status;
185     }
186 
187     return(status);
188 #else
189     NX_PARAMETER_NOT_USED(dtls_session);
190     NX_PARAMETER_NOT_USED(wait_option);
191 
192     return(NX_NOT_SUPPORTED);
193 #endif /* NX_SECURE_ENABLE_DTLS */
194 }
195 
196