Coverage Report

Created: 2024-11-21 07:03

/src/SymCrypt/lib/gcm.c
Line
Count
Source (jump to first uncovered line)
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
0
#define GCM_MIN_NONCE_SIZE          (1)
10
0
#define GCM_MIN_TAG_SIZE            (12)
11
0
#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
0
{
23
0
    if( pBlockCipher->blockSize != SYMCRYPT_GCM_BLOCK_SIZE )
24
0
    {
25
0
        return SYMCRYPT_WRONG_BLOCK_SIZE;
26
0
    }
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
0
    if( cbNonce < GCM_MIN_NONCE_SIZE )
33
0
    {
34
0
        return SYMCRYPT_WRONG_NONCE_SIZE;
35
0
    }
36
37
    //
38
    // cbAssociatedData is limited to <2^61 bytes
39
    //
40
0
    if( (cbAssociatedData >> 61) > 0 )
41
0
    {
42
0
        return SYMCRYPT_WRONG_DATA_SIZE;
43
0
    }
44
45
    //
46
    // per SP800-38D cbData is limited to 2^36 - 32 bytes
47
    //
48
0
    if( cbData > SYMCRYPT_GCM_MAX_DATA_SIZE )
49
0
    {
50
0
        return SYMCRYPT_WRONG_DATA_SIZE;
51
0
    }
52
53
0
    if( cbTag < GCM_MIN_TAG_SIZE || cbTag > GCM_MAX_TAG_SIZE )
54
0
    {
55
0
        return SYMCRYPT_WRONG_TAG_SIZE;
56
0
    }
57
58
0
    return SYMCRYPT_NO_ERROR;
59
0
}
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
0
{
70
0
    SIZE_T bytesToProcess;
71
0
    if( pState->bytesInMacBlock > 0 )
72
0
    {
73
0
        bytesToProcess = SYMCRYPT_MIN( cbData, SYMCRYPT_GCM_BLOCK_SIZE - pState->bytesInMacBlock );
74
0
        memcpy( &pState->macBlock[pState->bytesInMacBlock], pbData, bytesToProcess );
75
0
        pbData += bytesToProcess;
76
0
        cbData -= bytesToProcess;
77
0
        pState->bytesInMacBlock += bytesToProcess;
78
79
0
        if( pState->bytesInMacBlock == SYMCRYPT_GCM_BLOCK_SIZE )
80
0
        {
81
0
            SymCryptGHashAppendData(    &pState->pKey->ghashKey,
82
0
                                        &pState->ghashState,
83
0
                                        &pState->macBlock[0],
84
0
                                        SYMCRYPT_GCM_BLOCK_SIZE );
85
0
            pState->bytesInMacBlock = 0;
86
0
        }
87
0
    }
88
89
0
    if( cbData >= SYMCRYPT_GCM_BLOCK_SIZE )
90
0
    {
91
0
        bytesToProcess = cbData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
92
93
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, pbData, bytesToProcess );
94
95
0
        pbData += bytesToProcess;
96
0
        cbData -= bytesToProcess;
97
0
    }
98
99
0
    if( cbData > 0 )
100
0
    {
101
0
        memcpy( &pState->macBlock[0], pbData, cbData );
102
0
        pState->bytesInMacBlock = cbData;
103
0
    }
