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