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 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
27 const UCHAR _nx_secure_tls_hello_retry_request_random[32] =
28 {
29 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
30 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
31 };
32
33 const UCHAR _nx_secure_tls_1_2_random[8] =
34 {
35 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x01
36 };
37
38 const UCHAR _nx_secure_tls_1_1_random[8] =
39 {
40 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x00
41 };
42 #endif
43
44 /**************************************************************************/
45 /* */
46 /* FUNCTION RELEASE */
47 /* */
48 /* _nx_secure_tls_send_serverhello PORTABLE C */
49 /* 6.1.9 */
50 /* AUTHOR */
51 /* */
52 /* Timothy Stapko, Microsoft Corporation */
53 /* */
54 /* DESCRIPTION */
55 /* */
56 /* This function generates a ServerHello message, which is used to */
57 /* respond to an incoming ClientHello message and provide the remote */
58 /* TLS Client with the chosen ciphersuite and key generation data. */
59 /* */
60 /* INPUT */
61 /* */
62 /* tls_session TLS control block */
63 /* send_packet Packet used to send message */
64 /* */
65 /* OUTPUT */
66 /* */
67 /* status Completion status */
68 /* */
69 /* CALLS */
70 /* */
71 /* _nx_secure_tls_send_serverhello_extensions */
72 /* Send TLS ServerHello extension*/
73 /* */
74 /* CALLED BY */
75 /* */
76 /* _nx_secure_tls_server_handshake TLS server state machine */
77 /* */
78 /* RELEASE HISTORY */
79 /* */
80 /* DATE NAME DESCRIPTION */
81 /* */
82 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
83 /* 09-30-2020 Timothy Stapko Modified comment(s), improved */
84 /* buffer length verification, */
85 /* verified memcpy use cases, */
86 /* resulting in version 6.1 */
87 /* 10-15-2021 Timothy Stapko Modified comment(s), fixed */
88 /* compilation issue with */
89 /* TLS 1.3 and disabling TLS */
90 /* server, */
91 /* resulting in version 6.1.9 */
92 /* */
93 /**************************************************************************/
_nx_secure_tls_send_serverhello(NX_SECURE_TLS_SESSION * tls_session,NX_PACKET * send_packet)94 UINT _nx_secure_tls_send_serverhello(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet)
95 {
96 #ifndef NX_SECURE_TLS_SERVER_DISABLED
97 ULONG length;
98 UINT gmt_time;
99 UINT random_value;
100 UINT i;
101 USHORT ciphersuite;
102 UCHAR *packet_buffer;
103 USHORT protocol_version;
104 UINT status;
105
106
107 /* Build up the ServerHello message.
108 * Structure:
109 * | 2 | 4 + 28 | 1 | <SID len> | 2 | 1 | 2 | <Ext. Len> |
110 * | TLS version | Random (time + random) | SID length | Session ID | Ciphersuite | Compression | Ext. Len | Extensions |
111 */
112
113 if ((6u + sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random)) >
114 ((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)))
115
116 {
117
118 /* Packet buffer is too small to hold random. */
119 return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
120 }
121
122 packet_buffer = send_packet -> nx_packet_append_ptr;
123
124 /* Use our length as an index into the buffer. */
125 length = 0;
126
127 /* First two bytes of the hello following the header are the TLS major and minor version numbers. */
128 protocol_version = tls_session -> nx_secure_tls_protocol_version;
129
130 packet_buffer[length] = (UCHAR)((protocol_version & 0xFF00) >> 8);
131 packet_buffer[length + 1] = (UCHAR)(protocol_version & 0x00FF);
132 length += 2;
133
134 /* Set the Server random data, used in key generation. First 4 bytes is GMT time. */
135 gmt_time = 0;
136 if (tls_session -> nx_secure_tls_session_time_function != NX_NULL)
137 {
138 gmt_time = tls_session -> nx_secure_tls_session_time_function();
139 }
140 NX_CHANGE_ULONG_ENDIAN(gmt_time);
141
142 NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, (UCHAR *)&gmt_time, sizeof(gmt_time)); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */
143
144 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
145 if (tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY)
146 {
147 NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random,
148 _nx_secure_tls_hello_retry_request_random,
149 sizeof(_nx_secure_tls_hello_retry_request_random)); /* Use case of memcpy is verified. */
150 }
151 else if (!(tls_session -> nx_secure_tls_1_3) && !(tls_session -> nx_secure_tls_protocol_version_override))
152 {
153 /* Next 20 bytes is random data. */
154 for (i = 4; i <= 20; i += (UINT)sizeof(random_value))
155 {
156 random_value = (UINT)NX_RAND();
157 tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[i] = (UCHAR)(random_value);
158 tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[i + 1] = (UCHAR)(random_value >> 8);
159 tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[i + 2] = (UCHAR)(random_value >> 16);
160 tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[i + 3] = (UCHAR)(random_value >> 24);
161 }
162
163 /* RFC 8446 4.1.3:
164 TLS 1.3 servers which negotiate TLS 1.2 or below in response to a ClientHello
165 MUST set the last 8 bytes of their Random value specially in their ServerHello. */
166 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
167 {
168 NX_SECURE_MEMCPY(&(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[24]),
169 _nx_secure_tls_1_2_random,
170 sizeof(_nx_secure_tls_1_2_random)); /* Use case of memcpy is verified. */
171 }
172 else
173 {
174 NX_SECURE_MEMCPY(&(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[24]),
175 _nx_secure_tls_1_1_random,
176 sizeof(_nx_secure_tls_1_1_random)); /* Use case of memcpy is verified. */
177 }
178 }
179 else
180 #endif
181 {
182
183 /* Next 28 bytes is random data. */
184 for (i = 4; i <= 28; i += (UINT)sizeof(random_value))
185 {
186 random_value = (UINT)NX_RAND();
187 tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[i] = (UCHAR)(random_value);
188 tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[i + 1] = (UCHAR)(random_value >> 8);
189 tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[i + 2] = (UCHAR)(random_value >> 16);
190 tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[i + 3] = (UCHAR)(random_value >> 24);
191 }
192 }
193
194 /* Copy the random data into the packet. */
195 NX_SECURE_MEMCPY(&packet_buffer[length], tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, /* lgtm[cpp/banned-api-usage-required-any] */
196 sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random)); /* Use case of memcpy is verified. */
197 length += sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random);
198
199 /* Session ID length is one byte. Session ID data follows if we ever implement session resumption. */
200 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
201 if(tls_session->nx_secure_tls_1_3)
202 {
203 /* TLS 1.3 doesn't use the session ID, but the Server must echo the server ID provided in the ClientHello
204 back to the client or the client will abort the handshake (RFC 8446, Section 4.1.3). */
205
206 packet_buffer[length] = tls_session->nx_secure_tls_session_id_length;
207 length++;
208
209 if ((length + tls_session->nx_secure_tls_session_id_length + 3) >
210 ((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)))
211 {
212
213 /* Packet buffer is too small to hold random. */
214 return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
215 }
216
217 NX_SECURE_MEMCPY(&packet_buffer[length], tls_session -> nx_secure_tls_session_id, tls_session->nx_secure_tls_session_id_length); /* Use case of memcpy is verified. */
218 length += tls_session->nx_secure_tls_session_id_length;
219 }
220 else
221 #endif
222 {
223 packet_buffer[length] = 0;
224 length++;
225 }
226 /* Finally, our chosen ciphersuite - this is selected when we receive the Client Hello. */
227 ciphersuite = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_ciphersuite;
228 packet_buffer[length] = (UCHAR)(ciphersuite >> 8);
229 packet_buffer[length + 1] = (UCHAR)ciphersuite;
230 length += 2;
231
232 /* Compression method - for now this is NULL. */
233 packet_buffer[length] = 0x0;
234 length++;
235
236 /* ============ TLS ServerHello extensions. ============= */
237 status = _nx_secure_tls_send_serverhello_extensions(tls_session, packet_buffer, &length,
238 ((ULONG)(send_packet -> nx_packet_data_end) -
239 (ULONG)packet_buffer));
240
241 if (status)
242 {
243 return(status);
244 }
245
246 /* Finally, we have a complete length and can put it into the buffer. Before that,
247 save off and return the number of bytes we wrote and need to send. */
248 send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_append_ptr + length;
249 send_packet -> nx_packet_length = send_packet -> nx_packet_length + length;
250
251 return(status);
252 #else
253
254 NX_PARAMETER_NOT_USED(send_packet);
255
256 /* If TLS Server is disabled and we have processed a ClientKeyExchange, something is wrong... */
257 tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_ERROR;
258
259 /* Server is disabled, we shouldn't be sending a ServerHello - error! */
260 return(NX_SECURE_TLS_INVALID_STATE);
261 #endif
262
263 }
264
265