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 /** CBC Mode */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #include "nx_crypto_cbc.h"
24
25 /**************************************************************************/
26 /* */
27 /* FUNCTION RELEASE */
28 /* */
29 /* _nx_crypto_cbc_xor PORTABLE C */
30 /* 6.1 */
31 /* AUTHOR */
32 /* */
33 /* Timothy Stapko, Microsoft Corporation */
34 /* */
35 /* DESCRIPTION */
36 /* */
37 /* This function performs XOR operation on the output buffer. */
38 /* */
39 /* INPUT */
40 /* */
41 /* plaintext Pointer to input plantext */
42 /* key Value to be xor'ed */
43 /* ciphertext Output buffer */
44 /* block_size Block size */
45 /* */
46 /* OUTPUT */
47 /* */
48 /* None */
49 /* */
50 /* CALLS */
51 /* */
52 /* None */
53 /* */
54 /* CALLED BY */
55 /* */
56 /* _nx_crypto_cbc_encrypt Perform CBC mode encryption */
57 /* _nx_crypto_cbc_decrypt Perform CBC mode decryption */
58 /* */
59 /* RELEASE HISTORY */
60 /* */
61 /* DATE NAME DESCRIPTION */
62 /* */
63 /* 09-30-2020 Timothy Stapko Initial Version 6.1 */
64 /* */
65 /**************************************************************************/
_nx_crypto_cbc_xor(UCHAR * plaintext,UCHAR * key,UCHAR * ciphertext,UCHAR block_size)66 NX_CRYPTO_KEEP static VOID _nx_crypto_cbc_xor(UCHAR *plaintext, UCHAR *key, UCHAR *ciphertext, UCHAR block_size)
67 {
68 UINT i;
69
70 for (i = 0; i < block_size; i++)
71 {
72 ciphertext[i] = plaintext[i] ^ key[i];
73 }
74 }
75
76 /**************************************************************************/
77 /* */
78 /* FUNCTION RELEASE */
79 /* */
80 /* _nx_crypto_cbc_encrypt PORTABLE C */
81 /* 6.1 */
82 /* AUTHOR */
83 /* */
84 /* Timothy Stapko, Microsoft Corporation */
85 /* */
86 /* DESCRIPTION */
87 /* */
88 /* This function performs CBC mode encryption. */
89 /* */
90 /* INPUT */
91 /* */
92 /* crypto_metadata Pointer to crypto metadata */
93 /* cbc_metadata Pointer to CBC metadata */
94 /* crypto_function Pointer to crypto function */
95 /* input Pointer to clear text input */
96 /* output Pointer to encrypted output */
97 /* The size of the output */
98 /* buffer must be at least */
99 /* the size of input message. */
100 /* length Length of the input message. */
101 /* block_size Block size */
102 /* */
103 /* OUTPUT */
104 /* */
105 /* status Completion status */
106 /* */
107 /* CALLS */
108 /* */
109 /* _nx_crypto_cbc_xor Perform CBC XOR operation */
110 /* */
111 /* CALLED BY */
112 /* */
113 /* _nx_crypto_method_aes_cbc_operation Handle AES encrypt or decrypt */
114 /* _nx_crypto_method_des_operation Handle DES encrypt or decrypt */
115 /* _nx_crypto_method_3des_operation Handle 3DES encrypt or decrypt*/
116 /* */
117 /* RELEASE HISTORY */
118 /* */
119 /* DATE NAME DESCRIPTION */
120 /* */
121 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
122 /* 09-30-2020 Timothy Stapko Modified comment(s), */
123 /* verified memcpy use cases, */
124 /* and updated constants, */
125 /* resulting in version 6.1 */
126 /* */
127 /**************************************************************************/
_nx_crypto_cbc_encrypt(VOID * crypto_metadata,NX_CRYPTO_CBC * cbc_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * input,UCHAR * output,UINT length,UCHAR block_size)128 NX_CRYPTO_KEEP UINT _nx_crypto_cbc_encrypt(VOID *crypto_metadata, NX_CRYPTO_CBC *cbc_metadata,
129 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
130 UCHAR *input, UCHAR *output, UINT length, UCHAR block_size)
131 {
132 UCHAR *last_cipher;
133 UINT i;
134
135 if (block_size == 0)
136 {
137 return(NX_CRYPTO_INVALID_PARAMETER);
138 }
139
140 /* Determine if data length is multiple of block size. */
141 if (length % block_size)
142 {
143 return(NX_CRYPTO_PTR_ERROR);
144 }
145
146 /* Determine if block size is larger than the size of save_input. */
147 if (block_size > sizeof(cbc_metadata -> nx_crypto_cbc_last_block))
148 {
149 return(NX_CRYPTO_PTR_ERROR);
150 }
151
152 /* Pick up last cipher. */
153 last_cipher = cbc_metadata -> nx_crypto_cbc_last_block;
154
155 for (i = 0; i < length; i += block_size)
156 {
157
158 /* XOR. */
159 _nx_crypto_cbc_xor(&input[i], last_cipher, output, block_size);
160
161 /* Encrypt the block. */
162 crypto_function(crypto_metadata, output, output, block_size);
163
164 /* Remember the previous encrypt block result. */
165 last_cipher = output;
166
167 output += block_size;
168 }
169
170 /* Store the last cipher for next round. */
171 NX_CRYPTO_MEMCPY(cbc_metadata -> nx_crypto_cbc_last_block, last_cipher, block_size); /* Use case of memcpy is verified. */
172
173 return(NX_CRYPTO_SUCCESS);
174 }
175
176
177 /**************************************************************************/
178 /* */
179 /* FUNCTION RELEASE */
180 /* */
181 /* _nx_crypto_cbc_decrypt PORTABLE C */
182 /* 6.1 */
183 /* AUTHOR */
184 /* */
185 /* Timothy Stapko, Microsoft Corporation */
186 /* */
187 /* DESCRIPTION */
188 /* */
189 /* This function performs CBC mode decryption. */
190 /* */
191 /* INPUT */
192 /* */
193 /* crypto_metadata Pointer to crypto metadata */
194 /* cbc_metadata Pointer to CBC metadata */
195 /* crypto_function Pointer to crypto function */
196 /* input Pointer to clear text input */
197 /* output Pointer to encrypted output */
198 /* The size of the output */
199 /* buffer must be at least */
200 /* the size of input message. */
201 /* length Length of the input message. */
202 /* block_size Block size */
203 /* */
204 /* OUTPUT */
205 /* */
206 /* status Completion status */
207 /* */
208 /* CALLS */
209 /* */
210 /* _nx_crypto_cbc_xor Perform CBC XOR operation */
211 /* */
212 /* CALLED BY */
213 /* */
214 /* _nx_crypto_method_aes_cbc_operation Handle AES encrypt or decrypt */
215 /* _nx_crypto_method_des_operation Handle DES encrypt or decrypt */
216 /* _nx_crypto_method_3des_operation Handle 3DES encrypt or decrypt*/
217 /* */
218 /* RELEASE HISTORY */
219 /* */
220 /* DATE NAME DESCRIPTION */
221 /* */
222 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
223 /* 09-30-2020 Timothy Stapko Modified comment(s), */
224 /* verified memcpy use cases, */
225 /* and updated constants, */
226 /* resulting in version 6.1 */
227 /* */
228 /**************************************************************************/
_nx_crypto_cbc_decrypt(VOID * crypto_metadata,NX_CRYPTO_CBC * cbc_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * input,UCHAR * output,UINT length,UCHAR block_size)229 NX_CRYPTO_KEEP UINT _nx_crypto_cbc_decrypt(VOID *crypto_metadata, NX_CRYPTO_CBC *cbc_metadata,
230 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
231 UCHAR *input, UCHAR *output, UINT length, UCHAR block_size)
232 {
233 UCHAR *last_cipher;
234 UCHAR save_input[16];
235 UINT i;
236
237 if (block_size == 0)
238 {
239 return(NX_CRYPTO_INVALID_PARAMETER);
240 }
241
242 /* Determine if data length is multiple of block size. */
243 if (length % block_size)
244 {
245 return(NX_CRYPTO_PTR_ERROR);
246 }
247
248 /* Determine if block size is larger than the size of save_input. */
249 if (block_size > sizeof(cbc_metadata -> nx_crypto_cbc_last_block))
250 {
251 return(NX_CRYPTO_PTR_ERROR);
252 }
253
254 last_cipher = cbc_metadata -> nx_crypto_cbc_last_block;
255
256 for (i = 0; i < length; i += block_size)
257 {
258 /* If input == output, the xor clobbers the input buffer so we need to save off our last ciphertext
259 before doing the xor. */
260 NX_CRYPTO_MEMCPY(save_input, &input[i], block_size); /* Use case of memcpy is verified. */
261
262 /* Decrypt the block. */
263 crypto_function(crypto_metadata, &input[i], &output[i], block_size);
264
265 /* XOR. */
266 _nx_crypto_cbc_xor(&output[i], last_cipher, &output[i], block_size);
267
268 NX_CRYPTO_MEMCPY(last_cipher, save_input, block_size); /* Use case of memcpy is verified. */
269 }
270
271 #ifdef NX_SECURE_KEY_CLEAR
272 NX_CRYPTO_MEMSET(save_input, 0, sizeof(save_input));
273 #endif /* NX_SECURE_KEY_CLEAR */
274
275 return(NX_CRYPTO_SUCCESS);
276 }
277
278
279 /**************************************************************************/
280 /* */
281 /* FUNCTION RELEASE */
282 /* */
283 /* _nx_crypto_cbc_encrypt_init PORTABLE C */
284 /* 6.1 */
285 /* AUTHOR */
286 /* */
287 /* Timothy Stapko, Microsoft Corporation */
288 /* */
289 /* DESCRIPTION */
290 /* */
291 /* This function performs CBC mode initialization. */
292 /* */
293 /* INPUT */
294 /* */
295 /* cbc_metadata Pointer to CBC metadata */
296 /* iv Pointer to Initial Vector */
297 /* iv_len Length of Initial Vector */
298 /* */
299 /* OUTPUT */
300 /* */
301 /* status Completion status */
302 /* */
303 /* CALLS */
304 /* */
305 /* None */
306 /* */
307 /* CALLED BY */
308 /* */
309 /* _nx_crypto_method_aes_cbc_operation Handle AES encrypt or decrypt */
310 /* _nx_crypto_method_des_operation Handle DES encrypt or decrypt */
311 /* _nx_crypto_method_3des_operation Handle 3DES encrypt or decrypt*/
312 /* */
313 /* RELEASE HISTORY */
314 /* */
315 /* DATE NAME DESCRIPTION */
316 /* */
317 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
318 /* 09-30-2020 Timothy Stapko Modified comment(s), */
319 /* verified memcpy use cases, */
320 /* resulting in version 6.1 */
321 /* */
322 /**************************************************************************/
_nx_crypto_cbc_encrypt_init(NX_CRYPTO_CBC * cbc_metadata,UCHAR * iv,UINT iv_len)323 NX_CRYPTO_KEEP UINT _nx_crypto_cbc_encrypt_init(NX_CRYPTO_CBC *cbc_metadata, UCHAR *iv, UINT iv_len)
324 {
325
326 /* Determine if IV size is larger than the size of save_input. */
327 if (iv_len > sizeof(cbc_metadata -> nx_crypto_cbc_last_block))
328 {
329 return(NX_CRYPTO_PTR_ERROR);
330 }
331
332 /* Copy IV to last cipher. */
333 NX_CRYPTO_MEMCPY(cbc_metadata -> nx_crypto_cbc_last_block, iv, iv_len); /* Use case of memcpy is verified. */
334
335 return(NX_CRYPTO_SUCCESS);
336 }
337