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 Crypto Component                                                 */
16 /**                                                                       */
17 /**   Transport Layer Security (TLS)                                      */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 #include "nx_crypto_tls_prf_1.h"
24 
25 /**************************************************************************/
26 /*                                                                        */
27 /*  FUNCTION                                               RELEASE        */
28 /*                                                                        */
29 /*    _nx_crypto_method_prf_1_init                        PORTABLE C      */
30 /*                                                           6.3.0        */
31 /*  AUTHOR                                                                */
32 /*                                                                        */
33 /*    Timothy Stapko, Microsoft Corporation                               */
34 /*                                                                        */
35 /*  DESCRIPTION                                                           */
36 /*                                                                        */
37 /*    This function initializes the PRF crypto module with SHA-1.         */
38 /*                                                                        */
39 /*  INPUT                                                                 */
40 /*                                                                        */
41 /*    method                                Crypto Method Object          */
42 /*    key                                   Key                           */
43 /*    key_size_in_bits                      Size of the key, in bits      */
44 /*    handle                                Handle, specified by user     */
45 /*    crypto_metadata                       Metadata area                 */
46 /*    crypto_metadata_size                  Size of the metadata area     */
47 /*                                                                        */
48 /*  OUTPUT                                                                */
49 /*                                                                        */
50 /*    status                                Completion status             */
51 /*                                                                        */
52 /*  CALLS                                                                 */
53 /*                                                                        */
54 /*    None                                                                */
55 /*                                                                        */
56 /*  CALLED BY                                                             */
57 /*                                                                        */
58 /*    Application Code                                                    */
59 /*                                                                        */
60 /*  RELEASE HISTORY                                                       */
61 /*                                                                        */
62 /*    DATE              NAME                      DESCRIPTION             */
63 /*                                                                        */
64 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
65 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
66 /*                                            resulting in version 6.1    */
67 /*  10-31-2023     Yanwu Cai                Modified comment(s),          */
68 /*                                            resulting in version 6.3.0  */
69 /*                                                                        */
70 /**************************************************************************/
_nx_crypto_method_prf_1_init(struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,VOID ** handle,VOID * crypto_metadata,ULONG crypto_metadata_size)71 NX_CRYPTO_KEEP UINT  _nx_crypto_method_prf_1_init(struct NX_CRYPTO_METHOD_STRUCT *method,
72                                                   UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
73                                                   VOID **handle,
74                                                   VOID *crypto_metadata,
75                                                   ULONG crypto_metadata_size)
76 {
77 NX_CRYPTO_TLS_PRF_1 *prf;
78 NX_CRYPTO_PHASH *phash;
79 
80     NX_CRYPTO_PARAMETER_NOT_USED(handle);
81 
82     NX_CRYPTO_STATE_CHECK
83 
84     if ((method == NX_CRYPTO_NULL) || (key == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
85     {
86         return(NX_CRYPTO_PTR_ERROR);
87     }
88 
89     /* Verify the metadata address is 4-byte aligned. */
90     if((((ULONG)crypto_metadata) & 0x3) != 0)
91     {
92         return(NX_CRYPTO_PTR_ERROR);
93     }
94 
95     if(crypto_metadata_size < sizeof(NX_CRYPTO_TLS_PRF_1))
96     {
97         return(NX_CRYPTO_PTR_ERROR);
98     }
99 
100     /* Get our control block. */
101     prf = (NX_CRYPTO_TLS_PRF_1 *)crypto_metadata;
102     phash = &(prf -> nx_secure_tls_prf_phash_info);
103 
104     /* Set the secret using the key value. */
105     phash -> nx_crypto_phash_secret = key;
106     /* This is the length of secret in bytes actually */
107     phash -> nx_crypto_phash_secret_length = key_size_in_bits;
108 
109     return(NX_CRYPTO_SUCCESS);
110 }
111 
112 
113 /**************************************************************************/
114 /*                                                                        */
115 /*  FUNCTION                                               RELEASE        */
116 /*                                                                        */
117 /*    _nx_crypto_method_prf_1_cleanup                     PORTABLE C      */
118 /*                                                           6.1          */
119 /*  AUTHOR                                                                */
120 /*                                                                        */
121 /*    Timothy Stapko, Microsoft Corporation                               */
122 /*                                                                        */
123 /*  DESCRIPTION                                                           */
124 /*                                                                        */
125 /*    This function cleans up the crypto metadata.                        */
126 /*                                                                        */
127 /*  INPUT                                                                 */
128 /*                                                                        */
129 /*    crypto_metadata                       Crypto metadata               */
130 /*                                                                        */
131 /*  OUTPUT                                                                */
132 /*                                                                        */
133 /*    status                                Completion status             */
134 /*                                                                        */
135 /*  CALLS                                                                 */
136 /*                                                                        */
137 /*    NX_CRYPTO_MEMSET                      Set the memory                */
138 /*                                                                        */
139 /*  CALLED BY                                                             */
140 /*                                                                        */
141 /*    Application Code                                                    */
142 /*                                                                        */
143 /*  RELEASE HISTORY                                                       */
144 /*                                                                        */
145 /*    DATE              NAME                      DESCRIPTION             */
146 /*                                                                        */
147 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
148 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
149 /*                                            resulting in version 6.1    */
150 /*                                                                        */
151 /**************************************************************************/
_nx_crypto_method_prf_1_cleanup(VOID * crypto_metadata)152 NX_CRYPTO_KEEP UINT  _nx_crypto_method_prf_1_cleanup(VOID *crypto_metadata)
153 {
154 
155     NX_CRYPTO_STATE_CHECK
156 
157 #ifdef NX_SECURE_KEY_CLEAR
158     if (!crypto_metadata)
159         return (NX_CRYPTO_SUCCESS);
160 
161     /* Clean up the crypto metadata.  */
162     NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_TLS_PRF_1));
163 #else
164     NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
165 #endif/* NX_SECURE_KEY_CLEAR  */
166 
167     return(NX_CRYPTO_SUCCESS);
168 }
169 
170 
171 /**************************************************************************/
172 /*                                                                        */
173 /*  FUNCTION                                               RELEASE        */
174 /*                                                                        */
175 /*    _nx_crypto_method_prf_1_operation                   PORTABLE C      */
176 /*                                                           6.3.0        */
177 /*  AUTHOR                                                                */
178 /*                                                                        */
179 /*    Timothy Stapko, Microsoft Corporation                               */
180 /*                                                                        */
181 /*  DESCRIPTION                                                           */
182 /*                                                                        */
183 /*    This function encrypts and decrypts a message using                 */
184 /*    the PRF SHA-1 algorithm.                                            */
185 /*                                                                        */
186 /*  INPUT                                                                 */
187 /*                                                                        */
188 /*    op                                    PRF operation                 */
189 /*    handle                                Crypto handle                 */
190 /*    method                                Cryption Method Object        */
191 /*    key                                   Encryption Key                */
192 /*    key_size_in_bits                      Key size in bits              */
193 /*    input                                 Input data                    */
194 /*    input_length_in_byte                  Input data size               */
195 /*    iv_ptr                                Initial vector                */
196 /*    output                                Output buffer                 */
197 /*    output_length_in_byte                 Output buffer size            */
198 /*    crypto_metadata                       Metadata area                 */
199 /*    crypto_metadata_size                  Metadata area size            */
200 /*    packet_ptr                            Pointer to packet             */
201 /*    nx_crypto_hw_process_callback         Callback function pointer     */
202 /*                                                                        */
203 /*  OUTPUT                                                                */
204 /*                                                                        */
205 /*    status                                Completion status             */
206 /*                                                                        */
207 /*  CALLS                                                                 */
208 /*                                                                        */
209 /*    _nx_crypto_tls_prf_1                  Implement the TLS PRF         */
210 /*                                            using SHA-1                 */
211 /*                                                                        */
212 /*  CALLED BY                                                             */
213 /*                                                                        */
214 /*    Application Code                                                    */
215 /*                                                                        */
216 /*  RELEASE HISTORY                                                       */
217 /*                                                                        */
218 /*    DATE              NAME                      DESCRIPTION             */
219 /*                                                                        */
220 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
221 /*  09-30-2020     Timothy Stapko           Modified comment(s), improved */
222 /*                                            buffer length verification, */
223 /*                                            verified memcpy use cases,  */
224 /*                                            resulting in version 6.1    */
225 /*  10-31-2023     Yanwu Cai                Modified comment(s),          */
226 /*                                            resulting in version 6.3.0  */
227 /*                                                                        */
228 /**************************************************************************/
_nx_crypto_method_prf_1_operation(UINT op,VOID * handle,struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,UCHAR * input,ULONG input_length_in_byte,UCHAR * iv_ptr,UCHAR * output,ULONG output_length_in_byte,VOID * crypto_metadata,ULONG crypto_metadata_size,VOID * packet_ptr,VOID (* nx_crypto_hw_process_callback)(VOID * packet_ptr,UINT status))229 NX_CRYPTO_KEEP UINT  _nx_crypto_method_prf_1_operation(UINT op,      /* Encrypt, Decrypt, Authenticate */
230                                                        VOID *handle, /* Crypto handler */
231                                                        struct NX_CRYPTO_METHOD_STRUCT *method,
232                                                        UCHAR *key,
233                                                        NX_CRYPTO_KEY_SIZE key_size_in_bits,
234                                                        UCHAR *input,
235                                                        ULONG input_length_in_byte,
236                                                        UCHAR *iv_ptr,
237                                                        UCHAR *output,
238                                                        ULONG output_length_in_byte,
239                                                        VOID *crypto_metadata,
240                                                        ULONG crypto_metadata_size,
241                                                        VOID *packet_ptr,
242                                                        VOID (*nx_crypto_hw_process_callback)(VOID *packet_ptr, UINT status))
243 {
244 UINT status, secret_len;
245 UCHAR *secret_half_point;
246 NX_CRYPTO_TLS_PRF_1 *prf;
247 NX_CRYPTO_PHASH *phash;
248 
249     NX_CRYPTO_PARAMETER_NOT_USED(handle);
250     NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr);
251     NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
252     NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
253 
254     NX_CRYPTO_STATE_CHECK
255 
256     /* Verify the metadata address is 4-byte aligned. */
257     if((method == NX_CRYPTO_NULL) || (key == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL) || ((((ULONG)crypto_metadata) & 0x3) != 0))
258     {
259         return(NX_CRYPTO_PTR_ERROR);
260     }
261 
262     if(crypto_metadata_size < sizeof(NX_CRYPTO_TLS_PRF_1))
263     {
264         return(NX_CRYPTO_PTR_ERROR);
265     }
266 
267     /* This must be a PRF operation. */
268     if (op != NX_CRYPTO_PRF)
269     {
270         return(NX_CRYPTO_NOT_SUCCESSFUL);
271     }
272 
273     /* Get our control block. */
274     prf = (NX_CRYPTO_TLS_PRF_1 *)crypto_metadata;
275     phash = &(prf -> nx_secure_tls_prf_phash_info);
276 
277     /* Install the label_seed_buffer to the phash structure as the buffer of phash seed. */
278     phash -> nx_crypto_phash_seed = prf -> nx_secure_tls_prf_label_seed_buffer;
279     if ((key_size_in_bits + input_length_in_byte) > sizeof(prf -> nx_secure_tls_prf_label_seed_buffer))
280     {
281         return(NX_CRYPTO_SIZE_ERROR);
282     }
283 
284     /* Concatenate label and seed. */
285     NX_CRYPTO_MEMCPY(phash -> nx_crypto_phash_seed, key, key_size_in_bits); /* Use case of memcpy is verified. */
286     NX_CRYPTO_MEMCPY(&phash -> nx_crypto_phash_seed[key_size_in_bits], input, input_length_in_byte); /* Use case of memcpy is verified. */
287     phash -> nx_crypto_phash_seed_length = key_size_in_bits + input_length_in_byte;
288 
289     /* Install the temp_A_buffer to the phash structure. */
290     phash -> nx_crypto_phash_temp_A = prf -> nx_secure_tls_prf_temp_A_buffer;
291     phash -> nx_crypto_phash_temp_A_size = sizeof(prf -> nx_secure_tls_prf_temp_A_buffer);
292 
293     /* Install metadata buffer for the hmac method. */
294     phash -> nx_crypto_hmac_metadata = prf -> nx_secure_tls_prf_hmac_metadata_area;
295     phash -> nx_crypto_hmac_metadata_size = sizeof(prf -> nx_secure_tls_prf_hmac_metadata_area);
296 
297     /* Install the buffer for hmac output. */
298     phash -> nx_crypto_hmac_output = prf -> nx_secure_tls_prf_temp_hmac_output_buffer;
299     phash -> nx_crypto_hmac_output_size = sizeof(prf -> nx_secure_tls_prf_temp_hmac_output_buffer);
300 
301     /* SHA1 first. */
302     /* Clear the output buffer for the generic phash routine will show the output by XOR. */
303     NX_CRYPTO_MEMSET(output, 0, output_length_in_byte);
304 
305     /* Install the hmac method to the phash structure. */
306     phash -> nx_crypto_hmac_method = &crypto_method_hmac_md5;
307 
308     /* Calculate secret half-length. */
309     secret_len = (phash -> nx_crypto_phash_secret_length + 1) / 2;
310 
311     /* Find the offset of the half-way point. If the size of the secret is not even, overlap
312        the last byte of the first half and first byte of the second half. */
313     if (phash -> nx_crypto_phash_secret_length % 2)
314     {
315         /* Length is odd - overlap a byte. */
316         secret_half_point = &(phash -> nx_crypto_phash_secret[secret_len - 1]);
317     }
318     else
319     {
320         /* Evenly divisible, offset is just after the half-length. */
321         secret_half_point = &(phash -> nx_crypto_phash_secret[secret_len]);
322     }
323 
324     /* Update secret length. */
325     phash -> nx_crypto_phash_secret_length = secret_len;
326 
327     status = _nx_crypto_phash(phash, output, output_length_in_byte);
328 
329     if (status)
330     {
331         return status;
332     }
333 
334     /* Install the hmac method to the phash structure. */
335     phash -> nx_crypto_hmac_method = &crypto_method_hmac_sha1;
336 
337     /* Take use of the second half of the secret. */
338     phash -> nx_crypto_phash_secret = secret_half_point;
339 
340     /* Do not clear the output buffer this time. */
341     status = _nx_crypto_phash(phash, output, output_length_in_byte);
342 
343     return status;
344 }
345 
346