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
27 /**************************************************************************/
28 /* */
29 /* FUNCTION RELEASE */
30 /* */
31 /* _nx_secure_generate_server_key_exchange PORTABLE C */
32 /* 6.2.0 */
33 /* AUTHOR */
34 /* */
35 /* Yanwu Cai, Microsoft Corporation */
36 /* */
37 /* DESCRIPTION */
38 /* */
39 /* This function generates a ServerKeyExchange message, which is used */
40 /* when the chosen ciphersuite requires additional information for key */
41 /* generation, such as when using Diffie-Hellman ciphers. */
42 /* */
43 /* INPUT */
44 /* */
45 /* ciphersuite Selected cipher suite */
46 /* protocol_version Selected TLS version */
47 /* tls_1_3 Whether TLS 1.3 is chosen */
48 /* tls_crypto_table TLS crypto methods */
49 /* tls_handshake_hash Metadata for handshake hash */
50 /* tls_key_material TLS key material */
51 /* tls_credentials TLS credentials */
52 /* data_buffer Pointer to output buffer */
53 /* buffer_length Length of data buffer */
54 /* output_size Size of data written to buffer*/
55 /* public_cipher_metadata Metadata for public cipher */
56 /* public_cipher_metadata_size Size of public cipher metadata*/
57 /* public_auth_metadata Metadata for public auth */
58 /* public_auth_metadata_size Size of public auth metadata */
59 /* tls_ecc_curves ECC curves */
60 /* */
61 /* OUTPUT */
62 /* */
63 /* status Completion status */
64 /* */
65 /* CALLS */
66 /* */
67 /* _nx_secure_tls_ecc_generate_keys Generate keys for ECC exchange*/
68 /* [nx_crypto_init] Initialize Crypto Method */
69 /* [nx_crypto_operation] Crypto operation */
70 /* */
71 /* CALLED BY */
72 /* */
73 /* _nx_secure_tls_send_server_key_exchange */
74 /* Send ServerKeyExchange */
75 /* */
76 /* RELEASE HISTORY */
77 /* */
78 /* DATE NAME DESCRIPTION */
79 /* */
80 /* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */
81 /* */
82 /**************************************************************************/
_nx_secure_generate_server_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO * ciphersuite,USHORT protocol_version,UCHAR tls_1_3,NX_SECURE_TLS_CRYPTO * tls_crypto_table,NX_SECURE_TLS_HANDSHAKE_HASH * tls_handshake_hash,NX_SECURE_TLS_KEY_MATERIAL * tls_key_material,NX_SECURE_TLS_CREDENTIALS * tls_credentials,UCHAR * data_buffer,ULONG buffer_length,ULONG * output_size,VOID * public_cipher_metadata,ULONG public_cipher_metadata_size,VOID * public_auth_metadata,ULONG public_auth_metadata_size,VOID * tls_ecc_curves)83 UINT _nx_secure_generate_server_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, UCHAR tls_1_3,
84 NX_SECURE_TLS_CRYPTO *tls_crypto_table, NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash,
85 NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials,
86 UCHAR *data_buffer, ULONG buffer_length, ULONG *output_size,
87 VOID *public_cipher_metadata, ULONG public_cipher_metadata_size,
88 VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves)
89 {
90 UINT length;
91
92 #if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE)
93 UINT status;
94 #endif /* defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) */
95
96 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
97 USHORT identity_length;
98 UCHAR *identity;
99 #endif
100
101 #if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE)
102 VOID *handler = NX_NULL;
103 USHORT named_curve;
104 NX_CRYPTO_METHOD *crypto_method;
105 NX_CRYPTO_EXTENDED_OUTPUT extended_output;
106 #endif /* defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) */
107
108 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
109 NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data;
110 #endif
111
112
113 /* Build up the server key exchange message. Structure:
114 * | 2 | <key data length> |
115 * | Key data length | Key data (opaque) |
116 */
117
118 #ifndef NX_SECURE_ENABLE_ECC_CIPHERSUITE
119 NX_PARAMETER_NOT_USED(ciphersuite);
120 NX_PARAMETER_NOT_USED(protocol_version);
121 NX_PARAMETER_NOT_USED(tls_1_3);
122 NX_PARAMETER_NOT_USED(tls_crypto_table);
123 NX_PARAMETER_NOT_USED(tls_handshake_hash);
124 NX_PARAMETER_NOT_USED(tls_key_material);
125 NX_PARAMETER_NOT_USED(tls_credentials);
126 NX_PARAMETER_NOT_USED(data_buffer);
127 NX_PARAMETER_NOT_USED(buffer_length);
128 NX_PARAMETER_NOT_USED(public_cipher_metadata);
129 NX_PARAMETER_NOT_USED(public_cipher_metadata_size);
130 NX_PARAMETER_NOT_USED(public_auth_metadata);
131 NX_PARAMETER_NOT_USED(public_auth_metadata_size);
132 NX_PARAMETER_NOT_USED(tls_ecc_curves);
133 #endif
134
135 length = 0;
136
137 /* In the future, any Diffie-Hellman-based ciphersuites will populate this message with key
138 data. RSA ciphersuites do not use this message. */
139
140 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
141
142 /* Check for PSK ciphersuites. */
143 if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK)
144 {
145 /* If PSK is being used, the server sends an identity value to the client so
146 the client can respond with the appropriate PSK. */
147
148 /* Get identity hint and length. */
149 identity = tls_credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_id_hint;
150 identity_length = (USHORT)tls_credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_id_hint_size;
151
152 if ((identity_length + 2u) > buffer_length)
153 {
154
155 /* Packet buffer too small. */
156 return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
157 }
158
159 /* Use identity hint length for key data length. */
160 data_buffer[length] = (UCHAR)((identity_length & 0xFF00) >> 8);
161 data_buffer[length + 1] = (UCHAR)(identity_length & 0x00FF);
162 length = (USHORT)(length + 2);
163
164 /* Extract the identity hint and put it into the packet buffer. */
165 NX_SECURE_MEMCPY(&data_buffer[length], identity, identity_length); /* Use case of memcpy is verified. */
166
167 /* Advance our total length. */
168 length = (USHORT)(length + identity_length);
169 }
170 #endif
171
172 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
173
174 /* Check for ECJ-PAKE ciphersuites. */
175 if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE)
176 {
177
178 if (buffer_length < 3)
179 {
180
181 /* Packet buffer too small. */
182 return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
183 }
184
185 /* ECCurveType: named_curve (3). */
186 data_buffer[length] = NX_CRYPTO_EC_CURVE_TYPE_NAMED_CURVE;
187 length += 1;
188
189 /* NamedCurve: secp256r1 (23) */
190 named_curve = (USHORT)NX_CRYPTO_EC_SECP256R1;
191 data_buffer[length] = (UCHAR)((named_curve >> 8) & 0xFF);
192 data_buffer[length + 1] = (UCHAR)(named_curve & 0xFF);
193 length += 2;
194
195 extended_output.nx_crypto_extended_output_data = &data_buffer[length];
196 extended_output.nx_crypto_extended_output_length_in_byte = buffer_length - length;
197 extended_output.nx_crypto_extended_output_actual_size = 0;
198
199 crypto_method = (NX_CRYPTO_METHOD*)ciphersuite -> nx_secure_tls_public_auth;
200 status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_SERVER_KEY_EXCHANGE_GENERATE,
201 handler,
202 crypto_method,
203 NX_NULL, 0,
204 NX_NULL, 0, NX_NULL,
205 (UCHAR *)&extended_output,
206 sizeof(extended_output),
207 public_auth_metadata,
208 public_auth_metadata_size,
209 NX_NULL, NX_NULL);
210 if (status)
211 {
212 return(status);
213 }
214 length += extended_output.nx_crypto_extended_output_actual_size;
215 }
216 #endif
217
218 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
219 /* Check for ECDHE ciphersuites. */
220 if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE)
221 {
222 ecdhe_data = (NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *)tls_key_material -> nx_secure_tls_new_key_material_data;
223
224 length = buffer_length;
225
226 status = _nx_secure_tls_ecc_generate_keys(ciphersuite, protocol_version, tls_1_3,
227 tls_crypto_table, tls_handshake_hash, (NX_SECURE_TLS_ECC *)tls_ecc_curves,
228 tls_key_material, tls_credentials, ecdhe_data -> nx_secure_tls_ecdhe_named_curve, NX_TRUE,
229 data_buffer, &length, ecdhe_data, public_cipher_metadata, public_cipher_metadata_size,
230 public_auth_metadata, public_auth_metadata_size);
231
232 if (status != NX_SUCCESS)
233 {
234 return(status);
235 }
236 }
237 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
238
239
240 /* Finally, we let the caller know the length . */
241 *output_size = length;
242
243 return(NX_SECURE_TLS_SUCCESS);
244 }
245
246