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