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 /**************************************************************************/
27 /*                                                                        */
28 /*  FUNCTION                                               RELEASE        */
29 /*                                                                        */
30 /*    _nx_secure_generate_premaster_secret                PORTABLE C      */
31 /*                                                           6.2.1        */
32 /*  AUTHOR                                                                */
33 /*                                                                        */
34 /*    Yanwu Cai, Microsoft Corporation                                    */
35 /*                                                                        */
36 /*  DESCRIPTION                                                           */
37 /*                                                                        */
38 /*    This function generates the Pre-Master Secret for TLS Client        */
39 /*    instances. It is sent to the remote host and used as the seed for   */
40 /*    session key generation.                                             */
41 /*                                                                        */
42 /*  INPUT                                                                 */
43 /*                                                                        */
44 /*    ciphersuite                           Selected cipher suite         */
45 /*    protocol_version                      Selected TLS version          */
46 /*    tls_key_material                      TLS key material              */
47 /*    tls_credentials                       TLS credentials               */
48 /*    session_type                          Server or client session      */
49 /*    received_remote_credentials           Indicates credentials received*/
50 /*    public_cipher_metadata                Metadata for public cipher    */
51 /*    public_cipher_metadata_size           Size of public cipher metadata*/
52 /*    tls_ecc_curves                        ECC curves                    */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    status                                Completion status             */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    _nx_secure_tls_psk_find               Find PSK from store           */
61 /*    _nx_secure_tls_find_curve_method      Find named curve used         */
62 /*    [nx_crypto_init]                      Initialize crypto             */
63 /*    [nx_crypto_operation]                 Crypto operation              */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    _nx_secure_tls_generate_premaster_secret                            */
68 /*                                          Generate pre-master secret    */
69 /*                                                                        */
70 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  10-31-2022     Yanwu Cai                Initial Version 6.2.0         */
75 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
76 /*                                            fixed compiler errors when  */
77 /*                                            x509 is disabled,           */
78 /*                                            resulting in version 6.2.1  */
79 /*                                                                        */
80 /**************************************************************************/
_nx_secure_generate_premaster_secret(const NX_SECURE_TLS_CIPHERSUITE_INFO * ciphersuite,USHORT protocol_version,NX_SECURE_TLS_KEY_MATERIAL * tls_key_material,NX_SECURE_TLS_CREDENTIALS * tls_credentials,UINT session_type,USHORT * received_remote_credentials,VOID * public_cipher_metadata,ULONG public_cipher_metadata_size,VOID * tls_ecc_curves)81 UINT _nx_secure_generate_premaster_secret(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material,
82                                           NX_SECURE_TLS_CREDENTIALS *tls_credentials, UINT session_type, USHORT *received_remote_credentials,
83                                           VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, VOID *tls_ecc_curves)
84 {
85 UINT                      *buffer_ptr;
86 UINT                       i;
87 UINT                       status = NX_SECURE_TLS_SUCCESS;
88 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
89 UCHAR                     *psk_data;
90 UINT                       psk_length;
91 UINT                       index;
92 #endif
93 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
94 NX_SECURE_X509_CERT       *server_certificate;
95 const NX_CRYPTO_METHOD    *curve_method_cert;
96 const NX_CRYPTO_METHOD    *ecdh_method;
97 NX_SECURE_EC_PUBLIC_KEY   *ec_pubkey;
98 VOID                      *handler = NX_NULL;
99 NX_CRYPTO_EXTENDED_OUTPUT  extended_output;
100 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
101 
102 #if !defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) || defined(NX_SECURE_DISABLE_X509)
103     NX_PARAMETER_NOT_USED(public_cipher_metadata);
104     NX_PARAMETER_NOT_USED(public_cipher_metadata_size);
105     NX_PARAMETER_NOT_USED(tls_ecc_curves);
106 #endif
107 #ifndef NX_SECURE_ENABLE_PSK_CIPHERSUITES
108     NX_PARAMETER_NOT_USED(session_type);
109     NX_PARAMETER_NOT_USED(ciphersuite);
110     NX_PARAMETER_NOT_USED(tls_credentials);
111     NX_PARAMETER_NOT_USED(public_cipher_metadata);
112     NX_PARAMETER_NOT_USED(public_cipher_metadata_size);
113     NX_PARAMETER_NOT_USED(tls_ecc_curves);
114 #ifndef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
115     NX_PARAMETER_NOT_USED(received_remote_credentials);
116 #endif
117 #endif
118 
119 #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
120     if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE)
121     {
122 
123         return(NX_SECURE_TLS_SUCCESS);
124     }
125     else if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH)
126     {
127         /* Get reference to remote server certificate so we can find out the named curve. */
128         status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store,
129                                                                  &server_certificate);
130         if (status)
131         {
132             /* No certificate found, error! */
133             return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND);
134         }
135 
136         ec_pubkey = &server_certificate -> nx_secure_x509_public_key.ec_public_key;
137 
138         /* Find out which named curve the remote certificate is using. */
139         status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL);
140 
141         if(status != NX_SUCCESS)
142         {
143             return(status);
144         }
145 
146         ecdh_method = ciphersuite -> nx_secure_tls_public_cipher;
147         if (ecdh_method -> nx_crypto_operation == NX_NULL)
148         {
149             return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
150         }
151 
152         if (ecdh_method -> nx_crypto_init != NX_NULL)
153         {
154             status = ecdh_method -> nx_crypto_init((NX_CRYPTO_METHOD*)ecdh_method,
155                                                    NX_NULL,
156                                                    0,
157                                                    &handler,
158                                                    public_cipher_metadata,
159                                                    public_cipher_metadata_size);
160             if(status != NX_CRYPTO_SUCCESS)
161             {
162                 return(status);
163             }
164         }
165 
166         status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
167                                                     (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0,
168                                                     (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
169                                                     NX_NULL, 0,
170                                                     public_cipher_metadata,
171                                                     public_cipher_metadata_size,
172                                                     NX_NULL, NX_NULL);
173         if (status != NX_CRYPTO_SUCCESS)
174         {
175             return(status);
176         }
177 
178         /* Store public key in the nx_secure_tls_new_key_material_data. */
179         extended_output.nx_crypto_extended_output_data = &tls_key_material -> nx_secure_tls_new_key_material_data[1];
180         extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_new_key_material_data) - 1;
181         extended_output.nx_crypto_extended_output_actual_size = 0;
182         status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_SETUP, handler,
183                                                     (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0,
184                                                     NX_NULL, 0, NX_NULL,
185                                                     (UCHAR *)&extended_output,
186                                                     sizeof(extended_output),
187                                                     public_cipher_metadata,
188                                                     public_cipher_metadata_size,
189                                                     NX_NULL, NX_NULL);
190         if (status != NX_CRYPTO_SUCCESS)
191         {
192             return(status);
193         }
194 
195         tls_key_material -> nx_secure_tls_new_key_material_data[0] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size;
196 
197         extended_output.nx_crypto_extended_output_data = tls_key_material -> nx_secure_tls_pre_master_secret;
198         extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_pre_master_secret);
199         extended_output.nx_crypto_extended_output_actual_size = 0;
200         status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler,
201                                                     (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0,
202                                                     (UCHAR *)ec_pubkey -> nx_secure_ec_public_key,
203                                                     ec_pubkey -> nx_secure_ec_public_key_length, NX_NULL,
204                                                     (UCHAR *)&extended_output,
205                                                     sizeof(extended_output),
206                                                     public_cipher_metadata,
207                                                     public_cipher_metadata_size,
208                                                     NX_NULL, NX_NULL);
209         if (status != NX_CRYPTO_SUCCESS)
210         {
211             return(status);
212         }
213 
214         tls_key_material -> nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size;
215 
216         if (ecdh_method -> nx_crypto_cleanup)
217         {
218             status = ecdh_method -> nx_crypto_cleanup(public_cipher_metadata);
219             if(status != NX_CRYPTO_SUCCESS)
220             {
221                 return(status);
222             }
223         }
224 
225         return(NX_SECURE_TLS_SUCCESS);
226     }
227 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
228 
229 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
230     /* Check for PSK ciphersuites. */
231     if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK)
232     {
233         /* Now, using the identity as a key, find the PSK in our PSK store. */
234         if (session_type == NX_SECURE_TLS_SESSION_TYPE_SERVER)
235         {
236             /* Server just uses its PSK. */
237             psk_data = tls_credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_data;
238             psk_length = tls_credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_data_size;
239         }
240         else
241         {
242             /*  Client has to search for the PSK based on the identity hint. */
243             status = _nx_secure_tls_psk_find(tls_credentials, &psk_data, &psk_length, tls_credentials -> nx_secure_tls_remote_psk_id,
244                                              tls_credentials -> nx_secure_tls_remote_psk_id_size, NX_NULL);
245 
246             if (status != NX_SUCCESS)
247             {
248                 return(status);
249             }
250         }
251 
252         /* From RFC 4279:
253            The premaster secret is formed as follows: if the PSK is N octets
254            long, concatenate a uint16 with the value N, N zero octets, a second
255            uint16 with the value N, and the PSK itself.
256          |   2   |   <N>  |   2   |   <N>   |
257          |   N   |    0   |   N   |   PSK   |
258          */
259         index = 0;
260 
261         if ((2 + psk_length + 2 + psk_length) > sizeof(tls_key_material -> nx_secure_tls_pre_master_secret))
262         {
263 
264             /* No more PSK space. */
265             return(NX_SECURE_TLS_NO_MORE_PSK_SPACE);
266         }
267 
268         tls_key_material -> nx_secure_tls_pre_master_secret[0] = (UCHAR)(psk_length >> 8);
269         tls_key_material -> nx_secure_tls_pre_master_secret[1] = (UCHAR)psk_length;
270         index += 2;
271 
272         NX_SECURE_MEMSET(&tls_key_material -> nx_secure_tls_pre_master_secret[index], 0, psk_length);
273         index += psk_length;
274 
275         tls_key_material -> nx_secure_tls_pre_master_secret[index] = (UCHAR)(psk_length >> 8);
276         tls_key_material -> nx_secure_tls_pre_master_secret[index + 1] = (UCHAR)psk_length;
277         index += 2;
278 
279         NX_SECURE_MEMCPY(&tls_key_material -> nx_secure_tls_pre_master_secret[index], psk_data, psk_length); /* Use case of memcpy is verified. */
280         index += psk_length;
281 
282         /* Save the pre-master secret size for later use. */
283         tls_key_material -> nx_secure_tls_pre_master_secret_size = 2 + psk_length + 2 + psk_length;
284 
285         /* We are using PSK for our credentials and now that we have generated keys we can consider the
286            remote host's credentials to have been received. */
287         *received_remote_credentials = NX_TRUE;
288 
289         return(NX_SECURE_TLS_SUCCESS);
290     }
291 #endif
292 
293 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
294     /* When using ECJ-PAKE ciphersuite, pre-master secret is already generated. */
295     if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE)
296     {
297         /* If using EC-JPAKE, credentials are passed differently - if we get here credentials should be OK. */
298         *received_remote_credentials = NX_TRUE;
299 
300         return(NX_SECURE_TLS_SUCCESS);
301     }
302 #endif
303 
304     /* Generate the Pre-Master Secret that is used to generate the key material
305        used in the session. For TLS 1.1, the secret consists of two bytes
306        representing the highest protocol version the client supports, followed
307        by 46 random bytes. */
308     buffer_ptr = (UINT *)tls_key_material -> nx_secure_tls_pre_master_secret;
309 
310     /* Generate 48 bytes of random data, fill in the version afterwards. */
311     for (i = 0; i < 12; i++)
312     {
313         /* Fill with 12 ULONG randoms, then fix first two bytes to protocol version after. */
314         *(buffer_ptr + i) = (UINT)NX_RAND();
315     }
316 
317     /* First two bytes are newest version supported by client . */
318     buffer_ptr[0] = ((ULONG)protocol_version << 16) | (buffer_ptr[0] & 0x0000FFFF);
319     NX_CHANGE_ULONG_ENDIAN(buffer_ptr[0]);
320 
321     tls_key_material -> nx_secure_tls_pre_master_secret_size = 48;
322 
323     return(status);
324 }
325 
326