104
0
}
105
106
107
108
VOID
109
SYMCRYPT_CALL
110
SymCryptGcmPadMacData( _Inout_ PSYMCRYPT_GCM_STATE  pState )
111
0
{
112
0
    SIZE_T nBytes;
113
    //
114
    // Pad the MAC data with zeroes until we hit the block size.
115
    //
116
0
    nBytes = pState->bytesInMacBlock;
117
0
    if( nBytes > 0 )
118
0
    {
119
0
        SymCryptWipe( &pState->macBlock[nBytes], SYMCRYPT_GCM_BLOCK_SIZE - nBytes );
120
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
121
0
        pState->bytesInMacBlock = 0;
122
0
    }
123
0
}
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
0
{
135
0
    SIZE_T      bytesToProcess;
136
0
    SIZE_T      bytesUsedInKeyStreamBuffer;
137
138
0
    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
0
    SYMCRYPT_ASSERT( pState->cbData + cbData <= SYMCRYPT_GCM_MAX_DATA_SIZE );
145
0
    pState->cbData += cbData;
146
147
0
    if( bytesUsedInKeyStreamBuffer != 0 )
148
0
    {
149
0
        bytesToProcess = SYMCRYPT_MIN( cbData, SYMCRYPT_GCM_BLOCK_SIZE - bytesUsedInKeyStreamBuffer );
150
0
        SymCryptXorBytes( pbSrc, &pState->keystreamBlock[bytesUsedInKeyStreamBuffer], pbDst, bytesToProcess );
151
0
        pbSrc += bytesToProcess;
152
0
        pbDst += bytesToProcess;
153
0
        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
0
    }
160
161
0
    if( cbData >= SYMCRYPT_GCM_BLOCK_SIZE )
162
0
    {
163
0
        bytesToProcess = cbData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
164
165
0
        SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
166
0
        SymCryptCtrMsb32(   pState->pKey->pBlockCipher,
167
0
                            &pState->pKey->blockcipherKey,
168
0
                            &pState->counterBlock[0],
169
0
                            pbSrc,
170
0
                            pbDst,
171
0
                            bytesToProcess );
172
173
0
        pbSrc += bytesToProcess;
174
0
        pbDst += bytesToProcess;
175
0
        cbData -= bytesToProcess;
176
0
    }
177
178
0
    if( cbData > 0 )
179
0
    {
180
0
        SymCryptWipeKnownSize( &pState->keystreamBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
181
182
0
        SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
183
0
        SymCryptCtrMsb32(   pState->pKey->pBlockCipher,
184
0
                            &pState->pKey->blockcipherKey,
185
0
                            &pState->counterBlock[0],
186
0
                            &pState->keystreamBlock[0],
187
0
                            &pState->keystreamBlock[0],
188
0
                            SYMCRYPT_GCM_BLOCK_SIZE );
189
190
0
        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
0
    }
197
198
0
}
199
200
FORCEINLINE
201
VOID
202
SYMCRYPT_CALL
203
SymCryptGcmResetCounterBlock(
204
    _Inout_ PSYMCRYPT_GCM_STATE pState )
205
0
{
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
0
    UINT32 preCounter32 = SYMCRYPT_LOAD_MSBFIRST32(&pState->counterBlock[12]) -
215
0
        (UINT32) ((pState->cbData + SYMCRYPT_GCM_BLOCK_SIZE - 1) / SYMCRYPT_GCM_BLOCK_SIZE) - 1;
216
217
0
    SYMCRYPT_STORE_MSBFIRST32(&pState->counterBlock[12], preCounter32);
218
0
}
219
220
VOID
221
SYMCRYPT_CALL
222
SymCryptGcmComputeTag(
223
    _Inout_                                 PSYMCRYPT_GCM_STATE pState,
224
    _Out_writes_( SYMCRYPT_GCM_BLOCK_SIZE ) PBYTE               pbTag )
225
0
{
226
0
    SYMCRYPT_ALIGN BYTE  buf[2 * SYMCRYPT_GCM_BLOCK_SIZE];
227
228
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[16], pState->cbAuthData * 8 );
229
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[24], pState->cbData * 8 );
230
231
0
    if( pState->bytesInMacBlock > 0 )
232
0
    {
233
        //
234
        // Pad the MAC data with zeroes until we hit the block size
235
        //
236
0
        SymCryptWipeKnownSize( &buf[0], SYMCRYPT_GCM_BLOCK_SIZE );
237
0
        memcpy( buf, &pState->macBlock[0], pState->bytesInMacBlock );
238
239
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[0], 2 * SYMCRYPT_GCM_BLOCK_SIZE );
240
0
    }
241
0
    else
242
0
    {
243
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[16], SYMCRYPT_GCM_BLOCK_SIZE );
244
0
    }
245
246
0
    SymCryptGcmResetCounterBlock(pState);
247
248
    //
249
    // Convert the GHash state to an array of bytes
250
    //
251
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[0], pState->ghashState.ull[1] );
252
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[8], pState->ghashState.ull[0] );
253
254
0
    SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
