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 
27 /**************************************************************************/
28 /*                                                                        */
29 /*  FUNCTION                                               RELEASE        */
30 /*                                                                        */
31 /*    _nx_secure_tls_handshake_hash_init                  PORTABLE C      */
32 /*                                                           6.1          */
33 /*  AUTHOR                                                                */
34 /*                                                                        */
35 /*    Timothy Stapko, Microsoft Corporation                               */
36 /*                                                                        */
37 /*  DESCRIPTION                                                           */
38 /*                                                                        */
39 /*    This function initializes the hash function states needed for the   */
40 /*    TLS Finished message handshake hash.                                */
41 /*                                                                        */
42 /*  INPUT                                                                 */
43 /*                                                                        */
44 /*    tls_session                           TLS control block             */
45 /*                                                                        */
46 /*  OUTPUT                                                                */
47 /*                                                                        */
48 /*    status                                Completion status             */
49 /*                                                                        */
50 /*  CALLS                                                                 */
51 /*                                                                        */
52 /*    [nx_crypto_operation]                 Hash initialization functions */
53 /*                                                                        */
54 /*  CALLED BY                                                             */
55 /*                                                                        */
56 /*    _nx_secure_dtls_send_clienthello      Send ClientHello              */
57 /*    _nx_secure_dtls_server_handshake      DTLS server state machine     */
58 /*    _nx_secure_tls_send_clienthello       Send ClientHello              */
59 /*    _nx_secure_tls_server_handshake       TLS server state machine      */
60 /*                                                                        */
61 /*  RELEASE HISTORY                                                       */
62 /*                                                                        */
63 /*    DATE              NAME                      DESCRIPTION             */
64 /*                                                                        */
65 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
66 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
67 /*                                            resulting in version 6.1    */
68 /*                                                                        */
69 /**************************************************************************/
_nx_secure_tls_handshake_hash_init(NX_SECURE_TLS_SESSION * tls_session)70 UINT  _nx_secure_tls_handshake_hash_init(NX_SECURE_TLS_SESSION *tls_session)
71 {
72 const NX_CRYPTO_METHOD *method_ptr;
73 UINT              status;
74 VOID             *handler = NX_NULL;
75 VOID             *metadata;
76 UINT              metadata_size;
77 
78 
79     /* We need to hash all of the handshake messages that we receive and send. When sending a ClientHello,
80        we need to initialize the hashes (TLS 1.1 uses both MD5 and SHA-1, TLS 1.2 uses SHA-256). The final
81        hash is generated in the "Finished" message.
82        TLS 1.3 does things a little differently - the handshake hash is the same as that of the chosen
83        ciphersuite, so */
84 
85 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
86     if(tls_session->nx_secure_tls_1_3)
87     {
88         /* Hash handshake record using ciphersuite hash routine. */
89         if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
90         {
91             /* Set the hash method to the default of SHA-256 if no ciphersuite is available. */
92             method_ptr = tls_session -> nx_secure_tls_crypto_table->nx_secure_tls_handshake_hash_sha256_method;
93 
94         }
95         else
96         {
97             /* The handshake transcript hash in TLS 1.3 uses the hash routine associated with the chosen ciphersuite. */
98             method_ptr = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash;
99         }
100 
101         /* Generate the "transcript hash" for the point in the handshake where this message falls.
102          * This is needed for TLS 1.3 key generation which uses the hash of all previous handshake
103          * messages at multiple points during the handshake. Instead of saving the entirety of the
104          * handshake messages, just generate a hash when each record is hashed. */
105 
106 
107         /* The handshake transcript hash in TLS 1.3 uses the hash routine associated with the chosen ciphersuite. */
108         metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata;
109         metadata_size = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size;
110 
111         if (method_ptr -> nx_crypto_init)
112         {
113             status = method_ptr -> nx_crypto_init((NX_CRYPTO_METHOD*)method_ptr,
114                                          NX_NULL,
115                                          0,
116                                          &handler,
117                                          metadata,
118                                          metadata_size);
119             tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler = handler;
120 
121             if(status != NX_CRYPTO_SUCCESS)
122             {
123                 return(status);
124             }
125         }
126 
127         if (method_ptr -> nx_crypto_operation != NX_NULL)
128         {
129             status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
130                                               handler,
131                                               (NX_CRYPTO_METHOD*)method_ptr,
132                                               NX_NULL,
133                                               0,
134                                               NX_NULL,
135                                               0,
136                                               NX_NULL,
137                                               NX_NULL,
138                                               0,
139                                               metadata,
140                                               metadata_size,
141                                               NX_NULL,
142                                               NX_NULL);
143         }
144 
145         return(status);
146 
147     }
148 #endif
149 
150 
151 
152     /* Initialize both the handshake "finished" hashes - TLS 1.1 uses both SHA-1 and MD5, TLS 1.2 uses SHA-256 by default.
153        At this point we don't yet know the version we will use, so initialize all of them. */
154     /* Hash is determined by ciphersuite in TLS 1.2. Default is SHA-256. */
155 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
156     if (tls_session -> nx_secure_tls_supported_versions & (USHORT)(NX_SECURE_TLS_BITFIELD_VERSION_1_2))
157     {
158         method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method;
159         metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata;
160         metadata_size = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size;
161 
162         if (method_ptr -> nx_crypto_init)
163         {
164             status = method_ptr -> nx_crypto_init((NX_CRYPTO_METHOD*)method_ptr,
165                                          NX_NULL,
166                                          0,
167                                          &handler,
168                                          metadata,
169                                          metadata_size);
170 
171             if(status != NX_CRYPTO_SUCCESS)
172             {
173                 return(status);
174             }
175             tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler = handler;
176         }
177 
178         if (method_ptr -> nx_crypto_operation != NX_NULL)
179         {
180             status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
181                                               handler,
182                                               (NX_CRYPTO_METHOD*)method_ptr,
183                                               NX_NULL,
184                                               0,
185                                               NX_NULL,
186                                               0,
187                                               NX_NULL,
188                                               NX_NULL,
189                                               0,
190                                               metadata,
191                                               metadata_size,
192                                               NX_NULL,
193                                               NX_NULL);
194 
195             if(status != NX_CRYPTO_SUCCESS)
196             {
197                 return(status);
198             }
199         }
200     }
201 #endif
202 
203 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
204     if (tls_session -> nx_secure_tls_supported_versions & (USHORT)(NX_SECURE_TLS_BITFIELD_VERSION_1_0 | NX_SECURE_TLS_BITFIELD_VERSION_1_1))
205     {
206         /* TLS 1.0 and 1.1 use both MD5 and SHA-1. */
207         method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
208         metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata;
209         metadata_size = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size;
210 
211         if (method_ptr -> nx_crypto_init)
212         {
213             status = method_ptr -> nx_crypto_init((NX_CRYPTO_METHOD*)method_ptr,
214                                          NX_NULL,
215                                          0,
216                                          &handler,
217                                          metadata,
218                                          metadata_size);
219 
220             if(status != NX_CRYPTO_SUCCESS)
221             {
222                 return(status);
223             }
224 
225             tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_handler = handler;
226         }
227 
228         if (method_ptr -> nx_crypto_operation != NX_NULL)
229         {
230             status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
231                                               handler,
232                                               (NX_CRYPTO_METHOD*)method_ptr,
233                                               NX_NULL,
234                                               0,
235                                               NX_NULL,
236                                               0,
237                                               NX_NULL,
238                                               NX_NULL,
239                                               0,
240                                               metadata,
241                                               metadata_size,
242                                               NX_NULL,
243                                               NX_NULL);
244 
245             if(status != NX_CRYPTO_SUCCESS)
246             {
247                 return(status);
248             }
249         }
250 
251         method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
252         metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata;
253         metadata_size = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size;
254 
255         if (method_ptr -> nx_crypto_init)
256         {
257             status = method_ptr -> nx_crypto_init((NX_CRYPTO_METHOD*)method_ptr,
258                                          NX_NULL,
259                                          0,
260                                          &handler,
261                                          metadata,
262                                          metadata_size);
263 
264             if(status != NX_CRYPTO_SUCCESS)
265             {
266                 return(status);
267             }
268             tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_handler = handler;
269         }
270 
271         if (method_ptr -> nx_crypto_operation != NX_NULL)
272         {
273             status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
274                                               handler,
275                                               (NX_CRYPTO_METHOD*)method_ptr,
276                                               NX_NULL,
277                                               0,
278                                               NX_NULL,
279                                               0,
280                                               NX_NULL,
281                                               NX_NULL,
282                                               0,
283                                               metadata,
284                                               metadata_size,
285                                               NX_NULL,
286                                               NX_NULL);
287 
288             if(status != NX_CRYPTO_SUCCESS)
289             {
290                 return(status);
291             }
292         }
293     }
294 #endif
295 
296     return(NX_SUCCESS);
297 }
298 
299