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