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