255
0
    SymCryptCtrMsb32(   pState->pKey->pBlockCipher,
256
0
                        &pState->pKey->blockcipherKey,
257
0
                        &pState->counterBlock[0],
258
0
                        buf,
259
0
                        pbTag,
260
0
                        SYMCRYPT_GCM_BLOCK_SIZE );
261
262
0
    SymCryptWipeKnownSize( buf, sizeof( buf ) );
263
0
}
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
0
{
274
0
    SYMCRYPT_ALIGN BYTE    H[SYMCRYPT_GCM_BLOCK_SIZE];
275
0
    SYMCRYPT_ERROR status = SYMCRYPT_NO_ERROR;
276
277
0
    if( cbKey > SYMCRYPT_GCM_MAX_KEY_SIZE )
278
0
    {
279
0
        status = SYMCRYPT_WRONG_KEY_SIZE;
280
0
        goto cleanup;
281
0
    }
282
283
    //
284
    // Perform the Block cipher key expansion first
285
    //
286
0
    pExpandedKey->pBlockCipher = pBlockCipher;
287
0
    status = pBlockCipher->expandKeyFunc( &pExpandedKey->blockcipherKey, pbKey, cbKey );
288
289
0
    if( status != SYMCRYPT_NO_ERROR )
290
0
    {
291
0
        goto cleanup;
292
0
    }
293
294
    //
295
    // We keep a copy of the key to make it easy to
296
    // implement the SymCryptGcmKeyCopy function
297
    //
298
0
    pExpandedKey->cbKey = cbKey;
299
0
    memcpy( &pExpandedKey->abKey[0], pbKey, cbKey );
300
301
    //
302
    // Compute H and the GHASH expanded key
303
    //
304
0
    SymCryptWipeKnownSize( H, sizeof( H ) );
305
0
    pBlockCipher->encryptFunc( &pExpandedKey->blockcipherKey, H, H );
306
307
308
0
    SymCryptGHashExpandKey( &pExpandedKey->ghashKey, H );
309
310
311
0
    SYMCRYPT_SET_MAGIC( pExpandedKey );
312
313
0
    SymCryptWipeKnownSize( H, sizeof( H ) );
314
315
0
cleanup:
316
317
0
    return status;
318
0
}
319
320
VOID
321
SYMCRYPT_CALL
322
SymCryptGcmKeyCopy( _In_ PCSYMCRYPT_GCM_EXPANDED_KEY pSrc, _Out_ PSYMCRYPT_GCM_EXPANDED_KEY pDst )
323
0
{
324
0
    SYMCRYPT_ERROR  status;
325
326
0
    SYMCRYPT_CHECK_MAGIC( pSrc );
327
328
0
    status = SymCryptGcmExpandKey( pDst, pSrc->pBlockCipher, &pSrc->abKey[0], pSrc->cbKey );
329
0
    SYMCRYPT_ASSERT( status == SYMCRYPT_NO_ERROR );
330
0
}
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
0
{
339
0
    SYMCRYPT_ASSERT( cbNonce >= GCM_MIN_NONCE_SIZE );
340
341
    // Handle the nonce depending on its size, as specified in NIST SP800-38D
342
0
    if( cbNonce == 12 )
343
0
    {
344
        // If len(nonce) = 96 bits (12 bytes), pre-counter block = nonce || (DWORD) 1
345
0
        memcpy( &pState->counterBlock[0], pbNonce, cbNonce );
346
0
        SymCryptWipeKnownSize( &pState->counterBlock[12], 4 );
347
0
        pState->counterBlock[15] = 1;
348
0
    }
349
0
    else
350
0
    {
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
0
        BYTE buf[SYMCRYPT_GF128_BLOCK_SIZE];
354
0
        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
0
        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
0
        if(cbNonceRemainder > 0)
365
0
        {
366
0
            SymCryptWipeKnownSize( buf, sizeof(buf) );
367
0
            memcpy(buf, pbNonce + cbNonce - cbNonceRemainder, cbNonceRemainder);
368
0
            SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, buf, sizeof(buf) );
369
0
        }
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
0
        SymCryptWipeKnownSize( buf, 8 );
374
0
        SYMCRYPT_STORE_MSBFIRST64( &buf[8], cbNonce * 8 );
375
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, buf, sizeof(buf) );
376
377
0
        SymCryptGHashResult( &pState->ghashState, pState->counterBlock );
