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