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