Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/gcm.c
15010 views
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
14
SYMCRYPT_ERROR
15
SYMCRYPT_CALL
16
SymCryptGcmValidateParameters(
17
_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher,
18
_In_ SIZE_T cbNonce,
19
_In_ UINT64 cbAssociatedData,
20
_In_ UINT64 cbData,
21
_In_ SIZE_T cbTag )
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
//
32
if( cbNonce < GCM_MIN_NONCE_SIZE )
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
//
48
if( cbData > SYMCRYPT_GCM_MAX_DATA_SIZE )
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
63
VOID
64
SYMCRYPT_CALL
65
SymCryptGcmAddMacData(
66
_Inout_ PSYMCRYPT_GCM_STATE pState,
67
_In_reads_opt_( cbData ) PCBYTE pbData,
68
SIZE_T cbData )
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],
84
SYMCRYPT_GCM_BLOCK_SIZE );
85
pState->bytesInMacBlock = 0;
86
}
87
}
88
89
if( cbData >= SYMCRYPT_GCM_BLOCK_SIZE )
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
108
VOID
109
SYMCRYPT_CALL
110
SymCryptGcmPadMacData( _Inout_ PSYMCRYPT_GCM_STATE pState )
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
127
VOID
128
SYMCRYPT_CALL
129
SymCryptGcmEncryptDecryptPart(
130
_Inout_ PSYMCRYPT_GCM_STATE pState,
131
_In_reads_( cbData ) PCBYTE pbSrc,
132
_Out_writes_( cbData ) PBYTE pbDst,
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
//
144
SYMCRYPT_ASSERT( pState->cbData + cbData <= SYMCRYPT_GCM_MAX_DATA_SIZE );
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
161
if( cbData >= SYMCRYPT_GCM_BLOCK_SIZE )
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
{
180
SymCryptWipeKnownSize( &pState->keystreamBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
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],
188
SYMCRYPT_GCM_BLOCK_SIZE );
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
200
FORCEINLINE
201
VOID
202
SYMCRYPT_CALL
203
SymCryptGcmResetCounterBlock(
204
_Inout_ PSYMCRYPT_GCM_STATE pState )
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]) -
215
(UINT32) ((pState->cbData + SYMCRYPT_GCM_BLOCK_SIZE - 1) / SYMCRYPT_GCM_BLOCK_SIZE) - 1;
216
217
SYMCRYPT_STORE_MSBFIRST32(&pState->counterBlock[12], preCounter32);
218
}
219
220
VOID
221
SYMCRYPT_CALL
222
SymCryptGcmComputeTag(
223
_Inout_ PSYMCRYPT_GCM_STATE pState,
224
_Out_writes_( SYMCRYPT_GCM_BLOCK_SIZE ) PBYTE pbTag )
225
{
226
SYMCRYPT_ALIGN BYTE buf[2 * SYMCRYPT_GCM_BLOCK_SIZE];
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
//
236
SymCryptWipeKnownSize( &buf[0], SYMCRYPT_GCM_BLOCK_SIZE );
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
246
SymCryptGcmResetCounterBlock(pState);
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,
260
SYMCRYPT_GCM_BLOCK_SIZE );
261
262
SymCryptWipeKnownSize( buf, sizeof( buf ) );
263
}
264
265
SYMCRYPT_NOINLINE
266
SYMCRYPT_ERROR
267
SYMCRYPT_CALL
268
SymCryptGcmExpandKey(
269
_Out_ PSYMCRYPT_GCM_EXPANDED_KEY pExpandedKey,
270
_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher,
271
_In_reads_( cbKey ) PCBYTE pbKey,
272
SIZE_T cbKey )
273
{
274
SYMCRYPT_ALIGN BYTE H[SYMCRYPT_GCM_BLOCK_SIZE];
275
SYMCRYPT_ERROR status = SYMCRYPT_NO_ERROR;
276
277
if( cbKey > SYMCRYPT_GCM_MAX_KEY_SIZE )
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
308
SymCryptGHashExpandKey( &pExpandedKey->ghashKey, H );
309
310
311
SYMCRYPT_SET_MAGIC( pExpandedKey );
312
313
SymCryptWipeKnownSize( H, sizeof( H ) );
314
315
cleanup:
316
317
return status;
318
}
319
320
VOID
321
SYMCRYPT_CALL
322
SymCryptGcmKeyCopy( _In_ PCSYMCRYPT_GCM_EXPANDED_KEY pSrc, _Out_ PSYMCRYPT_GCM_EXPANDED_KEY pDst )
323
{
324
SYMCRYPT_ERROR status;
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
332
VOID
333
SYMCRYPT_CALL
334
SymCryptGcmSetNonce(
335
_Out_ PSYMCRYPT_GCM_STATE pState,
336
_In_reads_( cbNonce ) PCBYTE pbNonce,
337
SIZE_T cbNonce )
338
{
339
SYMCRYPT_ASSERT( cbNonce >= GCM_MIN_NONCE_SIZE );
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))
353
BYTE buf[SYMCRYPT_GF128_BLOCK_SIZE];
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.
373
SymCryptWipeKnownSize( buf, 8 );
374
SYMCRYPT_STORE_MSBFIRST64( &buf[8], cbNonce * 8 );
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.
383
SYMCRYPT_STORE_MSBFIRST32(
384
&pState->counterBlock[12],
385
1 + SYMCRYPT_LOAD_MSBFIRST32( &pState->counterBlock[12] ) );
386
}
387
388
SYMCRYPT_NOINLINE
389
VOID
390
SYMCRYPT_CALL
391
SymCryptGcmInit(
392
_Out_ PSYMCRYPT_GCM_STATE pState,
393
_In_ PCSYMCRYPT_GCM_EXPANDED_KEY pExpandedKey,
394
_In_reads_( cbNonce ) PCBYTE pbNonce,
395
SIZE_T cbNonce )
396
{
397
UNREFERENCED_PARAMETER( cbNonce ); // It is used in an ASSERT, but only in CHKed builds.
398
399
SYMCRYPT_CHECK_MAGIC( pExpandedKey );
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
407
SymCryptGcmSetNonce(pState, pbNonce, cbNonce);
408
409
SYMCRYPT_SET_MAGIC( pState );
410
}
411
412
413
VOID
414
SYMCRYPT_CALL
415
SymCryptGcmStateCopy(
416
_In_ PCSYMCRYPT_GCM_STATE pSrc,
417
_In_opt_ PCSYMCRYPT_GCM_EXPANDED_KEY pExpandedKeyCopy,
418
_Out_ PSYMCRYPT_GCM_STATE pDst )
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
432
SYMCRYPT_NOINLINE
433
VOID
434
SYMCRYPT_CALL
435
SymCryptGcmAuthPart(
436
_Inout_ PSYMCRYPT_GCM_STATE pState,
437
_In_reads_opt_( cbData ) PCBYTE pbAuthData,
438
SIZE_T cbData )
439
{
440
SYMCRYPT_CHECK_MAGIC( pState );
441
SYMCRYPT_ASSERT( pState->cbData == 0 );
442
443
SymCryptGcmAddMacData( pState, pbAuthData, cbData );
444
pState->cbAuthData += cbData;
445
}
446
447
SYMCRYPT_NOINLINE
448
VOID
449
SYMCRYPT_CALL
450
SymCryptGcmEncryptPart(
451
_Inout_ PSYMCRYPT_GCM_STATE pState,
452
_In_reads_( cbData ) PCBYTE pbSrc,
453
_Out_writes_( cbData ) PBYTE pbDst,
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
//
461
SymCryptGcmPadMacData( pState );
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
{
474
SymCryptGcmEncryptPartTwoPass( pState, pbSrc, pbDst, cbData );
475
}
476
}
477
478
SYMCRYPT_NOINLINE
479
VOID
480
SYMCRYPT_CALL
481
SymCryptGcmEncryptPartTwoPass(
482
_Inout_ PSYMCRYPT_GCM_STATE pState,
483
_In_reads_( cbData ) PCBYTE pbSrc,
484
_Out_writes_( cbData ) PBYTE pbDst,
485
SIZE_T cbData )
486
{
487
//
488
// Do the actual encryption
489
//
490
SymCryptGcmEncryptDecryptPart( pState, pbSrc, pbDst, cbData );
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
505
SymCryptGcmAddMacData( pState, pbDst, cbData );
506
}
507
508
509
SYMCRYPT_NOINLINE
510
VOID
511
SYMCRYPT_CALL
512
SymCryptGcmDecryptPart(
513
_Inout_ PSYMCRYPT_GCM_STATE pState,
514
_In_reads_( cbData ) PCBYTE pbSrc,
515
_Out_writes_( cbData ) PBYTE pbDst,
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
//
523
SymCryptGcmPadMacData( pState );
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
{
536
SymCryptGcmDecryptPartTwoPass( pState, pbSrc, pbDst, cbData );
537
}
538
}
539
540
SYMCRYPT_NOINLINE
541
VOID
542
SYMCRYPT_CALL
543
SymCryptGcmDecryptPartTwoPass(
544
_Inout_ PSYMCRYPT_GCM_STATE pState,
545
_In_reads_( cbData ) PCBYTE pbSrc,
546
_Out_writes_( cbData ) PBYTE pbDst,
547
SIZE_T cbData )
548
{
549
SymCryptGcmAddMacData( pState, pbSrc, cbData );
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
557
SymCryptGcmEncryptDecryptPart( pState, pbSrc, pbDst, cbData );
558
}
559
560
561
SYMCRYPT_NOINLINE
562
VOID
563
SYMCRYPT_CALL
564
SymCryptGcmEncryptFinal(
565
_Inout_ PSYMCRYPT_GCM_STATE pState,
566
_Out_writes_( cbTag ) PBYTE pbTag,
567
SIZE_T cbTag )
568
{
569
SYMCRYPT_ALIGN BYTE buf[SYMCRYPT_GCM_BLOCK_SIZE];
570
571
SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE );
572
573
SymCryptGcmComputeTag( pState, &buf[0] );
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
582
SYMCRYPT_NOINLINE
583
SYMCRYPT_ERROR
584
SYMCRYPT_CALL
585
SymCryptGcmDecryptFinal(
586
_Inout_ PSYMCRYPT_GCM_STATE pState,
587
_In_reads_( cbTag ) PCBYTE pbTag,
588
SIZE_T cbTag )
589
{
590
SYMCRYPT_ALIGN BYTE buf[SYMCRYPT_GCM_BLOCK_SIZE];
591
SYMCRYPT_ERROR status;
592
593
SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE );
594
595
SymCryptGcmComputeTag( pState, &buf[0] );
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
615
SYMCRYPT_NOINLINE
616
VOID
617
SYMCRYPT_CALL
618
SymCryptGcmEncrypt(
619
_In_ PCSYMCRYPT_GCM_EXPANDED_KEY pExpandedKey,
620
_In_reads_( cbNonce ) PCBYTE pbNonce,
621
SIZE_T cbNonce,
622
_In_reads_opt_( cbAuthData ) PCBYTE pbAuthData,
623
SIZE_T cbAuthData,
624
_In_reads_( cbData ) PCBYTE pbSrc,
625
_Out_writes_( cbData ) PBYTE pbDst,
626
SIZE_T cbData,
627
_Out_writes_( cbTag ) PBYTE pbTag,
628
SIZE_T cbTag )
629
{
630
SYMCRYPT_ALIGN BYTE buf[2 * SYMCRYPT_GCM_BLOCK_SIZE];
631
SYMCRYPT_GCM_STATE state;
632
PSYMCRYPT_GCM_STATE pState = &state;
633
634
// SymCryptGcmInit( &state, pExpandedKey, pbNonce, cbNonce );
635
UNREFERENCED_PARAMETER( cbNonce ); // It is used in an ASSERT, but only in CHKed builds.
636
637
SYMCRYPT_ASSERT( cbNonce >= GCM_MIN_NONCE_SIZE );
638
SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE );
639
640
SYMCRYPT_CHECK_MAGIC( pExpandedKey );
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
648
SymCryptGcmSetNonce( pState, pbNonce, cbNonce );
649
650
// SymCryptGcmAuthPart( &state, pbAuthData, cbAuthData );
651
pState->cbAuthData += cbAuthData;
652
if( cbAuthData >= SYMCRYPT_GCM_BLOCK_SIZE )
653
{
654
SIZE_T bytesToDo = cbAuthData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
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
//
667
SymCryptWipeKnownSize( &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
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
{
682
SymCryptGcmEncryptPartTwoPass( pState, pbSrc, pbDst, cbData );
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
//
694
SymCryptWipeKnownSize( &buf[0], SYMCRYPT_GCM_BLOCK_SIZE );
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
705
SymCryptGcmResetCounterBlock( pState );
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,
719
SYMCRYPT_GCM_BLOCK_SIZE );
720
721
memcpy( pbTag, buf, cbTag );
722
723
SymCryptWipeKnownSize( buf, sizeof( buf ) );
724
SymCryptWipeKnownSize( pState, sizeof( *pState ) );
725
}
726
727
728
SYMCRYPT_NOINLINE
729
SYMCRYPT_ERROR
730
SYMCRYPT_CALL
731
SymCryptGcmDecrypt(
732
_In_ PCSYMCRYPT_GCM_EXPANDED_KEY pExpandedKey,
733
_In_reads_( cbNonce ) PCBYTE pbNonce,
734
SIZE_T cbNonce,
735
_In_reads_opt_( cbAuthData ) PCBYTE pbAuthData,
736
SIZE_T cbAuthData,
737
_In_reads_( cbData ) PCBYTE pbSrc,
738
_Out_writes_( cbData ) PBYTE pbDst,
739
SIZE_T cbData,
740
_In_reads_( cbTag ) PCBYTE pbTag,
741
SIZE_T cbTag )
742
{
743
SYMCRYPT_ERROR status;
744
SYMCRYPT_ALIGN BYTE buf[2 * SYMCRYPT_GCM_BLOCK_SIZE];
745
SYMCRYPT_GCM_STATE state;
746
PSYMCRYPT_GCM_STATE pState = &state;
747
748
// SymCryptGcmInit( &state, pExpandedKey, pbNonce, cbNonce );
749
UNREFERENCED_PARAMETER( cbNonce ); // It is used in an ASSERT, but only in CHKed builds.
750
751
SYMCRYPT_ASSERT( cbNonce >= GCM_MIN_NONCE_SIZE );
752
SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE );
753
754
SYMCRYPT_CHECK_MAGIC( pExpandedKey );
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
762
SymCryptGcmSetNonce( pState, pbNonce, cbNonce );
763
764
// SymCryptGcmAuthPart( &state, pbAuthData, cbAuthData );
765
pState->cbAuthData += cbAuthData;
766
if( cbAuthData >= SYMCRYPT_GCM_BLOCK_SIZE )
767
{
768
SIZE_T bytesToDo = cbAuthData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
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
//
781
SymCryptWipeKnownSize( &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
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
{
796
SymCryptGcmDecryptPartTwoPass( pState, pbSrc, pbDst, cbData );
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
//
808
SymCryptWipeKnownSize( &buf[0], SYMCRYPT_GCM_BLOCK_SIZE );
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
818
SymCryptGcmResetCounterBlock( pState );
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,
832
SYMCRYPT_GCM_BLOCK_SIZE );
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
{
848
SymCryptWipe( pbDst, cbData );
849
}
850
851
return status;
852
}
853
854
855
static const BYTE SymCryptGcmSelftestResult[3 + SYMCRYPT_AES_BLOCK_SIZE ] =
856
{
857
0xa5, 0x4c, 0x60,
858
0x80, 0xb0, 0x48, 0x6d, 0x03, 0x9f, 0xea, 0xc3, 0x3c, 0x28, 0x96, 0x3f, 0x99, 0x8a, 0x77, 0x43,
859
};
860
861
VOID
862
SYMCRYPT_CALL
863
SymCryptGcmSelftest(void)
864
{
865
BYTE buf[ 3 + SYMCRYPT_AES_BLOCK_SIZE ];
866
SYMCRYPT_GCM_EXPANDED_KEY key;
867
SYMCRYPT_ERROR err;
868
869
if( SymCryptGcmExpandKey( &key, SymCryptAesBlockCipher, SymCryptTestKey32, 16 ) != SYMCRYPT_NO_ERROR )
870
{
871
SymCryptFatal( 'gcm0' );
872
}
873
874
SymCryptGcmEncrypt( &key,
875
&SymCryptTestKey32[16], 12,
876
NULL, 0,
877
&SymCryptTestMsg3[0], buf, 3,
878
&buf[3], SYMCRYPT_AES_BLOCK_SIZE );
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
889
err = SymCryptGcmDecrypt( &key,
890
&SymCryptTestKey32[16], 12,
891
NULL, 0,
892
buf, buf, 3,
893
&buf[3], SYMCRYPT_AES_BLOCK_SIZE );
894
895
SymCryptInjectError( buf, 3 );
896
897
if( err != SYMCRYPT_NO_ERROR || memcmp( buf, SymCryptTestMsg3, 3 ) != 0 )
898
{
899
SymCryptFatal( 'gcm2' );
900
}
901
902
}
903
904