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