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 /** CTR Mode */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #include "nx_crypto_ctr.h"
24
25 /**************************************************************************/
26 /* */
27 /* FUNCTION RELEASE */
28 /* */
29 /* _nx_crypto_ctr_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 of 16 bytes */
44 /* */
45 /* OUTPUT */
46 /* */
47 /* None */
48 /* */
49 /* CALLS */
50 /* */
51 /* None */
52 /* */
53 /* CALLED BY */
54 /* */
55 /* _nx_crypto_ctr_encrypt Perform CTR mode encryption */
56 /* */
57 /* RELEASE HISTORY */
58 /* */
59 /* DATE NAME DESCRIPTION */
60 /* */
61 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
62 /* 09-30-2020 Timothy Stapko Modified comment(s), disabled */
63 /* unaligned access by default,*/
64 /* resulting in version 6.1 */
65 /* */
66 /**************************************************************************/
_nx_crypto_ctr_xor(UCHAR * plaintext,UCHAR * key,UCHAR * ciphertext)67 NX_CRYPTO_KEEP static VOID _nx_crypto_ctr_xor(UCHAR *plaintext, UCHAR *key, UCHAR *ciphertext)
68 {
69 #ifdef NX_CRYPTO_ENABLE_UNALIGNED_ACCESS
70 UINT *p = (UINT *)plaintext;
71 UINT *c = (UINT *)ciphertext;
72 UINT *k = (UINT *)key;
73
74 c[0] = p[0] ^ k[0];
75 c[1] = p[1] ^ k[1];
76 c[2] = p[2] ^ k[2];
77 c[3] = p[3] ^ k[3];
78 #else
79 ciphertext[0] = plaintext[0] ^ key[0];
80 ciphertext[1] = plaintext[1] ^ key[1];
81 ciphertext[2] = plaintext[2] ^ key[2];
82 ciphertext[3] = plaintext[3] ^ key[3];
83 ciphertext[4] = plaintext[4] ^ key[4];
84 ciphertext[5] = plaintext[5] ^ key[5];
85 ciphertext[6] = plaintext[6] ^ key[6];
86 ciphertext[7] = plaintext[7] ^ key[7];
87 ciphertext[8] = plaintext[8] ^ key[8];
88 ciphertext[9] = plaintext[9] ^ key[9];
89 ciphertext[10] = plaintext[10] ^ key[10];
90 ciphertext[11] = plaintext[11] ^ key[11];
91 ciphertext[12] = plaintext[12] ^ key[12];
92 ciphertext[13] = plaintext[13] ^ key[13];
93 ciphertext[14] = plaintext[14] ^ key[14];
94 ciphertext[15] = plaintext[15] ^ key[15];
95 #endif
96 }
97
98 /**************************************************************************/
99 /* */
100 /* FUNCTION RELEASE */
101 /* */
102 /* _nx_crypto_ctr_add_one PORTABLE C */
103 /* 6.1 */
104 /* AUTHOR */
105 /* */
106 /* Timothy Stapko, Microsoft Corporation */
107 /* */
108 /* DESCRIPTION */
109 /* */
110 /* This function adds one for the last byte. */
111 /* */
112 /* INPUT */
113 /* */
114 /* control_block Pointer to control block */
115 /* */
116 /* OUTPUT */
117 /* */
118 /* None */
119 /* */
120 /* CALLS */
121 /* */
122 /* None */
123 /* */
124 /* CALLED BY */
125 /* */
126 /* _nx_crypto_ctr_encrypt Perform CTR mode encryption */
127 /* */
128 /* RELEASE HISTORY */
129 /* */
130 /* DATE NAME DESCRIPTION */
131 /* */
132 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
133 /* 09-30-2020 Timothy Stapko Modified comment(s), */
134 /* resulting in version 6.1 */
135 /* */
136 /**************************************************************************/
_nx_crypto_ctr_add_one(UCHAR * control_block)137 NX_CRYPTO_KEEP static VOID _nx_crypto_ctr_add_one(UCHAR *control_block)
138 {
139 USHORT result;
140
141 /* Add one for last byte. */
142 result = (USHORT)(control_block[15] + 1);
143 control_block[15] = (UCHAR)(result & 0xFF);
144
145 /* Handle carry. */
146 result = (USHORT)((result >> 8) + control_block[14]);
147 control_block[14] = (UCHAR)(result & 0xFF);
148 result = (USHORT)((result >> 8) + control_block[13]);
149 control_block[13] = (UCHAR)(result & 0xFF);
150 result = (USHORT)((result >> 8) + control_block[12]);
151 control_block[12] = (UCHAR)(result & 0xFF);
152 }
153
154 /**************************************************************************/
155 /* */
156 /* FUNCTION RELEASE */
157 /* */
158 /* _nx_crypto_ctr_encrypt PORTABLE C */
159 /* 6.1 */
160 /* AUTHOR */
161 /* */
162 /* Timothy Stapko, Microsoft Corporation */
163 /* */
164 /* DESCRIPTION */
165 /* */
166 /* This function performs CTR mode encryption, only support block of */
167 /* 16 bytes. */
168 /* */
169 /* INPUT */
170 /* */
171 /* crypto_metadata Pointer to crypto metadata */
172 /* ctr_metadata Pointer to CTR metadata */
173 /* crypto_function Pointer to crypto function */
174 /* key_set_function Pointer to key set function */
175 /* additional_data Pointer to the additional data*/
176 /* additional_len Length of additional data */
177 /* input Pointer to clear text input */
178 /* output Pointer to encrypted output */
179 /* The size of the output */
180 /* buffer must be at least */
181 /* the size of input message. */
182 /* length Length of the input message. */
183 /* iv Nonce length + Nonce */
184 /* icv_len ICV length */
185 /* block_size Block size */
186 /* */
187 /* OUTPUT */
188 /* */
189 /* status Completion status */
190 /* */
191 /* CALLS */
192 /* */
193 /* _nx_crypto_ctr_xor Perform XOR operation */
194 /* _nx_crypto_ctr_add_one Perform add one operation */
195 /* */
196 /* CALLED BY */
197 /* */
198 /* _nx_crypto_method_aes_ctr_operation Handle AES encrypt or decrypt */
199 /* */
200 /* RELEASE HISTORY */
201 /* */
202 /* DATE NAME DESCRIPTION */
203 /* */
204 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
205 /* 09-30-2020 Timothy Stapko Modified comment(s), */
206 /* verified memcpy use cases, */
207 /* resulting in version 6.1 */
208 /* */
209 /**************************************************************************/
_nx_crypto_ctr_encrypt(VOID * crypto_metadata,NX_CRYPTO_CTR * ctr_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * input,UCHAR * output,UINT length,UINT block_size)210 NX_CRYPTO_KEEP UINT _nx_crypto_ctr_encrypt(VOID *crypto_metadata, NX_CRYPTO_CTR *ctr_metadata,
211 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
212 UCHAR *input, UCHAR *output, UINT length, UINT block_size)
213 {
214 UCHAR *control_block = ctr_metadata -> nx_crypto_ctr_counter_block;
215 UCHAR aes_output[NX_CRYPTO_CTR_BLOCK_SIZE];
216 UINT i;
217
218 /* Check the block size. */
219 if (block_size != NX_CRYPTO_CTR_BLOCK_SIZE)
220 {
221 return(NX_CRYPTO_PTR_ERROR);
222 }
223
224 for (i = 0; i < length; i += block_size)
225 {
226 if (length - i < block_size)
227 {
228 break;
229 }
230 crypto_function(crypto_metadata, control_block, aes_output, block_size);
231 _nx_crypto_ctr_xor(&input[i], aes_output, &output[i]);
232 _nx_crypto_ctr_add_one(control_block);
233 }
234
235 /* If the input is not an even multiple of 16 bytes, we need to truncate and xor the remainder. */
236 if (length - i != 0)
237 {
238 crypto_function(crypto_metadata, control_block, aes_output, block_size);
239 _nx_crypto_ctr_xor(&input[i], aes_output, aes_output);
240 NX_CRYPTO_MEMCPY(&output[i], aes_output, length - i); /* Use case of memcpy is verified. */
241 }
242
243 #ifdef NX_SECURE_KEY_CLEAR
244 NX_CRYPTO_MEMSET(aes_output, 0, sizeof(aes_output));
245 #endif /* NX_SECURE_KEY_CLEAR */
246
247 return(NX_CRYPTO_SUCCESS);
248 }
249
250 /**************************************************************************/
251 /* */
252 /* FUNCTION RELEASE */
253 /* */
254 /* _nx_crypto_ctr_encrypt_init PORTABLE C */
255 /* 6.1 */
256 /* AUTHOR */
257 /* */
258 /* Timothy Stapko, Microsoft Corporation */
259 /* */
260 /* DESCRIPTION */
261 /* */
262 /* This function performs CTR mode initialization. */
263 /* */
264 /* INPUT */
265 /* */
266 /* ctr_metadata Pointer to CTR metadata */
267 /* iv Pointer to Initial Vector */
268 /* iv_len Length of IV. Must be 8 */
269 /* nonce Pointer to Nonce */
270 /* nonce_len Length of Nonce. Must be 4 */
271 /* */
272 /* OUTPUT */
273 /* */
274 /* status Completion status */
275 /* */
276 /* CALLS */
277 /* */
278 /* None */
279 /* */
280 /* CALLED BY */
281 /* */
282 /* _nx_crypto_method_aes_ctr_operation Handle AES encrypt or decrypt */
283 /* */
284 /* RELEASE HISTORY */
285 /* */
286 /* DATE NAME DESCRIPTION */
287 /* */
288 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
289 /* 09-30-2020 Timothy Stapko Modified comment(s), */
290 /* verified memcpy use cases, */
291 /* resulting in version 6.1 */
292 /* */
293 /**************************************************************************/
_nx_crypto_ctr_encrypt_init(NX_CRYPTO_CTR * ctr_metadata,UCHAR * iv,UINT iv_len,UCHAR * nonce,UINT nonce_len)294 NX_CRYPTO_KEEP UINT _nx_crypto_ctr_encrypt_init(NX_CRYPTO_CTR *ctr_metadata, UCHAR *iv, UINT iv_len,
295 UCHAR *nonce, UINT nonce_len)
296 {
297 UCHAR *control_block = ctr_metadata -> nx_crypto_ctr_counter_block;
298
299 /* Check IV length and Nonce length. */
300 if ((iv_len != 8) || (nonce_len != 4))
301 {
302 return(NX_CRYPTO_PTR_ERROR);
303 }
304
305 /* Control block consists of the following data:
306 * Bits: | 0-31 (32 bits) | 32-95 (64 bits) | 96-127 (32 bits) |
307 * | All set to 1 | Initialization Vector (IV) | Nonce |
308 */
309 NX_CRYPTO_MEMSET(control_block, 0x0, 16);
310 control_block[15] = 1;
311 NX_CRYPTO_MEMCPY(&control_block[4], iv, 8); /* Use case of memcpy is verified. */
312 NX_CRYPTO_MEMCPY(&control_block[0], nonce, 4); /* Use case of memcpy is verified. */
313
314 return(NX_CRYPTO_SUCCESS);
315 }
316
317