378
0
        SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) );
379
0
    }
380
381
    // Increment the last 32 bits of the counter. We'll recalculate the pre-counter block later
382
    // when computing the tag.
383
0
    SYMCRYPT_STORE_MSBFIRST32(
384
0
        &pState->counterBlock[12], 
385
0
        1 + SYMCRYPT_LOAD_MSBFIRST32( &pState->counterBlock[12] ) );
386
0
}
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
0
{
397
0
    UNREFERENCED_PARAMETER( cbNonce );          // It is used in an ASSERT, but only in CHKed builds.
398
399
0
    SYMCRYPT_CHECK_MAGIC( pExpandedKey );
400
401
0
    pState->pKey = pExpandedKey;
402
0
    pState->cbData = 0;
403
0
    pState->cbAuthData = 0;
404
0
    pState->bytesInMacBlock = 0;
405
0
    SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) );
406
407
0
    SymCryptGcmSetNonce(pState, pbNonce, cbNonce);
408
409
0
    SYMCRYPT_SET_MAGIC( pState );
410
0
}
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
0
{
420
0
    SYMCRYPT_CHECK_MAGIC( pSrc );
421
422
0
    *pDst = *pSrc;
423
0
    if( pExpandedKeyCopy != NULL )
424
0
    {
425
0
        pDst->pKey = pExpandedKeyCopy;
426
0
    }
427
428
0
    SYMCRYPT_SET_MAGIC( pDst );
429
0
}
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
0
{
440
0
    SYMCRYPT_CHECK_MAGIC( pState );
441
0
    SYMCRYPT_ASSERT( pState->cbData == 0 );
442
443
0
    SymCryptGcmAddMacData( pState, pbAuthData, cbData );
444
0
    pState->cbAuthData += cbData;
445
0
}
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
0
{
456
0
    if( pState->cbData == 0 )
457
0
    {
458
        //
459
        // This is the first actual encryption data, pad the Auth data with zeroes if needed.
460
        //
461
0
        SymCryptGcmPadMacData( pState );
462
0
    }
463
464
0
    if ( pState->pKey->pBlockCipher->gcmEncryptPartFunc != NULL )
465
0
    {
466
        //
467
        // Use optimized implementation if available
468
        //
469
0
        (*pState->pKey->pBlockCipher->gcmEncryptPartFunc) ( pState, pbSrc, pbDst, cbData );
470
0
        SYMCRYPT_ASSERT( pState->bytesInMacBlock <= 15 );
471
0
    }
472
0
    else
473
0
    {
474
0
        SymCryptGcmEncryptPartTwoPass( pState, pbSrc, pbDst, cbData );
475
0
    }
476
0
}
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
0
{
487
    //
488
    // Do the actual encryption
489
    //
490
0
    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
0
    SymCryptGcmAddMacData( pState, pbDst, cbData );
506
0
}
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
0
{
518
0
    if( pState->cbData == 0 )
519
0
    {
520
        //
521
        // This is the first actual encryption data, pad the Auth data with zeroes if needed.
522
        //
523
0
        SymCryptGcmPadMacData( pState );
524
0
    }
525
526
0
    if ( pState->pKey->pBlockCipher->gcmDecryptPartFunc != NULL )
527
0
    {
528
        //
529
        // Use optimized implementation if available
530
        //
531
0
        (*pState->pKey->pBlockCipher->gcmDecryptPartFunc) ( pState, pbSrc, pbDst, cbData );
532
0
        SYMCRYPT_ASSERT( pState->bytesInMacBlock <= 15 );
533
0
    }
534
0
    else
535
0
    {
536
0
        SymCryptGcmDecryptPartTwoPass( pState, pbSrc, pbDst, cbData );
537
0
    }
538
0
}
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
0
{
549
0
    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
0
    SymCryptGcmEncryptDecryptPart( pState, pbSrc, pbDst, cbData );
558
0
}
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
0
{
569
0
    SYMCRYPT_ALIGN BYTE    buf[SYMCRYPT_GCM_BLOCK_SIZE];
570
571
0
    SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE );
