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
26 #include "nx_secure_tls.h"
27
28
29 /**************************************************************************/
30 /* */
31 /* FUNCTION RELEASE */
32 /* */
33 /* _nx_secure_tls_server_handshake PORTABLE C */
34 /* 6.2.0 */
35 /* AUTHOR */
36 /* */
37 /* Timothy Stapko, Microsoft Corporation */
38 /* */
39 /* DESCRIPTION */
40 /* */
41 /* This function runs the TLS Server mode state machine. It processes */
42 /* an incoming handshake record and takes appropriate action to */
43 /* advance the TLS Server handshake. */
44 /* */
45 /* INPUT */
46 /* */
47 /* tls_session TLS control block */
48 /* packet_buffer Pointer into record buffer */
49 /* wait_option Controls timeout actions */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* status Completion status */
54 /* */
55 /* CALLS */
56 /* */
57 /* _nx_secure_tls_allocate_handshake_packet */
58 /* Allocate TLS packet */
59 /* _nx_secure_tls_generate_keys Generate session keys */
60 /* _nx_secure_tls_handshake_hash_init Initialize Finished hash */
61 /* _nx_secure_tls_handshake_hash_update Update Finished hash */
62 /* _nx_secure_tls_packet_allocate Allocate internal TLS packet */
63 /* _nx_secure_tls_process_client_key_exchange */
64 /* Process ClientKeyExchange */
65 /* _nx_secure_tls_process_clienthello Process ClientHello */
66 /* _nx_secure_tls_process_finished Process Finished message */
67 /* _nx_secure_tls_process_handshake_header */
68 /* Process handshake header */
69 /* _nx_secure_tls_process_remote_certificate */
70 /* Process server certificate */
71 /* _nx_secure_tls_send_certificate Send TLS certificate */
72 /* _nx_secure_tls_send_certificate_request */
73 /* Send TLS CertificateRequest */
74 /* _nx_secure_tls_send_changecipherspec Send ChangeCipherSpec */
75 /* _nx_secure_tls_send_finished Send Finished message */
76 /* _nx_secure_tls_send_handshake_record Send TLS handshake record */
77 /* _nx_secure_tls_send_record Send TLS records */
78 /* _nx_secure_tls_send_server_key_exchange */
79 /* Send ServerKeyExchange */
80 /* _nx_secure_tls_send_serverhello Send TLS ServerHello */
81 /* _nx_secure_tls_session_keys_set Set session keys */
82 /* nx_secure_tls_packet_release Release packet */
83 /* tx_mutex_get Get protection mutex */
84 /* tx_mutex_put Put protection mutex */
85 /* */
86 /* CALLED BY */
87 /* */
88 /* _nx_secure_tls_process_record Process TLS record data */
89 /* */
90 /* RELEASE HISTORY */
91 /* */
92 /* DATE NAME DESCRIPTION */
93 /* */
94 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
95 /* 09-30-2020 Timothy Stapko Modified comment(s), */
96 /* released packet securely, */
97 /* fixed certificate buffer */
98 /* allocation, */
99 /* resulting in version 6.1 */
100 /* 12-31-2020 Timothy Stapko Modified comment(s), */
101 /* improved buffer length */
102 /* verification, */
103 /* resulting in version 6.1.3 */
104 /* 02-02-2021 Timothy Stapko Modified comment(s), added */
105 /* support for fragmented TLS */
106 /* Handshake messages, */
107 /* resulting in version 6.1.4 */
108 /* 07-29-2022 Yuxin Zhou Modified comment(s), */
109 /* removed duplicated alert, */
110 /* resulting in version 6.1.12 */
111 /* 10-31-2022 Yanwu Cai Modified comment(s), */
112 /* fixed handling of multiple */
113 /* handshake messages, */
114 /* resulting in version 6.2.0 */
115 /* */
116 /**************************************************************************/
_nx_secure_tls_server_handshake(NX_SECURE_TLS_SESSION * tls_session,UCHAR * packet_buffer,UINT data_length,ULONG wait_option)117 UINT _nx_secure_tls_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer,
118 UINT data_length, ULONG wait_option)
119 {
120 #ifndef NX_SECURE_TLS_SERVER_DISABLED
121 UINT status;
122 UINT temp_status;
123 USHORT message_type;
124 UINT header_bytes;
125 UINT message_length;
126 NX_PACKET *send_packet;
127 NX_PACKET_POOL *packet_pool;
128 UCHAR *packet_start;
129 const NX_CRYPTO_METHOD *method_ptr = NX_NULL;
130
131 /* Basic state machine for handshake:
132 * 1. We have received a handshake message, now process the header.
133 * 2. Then process the message itself and populate the TLS socket structure.
134 * 3. Follow up with whatever actions are needed.
135 */
136
137 /* Loop through multiple messages in a single record. This can happen if the remote host
138 packs multiple handshake messages into a single TLS record. */
139 while (data_length > 0)
140 {
141
142 /* Save a pointer to the start of our packet for the hash that happens below. */
143 packet_start = packet_buffer;
144
145 header_bytes = data_length;
146
147 status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length);
148
149 if (status != NX_SECURE_TLS_SUCCESS)
150 {
151 return(status);
152 }
153
154 /* Check for fragmented message. */
155 if((message_length + header_bytes) > data_length)
156 {
157 /* Incomplete message! A single message is fragmented across several records. We need to obtain the next fragment. */
158 tls_session -> nx_secure_tls_handshake_record_expected_length = message_length + header_bytes;
159
160 tls_session -> nx_secure_tls_handshake_record_fragment_state = NX_SECURE_TLS_HANDSHAKE_RECEIVED_FRAGMENT;
161
162 return(NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED);
163 }
164
165 /* Advance the buffer pointer past the handshake header. */
166 packet_buffer += header_bytes;
167
168 /* Get reference to the packet pool so we can allocate a packet for all send operations. */
169 packet_pool = tls_session -> nx_secure_tls_packet_pool;
170
171 /* We need to hash all of the handshake messages that we receive and send. If this message is a ClientHello,
172 then we need to initialize the hashes (TLS 1.1 uses both MD5 and SHA-1). The final hash is generated
173 in the "Finished" message. */
174 if (message_type == NX_SECURE_TLS_CLIENT_HELLO)
175 {
176 /* Initialize the handshake hashes used for the Finished message. */
177 _nx_secure_tls_handshake_hash_init(tls_session);
178 }
179
180 /* Reduce total length by the size of this message. */
181 data_length -= (message_length + header_bytes);
182
183 /* Process the message itself information from the header. */
184 status = NX_SECURE_TLS_SUCCESS;
185 switch (message_type)
186 {
187 case NX_SECURE_TLS_CLIENT_HELLO:
188 /* Client is establishing a TLS session with our server. */
189 status = _nx_secure_tls_process_clienthello(tls_session, packet_buffer, message_length);
190 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_SEND_HELLO;
191 break;
192 #ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY
193 case NX_SECURE_TLS_CERTIFICATE_MSG:
194 /* Client sent certificate message (in response to a request from us. Process it now. */
195 status = _nx_secure_tls_process_remote_certificate(tls_session, packet_buffer, message_length, data_length);
196 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE;
197 break;
198 case NX_SECURE_TLS_CERTIFICATE_VERIFY:
199 /* Client has responded to a certificate request with a CertificateVerify message. */
200 status = _nx_secure_tls_process_certificate_verify(tls_session, packet_buffer, message_length);
201
202 if(status == NX_SUCCESS)
203 {
204 /* If remote certificate verification was a success, we have received credentials
205 from the remote host and may now pass Finished message processing once received. */
206 tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE;
207 }
208
209 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY;
210 break;
211 #endif /* NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY */
212 case NX_SECURE_TLS_CLIENT_KEY_EXCHANGE:
213 /* Received a client key exchange message, meaning it is time to generate keys if we can. */
214 status = _nx_secure_tls_process_client_key_exchange(tls_session, packet_buffer, message_length, NX_SECURE_TLS);
215 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE;
216
217 if (status == NX_SECURE_TLS_SUCCESS)
218 {
219 /* Generate our key material from the data collected thus far and put it all into our
220 socket structure. */
221 status = _nx_secure_tls_generate_keys(tls_session);
222 }
223 break;
224 case NX_SECURE_TLS_FINISHED:
225 /* Final handshake message from the client, process it (verify the client handshake hash). */
226 status = _nx_secure_tls_process_finished(tls_session, packet_buffer, message_length);
227 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE;
228 break;
229 case NX_SECURE_TLS_HELLO_VERIFY_REQUEST:
230 case NX_SECURE_TLS_HELLO_REQUEST:
231 case NX_SECURE_TLS_SERVER_HELLO:
232 case NX_SECURE_TLS_SERVER_KEY_EXCHANGE:
233 case NX_SECURE_TLS_CERTIFICATE_REQUEST:
234 case NX_SECURE_TLS_SERVER_HELLO_DONE:
235 case NX_SECURE_TLS_CERTIFICATE_URL:
236 case NX_SECURE_TLS_CERTIFICATE_STATUS:
237 default:
238 /* The message received was not a valid TLS server handshake message, send alert and return. */
239 status = NX_SECURE_TLS_UNEXPECTED_MESSAGE;
240 break;
241 }
242
243 /* Check for errors in processing messages. */
244 if (status != NX_SECURE_TLS_SUCCESS)
245 {
246 /* If we encountered an error in message processing set the state to the error condition. */
247 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_ERROR;
248 }
249 else
250 {
251 /* Hash this handshake message. We do not hash HelloRequest messages, but since only the server will send them,
252 we do not worry about them here because these are only messages received from the client at this point.
253 Hashes include the handshake layer header but not the record layer header. */
254 _nx_secure_tls_handshake_hash_update(tls_session, packet_start, (UINT)(message_length + header_bytes));
255 }
256
257 /* Now take any actions based on state set in the message processing. */
258 switch (tls_session -> nx_secure_tls_server_state)
259 {
260 case NX_SECURE_TLS_SERVER_STATE_SEND_HELLO:
261 /* We have received and processed a client hello. Now respond to the client appropriately. */
262 status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
263
264 if (status != NX_SUCCESS)
265 {
266 break;
267 }
268
269 status = _nx_secure_tls_send_serverhello(tls_session, send_packet);
270
271 if (status != NX_SUCCESS)
272 {
273 break;
274 }
275
276 status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO, wait_option);
277
278 if (status != NX_SUCCESS)
279 {
280 break;
281 }
282
283 NX_ASSERT(tls_session -> nx_secure_tls_session_ciphersuite != NX_NULL);
284
285 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
286 /* For PSK ciphersuites, don't send the certificate message. */
287 if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm != NX_CRYPTO_KEY_EXCHANGE_PSK)
288 {
289 #endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */
290 status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
291
292 if (status != NX_SUCCESS)
293 {
294 break;
295 }
296
297 _nx_secure_tls_send_certificate(tls_session, send_packet, wait_option);
298 status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_MSG, wait_option);
299 if (status != NX_SUCCESS)
300 {
301 break;
302 }
303
304 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
305 }
306 #endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */
307
308 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) || defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES)
309 if (NX_FALSE
310 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
311 || tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE
312 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
313 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
314 || tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK
315 #endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */
316 )
317 {
318 /* PSK and ECDHE ciphersuites use the ServerKeyExchange message to send cryptographic information. */
319 status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
320
321 if (status != NX_SUCCESS)
322 {
323 break;
324 }
325
326 /* This is a PSK ciphersuite so we always send a ServerKeyExchange message. */
327 status = _nx_secure_tls_send_server_key_exchange(tls_session, send_packet);
328 if (status != NX_SUCCESS)
329 {
330 break;
331 }
332
333 status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_KEY_EXCHANGE, wait_option);
334 if (status != NX_SUCCESS)
335 {
336 break;
337 }
338 }
339 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE || NX_CRYPTO_KEY_EXCHANGE_PSK */
340
341 #ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY
342 /* Application has requested that we request and verify the remote Client certificate. */
343 if (tls_session -> nx_secure_tls_verify_client_certificate)
344 {
345 /* Allocate a packet for our certificate request message. */
346 status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
347
348 if (status != NX_SUCCESS)
349 {
350 break;
351 }
352
353 /* Populate our packet with the desired message (CertificateRequest). */
354 status = _nx_secure_tls_send_certificate_request(tls_session, send_packet);
355 NX_ASSERT(status == NX_SUCCESS);
356
357 status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_REQUEST, wait_option);
358 if (status != NX_SUCCESS)
359 {
360 break;
361 }
362 }
363 else
364 #endif
365 {
366 /* Server is not expecting credentials, so indicate that we have received the client's credentials
367 to pass Finished processing. */
368 tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE;
369 }
370 /* Allocate a new packet for the ServerHelloDone. */
371 status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
372
373 if (status != NX_SUCCESS)
374 {
375 break;
376 }
377
378 /* Server hello done message is 0 bytes, but it still has a TLS header so don't modify the length here. */
379 status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO_DONE, wait_option);
380
381 if (status != NX_SUCCESS)
382 {
383 break;
384 }
385
386
387 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HELLO_SENT;
388
389 break;
390 case NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE:
391 /* We processed the certificate above, do nothing. */
392 break;
393 case NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY:
394 /* We processed the certificate above, do nothing. */
395 break;
396 case NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE:
397 break;
398 case NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE:
399
400 /* Release the protection before suspending on nx_packet_allocate. */
401 tx_mutex_put(&_nx_secure_tls_protection);
402
403 /* We have received everything we need to complete the handshake and keys have been
404 * generated above. Now end the handshake with a ChangeCipherSpec (indicating following
405 * messages are encrypted) and the encrypted Finished message. */
406
407 status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option);
408
409 /* Get the protection after nx_packet_allocate. */
410 tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
411
412 if (status != NX_SUCCESS)
413 {
414 break;
415 }
416
417 _nx_secure_tls_send_changecipherspec(tls_session, send_packet);
418
419 /* ChangeCipherSpec is NOT a handshake message, so send as a normal TLS record. */
420 status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_CHANGE_CIPHER_SPEC, wait_option);
421
422 if (status != NX_SUCCESS)
423 {
424 nx_secure_tls_packet_release(send_packet);
425 break;
426 }
427
428 /* Reset the sequence number now that we are starting a new session. */
429 NX_SECURE_MEMSET(tls_session -> nx_secure_tls_local_sequence_number, 0, sizeof(tls_session -> nx_secure_tls_local_sequence_number));
430
431 /* The local session is now active since we sent the changecipherspec message.
432 NOTE: Do not set the keys until after the changecipherspec message has been passed to the send record
433 routine - this call causes encryption and hashing to happen on records. ChangeCipherSpec should be the last
434 un-encrypted/un-hashed record sent. For a renegotiation handshake, CCS is the last message encrypted using
435 the original session keys. */
436
437 /* Set our local session keys since we sent a CCS message. */
438 status = _nx_secure_tls_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_LOCAL);
439
440 if (status != NX_SUCCESS)
441 {
442 break;
443 }
444
445 /* We processed the incoming finished message above, so now we can send our own finished message. */
446 status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option);
447 if (status != NX_SUCCESS)
448 {
449 break;
450 }
451
452 _nx_secure_tls_send_finished(tls_session, send_packet);
453 status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_FINISHED, wait_option);
454
455 /* For server, cleanup hash handler after sent the finished message to server. */
456 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
457 method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method;
458
459 if (method_ptr -> nx_crypto_cleanup != NX_NULL)
460 {
461 temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata);
462 if(temp_status != NX_CRYPTO_SUCCESS)
463 {
464 status = temp_status;
465 }
466
467 }
468 #endif /* (NX_SECURE_TLS_TLS_1_2_ENABLED) */
469
470 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
471 method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
472 if (method_ptr != NX_NULL && method_ptr -> nx_crypto_cleanup != NX_NULL)
473 {
474 temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata);
475 if(temp_status != NX_CRYPTO_SUCCESS)
476 {
477 status = temp_status;
478 }
479
480 }
481
482 method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
483 if (method_ptr != NX_NULL && method_ptr -> nx_crypto_cleanup != NX_NULL)
484 {
485 temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata);
486 if(temp_status != NX_CRYPTO_SUCCESS)
487 {
488 status = temp_status;
489 }
490
491 }
492 #endif /* (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) */
493
494 tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED;
495
496 break;
497 default: /* NX_SECURE_TLS_SERVER_STATE_ERROR */
498 /* Default is to break out of the switch because either we encountered an error or
499 we are in an invalid state. DO NOT change the value of "status" here because
500 we need its value in the alert processing below. NOTE: we should never
501 get to this branch with status == NX_SUCCESS because the state will only
502 be set to NX_SECURE_TLS_SERVER_STATE_ERROR if status indicates an error. */
503 NX_ASSERT(status != NX_SUCCESS);
504 break;
505 }
506
507 /* If we have an error at this point, we have experienced a problem in sending
508 handshake messages, which is some type of internal issue. */
509 if (status != NX_SUCCESS)
510 {
511
512 return(status);
513 }
514
515 /* Advance the buffer pointer past the message. */
516 packet_buffer += message_length;
517 } /* End while. */
518
519 return(NX_SUCCESS);
520 #else /* TLS Server disabled. */
521
522 /* We don't use the parameters since this is an error case. */
523 NX_PARAMETER_NOT_USED(packet_buffer);
524 NX_PARAMETER_NOT_USED(wait_option);
525 NX_PARAMETER_NOT_USED(data_length);
526
527 /* If TLS Server is disabled and we are in the server state machine, something is wrong... */
528 tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_ERROR;
529 return(NX_SECURE_TLS_INVALID_STATE);
530 #endif
531 }
532
533