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