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 #ifdef NX_SECURE_ENABLE_DTLS
26 #include "nx_secure_dtls.h"
27 #endif /* NX_SECURE_ENABLE_DTLS */
28 
29 /**************************************************************************/
30 /*                                                                        */
31 /*  FUNCTION                                               RELEASE        */
32 /*                                                                        */
33 /*    _nx_secure_tls_handshake_hash_update                PORTABLE C      */
34 /*                                                           6.1.9        */
35 /*  AUTHOR                                                                */
36 /*                                                                        */
37 /*    Timothy Stapko, Microsoft Corporation                               */
38 /*                                                                        */
39 /*  DESCRIPTION                                                           */
40 /*                                                                        */
41 /*    This function updates the hash function states with handshake       */
42 /*    messages, both generated by this host and received from a remote    */
43 /*    host. This is needed for the TLS Finished message handshake hash.   */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    tls_session                           TLS control block             */
48 /*    data                                  Data to be hashed             */
49 /*    length                                Data length                   */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    status                                Completion status             */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    [nx_crypto_operation]                 Hash update functions         */
58 /*                                                                        */
59 /*  CALLED BY                                                             */
60 /*                                                                        */
61 /*    _nx_secure_dtls_send_clienthello      Send ClientHello              */
62 /*    _nx_secure_dtls_send_handshake_record Send DTLS handshake record    */
63 /*    _nx_secure_dtls_server_handshake      DTLS server state machine     */
64 /*    _nx_secure_tls_send_clienthello       Send ClientHello              */
65 /*    _nx_secure_tls_send_handshake_record  Send TLS handshake record     */
66 /*    _nx_secure_tls_server_handshake       TLS server state machine      */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
73 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*  10-15-2021     Timothy Stapko           Modified comment(s), fixed    */
76 /*                                            compilation issue with      */
77 /*                                            TLS 1.3 and disabling TLS   */
78 /*                                            server,                     */
79 /*                                            resulting in version 6.1.9  */
80 /*                                                                        */
81 /**************************************************************************/
_nx_secure_tls_handshake_hash_update(NX_SECURE_TLS_SESSION * tls_session,UCHAR * data,UINT length)82 UINT  _nx_secure_tls_handshake_hash_update(NX_SECURE_TLS_SESSION *tls_session, UCHAR *data,
83                                            UINT length)
84 {
85 UINT                    status = NX_NOT_SUCCESSFUL;
86 const NX_CRYPTO_METHOD *method_ptr;
87 
88 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
89 UINT                    hash_length;
90 USHORT                  hello_retry_process = 0;
91 #endif
92 
93 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
94     if(tls_session->nx_secure_tls_1_3)
95     {
96         /* Hash handshake record using ciphersuite hash routine. */
97         if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
98         {
99             /* Set the hash method to the default of SHA-256 if no ciphersuite is available. */
100             method_ptr = tls_session -> nx_secure_tls_crypto_table->nx_secure_tls_handshake_hash_sha256_method;
101 
102         }
103         else
104         {
105             /* The handshake transcript hash in TLS 1.3 uses the hash routine associated with the chosen ciphersuite. */
106             method_ptr = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash;
107         }
108 
109         /* Generate the "transcript hash" for the point in the handshake where this message falls.
110          * This is needed for TLS 1.3 key generation which uses the hash of all previous handshake
111          * messages at multiple points during the handshake. Instead of saving the entirety of the
112          * handshake messages, just generate a hash when each record is hashed. */
113         if (method_ptr -> nx_crypto_operation != NX_NULL)
114         {
115             status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
116                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
117                                                        (NX_CRYPTO_METHOD*)method_ptr,
118                                                        NX_NULL,
119                                                        0,
120                                                        data,
121                                                        length,
122                                                        NX_NULL,
123                                                        NX_NULL,
124                                                        0,
125                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
126                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
127                                                        NX_NULL,
128                                                        NX_NULL);
129 
130             /* See if we have recieved or are sending a hello retry message - we need to process the hash differently. */
131 #ifndef NX_SECURE_TLS_SERVER_DISABLED
132             if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER)
133             {
134                 hello_retry_process = (tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY);
135             }
136 #endif
137 #ifndef NX_SECURE_TLS_CLIENT_DISABLED
138             if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT)
139             {
140                 hello_retry_process = (tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HELLO_RETRY);
141             }
142 #endif
143 
144            /* Modify message buffer - replace message with hash used for HelloRetryRequest processing. */
145             if ((status == NX_SUCCESS) &&
146                 (hello_retry_process) &&
147                 (data[0] == NX_SECURE_TLS_CLIENT_HELLO) &&
148                 (length > NX_SECURE_TLS_HANDSHAKE_HEADER_SIZE))
149             {
150 
151                 /* ClientHello1 is replaced with "message_hash || 00 00 Hash.length || Hash(ClientHello1)"*/
152                 status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
153                                                            tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
154                                                            (NX_CRYPTO_METHOD*)method_ptr,
155                                                            NX_NULL,
156                                                            0,
157                                                            NX_NULL,
158                                                            0,
159                                                            NX_NULL,
160                                                            data + 4, /* Reuse input buffer since the input will not be used anymore. */
161                                                            NX_SECURE_TLS_MAX_HASH_SIZE,
162                                                            tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
163                                                            tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
164                                                            NX_NULL,
165                                                            NX_NULL);
166 
167                 /* Initialize handshake HASH again. */
168                 if (status == NX_SUCCESS)
169                 {
170                     status = _nx_secure_tls_handshake_hash_init(tls_session);
171                 }
172 
173                 if (status == NX_SUCCESS)
174                 {
175                     hash_length = method_ptr -> nx_crypto_ICV_size_in_bits >> 3;
176                     data[0] = NX_SECURE_TLS_MESSAGE_HASH & 0xFF;
177                     data[1] = 0;
178                     data[2] = 0;
179                     data[3] = hash_length & 0xFF;
180 
181                     status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
182                                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
183                                                                (NX_CRYPTO_METHOD*)method_ptr,
184                                                                NX_NULL,
185                                                                0,
186                                                                data,
187                                                                hash_length + 4,
188                                                                NX_NULL,
189                                                                NX_NULL,
190                                                                0,
191                                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
192                                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
193                                                                NX_NULL,
194                                                                NX_NULL);
195                 }
196             }
197         }
198 
199         return(status);
200 
201 
202     }
203 #endif
204 
205     /* Hash this handshake message. We do not hash HelloRequest messages, but since only the server will send them,
206        we do not worry about them here because these are only messages received from the client at this point.
207        Hashes include the handshake layer header but not the record layer header. */
208 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
209 #ifdef NX_SECURE_ENABLE_DTLS
210     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 ||
211         tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2)
212 #else
213     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
214 #endif /* NX_SECURE_ENABLE_DTLS */
215     {
216         /* Hash is determined by ciphersuite in TLS 1.2. Default is SHA-256. */
217         method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method;
218         if (method_ptr -> nx_crypto_operation != NX_NULL)
219         {
220             status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
221                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
222                                                        (NX_CRYPTO_METHOD*)method_ptr,
223                                                        NX_NULL,
224                                                        0,
225                                                        data,
226                                                        length,
227                                                        NX_NULL,
228                                                        NX_NULL,
229                                                        0,
230                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
231                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
232                                                        NX_NULL,
233                                                        NX_NULL);
234 
235             if (status != NX_CRYPTO_SUCCESS)
236             {
237                 return(status);
238             }
239         }
240     }
241 #endif
242 
243 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
244 #ifdef NX_SECURE_ENABLE_DTLS
245     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
246         tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
247         tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)
248 #else
249     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
250         tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
251 #endif /* NX_SECURE_ENABLE_DTLS */
252     {
253         /* TLS 1.0 and 1.1 use both MD5 and SHA-1. */
254         method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
255         if (method_ptr -> nx_crypto_operation != NX_NULL)
256         {
257             status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
258                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_handler,
259                                                        (NX_CRYPTO_METHOD*)method_ptr,
260                                                        NX_NULL,
261                                                        0,
262                                                        data,
263                                                        length,
264                                                        NX_NULL,
265                                                        NX_NULL,
266                                                        0,
267                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata,
268                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size,
269                                                        NX_NULL,
270                                                        NX_NULL);
271 
272             if (status != NX_CRYPTO_SUCCESS)
273             {
274                 return(status);
275             }
276         }
277 
278         method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
279         if (method_ptr -> nx_crypto_operation != NX_NULL)
280         {
281             status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
282                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_handler,
283                                                        (NX_CRYPTO_METHOD*)method_ptr,
284                                                        NX_NULL,
285                                                        0,
286                                                        data,
287                                                        length,
288                                                        NX_NULL,
289                                                        NX_NULL,
290                                                        0,
291                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata,
292                                                        tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
293                                                        NX_NULL,
294                                                        NX_NULL);
295 
296             if (status != NX_CRYPTO_SUCCESS)
297             {
298                 return(status);
299             }
300         }
301     }
302 #endif
303 
304     return(status);
305 }
306 
307