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 #define NX_SECURE_SOURCE_CODE
22 
23 #include "nx_crypto_tls_prf_sha256.h"
24 
25 /**************************************************************************/
26 /*                                                                        */
27 /*  FUNCTION                                               RELEASE        */
28 /*                                                                        */
29 /*    _nx_crypto_method_prf_sha_256_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-256.       */
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_sha_256_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_sha_256_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_SHA256 *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_SHA256))
96     {
97         return(NX_CRYPTO_PTR_ERROR);
98     }
99 
100     /* Get our control block. */
101     prf = (NX_CRYPTO_TLS_PRF_SHA256 *)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_sha_256_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_sha_256_cleanup(VOID * crypto_metadata)152 NX_CRYPTO_KEEP UINT  _nx_crypto_method_prf_sha_256_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_SHA256));
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_sha_256_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-256 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_sha256             Implement the TLS PRF         */
210 /*                                            using SHA-256               */
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_sha_256_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_sha_256_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;
245 NX_CRYPTO_TLS_PRF_SHA256 *prf;
246 NX_CRYPTO_PHASH *phash;
247 
248     NX_CRYPTO_PARAMETER_NOT_USED(handle);
249     NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr);
250     NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
251     NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
252 
253     NX_CRYPTO_STATE_CHECK
254 
255     /* Verify the metadata address is 4-byte aligned. */
256     if((method == NX_CRYPTO_NULL) || (key == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL) || ((((ULONG)crypto_metadata) & 0x3) != 0))
257     {
258         return(NX_CRYPTO_PTR_ERROR);
259     }
260 
261     if(crypto_metadata_size < sizeof(NX_CRYPTO_TLS_PRF_SHA256))
262     {
263         return(NX_CRYPTO_PTR_ERROR);
264     }
265 
266     /* This must be a PRF operation. */
267     if (op != NX_CRYPTO_PRF)
268     {
269         return(NX_CRYPTO_NOT_SUCCESSFUL);
270     }
271 
272     /* Get our control block. */
273     prf = (NX_CRYPTO_TLS_PRF_SHA256 *)crypto_metadata;
274     phash = &(prf -> nx_secure_tls_prf_phash_info);
275 
276     /* Install the label_seed_buffer to the phash structure as the buffer of phash seed. */
277     phash -> nx_crypto_phash_seed = prf -> nx_secure_tls_prf_label_seed_buffer;
278     if ((key_size_in_bits + input_length_in_byte) > sizeof(prf -> nx_secure_tls_prf_label_seed_buffer))
279     {
280         return(NX_CRYPTO_SIZE_ERROR);
281     }
282 
283     /* Concatenate label and seed. */
284     NX_CRYPTO_MEMCPY(phash -> nx_crypto_phash_seed, key, key_size_in_bits); /* Use case of memcpy is verified. */
285     NX_CRYPTO_MEMCPY(&phash -> nx_crypto_phash_seed[key_size_in_bits], input, input_length_in_byte); /* Use case of memcpy is verified. */
286     phash -> nx_crypto_phash_seed_length = key_size_in_bits + input_length_in_byte;
287 
288     /* Install the temp_A_buffer to the phash structure. */
289     phash -> nx_crypto_phash_temp_A = prf -> nx_secure_tls_prf_temp_A_buffer;
290     phash -> nx_crypto_phash_temp_A_size = sizeof(prf -> nx_secure_tls_prf_temp_A_buffer);
291 
292     /* Install the hmac method to the phash structure. */
293     phash -> nx_crypto_hmac_method = &crypto_method_hmac_sha256;
294 
295     /* Install metadata buffer for the hmac method. */
296     phash -> nx_crypto_hmac_metadata = prf -> nx_secure_tls_prf_hmac_metadata_area;
297     phash -> nx_crypto_hmac_metadata_size = sizeof(prf -> nx_secure_tls_prf_hmac_metadata_area);
298 
299     /* Install the buffer for hmac output. */
300     phash -> nx_crypto_hmac_output = prf -> nx_secure_tls_prf_temp_hmac_output_buffer;
301     phash -> nx_crypto_hmac_output_size = sizeof(prf -> nx_secure_tls_prf_temp_hmac_output_buffer);
302 
303     /* Clear the output buffer for the generic phash routine will show the output by XOR. */
304     NX_CRYPTO_MEMSET(output, 0, output_length_in_byte);
305 
306     /* Invoke generic phash routine. */
307     status = _nx_crypto_phash(phash, output, output_length_in_byte);
308 
309     return status;
310 }
311