ReactOS 0.4.17-dev-1005-g171e1de
gcm.c
Go to the documentation of this file.
1//
2// gcm.c Implementation of the GCM block cipher mode
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7#include "precomp.h"
8
9#define GCM_MIN_NONCE_SIZE (1)
10#define GCM_MIN_TAG_SIZE (12)
11#define GCM_MAX_TAG_SIZE (16)
12
13
19 _In_ UINT64 cbAssociatedData,
22{
23 if( pBlockCipher->blockSize != SYMCRYPT_GCM_BLOCK_SIZE )
24 {
25 return SYMCRYPT_WRONG_BLOCK_SIZE;
26 }
27
28 //
29 // SP800-38D specifies that the nonce must be at least one bit, but we operate on bytes,
30 // so the minimum is one byte.
31 //
33 {
34 return SYMCRYPT_WRONG_NONCE_SIZE;
35 }
36
37 //
38 // cbAssociatedData is limited to <2^61 bytes
39 //
40 if( (cbAssociatedData >> 61) > 0 )
41 {
42 return SYMCRYPT_WRONG_DATA_SIZE;
43 }
44
45 //
46 // per SP800-38D cbData is limited to 2^36 - 32 bytes
47 //
49 {
50 return SYMCRYPT_WRONG_DATA_SIZE;
51 }
52
53 if( cbTag < GCM_MIN_TAG_SIZE || cbTag > GCM_MAX_TAG_SIZE )
54 {
55 return SYMCRYPT_WRONG_TAG_SIZE;
56 }
57
58 return SYMCRYPT_NO_ERROR;
59}
60
61
62
63VOID
69{
70 SIZE_T bytesToProcess;
71 if( pState->bytesInMacBlock > 0 )
72 {
73 bytesToProcess = SYMCRYPT_MIN( cbData, SYMCRYPT_GCM_BLOCK_SIZE - pState->bytesInMacBlock );
74 memcpy( &pState->macBlock[pState->bytesInMacBlock], pbData, bytesToProcess );
75 pbData += bytesToProcess;
76 cbData -= bytesToProcess;
77 pState->bytesInMacBlock += bytesToProcess;
78
79 if( pState->bytesInMacBlock == SYMCRYPT_GCM_BLOCK_SIZE )
80 {
81 SymCryptGHashAppendData( &pState->pKey->ghashKey,
82 &pState->ghashState,
83 &pState->macBlock[0],
85 pState->bytesInMacBlock = 0;
86 }
87 }
88
90 {
91 bytesToProcess = cbData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
92
93 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, pbData, bytesToProcess );
94
95 pbData += bytesToProcess;
96 cbData -= bytesToProcess;
97 }
98
99 if( cbData > 0 )
100 {
101 memcpy( &pState->macBlock[0], pbData, cbData );
102 pState->bytesInMacBlock = cbData;
103 }
104}
105
106
107
108VOID
111{
112 SIZE_T nBytes;
113 //
114 // Pad the MAC data with zeroes until we hit the block size.
115 //
116 nBytes = pState->bytesInMacBlock;
117 if( nBytes > 0 )
118 {
119 SymCryptWipe( &pState->macBlock[nBytes], SYMCRYPT_GCM_BLOCK_SIZE - nBytes );
120 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
121 pState->bytesInMacBlock = 0;
122 }
123}
124
125
126
127VOID
133 SIZE_T cbData )
134{
135 SIZE_T bytesToProcess;
136 SIZE_T bytesUsedInKeyStreamBuffer;
137
138 bytesUsedInKeyStreamBuffer = (SIZE_T) (pState->cbData & SYMCRYPT_GCM_BLOCK_MOD_MASK);
139
140 //
141 // We update pState->cbData once before we modify cbData.
142 // pState->cbData is not used in the rest of this function
143 //
145 pState->cbData += cbData;
146
147 if( bytesUsedInKeyStreamBuffer != 0 )
148 {
149 bytesToProcess = SYMCRYPT_MIN( cbData, SYMCRYPT_GCM_BLOCK_SIZE - bytesUsedInKeyStreamBuffer );
150 SymCryptXorBytes( pbSrc, &pState->keystreamBlock[bytesUsedInKeyStreamBuffer], pbDst, bytesToProcess );
151 pbSrc += bytesToProcess;
152 pbDst += bytesToProcess;
153 cbData -= bytesToProcess;
154
155 //
156 // If there are bytes left in the key stream buffer, then cbData == 0 and we're done.
157 // If we used up all the bytes, then we are fine, no need to compute the next key stream block
158 //
159 }
160
162 {
163 bytesToProcess = cbData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
164
165 SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
166 SymCryptCtrMsb32( pState->pKey->pBlockCipher,
167 &pState->pKey->blockcipherKey,
168 &pState->counterBlock[0],
169 pbSrc,
170 pbDst,
171 bytesToProcess );
172
173 pbSrc += bytesToProcess;
174 pbDst += bytesToProcess;
175 cbData -= bytesToProcess;
176 }
177
178 if( cbData > 0 )
179 {
181
182 SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
183 SymCryptCtrMsb32( pState->pKey->pBlockCipher,
184 &pState->pKey->blockcipherKey,
185 &pState->counterBlock[0],
186 &pState->keystreamBlock[0],
187 &pState->keystreamBlock[0],
189
190 SymCryptXorBytes( &pState->keystreamBlock[0], pbSrc, pbDst, cbData );
191
192 //
193 // pState->cbData contains the data length after this call already, so it knows how many
194 // bytes are left in the keystream block
195 //
196 }
197
198}
199
201VOID
205{
206 // Computing the tag for GCM requires invoking the GCTR function with the pre-counter
207 // block which was computed when the nonce was set. Historically, we only supported 12-byte
208 // nonces, so we could trivially reset the counter block by just setting the last 4 bytes to
209 // (DWORD) 1. With support for larger IVs, the pre-counter block is computed from a GHash of
210 // the nonce, and we don't store the value. Adding a field in the GCM struct to store the value
211 // would be ABI-breaking, so instead we can recompute the value by decrementing the last 32 bits
212 // of the counter block by the number of blocks that have been processed (since the counter is
213 // incremented once per block), plus one for the initial increment.
214 UINT32 preCounter32 = SYMCRYPT_LOAD_MSBFIRST32(&pState->counterBlock[12]) -
216
217 SYMCRYPT_STORE_MSBFIRST32(&pState->counterBlock[12], preCounter32);
218}
219
220VOID
225{
227
228 SYMCRYPT_STORE_MSBFIRST64( &buf[16], pState->cbAuthData * 8 );
229 SYMCRYPT_STORE_MSBFIRST64( &buf[24], pState->cbData * 8 );
230
231 if( pState->bytesInMacBlock > 0 )
232 {
233 //
234 // Pad the MAC data with zeroes until we hit the block size
235 //
237 memcpy( buf, &pState->macBlock[0], pState->bytesInMacBlock );
238
239 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[0], 2 * SYMCRYPT_GCM_BLOCK_SIZE );
240 }
241 else
242 {
243 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[16], SYMCRYPT_GCM_BLOCK_SIZE );
244 }
245
247
248 //
249 // Convert the GHash state to an array of bytes
250 //
251 SYMCRYPT_STORE_MSBFIRST64( &buf[0], pState->ghashState.ull[1] );
252 SYMCRYPT_STORE_MSBFIRST64( &buf[8], pState->ghashState.ull[0] );
253
254 SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
255 SymCryptCtrMsb32( pState->pKey->pBlockCipher,
256 &pState->pKey->blockcipherKey,
257 &pState->counterBlock[0],
258 buf,
259 pbTag,
261
262 SymCryptWipeKnownSize( buf, sizeof( buf ) );
263}
264
265SYMCRYPT_NOINLINE
272 SIZE_T cbKey )
273{
275 SYMCRYPT_ERROR status = SYMCRYPT_NO_ERROR;
276
278 {
279 status = SYMCRYPT_WRONG_KEY_SIZE;
280 goto cleanup;
281 }
282
283 //
284 // Perform the Block cipher key expansion first
285 //
286 pExpandedKey->pBlockCipher = pBlockCipher;
287 status = pBlockCipher->expandKeyFunc( &pExpandedKey->blockcipherKey, pbKey, cbKey );
288
289 if( status != SYMCRYPT_NO_ERROR )
290 {
291 goto cleanup;
292 }
293
294 //
295 // We keep a copy of the key to make it easy to
296 // implement the SymCryptGcmKeyCopy function
297 //
298 pExpandedKey->cbKey = cbKey;
299 memcpy( &pExpandedKey->abKey[0], pbKey, cbKey );
300
301 //
302 // Compute H and the GHASH expanded key
303 //
304 SymCryptWipeKnownSize( H, sizeof( H ) );
305 pBlockCipher->encryptFunc( &pExpandedKey->blockcipherKey, H, H );
306
307
309
310
312
313 SymCryptWipeKnownSize( H, sizeof( H ) );
314
315cleanup:
316
317 return status;
318}
319
320VOID
323{
325
326 SYMCRYPT_CHECK_MAGIC( pSrc );
327
328 status = SymCryptGcmExpandKey( pDst, pSrc->pBlockCipher, &pSrc->abKey[0], pSrc->cbKey );
329 SYMCRYPT_ASSERT( status == SYMCRYPT_NO_ERROR );
330}
331
332VOID
336 _In_reads_( cbNonce ) PCBYTE pbNonce,
338{
340
341 // Handle the nonce depending on its size, as specified in NIST SP800-38D
342 if( cbNonce == 12 )
343 {
344 // If len(nonce) = 96 bits (12 bytes), pre-counter block = nonce || (DWORD) 1
345 memcpy( &pState->counterBlock[0], pbNonce, cbNonce );
346 SymCryptWipeKnownSize( &pState->counterBlock[12], 4 );
347 pState->counterBlock[15] = 1;
348 }
349 else
350 {
351 // If len(nonce) != 96 bits (12 bytes),
352 // pre-counter block = GHASH(nonce padded to a multiple of 128 bits || (QWORD) len(nonce))
354 SIZE_T cbNonceRemainder = cbNonce & (SYMCRYPT_GF128_BLOCK_SIZE - 1);
355
356 // Process all full blocks of the nonce, i.e. all nonce bytes up to a multiple of
357 // SYMCRYPT_GF128_BLOCK_SIZE. SymCryptGHashAppendData ignores additional data that are
358 // not a multiple of the block size. We will handle any such remaining data below.
359 // (This also works if the nonce is less than the block size.)
360 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, pbNonce, cbNonce );
361
362 // If the nonce length is not a multiple of SYMCRYPT_GF128_BLOCK_SIZE, we need to pad any
363 // remaining data to a multiple of the block size.
364 if(cbNonceRemainder > 0)
365 {
366 SymCryptWipeKnownSize( buf, sizeof(buf) );
367 memcpy(buf, pbNonce + cbNonce - cbNonceRemainder, cbNonceRemainder);
368 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, buf, sizeof(buf) );
369 }
370
371 // Now we append the length of the nonce in bits. We take the length as a 64-bit integer,
372 // but it too must be padded to 128 bits for use in GHASH.
375 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, buf, sizeof(buf) );
376
377 SymCryptGHashResult( &pState->ghashState, pState->counterBlock );
378 SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) );
379 }
380
381 // Increment the last 32 bits of the counter. We'll recalculate the pre-counter block later
382 // when computing the tag.
384 &pState->counterBlock[12],
385 1 + SYMCRYPT_LOAD_MSBFIRST32( &pState->counterBlock[12] ) );
386}
387
388SYMCRYPT_NOINLINE
389VOID
394 _In_reads_( cbNonce ) PCBYTE pbNonce,
396{
397 UNREFERENCED_PARAMETER( cbNonce ); // It is used in an ASSERT, but only in CHKed builds.
398
400
401 pState->pKey = pExpandedKey;
402 pState->cbData = 0;
403 pState->cbAuthData = 0;
404 pState->bytesInMacBlock = 0;
405 SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) );
406
408
410}
411
412
413VOID
417 _In_opt_ PCSYMCRYPT_GCM_EXPANDED_KEY pExpandedKeyCopy,
419{
420 SYMCRYPT_CHECK_MAGIC( pSrc );
421
422 *pDst = *pSrc;
423 if( pExpandedKeyCopy != NULL )
424 {
425 pDst->pKey = pExpandedKeyCopy;
426 }
427
428 SYMCRYPT_SET_MAGIC( pDst );
429}
430
431
432SYMCRYPT_NOINLINE
433VOID
437 _In_reads_opt_( cbData ) PCBYTE pbAuthData,
438 SIZE_T cbData )
439{
441 SYMCRYPT_ASSERT( pState->cbData == 0 );
442
443 SymCryptGcmAddMacData( pState, pbAuthData, cbData );
444 pState->cbAuthData += cbData;
445}
446
447SYMCRYPT_NOINLINE
448VOID
454 SIZE_T cbData )
455{
456 if( pState->cbData == 0 )
457 {
458 //
459 // This is the first actual encryption data, pad the Auth data with zeroes if needed.
460 //
462 }
463
464 if ( pState->pKey->pBlockCipher->gcmEncryptPartFunc != NULL )
465 {
466 //
467 // Use optimized implementation if available
468 //
469 (*pState->pKey->pBlockCipher->gcmEncryptPartFunc) ( pState, pbSrc, pbDst, cbData );
470 SYMCRYPT_ASSERT( pState->bytesInMacBlock <= 15 );
471 }
472 else
473 {
475 }
476}
477
478SYMCRYPT_NOINLINE
479VOID
485 SIZE_T cbData )
486{
487 //
488 // Do the actual encryption
489 //
491
492 //
493 // We break the read-once/write once rule here by reading the pbDst data back.
494 // In this particular situation this is safe, and avoiding it is expensive as it
495 // requires an extra copy and an extra memory buffer.
496 // The first write exposes the GCM key stream, independent of the underlying data that
497 // we are processing. From an attacking point of view we can think of this as literally
498 // handing over the key stream. So encryption consists of two steps:
499 // - hand over the key stream
500 // - MAC some ciphertext
501 // In this view (which has equivalent security properties to GCM) is obviously doesn't
502 // matter that we read pbDst back.
503 //
504
506}
507
508
509SYMCRYPT_NOINLINE
510VOID
516 SIZE_T cbData )
517{
518 if( pState->cbData == 0 )
519 {
520 //
521 // This is the first actual encryption data, pad the Auth data with zeroes if needed.
522 //
524 }
525
526 if ( pState->pKey->pBlockCipher->gcmDecryptPartFunc != NULL )
527 {
528 //
529 // Use optimized implementation if available
530 //
531 (*pState->pKey->pBlockCipher->gcmDecryptPartFunc) ( pState, pbSrc, pbDst, cbData );
532 SYMCRYPT_ASSERT( pState->bytesInMacBlock <= 15 );
533 }
534 else
535 {
537 }
538}
539
540SYMCRYPT_NOINLINE
541VOID
547 SIZE_T cbData )
548{
550
551 //
552 // Do the actual decryption
553 // This violates the read-once rule, but it is safe for the same reasons as above
554 // in the encryption case.
555 //
556
558}
559
560
561SYMCRYPT_NOINLINE
562VOID
566 _Out_writes_( cbTag ) PBYTE pbTag,
567 SIZE_T cbTag )
568{
570
572
574 memcpy( pbTag, buf, cbTag );
575
576 SymCryptWipeKnownSize( buf, sizeof( buf ) );
577
578 SymCryptWipeKnownSize( pState, sizeof( *pState ) );
579 SYMCRYPT_ASSERT( pState->bytesInMacBlock == 0 );
580}
581
582SYMCRYPT_NOINLINE
587 _In_reads_( cbTag ) PCBYTE pbTag,
588 SIZE_T cbTag )
589{
592
594
596
597 if( !SymCryptEqual( pbTag, buf, cbTag ) )
598 {
599 status = SYMCRYPT_AUTHENTICATION_FAILURE;
600 }
601 else
602 {
603 status = SYMCRYPT_NO_ERROR;
604 }
605
606 SymCryptWipeKnownSize( buf, sizeof( buf ) );
607
608 SymCryptWipeKnownSize( pState, sizeof( *pState ) );
609 SYMCRYPT_ASSERT( pState->bytesInMacBlock == 0 );
610
611 return status;
612}
613
614
615SYMCRYPT_NOINLINE
616VOID
620 _In_reads_( cbNonce ) PCBYTE pbNonce,
622 _In_reads_opt_( cbAuthData ) PCBYTE pbAuthData,
627 _Out_writes_( cbTag ) PBYTE pbTag,
628 SIZE_T cbTag )
629{
633
634 // SymCryptGcmInit( &state, pExpandedKey, pbNonce, cbNonce );
635 UNREFERENCED_PARAMETER( cbNonce ); // It is used in an ASSERT, but only in CHKed builds.
636
639
641
642 pState->pKey = pExpandedKey;
643 pState->cbData = 0;
644 pState->cbAuthData = 0;
645 pState->bytesInMacBlock = 0;
646 SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) );
647
649
650 // SymCryptGcmAuthPart( &state, pbAuthData, cbAuthData );
651 pState->cbAuthData += cbAuthData;
653 {
655
656 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, pbAuthData, bytesToDo );
657
658 pbAuthData += bytesToDo;
659 cbAuthData -= bytesToDo;
660 }
661
662 if( cbAuthData > 0 )
663 {
664 //
665 // Pad the MAC data with zeroes until we hit the block size.
666 //
668 memcpy( &pState->macBlock[0], pbAuthData, cbAuthData );
669 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
670 }
671
672 // SymCryptGcmEncryptPart( &state, pbSrc, pbDst, cbData );
673 if ( pState->pKey->pBlockCipher->gcmEncryptPartFunc != NULL )
674 {
675 //
676 // Use optimized implementation if available
677 //
678 (*pState->pKey->pBlockCipher->gcmEncryptPartFunc) ( pState, pbSrc, pbDst, cbData );
679 }
680 else
681 {
683 }
684
685 // SymCryptGcmEncryptFinal( &state, pbTag, cbTag );
686 SYMCRYPT_STORE_MSBFIRST64( &buf[16], pState->cbAuthData * 8 );
687 SYMCRYPT_STORE_MSBFIRST64( &buf[24], pState->cbData * 8 );
688
689 if( pState->bytesInMacBlock > 0 )
690 {
691 //
692 // Pad the MAC data with zeroes until we hit the block size
693 //
695 memcpy( buf, &pState->macBlock[0], pState->bytesInMacBlock );
696
697 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[0], 2 * SYMCRYPT_GCM_BLOCK_SIZE );
698 }
699 else
700 {
701 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[16], SYMCRYPT_GCM_BLOCK_SIZE );
702 }
703
704 // Reset the counter block prior to computing the tag
706
707 //
708 // Convert the GHash state to an array of bytes
709 //
710 SYMCRYPT_STORE_MSBFIRST64( &buf[0], pState->ghashState.ull[1] );
711 SYMCRYPT_STORE_MSBFIRST64( &buf[8], pState->ghashState.ull[0] );
712
713 SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
714 SymCryptCtrMsb32( pState->pKey->pBlockCipher,
715 &pState->pKey->blockcipherKey,
716 &pState->counterBlock[0],
717 buf,
718 buf,
720
721 memcpy( pbTag, buf, cbTag );
722
723 SymCryptWipeKnownSize( buf, sizeof( buf ) );
724 SymCryptWipeKnownSize( pState, sizeof( *pState ) );
725}
726
727
728SYMCRYPT_NOINLINE
733 _In_reads_( cbNonce ) PCBYTE pbNonce,
735 _In_reads_opt_( cbAuthData ) PCBYTE pbAuthData,
740 _In_reads_( cbTag ) PCBYTE pbTag,
741 SIZE_T cbTag )
742{
747
748 // SymCryptGcmInit( &state, pExpandedKey, pbNonce, cbNonce );
749 UNREFERENCED_PARAMETER( cbNonce ); // It is used in an ASSERT, but only in CHKed builds.
750
753
755
756 pState->pKey = pExpandedKey;
757 pState->cbData = 0;
758 pState->cbAuthData = 0;
759 pState->bytesInMacBlock = 0;
760 SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) );
761
763
764 // SymCryptGcmAuthPart( &state, pbAuthData, cbAuthData );
765 pState->cbAuthData += cbAuthData;
767 {
769
770 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, pbAuthData, bytesToDo );
771
772 pbAuthData += bytesToDo;
773 cbAuthData -= bytesToDo;
774 }
775
776 if( cbAuthData > 0 )
777 {
778 //
779 // Pad the MAC data with zeroes until we hit the block size.
780 //
782 memcpy( &pState->macBlock[0], pbAuthData, cbAuthData );
783 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
784 }
785
786 // SymCryptGcmDecryptPart( &state, pbSrc, pbDst, cbData );
787 if ( pState->pKey->pBlockCipher->gcmDecryptPartFunc != NULL )
788 {
789 //
790 // Use optimized implementation if available
791 //
792 (*pState->pKey->pBlockCipher->gcmDecryptPartFunc) ( pState, pbSrc, pbDst, cbData );
793 }
794 else
795 {
797 }
798
799 //status = SymCryptGcmDecryptFinal( &state, pbTag, cbTag );
800 SYMCRYPT_STORE_MSBFIRST64( &buf[16], pState->cbAuthData * 8 );
801 SYMCRYPT_STORE_MSBFIRST64( &buf[24], pState->cbData * 8 );
802
803 if( pState->bytesInMacBlock > 0 )
804 {
805 //
806 // Pad the MAC data with zeroes until we hit the block size
807 //
809 memcpy( buf, &pState->macBlock[0], pState->bytesInMacBlock );
810
811 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[0], 2 * SYMCRYPT_GCM_BLOCK_SIZE );
812 }
813 else
814 {
815 SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[16], SYMCRYPT_GCM_BLOCK_SIZE );
816 }
817
819
820 //
821 // Convert the GHash state to an array of bytes
822 //
823 SYMCRYPT_STORE_MSBFIRST64( &buf[0], pState->ghashState.ull[1] );
824 SYMCRYPT_STORE_MSBFIRST64( &buf[8], pState->ghashState.ull[0] );
825
826 SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
827 SymCryptCtrMsb32( pState->pKey->pBlockCipher,
828 &pState->pKey->blockcipherKey,
829 &pState->counterBlock[0],
830 buf,
831 buf,
833
834 if( !SymCryptEqual( pbTag, buf, cbTag ) )
835 {
836 status = SYMCRYPT_AUTHENTICATION_FAILURE;
837 }
838 else
839 {
840 status = SYMCRYPT_NO_ERROR;
841 }
842
843 SymCryptWipeKnownSize( buf, sizeof( buf ) );
844 SymCryptWipeKnownSize( pState, sizeof( *pState ) );
845
846 if( status != SYMCRYPT_NO_ERROR )
847 {
849 }
850
851 return status;
852}
853
854
856{
857 0xa5, 0x4c, 0x60,
858 0x80, 0xb0, 0x48, 0x6d, 0x03, 0x9f, 0xea, 0xc3, 0x3c, 0x28, 0x96, 0x3f, 0x99, 0x8a, 0x77, 0x43,
859};
860
861VOID
864{
868
869 if( SymCryptGcmExpandKey( &key, SymCryptAesBlockCipher, SymCryptTestKey32, 16 ) != SYMCRYPT_NO_ERROR )
870 {
871 SymCryptFatal( 'gcm0' );
872 }
873
875 &SymCryptTestKey32[16], 12,
876 NULL, 0,
877 &SymCryptTestMsg3[0], buf, 3,
879
880 SymCryptInjectError( buf, sizeof( buf ) );
881 if( memcmp( buf, SymCryptGcmSelftestResult, sizeof( buf ) ) != 0 )
882 {
883 SymCryptFatal( 'gcm1' );
884 }
885
886 // inject error into the ciphertext or tag
887 SymCryptInjectError( buf, sizeof( buf ) );
888
890 &SymCryptTestKey32[16], 12,
891 NULL, 0,
892 buf, buf, 3,
894
896
897 if( err != SYMCRYPT_NO_ERROR || memcmp( buf, SymCryptTestMsg3, 3 ) != 0 )
898 {
899 SymCryptFatal( 'gcm2' );
900 }
901
902}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
static int state
Definition: maze.c:121
VOID SYMCRYPT_CALL SymCryptCtrMsb32(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _Inout_updates_(pBlockCipher->blockSize) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
#define NULL
Definition: types.h:112
static void cleanup(void)
Definition: main.c:1335
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
VOID SYMCRYPT_CALL SymCryptGHashResult(_In_ PCSYMCRYPT_GF128_ELEMENT pState, _Out_writes_(SYMCRYPT_GF128_BLOCK_SIZE) PBYTE pbResult)
Definition: ghash.c:108
VOID SYMCRYPT_CALL SymCryptGHashExpandKey(_Out_ PSYMCRYPT_GHASH_EXPANDED_KEY expandedKey, _In_reads_(SYMCRYPT_GF128_BLOCK_SIZE) PCBYTE pH)
Definition: ghash.c:816
VOID SYMCRYPT_CALL SymCryptGHashAppendData(_In_ PCSYMCRYPT_GHASH_EXPANDED_KEY expandedKey, _Inout_ PSYMCRYPT_GF128_ELEMENT pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: ghash.c:884
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define H
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Inout_
Definition: no_sal2.h:162
#define _Out_writes_(s)
Definition: no_sal2.h:176
#define _Out_
Definition: no_sal2.h:160
#define _In_reads_opt_(s)
Definition: no_sal2.h:222
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
BYTE * PBYTE
Definition: pedump.c:66
#define err(...)
VOID SYMCRYPT_CALL SymCryptInjectError(PBYTE pbData, SIZE_T cbData)
const BYTE SymCryptTestKey32[32]
Definition: selftest.c:10
const BYTE SymCryptTestMsg3[3]
Definition: selftest.c:8
VOID SYMCRYPT_CALL SymCryptGcmAddMacData(_Inout_ PSYMCRYPT_GCM_STATE pState, _In_reads_opt_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: gcm.c:65
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptGcmDecrypt(_In_ PCSYMCRYPT_GCM_EXPANDED_KEY pExpandedKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData, _In_reads_(cbTag) PCBYTE pbTag, SIZE_T cbTag)
Definition: gcm.c:731
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptGcmDecryptFinal(_Inout_ PSYMCRYPT_GCM_STATE pState, _In_reads_(cbTag) PCBYTE pbTag, SIZE_T cbTag)
Definition: gcm.c:585
VOID SYMCRYPT_CALL SymCryptGcmPadMacData(_Inout_ PSYMCRYPT_GCM_STATE pState)
Definition: gcm.c:110
VOID SYMCRYPT_CALL SymCryptGcmEncryptDecryptPart(_Inout_ PSYMCRYPT_GCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: gcm.c:129
static const BYTE SymCryptGcmSelftestResult[3+SYMCRYPT_AES_BLOCK_SIZE]
Definition: gcm.c:855
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptGcmEncrypt(_In_ PCSYMCRYPT_GCM_EXPANDED_KEY pExpandedKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData, _Out_writes_(cbTag) PBYTE pbTag, SIZE_T cbTag)
Definition: gcm.c:618
VOID SYMCRYPT_CALL SymCryptGcmKeyCopy(_In_ PCSYMCRYPT_GCM_EXPANDED_KEY pSrc, _Out_ PSYMCRYPT_GCM_EXPANDED_KEY pDst)
Definition: gcm.c:322
#define GCM_MAX_TAG_SIZE
Definition: gcm.c:11
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptGcmDecryptPart(_Inout_ PSYMCRYPT_GCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: gcm.c:512
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptGcmEncryptPart(_Inout_ PSYMCRYPT_GCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: gcm.c:450
VOID SYMCRYPT_CALL SymCryptGcmStateCopy(_In_ PCSYMCRYPT_GCM_STATE pSrc, _In_opt_ PCSYMCRYPT_GCM_EXPANDED_KEY pExpandedKeyCopy, _Out_ PSYMCRYPT_GCM_STATE pDst)
Definition: gcm.c:415
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptGcmDecryptPartTwoPass(_Inout_ PSYMCRYPT_GCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: gcm.c:543
#define GCM_MIN_TAG_SIZE
Definition: gcm.c:10
#define GCM_MIN_NONCE_SIZE
Definition: gcm.c:9
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptGcmInit(_Out_ PSYMCRYPT_GCM_STATE pState, _In_ PCSYMCRYPT_GCM_EXPANDED_KEY pExpandedKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce)
Definition: gcm.c:391
VOID SYMCRYPT_CALL SymCryptGcmSelftest(void)
Definition: gcm.c:863
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptGcmExpandKey(_Out_ PSYMCRYPT_GCM_EXPANDED_KEY pExpandedKey, _In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey)
Definition: gcm.c:268
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptGcmValidateParameters(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ SIZE_T cbNonce, _In_ UINT64 cbAssociatedData, _In_ UINT64 cbData, _In_ SIZE_T cbTag)
Definition: gcm.c:16
VOID SYMCRYPT_CALL SymCryptGcmComputeTag(_Inout_ PSYMCRYPT_GCM_STATE pState, _Out_writes_(SYMCRYPT_GCM_BLOCK_SIZE) PBYTE pbTag)
Definition: gcm.c:222
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptGcmAuthPart(_Inout_ PSYMCRYPT_GCM_STATE pState, _In_reads_opt_(cbData) PCBYTE pbAuthData, SIZE_T cbData)
Definition: gcm.c:435
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptGcmEncryptFinal(_Inout_ PSYMCRYPT_GCM_STATE pState, _Out_writes_(cbTag) PBYTE pbTag, SIZE_T cbTag)
Definition: gcm.c:564
VOID SYMCRYPT_CALL SymCryptGcmSetNonce(_Out_ PSYMCRYPT_GCM_STATE pState, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce)
Definition: gcm.c:334
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptGcmEncryptPartTwoPass(_Inout_ PSYMCRYPT_GCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: gcm.c:481
FORCEINLINE VOID SYMCRYPT_CALL SymCryptGcmResetCounterBlock(_Inout_ PSYMCRYPT_GCM_STATE pState)
Definition: gcm.c:203
PSYMCRYPT_BLOCKCIPHER_CRYPT encryptFunc
PSYMCRYPT_BLOCKCIPHER_EXPAND_KEY expandKeyFunc
Definition: copy.c:22
Definition: ps.c:97
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
#define SYMCRYPT_LOAD_MSBFIRST32(p)
Definition: symcrypt.h:303
const PCSYMCRYPT_BLOCKCIPHER SymCryptAesBlockCipher
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
VOID SYMCRYPT_CALL SymCryptXorBytes(_In_reads_(cbBytes) PCBYTE pbSrc1, _In_reads_(cbBytes) PCBYTE pbSrc2, _Out_writes_(cbBytes) PBYTE pbResult, SIZE_T cbBytes)
Definition: libmain.c:236
#define SYMCRYPT_AES_BLOCK_SIZE
Definition: symcrypt.h:4255
#define SYMCRYPT_STORE_MSBFIRST32(p, v)
Definition: symcrypt.h:311
BOOLEAN SYMCRYPT_CALL SymCryptEqual(_In_reads_(cbBytes) PCBYTE pbSrc1, _In_reads_(cbBytes) PCBYTE pbSrc2, SIZE_T cbBytes)
Definition: equal.c:11
#define SYMCRYPT_STORE_MSBFIRST64(p, v)
Definition: symcrypt.h:312
SYMCRYPT_ERROR
Definition: symcrypt.h:227
SIZE_T cbTag
#define SYMCRYPT_ALIGN
PCBYTE pbSrc
#define SYMCRYPT_CALL
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_GCM_STATE
#define SYMCRYPT_GCM_BLOCK_SIZE
PCBYTE pbKey
UINT64 cbAuthData
#define SYMCRYPT_GCM_BLOCK_MOD_MASK
PCBYTE SIZE_T cbKey
PCSYMCRYPT_BLOCKCIPHER pBlockCipher
#define SYMCRYPT_GF128_BLOCK_SIZE
#define SYMCRYPT_MIN(_a, _b)
PCBYTE PBYTE SIZE_T cbData
#define SYMCRYPT_SET_MAGIC(p)
PCBYTE PBYTE pbDst
SIZE_T cbNonce
#define SYMCRYPT_GCM_MAX_DATA_SIZE
const SYMCRYPT_GCM_EXPANDED_KEY * PCSYMCRYPT_GCM_EXPANDED_KEY
#define SYMCRYPT_GCM_BLOCK_ROUND_MASK
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_GCM_EXPANDED_KEY
PSYMCRYPT_COMMON_HASH_STATE pState
const BYTE * PCBYTE
SYMCRYPT_MAGIC_FIELD SYMCRYPT_GCM_EXPANDED_KEY
PCBYTE pbData
SYMCRYPT_MAGIC_FIELD SYMCRYPT_GCM_STATE
const SYMCRYPT_GCM_STATE * PCSYMCRYPT_GCM_STATE
#define SYMCRYPT_CHECK_MAGIC(p)
PCVOID pExpandedKey
#define SYMCRYPT_GCM_MAX_KEY_SIZE
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
#define FORCEINLINE
Definition: wdftypes.h:67
unsigned char BYTE
Definition: xxhash.c:193