572
573
0
    SymCryptGcmComputeTag( pState, &buf[0] );
574
0
    memcpy( pbTag, buf, cbTag );
575
576
0
    SymCryptWipeKnownSize( buf, sizeof( buf ) );
577
578
0
    SymCryptWipeKnownSize( pState, sizeof( *pState ) );
579
0
    SYMCRYPT_ASSERT( pState->bytesInMacBlock == 0 );
580
0
}
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
0
{
590
0
    SYMCRYPT_ALIGN BYTE    buf[SYMCRYPT_GCM_BLOCK_SIZE];
591
0
    SYMCRYPT_ERROR status;
592
593
0
    SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE );
594
595
0
    SymCryptGcmComputeTag( pState, &buf[0] );
596
597
0
    if( !SymCryptEqual( pbTag, buf, cbTag ) )
598
0
    {
599
0
        status = SYMCRYPT_AUTHENTICATION_FAILURE;
600
0
    }
601
0
    else
602
0
    {
603
0
        status = SYMCRYPT_NO_ERROR;
604
0
    }
605
606
0
    SymCryptWipeKnownSize( buf, sizeof( buf ) );
607
608
0
    SymCryptWipeKnownSize( pState, sizeof( *pState ) );
609
0
    SYMCRYPT_ASSERT( pState->bytesInMacBlock == 0 );
610
611
0
    return status;
612
0
}
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
0
{
630
0
    SYMCRYPT_ALIGN BYTE buf[2 * SYMCRYPT_GCM_BLOCK_SIZE];
631
0
    SYMCRYPT_GCM_STATE  state;
632
0
    PSYMCRYPT_GCM_STATE pState = &state;
633
634
    // SymCryptGcmInit( &state, pExpandedKey, pbNonce, cbNonce );
635
0
    UNREFERENCED_PARAMETER( cbNonce );          // It is used in an ASSERT, but only in CHKed builds.
636
637
0
    SYMCRYPT_ASSERT( cbNonce >= GCM_MIN_NONCE_SIZE );
638
0
    SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE );
639
640
0
    SYMCRYPT_CHECK_MAGIC( pExpandedKey );
641
642
0
    pState->pKey = pExpandedKey;
643
0
    pState->cbData = 0;
644
0
    pState->cbAuthData = 0;
645
0
    pState->bytesInMacBlock = 0;
646
0
    SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) );
647
648
0
    SymCryptGcmSetNonce( pState, pbNonce, cbNonce );
649
650
    // SymCryptGcmAuthPart( &state, pbAuthData, cbAuthData );
651
0
    pState->cbAuthData += cbAuthData;
652
0
    if( cbAuthData >= SYMCRYPT_GCM_BLOCK_SIZE )
653
0
    {
654
0
        SIZE_T bytesToDo = cbAuthData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
655
656
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, pbAuthData, bytesToDo );
657
658
0
        pbAuthData += bytesToDo;
659
0
        cbAuthData -= bytesToDo;
660
0
    }
661
662
0
    if( cbAuthData > 0 )
663
0
    {
664
        //
665
        // Pad the MAC data with zeroes until we hit the block size.
666
        //
667
0
        SymCryptWipeKnownSize( &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
668
0
        memcpy( &pState->macBlock[0], pbAuthData, cbAuthData );
669
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
670
0
    }
671
672
    // SymCryptGcmEncryptPart( &state, pbSrc, pbDst, cbData );
673
0
    if ( pState->pKey->pBlockCipher->gcmEncryptPartFunc != NULL )
674
0
    {
675
        //
676
        // Use optimized implementation if available
677
        //
678
0
        (*pState->pKey->pBlockCipher->gcmEncryptPartFunc) ( pState, pbSrc, pbDst, cbData );
679
0
    }
680
0
    else
681
0
    {
682
0
        SymCryptGcmEncryptPartTwoPass( pState, pbSrc, pbDst, cbData );
683
0
    }
684
685
    // SymCryptGcmEncryptFinal( &state, pbTag, cbTag );
686
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[16], pState->cbAuthData * 8 );
687
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[24], pState->cbData * 8 );
688
689
0
    if( pState->bytesInMacBlock > 0 )
