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