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 #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 static UCHAR handshake_hash[16 + 20]; /* We concatenate MD5 and SHA-1 hashes into this buffer. */
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _nx_secure_tls_finished_hash_generate PORTABLE C */
36 /* 6.1.8 */
37 /* AUTHOR */
38 /* */
39 /* Timothy Stapko, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function generates the Finished message hash using the hash */
44 /* data collected in the TLS session control block during the */
45 /* handshake. */
46 /* */
47 /* INPUT */
48 /* */
49 /* tls_session TLS control block */
50 /* finished_label Label used to generate hash */
51 /* finished_hash Pointer to hash output buffer */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* status Completion status */
56 /* */
57 /* CALLS */
58 /* */
59 /* [nx_crypto_init] Initialize crypto */
60 /* [nx_crypto_operation] Crypto operation */
61 /* */
62 /* CALLED BY */
63 /* */
64 /* _nx_secure_tls_send_finished Send Finished message */
65 /* _nx_secure_tls_process_finished Process Finished message */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
72 /* 09-30-2020 Timothy Stapko Modified comment(s), */
73 /* verified memcpy use cases, */
74 /* resulting in version 6.1 */
75 /* 08-02-2021 Timothy Stapko Modified comment(s), added */
76 /* hash clone and cleanup, */
77 /* resulting in version 6.1.8 */
78 /* */
79 /**************************************************************************/
_nx_secure_tls_finished_hash_generate(NX_SECURE_TLS_SESSION * tls_session,UCHAR * finished_label,UCHAR * finished_hash)80 UINT _nx_secure_tls_finished_hash_generate(NX_SECURE_TLS_SESSION *tls_session,
81 UCHAR *finished_label, UCHAR *finished_hash)
82 {
83 UINT status;
84 UCHAR *master_sec;
85 const NX_CRYPTO_METHOD *method_ptr = NX_NULL;
86 VOID *handler = NX_NULL;
87 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
88 VOID *metadata;
89 UINT metadata_size;
90 #endif /* (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) */
91 UINT hash_size = 0;
92
93 /* We need to extract the Finished hash and verify that the handshake to this point
94 has not been corrupted or tampered with. */
95
96 /* From the RFC (TLS 1.1). TLS 1.2 uses the same strategy but uses only SHA-256.
97 struct {
98 opaque verify_data[12];
99 } Finished;
100
101 verify_data
102 PRF(master_secret, finished_label, MD5(handshake_messages) +
103 SHA-1(handshake_messages)) [0..11];
104
105 finished_label
106 For Finished messages sent by the client, the string "client
107 finished". For Finished messages sent by the server, the
108 string "server finished".
109
110 handshake_messages
111 All of the data from all messages in this handshake (not
112 including any HelloRequest messages) up to but not including
113 this message. This is only data visible at the handshake
114 layer and does not include record layer headers. This is the
115 concatenation of all the Handshake structures, as defined in
116 7.4, exchanged thus far.
117 */
118
119 if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL)
120 {
121 return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
122 }
123
124
125 /* Get our master secret that was generated when we generated our key material. */
126 master_sec = tls_session -> nx_secure_tls_key_material.nx_secure_tls_master_secret;
127
128 /* Finally, generate the verification data required by TLS - 12 bytes using the PRF and the data
129 we have collected. Place the result directly into the packet buffer. */
130 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
131 #ifdef NX_SECURE_ENABLE_DTLS
132 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 ||
133 tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2)
134 #else
135 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
136 #endif /* NX_SECURE_ENABLE_DTLS */
137 {
138 /* Copy over the handshake hash state into scratch space to do the intermediate calculation. */
139 NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, /* lgtm[cpp/banned-api-usage-required-any] */
140 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
141 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
142
143 /* Finalize the handshake message hash that we started at the beginning of the handshake. */
144 method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method;
145 handler = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler;
146
147 if (method_ptr -> nx_crypto_operation != NX_NULL)
148 {
149 status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
150 handler,
151 (NX_CRYPTO_METHOD*)method_ptr,
152 NX_NULL,
153 0,
154 NX_NULL,
155 0,
156 NX_NULL,
157 &handshake_hash[0],
158 sizeof(handshake_hash),
159 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
160 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
161 NX_NULL,
162 NX_NULL);
163
164 }
165 else
166 {
167 status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE;
168 }
169
170 NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
171 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
172
173 if (status != NX_CRYPTO_SUCCESS)
174 {
175 return(status);
176 }
177
178 /* For TLS 1.2, the PRF is defined by the ciphersuite. However, if we are using an older ciphersuite,
179 * default to the TLS 1.2 default PRF, which uses SHA-256-HMAC. */
180 method_ptr = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_prf;
181 hash_size = 32; /* Size of SHA-256 output. */
182 }
183
184 #endif
185
186 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
187 #ifdef NX_SECURE_ENABLE_DTLS
188 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
189 tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
190 tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)
191 #else
192 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
193 tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
194 #endif /* NX_SECURE_ENABLE_DTLS */
195 {
196 /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. */
197 NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
198 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
199 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata,
200 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */
201
202 /* Finalize the handshake message hashes that we started at the beginning of the handshake. */
203 method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
204 handler = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_handler;
205 metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
206 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size;
207 metadata_size = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size;
208 if (method_ptr -> nx_crypto_operation != NX_NULL)
209 {
210 status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
211 handler,
212 (NX_CRYPTO_METHOD*)method_ptr,
213 NX_NULL,
214 0,
215 NX_NULL,
216 0,
217 NX_NULL,
218 &handshake_hash[0],
219 16,
220 metadata,
221 metadata_size,
222 NX_NULL,
223 NX_NULL);
224 }
225 else
226 {
227 status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE;
228 }
229
230 NX_SECURE_HASH_CLONE_CLEANUP(metadata, metadata_size);
231
232 if (status != NX_CRYPTO_SUCCESS)
233 {
234 return(status);
235 }
236
237 NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
238 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata,
239 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */
240
241 method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
242 handler = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_handler;
243 metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch;
244 metadata_size = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size;
245
246 if (method_ptr -> nx_crypto_operation != NX_NULL)
247 {
248 status = method_ptr -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
249 handler,
250 (NX_CRYPTO_METHOD*)method_ptr,
251 NX_NULL,
252 0,
253 NX_NULL,
254 0,
255 NX_NULL,
256 &handshake_hash[16],
257 sizeof(handshake_hash) - 16,
258 metadata,
259 metadata_size,
260 NX_NULL,
261 NX_NULL);
262
263
264 }
265 else
266 {
267 status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE;
268 }
269
270 NX_SECURE_HASH_CLONE_CLEANUP(metadata, metadata_size);
271
272 if (status != NX_CRYPTO_SUCCESS)
273 {
274 return(status);
275 }
276
277 /* TLS 1.0 and TLS 1.1 use the same PRF. */
278 method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_prf_1_method;
279 hash_size = 36;
280 }
281 #endif
282
283 /* Make sure we found a supported version (essentially an assertion check). */
284 if (method_ptr == NX_NULL)
285 {
286 return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION);
287 }
288
289 /* Do the final PRF encoding of the finished hash. */
290 if (method_ptr -> nx_crypto_init != NX_NULL)
291 {
292 status = method_ptr -> nx_crypto_init((NX_CRYPTO_METHOD*)method_ptr,
293 master_sec, 48,
294 &handler,
295 tls_session -> nx_secure_tls_prf_metadata_area,
296 tls_session -> nx_secure_tls_prf_metadata_size);
297
298 if(status != NX_CRYPTO_SUCCESS)
299 {
300 return(status);
301 }
302 }
303 else
304 {
305 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
306 }
307
308 if (method_ptr -> nx_crypto_operation != NX_NULL)
309 {
310 status = method_ptr -> nx_crypto_operation(NX_CRYPTO_PRF,
311 handler,
312 (NX_CRYPTO_METHOD*)method_ptr,
313 finished_label,
314 15,
315 handshake_hash,
316 hash_size,
317 NX_NULL,
318 &finished_hash[0],
319 NX_SECURE_TLS_FINISHED_HASH_SIZE,
320 tls_session -> nx_secure_tls_prf_metadata_area,
321 tls_session -> nx_secure_tls_prf_metadata_size,
322 NX_NULL,
323 NX_NULL);
324
325 if(status != NX_CRYPTO_SUCCESS)
326 {
327 return(status);
328 }
329 }
330 else
331 {
332 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
333 }
334
335 if (method_ptr -> nx_crypto_cleanup != NX_NULL)
336 {
337 status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_prf_metadata_area);
338
339 if(status != NX_CRYPTO_SUCCESS)
340 {
341 return(status);
342 }
343 }
344 #ifdef NX_SECURE_KEY_CLEAR
345 NX_SECURE_MEMSET(handshake_hash, 0, hash_size);
346 #endif /* NX_SECURE_KEY_CLEAR */
347
348 return(NX_SUCCESS);
349 }
350
351