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 /** GCM Mode */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #include "nx_crypto_gcm.h"
24
25
26 /**************************************************************************/
27 /* */
28 /* FUNCTION RELEASE */
29 /* */
30 /* _nx_crypto_gcm_xor PORTABLE C */
31 /* 6.1 */
32 /* AUTHOR */
33 /* */
34 /* Timothy Stapko, Microsoft Corporation */
35 /* */
36 /* DESCRIPTION */
37 /* */
38 /* This function performs XOR operation on the output buffer. */
39 /* */
40 /* INPUT */
41 /* */
42 /* plaintext Pointer to input plantext */
43 /* key Value to be xor'ed */
44 /* ciphertext Output buffer of 16 bytes */
45 /* */
46 /* OUTPUT */
47 /* */
48 /* None */
49 /* */
50 /* CALLS */
51 /* */
52 /* None */
53 /* */
54 /* CALLED BY */
55 /* */
56 /* _nx_crypto_gcm_multi Compute multilication in GF */
57 /* _nx_crypto_gcm_ghash_update Compute GHASH */
58 /* _nx_crypto_gcm_gctr Perform GCTR operation */
59 /* */
60 /* RELEASE HISTORY */
61 /* */
62 /* DATE NAME DESCRIPTION */
63 /* */
64 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
65 /* 09-30-2020 Timothy Stapko Modified comment(s), disabled */
66 /* unaligned access by default,*/
67 /* resulting in version 6.1 */
68 /* */
69 /**************************************************************************/
_nx_crypto_gcm_xor(UCHAR * plaintext,UCHAR * key,UCHAR * ciphertext)70 NX_CRYPTO_KEEP static VOID _nx_crypto_gcm_xor(UCHAR *plaintext, UCHAR *key, UCHAR *ciphertext)
71 {
72 #ifdef NX_CRYPTO_ENABLE_UNALIGNED_ACCESS
73 UINT *p = (UINT *)plaintext;
74 UINT *c = (UINT *)ciphertext;
75 UINT *k = (UINT *)key;
76
77 c[0] = p[0] ^ k[0];
78 c[1] = p[1] ^ k[1];
79 c[2] = p[2] ^ k[2];
80 c[3] = p[3] ^ k[3];
81 #else
82 ciphertext[0] = plaintext[0] ^ key[0];
83 ciphertext[1] = plaintext[1] ^ key[1];
84 ciphertext[2] = plaintext[2] ^ key[2];
85 ciphertext[3] = plaintext[3] ^ key[3];
86 ciphertext[4] = plaintext[4] ^ key[4];
87 ciphertext[5] = plaintext[5] ^ key[5];
88 ciphertext[6] = plaintext[6] ^ key[6];
89 ciphertext[7] = plaintext[7] ^ key[7];
90 ciphertext[8] = plaintext[8] ^ key[8];
91 ciphertext[9] = plaintext[9] ^ key[9];
92 ciphertext[10] = plaintext[10] ^ key[10];
93 ciphertext[11] = plaintext[11] ^ key[11];
94 ciphertext[12] = plaintext[12] ^ key[12];
95 ciphertext[13] = plaintext[13] ^ key[13];
96 ciphertext[14] = plaintext[14] ^ key[14];
97 ciphertext[15] = plaintext[15] ^ key[15];
98 #endif
99 }
100
101
102
103 /**************************************************************************/
104 /* */
105 /* FUNCTION RELEASE */
106 /* */
107 /* _nx_crypto_gcm_inc32 PORTABLE C */
108 /* 6.1 */
109 /* AUTHOR */
110 /* */
111 /* Timothy Stapko, Microsoft Corporation */
112 /* */
113 /* DESCRIPTION */
114 /* */
115 /* This function adds one for the last byte. */
116 /* */
117 /* INPUT */
118 /* */
119 /* counter_block Pointer to counter block */
120 /* */
121 /* OUTPUT */
122 /* */
123 /* None */
124 /* */
125 /* CALLS */
126 /* */
127 /* None */
128 /* */
129 /* CALLED BY */
130 /* */
131 /* _nx_crypto_gcm_gctr Perform GCTR operation */
132 /* _nx_crypto_gcm_encrypt Perform GCM encrypt/decrypt */
133 /* */
134 /* RELEASE HISTORY */
135 /* */
136 /* DATE NAME DESCRIPTION */
137 /* */
138 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
139 /* 09-30-2020 Timothy Stapko Modified comment(s), */
140 /* resulting in version 6.1 */
141 /* */
142 /**************************************************************************/
_nx_crypto_gcm_inc32(UCHAR * counter_block)143 NX_CRYPTO_KEEP static VOID _nx_crypto_gcm_inc32(UCHAR *counter_block)
144 {
145 USHORT result;
146
147 /* Add one for last byte. */
148 result = (USHORT)(counter_block[15] + 1);
149 counter_block[15] = (UCHAR)(result & 0xFF);
150
151 /* Handle carry. */
152 result = (USHORT)((result >> 8) + counter_block[14]);
153 counter_block[14] = (UCHAR)(result & 0xFF);
154 result = (USHORT)((result >> 8) + counter_block[13]);
155 counter_block[13] = (UCHAR)(result & 0xFF);
156 result = (USHORT)((result >> 8) + counter_block[12]);
157 counter_block[12] = (UCHAR)(result & 0xFF);
158 }
159
160 /**************************************************************************/
161 /* */
162 /* FUNCTION RELEASE */
163 /* */
164 /* _nx_crypto_gcm_multi PORTABLE C */
165 /* 6.1 */
166 /* AUTHOR */
167 /* */
168 /* Timothy Stapko, Microsoft Corporation */
169 /* */
170 /* DESCRIPTION */
171 /* */
172 /* This function performs multiplication in GF(2^128). */
173 /* */
174 /* INPUT */
175 /* */
176 /* x Pointer to X block */
177 /* y Pointer to Y block */
178 /* output Pointer to result block */
179 /* */
180 /* OUTPUT */
181 /* */
182 /* None */
183 /* */
184 /* CALLS */
185 /* */
186 /* _nx_crypto_gcm_xor Perform XOR operation */
187 /* */
188 /* CALLED BY */
189 /* */
190 /* _nx_crypto_gcm_ghash_update Compute GHASH */
191 /* */
192 /* RELEASE HISTORY */
193 /* */
194 /* DATE NAME DESCRIPTION */
195 /* */
196 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
197 /* 09-30-2020 Timothy Stapko Modified comment(s), */
198 /* verified memcpy use cases, */
199 /* resulting in version 6.1 */
200 /* */
201 /**************************************************************************/
_nx_crypto_gcm_multi(UCHAR * x,UCHAR * y,UCHAR * output)202 NX_CRYPTO_KEEP static VOID _nx_crypto_gcm_multi(UCHAR *x, UCHAR *y, UCHAR *output)
203 {
204 UINT i;
205 INT j;
206 UCHAR v[NX_CRYPTO_GCM_BLOCK_SIZE];
207 UCHAR lsb;
208 UCHAR mask;
209
210 NX_CRYPTO_MEMSET(output, 0, NX_CRYPTO_GCM_BLOCK_SIZE);
211 NX_CRYPTO_MEMCPY(v, y, NX_CRYPTO_GCM_BLOCK_SIZE); /* Use case of memcpy is verified. */
212
213 mask = 0x80;
214 for (i = 0; i < NX_CRYPTO_GCM_BLOCK_SIZE_BITS; i++)
215 {
216
217 /* output = output xor v when the ith bit of x is set. */
218 if (*x & mask)
219 {
220 _nx_crypto_gcm_xor(output, v, output);
221 }
222
223 /* Store the LSB before shift right. */
224 j = NX_CRYPTO_GCM_BLOCK_SIZE - 1;
225 lsb = v[j];
226
227 /* v = v >> 1 */
228 for (; j > 0; j--)
229 {
230 v[j] = (UCHAR)((v[j] >> 1) | (v[j - 1] << 7));
231 }
232 v[0] = v[0] >> 1;
233
234 /* v = v xor R when LSB of v is set. */
235 if (lsb & 1)
236 {
237 v[0] = v[0] ^ 0xe1;
238 }
239
240 mask = mask >> 1;
241 if (!mask)
242 {
243 mask = 0x80;
244 x++;
245 }
246 }
247 }
248
249 /**************************************************************************/
250 /* */
251 /* FUNCTION RELEASE */
252 /* */
253 /* _nx_crypto_gcm_ghash_update PORTABLE C */
254 /* 6.1 */
255 /* AUTHOR */
256 /* */
257 /* Timothy Stapko, Microsoft Corporation */
258 /* */
259 /* DESCRIPTION */
260 /* */
261 /* This function updates GHASH with new input from the caller. The */
262 /* input is padded so that the length is a multiple of the block size. */
263 /* */
264 /* INPUT */
265 /* */
266 /* hkey Pointer to hash key */
267 /* input Pointer to bytes of input */
268 /* input_length Length of bytes of input */
269 /* output Pointer to updated hash */
270 /* */
271 /* OUTPUT */
272 /* */
273 /* None */
274 /* */
275 /* CALLS */
276 /* */
277 /* _nx_crypto_gcm_xor Perform XOR operation */
278 /* _nx_crypto_gcm_multi Perform multiplication in GF */
279 /* */
280 /* CALLED BY */
281 /* */
282 /* _nx_crypto_gcm_encrypt Perform GCM encrypt/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_gcm_ghash_update(UCHAR * hkey,UCHAR * input,UINT input_length,UCHAR * output)294 NX_CRYPTO_KEEP static VOID _nx_crypto_gcm_ghash_update(UCHAR *hkey, UCHAR *input, UINT input_length, UCHAR *output)
295 {
296 UCHAR tmp_block[NX_CRYPTO_GCM_BLOCK_SIZE];
297 UINT i, n;
298
299 n = input_length >> NX_CRYPTO_GCM_BLOCK_SIZE_SHIFT;
300 for (i = 0; i < n; i++)
301 {
302
303 /* output = (output xor input) multi hkey */
304 _nx_crypto_gcm_xor(output, input, tmp_block);
305 _nx_crypto_gcm_multi(tmp_block, hkey, output);
306 input += NX_CRYPTO_GCM_BLOCK_SIZE;
307 }
308
309 input_length -= n << NX_CRYPTO_GCM_BLOCK_SIZE_SHIFT;
310 if (input_length > 0)
311 {
312
313 /* Pad the block with zeros when the input length is not
314 multiple of the block size. */
315 NX_CRYPTO_MEMCPY(tmp_block, input, input_length); /* Use case of memcpy is verified. */
316 NX_CRYPTO_MEMSET(&tmp_block[input_length], 0, sizeof(tmp_block) - input_length);
317 _nx_crypto_gcm_xor(output, tmp_block, tmp_block);
318 _nx_crypto_gcm_multi(tmp_block, hkey, output);
319 }
320 }
321
322 /**************************************************************************/
323 /* */
324 /* FUNCTION RELEASE */
325 /* */
326 /* _nx_crypto_gcm_gctr PORTABLE C */
327 /* 6.1 */
328 /* AUTHOR */
329 /* */
330 /* Timothy Stapko, Microsoft Corporation */
331 /* */
332 /* DESCRIPTION */
333 /* */
334 /* This function performs GCTR mode encryption and decryption. The */
335 /* counter block is updated after calling this function. */
336 /* */
337 /* INPUT */
338 /* */
339 /* crypto_metadata Pointer to crypto metadata */
340 /* crypto_function Pointer to crypto function */
341 /* input Pointer to bytes of input */
342 /* output Pointer to output buffer */
343 /* length Length of bytes of input */
344 /* counter_block Pointer to counter block */
345 /* */
346 /* OUTPUT */
347 /* */
348 /* None */
349 /* */
350 /* CALLS */
351 /* */
352 /* _nx_crypto_gcm_xor Perform XOR operation */
353 /* _nx_crypto_gcm_inc32 Increase the counter by one */
354 /* */
355 /* CALLED BY */
356 /* */
357 /* _nx_crypto_gcm_encrypt Perform GCM encrypt/decrypt */
358 /* */
359 /* RELEASE HISTORY */
360 /* */
361 /* DATE NAME DESCRIPTION */
362 /* */
363 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
364 /* 09-30-2020 Timothy Stapko Modified comment(s), */
365 /* verified memcpy use cases, */
366 /* resulting in version 6.1 */
367 /* */
368 /**************************************************************************/
_nx_crypto_gcm_gctr(VOID * crypto_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * input,UCHAR * output,UINT length,UCHAR * counter_block)369 NX_CRYPTO_KEEP static VOID _nx_crypto_gcm_gctr(VOID *crypto_metadata,
370 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
371 UCHAR *input, UCHAR *output, UINT length, UCHAR *counter_block)
372 {
373 UCHAR aes_output[NX_CRYPTO_GCM_BLOCK_SIZE];
374 UINT i, n;
375
376 n = length >> NX_CRYPTO_GCM_BLOCK_SIZE_SHIFT;
377
378 for (i = 0; i < n; i++)
379 {
380
381 /* Encrypt the counter. */
382 crypto_function(crypto_metadata, counter_block, aes_output, NX_CRYPTO_GCM_BLOCK_SIZE);
383
384 /* XOR the input with encrypted counter. */
385 _nx_crypto_gcm_xor(input, aes_output, output);
386
387 /* Increase the counter block. */
388 _nx_crypto_gcm_inc32(counter_block);
389
390 input += NX_CRYPTO_GCM_BLOCK_SIZE;
391 output += NX_CRYPTO_GCM_BLOCK_SIZE;
392 }
393
394 length -= n << NX_CRYPTO_GCM_BLOCK_SIZE_SHIFT;
395 if (length > 0)
396 {
397 crypto_function(crypto_metadata, counter_block, aes_output, NX_CRYPTO_GCM_BLOCK_SIZE);
398
399 /* Perform XOR operation on local buffer when
400 remaining input length is smaller than block size. */
401 _nx_crypto_gcm_xor(input, aes_output, aes_output);
402 NX_CRYPTO_MEMCPY(output, aes_output, length); /* Use case of memcpy is verified. */
403 }
404
405 }
406
407 /**************************************************************************/
408 /* */
409 /* FUNCTION RELEASE */
410 /* */
411 /* _nx_crypto_gcm_encrypt_init PORTABLE C */
412 /* 6.1 */
413 /* AUTHOR */
414 /* */
415 /* Timothy Stapko, Microsoft Corporation */
416 /* */
417 /* DESCRIPTION */
418 /* */
419 /* This function initialize the GCM mode for encryption. */
420 /* */
421 /* Note, the first byte of iv represents the length of IV excluding its*/
422 /* first byte. For example, 0x0401020304 indicates the length of IV is */
423 /* 4 bytes and the content of IV is 0x01020304. */
424 /* */
425 /* INPUT */
426 /* */
427 /* crypto_metadata Pointer to crypto metadata */
428 /* gcm_metadata Pointer to GCM metadata */
429 /* crypto_function Pointer to crypto function */
430 /* additional_data Pointer to additional data */
431 /* additional_len Length of additional data */
432 /* iv Pointer to Initial Vector */
433 /* block_size Block size of crypto algorithm*/
434 /* */
435 /* OUTPUT */
436 /* */
437 /* status */
438 /* */
439 /* CALLS */
440 /* */
441 /* _nx_crypto_gcm_ghash_update Update GHASH */
442 /* _nx_crypto_gcm_inc32 Increase the counter by one */
443 /* */
444 /* CALLED BY */
445 /* */
446 /* _nx_crypto_method_aes_gcm_operation Handle AES encrypt or decrypt */
447 /* */
448 /* RELEASE HISTORY */
449 /* */
450 /* DATE NAME DESCRIPTION */
451 /* */
452 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
453 /* 09-30-2020 Timothy Stapko Modified comment(s), */
454 /* verified memcpy use cases, */
455 /* resulting in version 6.1 */
456 /* */
457 /**************************************************************************/
_nx_crypto_gcm_encrypt_init(VOID * crypto_metadata,NX_CRYPTO_GCM * gcm_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),VOID * additional_data,UINT additional_len,UCHAR * iv,UINT block_size)458 NX_CRYPTO_KEEP UINT _nx_crypto_gcm_encrypt_init(VOID *crypto_metadata, NX_CRYPTO_GCM *gcm_metadata,
459 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
460 VOID *additional_data, UINT additional_len,
461 UCHAR *iv, UINT block_size)
462 {
463 UCHAR *hkey = gcm_metadata -> nx_crypto_gcm_hkey;
464 UCHAR *j0 = gcm_metadata -> nx_crypto_gcm_j0;
465 UCHAR *s = gcm_metadata -> nx_crypto_gcm_s;
466 UCHAR *counter = gcm_metadata -> nx_crypto_gcm_counter;
467 UCHAR tmp_block[NX_CRYPTO_GCM_BLOCK_SIZE];
468 UCHAR iv_len;
469
470 /* Check the block size. */
471 if (block_size != NX_CRYPTO_GCM_BLOCK_SIZE)
472 {
473 return(NX_CRYPTO_PTR_ERROR);
474 }
475
476 /* Generate hash key by encrypt the zero block. */
477 NX_CRYPTO_MEMSET(hkey, 0, NX_CRYPTO_GCM_BLOCK_SIZE);
478 crypto_function(crypto_metadata, hkey, hkey, NX_CRYPTO_GCM_BLOCK_SIZE);
479
480 /* Generate the pre-counter block j0. */
481 iv_len = iv[0];
482 iv = iv + 1;
483 if (iv_len == NX_CRYPTO_GCM_BLOCK_SIZE - 4)
484 {
485
486 /* When the length of IV is 12 then 1 is appended to IV to form j0. */
487 /* j0 in increased before GCTR. */
488 NX_CRYPTO_MEMCPY(j0, iv, iv_len); /* Use case of memcpy is verified. */
489 j0[12] = 0;
490 j0[13] = 0;
491 j0[14] = 0;
492 j0[15] = 1;
493 }
494 else
495 {
496
497 /* When the length of IV is not 12 then apply GHASH to the IV. */
498 NX_CRYPTO_MEMSET(j0, 0, NX_CRYPTO_GCM_BLOCK_SIZE);
499 _nx_crypto_gcm_ghash_update(hkey, iv, iv_len, j0);
500
501 /* Apply GHASH to the length of IV to form j0.*/
502 NX_CRYPTO_MEMSET(tmp_block, 0, NX_CRYPTO_GCM_BLOCK_SIZE);
503 tmp_block[NX_CRYPTO_GCM_BLOCK_SIZE - 2] = (UCHAR)(((iv_len << 3) & 0xFF00) >> 8);
504 tmp_block[NX_CRYPTO_GCM_BLOCK_SIZE - 1] = (UCHAR)((iv_len << 3) & 0x00FF);
505 _nx_crypto_gcm_ghash_update(hkey, tmp_block, NX_CRYPTO_GCM_BLOCK_SIZE, j0);
506 }
507
508 /* Apply GHASH to the additional authenticated data. */
509 NX_CRYPTO_MEMSET(s, 0, NX_CRYPTO_GCM_BLOCK_SIZE);
510 _nx_crypto_gcm_ghash_update(hkey, additional_data, additional_len, s);
511
512 /* Initial counter block for GCTR is j0 + 1. */
513 NX_CRYPTO_MEMCPY(counter, j0, NX_CRYPTO_GCM_BLOCK_SIZE); /* Use case of memcpy is verified. */
514 _nx_crypto_gcm_inc32(counter);
515
516 gcm_metadata -> nx_crypto_gcm_additional_data_len = additional_len;
517 gcm_metadata -> nx_crypto_gcm_input_total_length = 0;
518
519 #ifdef NX_SECURE_KEY_CLEAR
520 NX_CRYPTO_MEMSET(tmp_block, 0, sizeof(tmp_block));
521 #endif
522
523 return(NX_CRYPTO_SUCCESS);
524 }
525
526 /**************************************************************************/
527 /* */
528 /* FUNCTION RELEASE */
529 /* */
530 /* _nx_crypto_gcm_encrypt_update PORTABLE C */
531 /* 6.1 */
532 /* AUTHOR */
533 /* */
534 /* Timothy Stapko, Microsoft Corporation */
535 /* */
536 /* DESCRIPTION */
537 /* */
538 /* This function updates data for GCM encryption. */
539 /* */
540 /* INPUT */
541 /* */
542 /* crypto_metadata Pointer to crypto metadata */
543 /* gcm_metadata Pointer to GCM metadata */
544 /* crypto_function Pointer to crypto function */
545 /* input Pointer to bytes of input */
546 /* output Pointer to output buffer */
547 /* length Length of bytes of input */
548 /* block_size Block size of crypto algorithm*/
549 /* */
550 /* OUTPUT */
551 /* */
552 /* status */
553 /* */
554 /* CALLS */
555 /* */
556 /* _nx_crypto_gcm_gctr Update data for GCM mode */
557 /* _nx_crypto_gcm_ghash_update Update GHASH */
558 /* */
559 /* CALLED BY */
560 /* */
561 /* _nx_crypto_method_aes_gcm_operation Handle AES encrypt or decrypt */
562 /* */
563 /* RELEASE HISTORY */
564 /* */
565 /* DATE NAME DESCRIPTION */
566 /* */
567 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
568 /* 09-30-2020 Timothy Stapko Modified comment(s), */
569 /* resulting in version 6.1 */
570 /* */
571 /**************************************************************************/
_nx_crypto_gcm_encrypt_update(VOID * crypto_metadata,NX_CRYPTO_GCM * gcm_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * input,UCHAR * output,UINT length,UINT block_size)572 NX_CRYPTO_KEEP UINT _nx_crypto_gcm_encrypt_update(VOID *crypto_metadata, NX_CRYPTO_GCM *gcm_metadata,
573 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
574 UCHAR *input, UCHAR *output, UINT length,
575 UINT block_size)
576 {
577 UCHAR *hkey = gcm_metadata -> nx_crypto_gcm_hkey;
578 UCHAR *s = gcm_metadata -> nx_crypto_gcm_s;
579 UCHAR *counter = gcm_metadata -> nx_crypto_gcm_counter;
580
581 /* Check the block size. */
582 if (block_size != NX_CRYPTO_GCM_BLOCK_SIZE)
583 {
584 return(NX_CRYPTO_PTR_ERROR);
585 }
586
587 /* Invoke GCTR function to encrypt or decrypt the input message. */
588 _nx_crypto_gcm_gctr(crypto_metadata, crypto_function, input, output, length, counter);
589
590 /* Apply GHASH to the cipher text. */
591 _nx_crypto_gcm_ghash_update(hkey, output, length, s);
592
593 gcm_metadata -> nx_crypto_gcm_input_total_length += length;
594
595 return(NX_CRYPTO_SUCCESS);
596 }
597
598 /**************************************************************************/
599 /* */
600 /* FUNCTION RELEASE */
601 /* */
602 /* _nx_crypto_gcm_encrypt_calculate PORTABLE C */
603 /* 6.1 */
604 /* AUTHOR */
605 /* */
606 /* Timothy Stapko, Microsoft Corporation */
607 /* */
608 /* DESCRIPTION */
609 /* */
610 /* This function calculates TAG for GCM mode. */
611 /* */
612 /* INPUT */
613 /* */
614 /* crypto_metadata Pointer to crypto metadata */
615 /* gcm_metadata Pointer to GCM metadata */
616 /* crypto_function Pointer to crypto function */
617 /* output Pointer to output buffer */
618 /* icv_len Length of TAG */
619 /* block_size Block size of crypto algorithm*/
620 /* */
621 /* OUTPUT */
622 /* */
623 /* status */
624 /* */
625 /* CALLS */
626 /* */
627 /* _nx_crypto_gcm_gctr Update data for GCM mode */
628 /* _nx_crypto_gcm_ghash_update Update GHASH */
629 /* */
630 /* CALLED BY */
631 /* */
632 /* _nx_crypto_method_aes_gcm_operation Handle AES encrypt or decrypt */
633 /* */
634 /* RELEASE HISTORY */
635 /* */
636 /* DATE NAME DESCRIPTION */
637 /* */
638 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
639 /* 09-30-2020 Timothy Stapko Modified comment(s), */
640 /* verified memcpy use cases, */
641 /* resulting in version 6.1 */
642 /* */
643 /**************************************************************************/
_nx_crypto_gcm_encrypt_calculate(VOID * crypto_metadata,NX_CRYPTO_GCM * gcm_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * output,UINT icv_len,UINT block_size)644 NX_CRYPTO_KEEP UINT _nx_crypto_gcm_encrypt_calculate(VOID *crypto_metadata, NX_CRYPTO_GCM *gcm_metadata,
645 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
646 UCHAR *output, UINT icv_len, UINT block_size)
647 {
648 UCHAR *hkey = gcm_metadata -> nx_crypto_gcm_hkey;
649 UCHAR *j0 = gcm_metadata -> nx_crypto_gcm_j0;
650 UCHAR *s = gcm_metadata -> nx_crypto_gcm_s;
651 UCHAR tmp_block[NX_CRYPTO_GCM_BLOCK_SIZE];
652 UINT additional_len = gcm_metadata -> nx_crypto_gcm_additional_data_len;
653 UINT length;
654
655 /* Check the block size. */
656 if (block_size != NX_CRYPTO_GCM_BLOCK_SIZE)
657 {
658 return(NX_CRYPTO_PTR_ERROR);
659 }
660
661 /* Apply GHASH to the length of additional authenticated data and the length of cipher text. */
662 length = gcm_metadata -> nx_crypto_gcm_input_total_length;
663 tmp_block[0] = 0;
664 tmp_block[1] = 0;
665 tmp_block[2] = 0;
666 tmp_block[3] = 0;
667 tmp_block[4] = (UCHAR)(((additional_len << 3) & 0xFF000000) >> 24);
668 tmp_block[5] = (UCHAR)(((additional_len << 3) & 0x00FF0000) >> 16);
669 tmp_block[6] = (UCHAR)(((additional_len << 3) & 0x0000FF00) >> 8);
670 tmp_block[7] = (UCHAR)((additional_len << 3) & 0x000000FF);
671 tmp_block[8] = 0;
672 tmp_block[9] = 0;
673 tmp_block[10] = 0;
674 tmp_block[11] = 0;
675 tmp_block[12] = (UCHAR)(((length << 3) & 0xFF000000) >> 24);
676 tmp_block[13] = (UCHAR)(((length << 3) & 0x00FF0000) >> 16);
677 tmp_block[14] = (UCHAR)(((length << 3) & 0x0000FF00) >> 8);
678 tmp_block[15] = (UCHAR)((length << 3) & 0x000000FF);
679 _nx_crypto_gcm_ghash_update(hkey, tmp_block, NX_CRYPTO_GCM_BLOCK_SIZE, s);
680
681 /* Encrypt the GHASH result using GCTR with j0 as initial counter block.
682 The result is the authentication tag. */
683 _nx_crypto_gcm_gctr(crypto_metadata, crypto_function, s, s, NX_CRYPTO_GCM_BLOCK_SIZE, j0);
684
685 /* Append authentication tag to the end of the cipher text. */
686 NX_CRYPTO_MEMCPY(output, s, icv_len); /* Use case of memcpy is verified. */
687
688 #ifdef NX_SECURE_KEY_CLEAR
689 NX_CRYPTO_MEMSET(tmp_block, 0, sizeof(tmp_block));
690 #endif
691
692 return(NX_CRYPTO_SUCCESS);
693 }
694
695 /**************************************************************************/
696 /* */
697 /* FUNCTION RELEASE */
698 /* */
699 /* _nx_crypto_gcm_decrypt_update PORTABLE C */
700 /* 6.1 */
701 /* AUTHOR */
702 /* */
703 /* Timothy Stapko, Microsoft Corporation */
704 /* */
705 /* DESCRIPTION */
706 /* */
707 /* This function updates data for GCM decryption. */
708 /* */
709 /* INPUT */
710 /* */
711 /* crypto_metadata Pointer to crypto metadata */
712 /* gcm_metadata Pointer to GCM metadata */
713 /* crypto_function Pointer to crypto function */
714 /* input Pointer to bytes of input */
715 /* output Pointer to output buffer */
716 /* length Length of bytes of input */
717 /* block_size Block size of crypto algorithm*/
718 /* */
719 /* OUTPUT */
720 /* */
721 /* status */
722 /* */
723 /* CALLS */
724 /* */
725 /* _nx_crypto_gcm_gctr Update data for GCM mode */
726 /* _nx_crypto_gcm_ghash_update Update GHASH */
727 /* */
728 /* CALLED BY */
729 /* */
730 /* _nx_crypto_method_aes_gcm_operation Handle AES encrypt or decrypt */
731 /* */
732 /* RELEASE HISTORY */
733 /* */
734 /* DATE NAME DESCRIPTION */
735 /* */
736 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
737 /* 09-30-2020 Timothy Stapko Modified comment(s), */
738 /* resulting in version 6.1 */
739 /* */
740 /**************************************************************************/
_nx_crypto_gcm_decrypt_update(VOID * crypto_metadata,NX_CRYPTO_GCM * gcm_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * input,UCHAR * output,UINT length,UINT block_size)741 NX_CRYPTO_KEEP UINT _nx_crypto_gcm_decrypt_update(VOID *crypto_metadata, NX_CRYPTO_GCM *gcm_metadata,
742 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
743 UCHAR *input, UCHAR *output, UINT length,
744 UINT block_size)
745 {
746 UCHAR *hkey = gcm_metadata -> nx_crypto_gcm_hkey;
747 UCHAR *s = gcm_metadata -> nx_crypto_gcm_s;
748 UCHAR *counter = gcm_metadata -> nx_crypto_gcm_counter;
749
750 /* Check the block size. */
751 if (block_size != NX_CRYPTO_GCM_BLOCK_SIZE)
752 {
753 return(NX_CRYPTO_PTR_ERROR);
754 }
755
756 /* Apply GHASH to the cipher text. */
757 _nx_crypto_gcm_ghash_update(hkey, input, length, s);
758
759 /* Invoke GCTR function to encrypt or decrypt the input message. */
760 _nx_crypto_gcm_gctr(crypto_metadata, crypto_function, input, output, length, counter);
761
762 gcm_metadata -> nx_crypto_gcm_input_total_length += length;
763
764 return(NX_CRYPTO_SUCCESS);
765 }
766
767 /**************************************************************************/
768 /* */
769 /* FUNCTION RELEASE */
770 /* */
771 /* _nx_crypto_gcm_decrypt_calculate PORTABLE C */
772 /* 6.1 */
773 /* AUTHOR */
774 /* */
775 /* Timothy Stapko, Microsoft Corporation */
776 /* */
777 /* DESCRIPTION */
778 /* */
779 /* This function verifies the TAG for GCM mode. */
780 /* */
781 /* INPUT */
782 /* */
783 /* crypto_metadata Pointer to crypto metadata */
784 /* gcm_metadata Pointer to GCM metadata */
785 /* crypto_function Pointer to crypto function */
786 /* input Pointer to TAG buffer */
787 /* icv_len Length of TAG */
788 /* block_size Block size of crypto algorithm*/
789 /* */
790 /* OUTPUT */
791 /* */
792 /* status */
793 /* */
794 /* CALLS */
795 /* */
796 /* _nx_crypto_gcm_gctr Update data for GCM mode */
797 /* _nx_crypto_gcm_ghash_update Update GHASH */
798 /* */
799 /* CALLED BY */
800 /* */
801 /* _nx_crypto_method_aes_gcm_operation Handle AES encrypt or decrypt */
802 /* */
803 /* RELEASE HISTORY */
804 /* */
805 /* DATE NAME DESCRIPTION */
806 /* */
807 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
808 /* 09-30-2020 Timothy Stapko Modified comment(s), */
809 /* resulting in version 6.1 */
810 /* */
811 /**************************************************************************/
_nx_crypto_gcm_decrypt_calculate(VOID * crypto_metadata,NX_CRYPTO_GCM * gcm_metadata,UINT (* crypto_function)(VOID *,UCHAR *,UCHAR *,UINT),UCHAR * input,UINT icv_len,UINT block_size)812 NX_CRYPTO_KEEP UINT _nx_crypto_gcm_decrypt_calculate(VOID *crypto_metadata, NX_CRYPTO_GCM *gcm_metadata,
813 UINT (*crypto_function)(VOID *, UCHAR *, UCHAR *, UINT),
814 UCHAR *input, UINT icv_len, UINT block_size)
815 {
816 UCHAR *hkey = gcm_metadata -> nx_crypto_gcm_hkey;
817 UCHAR *j0 = gcm_metadata -> nx_crypto_gcm_j0;
818 UCHAR *s = gcm_metadata -> nx_crypto_gcm_s;
819 UCHAR tmp_block[NX_CRYPTO_GCM_BLOCK_SIZE];
820 UINT additional_len = gcm_metadata -> nx_crypto_gcm_additional_data_len;
821 UINT length;
822 UINT i;
823
824 /* Check the block size. */
825 if (block_size != NX_CRYPTO_GCM_BLOCK_SIZE)
826 {
827 return(NX_CRYPTO_PTR_ERROR);
828 }
829
830 /* Apply GHASH to the length of additional authenticated data and the length of cipher text. */
831 length = gcm_metadata -> nx_crypto_gcm_input_total_length;
832 tmp_block[0] = 0;
833 tmp_block[1] = 0;
834 tmp_block[2] = 0;
835 tmp_block[3] = 0;
836 tmp_block[4] = (UCHAR)(((additional_len << 3) & 0xFF000000) >> 24);
837 tmp_block[5] = (UCHAR)(((additional_len << 3) & 0x00FF0000) >> 16);
838 tmp_block[6] = (UCHAR)(((additional_len << 3) & 0x0000FF00) >> 8);
839 tmp_block[7] = (UCHAR)((additional_len << 3) & 0x000000FF);
840 tmp_block[8] = 0;
841 tmp_block[9] = 0;
842 tmp_block[10] = 0;
843 tmp_block[11] = 0;
844 tmp_block[12] = (UCHAR)(((length << 3) & 0xFF000000) >> 24);
845 tmp_block[13] = (UCHAR)(((length << 3) & 0x00FF0000) >> 16);
846 tmp_block[14] = (UCHAR)(((length << 3) & 0x0000FF00) >> 8);
847 tmp_block[15] = (UCHAR)((length << 3) & 0x000000FF);
848 _nx_crypto_gcm_ghash_update(hkey, tmp_block, NX_CRYPTO_GCM_BLOCK_SIZE, s);
849
850 #ifdef NX_SECURE_KEY_CLEAR
851 NX_CRYPTO_MEMSET(tmp_block, 0, sizeof(tmp_block));
852 #endif
853
854 /* Encrypt the GHASH result using GCTR with j0 as initial counter block.
855 The result is the authentication tag. */
856 _nx_crypto_gcm_gctr(crypto_metadata, crypto_function, s, s, NX_CRYPTO_GCM_BLOCK_SIZE, j0);
857
858 for (i = 0; i < icv_len; i++)
859 {
860 if (input[i] != s[i])
861 {
862
863 /* Authentication failed. */
864 return(NX_CRYPTO_AUTHENTICATION_FAILED);
865 }
866 }
867
868 return(NX_CRYPTO_SUCCESS);
869 }
870