690
0
    {
691
        //
692
        // Pad the MAC data with zeroes until we hit the block size
693
        //
694
0
        SymCryptWipeKnownSize( &buf[0], SYMCRYPT_GCM_BLOCK_SIZE );
695
0
        memcpy( buf, &pState->macBlock[0], pState->bytesInMacBlock );
696
697
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[0], 2 * SYMCRYPT_GCM_BLOCK_SIZE );
698
0
    }
699
0
    else
700
0
    {
701
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[16], SYMCRYPT_GCM_BLOCK_SIZE );
702
0
    }
703
704
    // Reset the counter block prior to computing the tag
705
0
    SymCryptGcmResetCounterBlock( pState );
706
707
    //
708
    // Convert the GHash state to an array of bytes
709
    //
710
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[0], pState->ghashState.ull[1] );
711
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[8], pState->ghashState.ull[0] );
712
713
0
    SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
714
0
    SymCryptCtrMsb32(   pState->pKey->pBlockCipher,
715
0
                        &pState->pKey->blockcipherKey,
716
0
                        &pState->counterBlock[0],
717
0
                        buf,
718
0
                        buf,
719
0
                        SYMCRYPT_GCM_BLOCK_SIZE );
720
721
0
    memcpy( pbTag, buf, cbTag );
722
723
0
    SymCryptWipeKnownSize( buf, sizeof( buf ) );
724
0
    SymCryptWipeKnownSize( pState, sizeof( *pState ) );
725
0
}
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
0
{
743
0
    SYMCRYPT_ERROR status;
744
0
    SYMCRYPT_ALIGN BYTE buf[2 * SYMCRYPT_GCM_BLOCK_SIZE];
745
0
    SYMCRYPT_GCM_STATE  state;
746
0
    PSYMCRYPT_GCM_STATE pState = &state;
747
748
    // SymCryptGcmInit( &state, pExpandedKey, pbNonce, cbNonce );
749
0
    UNREFERENCED_PARAMETER( cbNonce );          // It is used in an ASSERT, but only in CHKed builds.
750
751
0
    SYMCRYPT_ASSERT( cbNonce >= GCM_MIN_NONCE_SIZE );
752
0
    SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE );
753
754
0
    SYMCRYPT_CHECK_MAGIC( pExpandedKey );
755
756
0
    pState->pKey = pExpandedKey;
757
0
    pState->cbData = 0;
758
0
    pState->cbAuthData = 0;
759
0
    pState->bytesInMacBlock = 0;
760
0
    SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) );
761
762
0
    SymCryptGcmSetNonce( pState, pbNonce, cbNonce );
763
764
    // SymCryptGcmAuthPart( &state, pbAuthData, cbAuthData );
765
0
    pState->cbAuthData += cbAuthData;
766
0
    if( cbAuthData >= SYMCRYPT_GCM_BLOCK_SIZE )
767
0
    {
768
0
        SIZE_T bytesToDo = cbAuthData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
769
770
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, pbAuthData, bytesToDo );
771
772
0
        pbAuthData += bytesToDo;
773
0
        cbAuthData -= bytesToDo;
774
0
    }
775
776
0
    if( cbAuthData > 0 )
777
0
    {
778
        //
779
        // Pad the MAC data with zeroes until we hit the block size.
780
        //
781
0
        SymCryptWipeKnownSize( &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
782
0
        memcpy( &pState->macBlock[0], pbAuthData, cbAuthData );
783
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &pState->macBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
784
0
    }
785
786
    // SymCryptGcmDecryptPart( &state, pbSrc, pbDst, cbData );
787
0
    if ( pState->pKey->pBlockCipher->gcmDecryptPartFunc != NULL )
788
0
    {
789
        //
790
        // Use optimized implementation if available
791
        //
792
0
        (*pState->pKey->pBlockCipher->gcmDecryptPartFunc) ( pState, pbSrc, pbDst, cbData );
793
0
    }
794
0
    else
795
0
    {
796
0
        SymCryptGcmDecryptPartTwoPass( pState, pbSrc, pbDst, cbData );
797
0
    }
798
799
    //status = SymCryptGcmDecryptFinal( &state, pbTag, cbTag );
800
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[16], pState->cbAuthData * 8 );
801
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[24], pState->cbData * 8 );
802
803
0
    if( pState->bytesInMacBlock > 0 )
