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 static UCHAR generated_hash[NX_SECURE_TLS_MAX_HASH_SIZE];
27 
28 /**************************************************************************/
29 /*                                                                        */
30 /*  FUNCTION                                               RELEASE        */
31 /*                                                                        */
32 /*    _nx_secure_tls_process_finished                     PORTABLE C      */
33 /*                                                           6.2.1        */
34 /*  AUTHOR                                                                */
35 /*                                                                        */
36 /*    Timothy Stapko, Microsoft Corporation                               */
37 /*                                                                        */
38 /*  DESCRIPTION                                                           */
39 /*                                                                        */
40 /*    This function processes an incoming Finished message by generating  */
41 /*    a hash of the received handshake messages (up to this point) and    */
42 /*    comparing the result to the hash received from the remote host.     */
43 /*    If the generated hash and the received hash do not match, it        */
44 /*    indicates that the handshake messages were corrupted in some way.   */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    tls_session                           TLS control block             */
49 /*    packet_buffer                         Pointer to received data      */
50 /*    message_length                        Length of received data       */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    status                                Result of hash comparison     */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _nx_secure_tls_finished_hash_generate Generate Finished hash        */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    _nx_secure_dtls_client_handshake      DTLS client state machine     */
63 /*    _nx_secure_dtls_server_handshake      DTLS server state machine     */
64 /*    _nx_secure_tls_client_handshake       TLS client state machine      */
65 /*    _nx_secure_tls_server_handshake       TLS server state machine      */
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 /*                                            verified memcpy use cases,  */
74 /*                                            fixed renegotiation bug,    */
75 /*                                            resulting in version 6.1    */
76 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
77 /*                                            fixed compiler errors when  */
78 /*                                            x509 is disabled,           */
79 /*                                            corrected hash cleanup,     */
80 /*                                            resulting in version 6.2.1  */
81 /*                                                                        */
82 /**************************************************************************/
_nx_secure_tls_process_finished(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,UINT message_length)83 UINT _nx_secure_tls_process_finished(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer,
84                                      UINT message_length)
85 {
86 UCHAR            *finished_label;
87 UINT              compare_result, status;
88 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
89 UINT              hash_size = 0;
90 UINT              is_server;
91 #endif
92 
93 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
94     /* Make sure the length is what we expect. */
95     if(tls_session -> nx_secure_tls_1_3)
96     {
97         /* TLS 1.3 Finished messages are different from earlier versions
98            and require specific processing. */
99         /* Check if the Finished is from server. */
100         is_server = (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT);
101 
102         /* Verify Finished hash. */
103         status = _nx_secure_tls_1_3_finished_hash_generate(tls_session, is_server, &hash_size, generated_hash, sizeof(generated_hash));
104 
105         if ((hash_size > message_length) || (hash_size > sizeof(generated_hash)))
106         {
107 
108             /* Size error. */
109             compare_result = 1;
110         }
111         else
112         {
113 
114             /* Compare to see if the Finished hash matches the received hash. */
115             compare_result = (UINT)NX_SECURE_MEMCMP(generated_hash, packet_buffer, hash_size);
116         }
117 
118 #ifdef NX_SECURE_KEY_CLEAR
119         NX_SECURE_MEMSET(generated_hash, 0, sizeof(generated_hash));
120 #endif /* NX_SECURE_KEY_CLEAR  */
121     }
122     else
123 #endif
124     {
125         /* TLS 1.2 and earlier use the same Finished hash construction. */
126         if (message_length != NX_SECURE_TLS_FINISHED_HASH_SIZE)
127         {
128             return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
129         }
130 
131 
132         /* If we received a Finished message but the session is not active, error! */
133         if (!tls_session -> nx_secure_tls_remote_session_active)
134         {
135             return(NX_SECURE_TLS_UNEXPECTED_MESSAGE);
136         }
137 
138         /* If we have not received credentials from the remote host, we
139            cannot validate the handshake under any circumstances. */
140         if (!tls_session -> nx_secure_tls_received_remote_credentials)
141         {
142             return(NX_SECURE_TLS_HANDSHAKE_FAILURE);
143         }
144 
145         /* Select our label for generating the finished hash expansion - we are comparing against
146            the remote hosts hash, so use the opposite label. */
147         if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER)
148         {
149             finished_label = (UCHAR *)"client finished";
150         }
151         else
152         {
153             finished_label = (UCHAR *)"server finished";
154         }
155 
156         /* Finally, generate the verification data required by TLS - 12 bytes using the PRF and the data
157            we have collected. */
158         status = _nx_secure_tls_finished_hash_generate(tls_session, finished_label, generated_hash);
159 
160         if(status != NX_SUCCESS)
161         {
162             return(status);
163         }
164 
165 #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION
166         /* If we are doing secure renegotiation as per RFC 5746, we need to save off the generated
167            verify data now. For TLS 1.0-1.2 this is 12 bytes. If SSLv3 is ever used, it will be 36 bytes. */
168         NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_remote_verify_data, generated_hash, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified.  lgtm[cpp/banned-api-usage-required-any] */
169 #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */
170 
171         /* The finished verify data is always 12 bytes (*except for SSLv3) - compare to see if the Finished hash matches the received hash. */
172         compare_result = (UINT)NX_SECURE_MEMCMP(generated_hash, packet_buffer, NX_SECURE_TLS_FINISHED_HASH_SIZE);
173     }
174 
175     if (compare_result != 0)
176     {
177         return(NX_SECURE_TLS_FINISHED_HASH_FAILURE);
178     }
179 
180     /* If the comparison was OK, set the state appropriately. */
181 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
182     if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT)
183     {
184         tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_HANDSHAKE_FINISHED;
185     }
186 #endif
187 
188 #ifndef NX_SECURE_DISABLE_X509
189 
190     /* Now that we are done with the handshake, free all remote certificates - we don't need them anymore. */
191     status = _nx_secure_tls_remote_certificate_free_all(tls_session);
192 
193     if (status != NX_SUCCESS)
194     {
195         return(status);
196     }
197 #endif
198 
199     return(NX_SECURE_TLS_SUCCESS);
200 }
201 
202