804
0
    {
805
        //
806
        // Pad the MAC data with zeroes until we hit the block size
807
        //
808
0
        SymCryptWipeKnownSize( &buf[0], SYMCRYPT_GCM_BLOCK_SIZE );
809
0
        memcpy( buf, &pState->macBlock[0], pState->bytesInMacBlock );
810
811
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[0], 2 * SYMCRYPT_GCM_BLOCK_SIZE );
812
0
    }
813
0
    else
814
0
    {
815
0
        SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[16], SYMCRYPT_GCM_BLOCK_SIZE );
816
0
    }
817
818
0
    SymCryptGcmResetCounterBlock( pState );
819
820
    //
821
    // Convert the GHash state to an array of bytes
822
    //
823
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[0], pState->ghashState.ull[1] );
824
0
    SYMCRYPT_STORE_MSBFIRST64( &buf[8], pState->ghashState.ull[0] );
825
826
0
    SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
827
0
    SymCryptCtrMsb32(   pState->pKey->pBlockCipher,
828
0
                        &pState->pKey->blockcipherKey,
829
0
                        &pState->counterBlock[0],
830
0
                        buf,
831
0
                        buf,
832
0
                        SYMCRYPT_GCM_BLOCK_SIZE );
833
834
0
    if( !SymCryptEqual( pbTag, buf, cbTag ) )
835
0
    {
836
0
        status = SYMCRYPT_AUTHENTICATION_FAILURE;
837
0
    }
838
0
    else
839
0
    {
840
0
        status = SYMCRYPT_NO_ERROR;
841
0
    }
842
843
0
    SymCryptWipeKnownSize( buf, sizeof( buf ) );
844
0
    SymCryptWipeKnownSize( pState, sizeof( *pState ) );
845
846
0
    if( status != SYMCRYPT_NO_ERROR )
847
0
    {
848
0
        SymCryptWipe( pbDst, cbData );
849
0
    }
850
851
0
    return status;
852
0
}
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
0
{
865
0
    BYTE    buf[ 3 + SYMCRYPT_AES_BLOCK_SIZE ];
866
0
    SYMCRYPT_GCM_EXPANDED_KEY key;
867
0
    SYMCRYPT_ERROR err;
868
869
0
    if( SymCryptGcmExpandKey( &key, SymCryptAesBlockCipher, SymCryptTestKey32, 16 ) != SYMCRYPT_NO_ERROR )
870
0
    {
871
0
        SymCryptFatal( 'gcm0' );
872
0
    }
873
874
0
    SymCryptGcmEncrypt( &key,
875
0
                        &SymCryptTestKey32[16], 12,
876
0
                        NULL, 0,
877
0
                        &SymCryptTestMsg3[0], buf, 3,
878
0
                        &buf[3], SYMCRYPT_AES_BLOCK_SIZE );
879
880
0
    SymCryptInjectError( buf, sizeof( buf ) );
881
0
    if( memcmp( buf, SymCryptGcmSelftestResult, sizeof( buf ) ) != 0 )
882
0
    {
883
0
        SymCryptFatal( 'gcm1' );
884
0
    }
885
886
    // inject error into the ciphertext or tag
887
0
    SymCryptInjectError( buf, sizeof( buf ) );
888
889
0
    err = SymCryptGcmDecrypt(   &key,
890
0
                                &SymCryptTestKey32[16], 12,
891
0
                                NULL, 0,
892
0
                                buf, buf, 3,
893
0
                                &buf[3], SYMCRYPT_AES_BLOCK_SIZE );
894
895
0
    SymCryptInjectError( buf, 3 );
896
897
0
    if( err != SYMCRYPT_NO_ERROR || memcmp( buf, SymCryptTestMsg3, 3 ) != 0 )
898
0
    {
899
0
        SymCryptFatal( 'gcm2' );
900
0
    }
901
902
0
}
903
904