Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/symcrypt/lib/ccm.c
15010 views
1
//
2
// CCM.c implementation of the CCM block cipher mode
3
//
4
// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5
//
6
7
#include "precomp.h"
8
9
#define CCM_MIN_NONCE_SIZE (7)
10
#define CCM_MAX_NONCE_SIZE (13)
11
#define CCM_MIN_TAG_SIZE (4)
12
#define CCM_MAX_TAG_SIZE (16)
13
14
#define CCM_MAX_COUNTER_SIZE (SYMCRYPT_CCM_BLOCK_SIZE - 1 - CCM_MIN_NONCE_SIZE)
15
16
#define AUTHDATA_16BIT_LIMIT ((1<<16) - (1<<8))
17
#define AUTHDATA_32BIT_LIMIT (1ull << 32)
18
19
// Compile time BOOL statically determines if we need to check cbAuthData < AUTHDATA_32BIT_LIMIT
20
// Used to suppress MSVC C4127 and clang Wtautological-constant-out-of-range-compare on 32b platforms
21
const BOOL fcbAuthDataLt32bitLimitStatic = SIZE_T_MAX < AUTHDATA_32BIT_LIMIT;
22
23
#define CCM_BLOCK_MOD_MASK (SYMCRYPT_CCM_BLOCK_SIZE - 1)
24
#define CCM_BLOCK_ROUND_MASK (~CCM_BLOCK_MOD_MASK)
25
26
SYMCRYPT_ERROR
27
SYMCRYPT_CALL
28
SymCryptCcmValidateParameters(
29
_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher,
30
_In_ SIZE_T cbNonce,
31
_In_ SIZE_T cbAssociatedData,
32
_In_ UINT64 cbData,
33
_In_ SIZE_T cbTag
34
)
35
{
36
SIZE_T cbCounter;
37
38
UNREFERENCED_PARAMETER( cbAssociatedData );
39
40
if( pBlockCipher->blockSize != SYMCRYPT_CCM_BLOCK_SIZE )
41
{
42
return SYMCRYPT_WRONG_BLOCK_SIZE;
43
}
44
45
//
46
// Test against limits in SP800-38C appendix A
47
//
48
if( cbNonce < CCM_MIN_NONCE_SIZE || cbNonce > CCM_MAX_NONCE_SIZE )
49
{
50
return SYMCRYPT_WRONG_NONCE_SIZE;
51
}
52
53
//
54
// cbAssociatedData is limited to <2^64
55
// We don't test for this. None of our platforms has a SIZE_T that is
56
// large enough to violate this condition. And the test
57
// is of a form that the compiler cannot optimize away.
58
//
59
60
//
61
// The counter block consists of a single flag byte, the nonce, and the counter field.
62
//
63
cbCounter = SYMCRYPT_CCM_BLOCK_SIZE - cbNonce - 1;
64
65
//
66
// per SP800-38C cbData is limited to 2^{8*cbCounter}
67
// There is no way to do this test in a single comparison.
68
// We don't have to worry about side-channels in the && because
69
// cbCounter depends only on the length of the nonce, and we do not
70
// try to hide any lengths.
71
//
72
if( cbCounter < sizeof( UINT64 ) &&
73
cbData >= ((UINT64)1 << (8*cbCounter)) )
74
{
75
return SYMCRYPT_WRONG_DATA_SIZE;
76
}
77
78
if( cbTag < CCM_MIN_TAG_SIZE ||
79
cbTag > CCM_MAX_TAG_SIZE ||
80
(cbTag & 1) == 1 // valid tag lengths are [4, 6, 8, ..., 16]
81
)
82
{
83
return SYMCRYPT_WRONG_TAG_SIZE;
84
}
85
86
return SYMCRYPT_NO_ERROR;
87
}
88
89
90
91
VOID
92
SYMCRYPT_CALL
93
SymCryptCcmEncryptDecryptPart(
94
_Inout_ PSYMCRYPT_CCM_STATE pState,
95
_In_reads_( cbData ) PCBYTE pbSrc,
96
_Out_writes_( cbData ) PBYTE pbDst,
97
SIZE_T cbData )
98
99
{
100
SIZE_T cbToDo = cbData;
101
SIZE_T bytesToProcess;
102
103
//
104
// Use any left-over key stream
105
//
106
while( (pState->bytesProcessed & CCM_BLOCK_MOD_MASK) != 0 && cbToDo > 0 )
107
{
108
*pbDst = *pbSrc ^ pState->keystreamBlock[ pState->bytesProcessed & CCM_BLOCK_MOD_MASK ];
109
pbDst++;
110
pbSrc++;
111
cbToDo--;
112
pState->bytesProcessed++;
113
}
114
115
//
116
// Bulk process the main part of the input and output
117
//
118
if( cbToDo >= SYMCRYPT_CCM_BLOCK_SIZE )
119
{
120
bytesToProcess = cbToDo & CCM_BLOCK_ROUND_MASK;
121
SYMCRYPT_ASSERT( bytesToProcess <= cbToDo );
122
123
SYMCRYPT_ASSERT( pState->pBlockCipher->blockSize == SYMCRYPT_CCM_BLOCK_SIZE );
124
SymCryptCtrMsb64( pState->pBlockCipher,
125
pState->pExpandedKey,
126
&pState->counterBlock[0],
127
pbSrc,
128
pbDst,
129
bytesToProcess );
130
pbSrc += bytesToProcess;
131
pbDst += bytesToProcess;
132
pState->bytesProcessed += bytesToProcess;
133
cbToDo -= bytesToProcess;
134
}
135
136
if( cbToDo > 0 )
137
{
138
//
139
// Encrypt an all-zero key stream block to get the key stream.
140
//
141
SymCryptWipeKnownSize( &pState->keystreamBlock[0], SYMCRYPT_CCM_BLOCK_SIZE );
142
143
SYMCRYPT_ASSERT( pState->pBlockCipher->blockSize == SYMCRYPT_CCM_BLOCK_SIZE );
144
SymCryptCtrMsb64( pState->pBlockCipher,
145
pState->pExpandedKey,
146
&pState->counterBlock[0],
147
&pState->keystreamBlock[0],
148
&pState->keystreamBlock[0],
149
SYMCRYPT_CCM_BLOCK_SIZE );
150
while( cbToDo > 0 )
151
{
152
*pbDst = *pbSrc ^ pState->keystreamBlock[ pState->bytesProcessed & CCM_BLOCK_MOD_MASK ];
153
pbDst++;
154
pbSrc++;
155
cbToDo--;
156
pState->bytesProcessed++;
157
}
158
}
159
}
160
161
162
VOID
163
SYMCRYPT_CALL
164
SymCryptCcmAddMacData(
165
_Inout_ PSYMCRYPT_CCM_STATE pState,
166
_In_reads_( cbData ) PCBYTE pbData,
167
SIZE_T cbData )
168
{
169
SIZE_T bytesToProcess;
170
if( pState->bytesInMacBlock > 0 )
171
{
172
bytesToProcess = SYMCRYPT_MIN( cbData, SYMCRYPT_CCM_BLOCK_SIZE - pState->bytesInMacBlock );
173
SymCryptXorBytes( &pState->macBlock[pState->bytesInMacBlock], pbData, &pState->macBlock[pState->bytesInMacBlock], bytesToProcess );
174
pbData += bytesToProcess;
175
cbData -= bytesToProcess;
176
pState->bytesInMacBlock += bytesToProcess;
177
178
if( pState->bytesInMacBlock == SYMCRYPT_CCM_BLOCK_SIZE )
179
{
180
pState->pBlockCipher->encryptFunc( pState->pExpandedKey, &pState->macBlock[0], &pState->macBlock[0] );
181
pState->bytesInMacBlock = 0;
182
}
183
}
184
185
if( cbData >= SYMCRYPT_CCM_BLOCK_SIZE )
186
{
187
bytesToProcess = cbData & CCM_BLOCK_ROUND_MASK;
188
SYMCRYPT_ASSERT( pState->pBlockCipher->blockSize == SYMCRYPT_CCM_BLOCK_SIZE );
189
190
SymCryptCbcMac( pState->pBlockCipher,
191
pState->pExpandedKey,
192
&pState->macBlock[0],
193
pbData,
194
bytesToProcess );
195
196
pbData += bytesToProcess;
197
cbData -= bytesToProcess;
198
}
199
200
if( cbData > 0 )
201
{
202
SymCryptXorBytes( &pState->macBlock[0], pbData, &pState->macBlock[0], cbData );
203
pState->bytesInMacBlock = cbData;
204
}
205
}
206
207
VOID
208
SYMCRYPT_CALL
209
SymCryptCcmPadMacData( _Inout_ PSYMCRYPT_CCM_STATE pState )
210
{
211
//
212
// Pad the MAC data with zeroes until we hit the block size.
213
// The data is xorred into macBlock, so we don't have to update that.
214
// All we do is apply the block cipher if there was any data remaining in the macBlock.
215
//
216
if( pState->bytesInMacBlock > 0 )
217
{
218
pState->pBlockCipher->encryptFunc( pState->pExpandedKey, &pState->macBlock[0], &pState->macBlock[0] );
219
pState->bytesInMacBlock = 0;
220
}
221
}
222
223
224
SYMCRYPT_NOINLINE
225
VOID
226
SYMCRYPT_CALL
227
SymCryptCcmEncrypt(
228
_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher,
229
_In_ PCVOID pExpandedKey,
230
_In_reads_( cbNonce ) PCBYTE pbNonce,
231
SIZE_T cbNonce,
232
_In_reads_opt_( cbAuthData ) PCBYTE pbAuthData,
233
SIZE_T cbAuthData,
234
_In_reads_( cbData ) PCBYTE pbSrc,
235
_Out_writes_( cbData ) PBYTE pbDst,
236
SIZE_T cbData,
237
_Out_writes_( cbTag ) PBYTE pbTag,
238
SIZE_T cbTag )
239
{
240
SYMCRYPT_CCM_STATE state;
241
242
SymCryptCcmInit( &state,
243
pBlockCipher,
244
pExpandedKey,
245
pbNonce, cbNonce,
246
pbAuthData, cbAuthData,
247
cbData, cbTag );
248
249
SymCryptCcmEncryptPart( &state, pbSrc, pbDst, cbData );
250
251
SymCryptCcmEncryptFinal( &state, pbTag, cbTag );
252
}
253
254
SYMCRYPT_NOINLINE
255
SYMCRYPT_ERROR
256
SYMCRYPT_CALL
257
SymCryptCcmDecrypt(
258
_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher,
259
_In_ PCVOID pExpandedKey,
260
_In_reads_( cbNonce ) PCBYTE pbNonce,
261
SIZE_T cbNonce,
262
_In_reads_opt_( cbAuthData ) PCBYTE pbAuthData,
263
SIZE_T cbAuthData,
264
_In_reads_( cbData ) PCBYTE pbSrc,
265
_Out_writes_( cbData ) PBYTE pbDst,
266
SIZE_T cbData,
267
_In_reads_( cbTag ) PCBYTE pbTag,
268
SIZE_T cbTag )
269
{
270
SYMCRYPT_CCM_STATE state;
271
SYMCRYPT_ERROR status;
272
273
SymCryptCcmInit( &state,
274
pBlockCipher,
275
pExpandedKey,
276
pbNonce, cbNonce,
277
pbAuthData, cbAuthData,
278
cbData, cbTag );
279
280
281
SymCryptCcmDecryptPart( &state, pbSrc, pbDst, cbData );
282
283
status = SymCryptCcmDecryptFinal( &state, pbTag, cbTag );
284
285
//
286
// If we failed for any reason we wipe our output buffer to avoid returning
287
// decrypted but unauthenticated data.
288
//
289
if( status != SYMCRYPT_NO_ERROR )
290
{
291
SymCryptWipe( pbDst, cbData );
292
}
293
294
return status;
295
}
296
297
SYMCRYPT_NOINLINE
298
VOID
299
SYMCRYPT_CALL
300
SymCryptCcmInit(
301
_Out_ PSYMCRYPT_CCM_STATE pState,
302
_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher,
303
_In_ PCVOID pExpandedKey,
304
_In_reads_( cbNonce ) PCBYTE pbNonce,
305
SIZE_T cbNonce,
306
_In_reads_opt_( cbAuthData ) PCBYTE pbAuthData,
307
SIZE_T cbAuthData,
308
UINT64 cbData,
309
SIZE_T cbTag )
310
{
311
BYTE flags;
312
BYTE tmpBuf[ SYMCRYPT_CCM_BLOCK_SIZE ];
313
SIZE_T cbCounter;
314
315
SYMCRYPT_SET_MAGIC( pState );
316
317
//
318
// Validate parameters in checked builds
319
//
320
SYMCRYPT_ASSERT( SymCryptCcmValidateParameters( pBlockCipher, cbNonce, cbAuthData, cbData, cbTag ) == SYMCRYPT_NO_ERROR );
321
322
323
//
324
// compute # bytes in the counter field
325
// We limit cbNonce to 15 so that cbCounter + cbNonce = 15 will always hold
326
// This is much cheaper than full parameter validation, and it is enough to
327
// avoid any buffer overflows.
328
//
329
cbNonce &= SYMCRYPT_CCM_BLOCK_SIZE - 1;
330
cbCounter = SYMCRYPT_CCM_BLOCK_SIZE - 1 - cbNonce;
331
332
pState->pBlockCipher = pBlockCipher;
333
pState->pExpandedKey = pExpandedKey;
334
pState->cbNonce = cbNonce;
335
pState->cbData = cbData;
336
pState->cbTag = cbTag;
337
pState->cbCounter = cbCounter;
338
pState->bytesProcessed = 0;
339
pState->bytesInMacBlock = 0;
340
341
//
342
// Build the initial blocks for authentication and en/decryption
343
//
344
// Per Sp800-38c the flag byte is made up of four fields:
345
// Bits 0-2 are cbCounter - 1
346
// Bits 3-5 are (cbTag-2)/2
347
// Bit 6 is 1 if cbAuthData > 0
348
// Bit 7 is reserved and set to 0.
349
flags = (BYTE) (pState->cbCounter - 1);
350
flags |= ((cbTag-2)/2) << 3;
351
if( cbAuthData > 0 )
352
{
353
//
354
// No side-channel concerns with this if statements as we don't try to hide the
355
// data length or presence of authdata.
356
//
357
flags |= (1 << 6);
358
}
359
360
361
//
362
// The MAC starting block consists of three fields:
363
// the flag byte, the nonce, and cbData encoded into cbCounter bytes.
364
//
365
pState->macBlock[0] = flags;
366
memcpy( &pState->macBlock[1], pbNonce, cbNonce );
367
SYMCRYPT_STORE_MSBFIRST64( &tmpBuf[0], cbData );
368
memcpy( &pState->macBlock[1+cbNonce], &tmpBuf[ 8 - cbCounter ], cbCounter );
369
370
//
371
// The counter block is similar in layout, but with two changes:
372
// Bits 3-7 of the flag bytes are set to 0.
373
// The counter field is set to one (first counter value used for data encryption).
374
// Wiping the whole block first is probably faster, as the size is known and the
375
// block is aligned.
376
// We also copy the nonce from the mac block to follow the read-once rule.
377
//
378
SymCryptWipeKnownSize( &pState->counterBlock[0], SYMCRYPT_CCM_BLOCK_SIZE );
379
pState->counterBlock[0] = (BYTE)(flags & 0x7);
380
memcpy( &pState->counterBlock[1], &pState->macBlock[1], cbNonce );
381
pState->counterBlock[ SYMCRYPT_CCM_BLOCK_SIZE - 1] = 1;
382
383
//
384
// Encrypt the current MAC block; our CBC convention is to do the encryption
385
// as soon as we have enough data.
386
//
387
pBlockCipher->encryptFunc( pExpandedKey, &pState->macBlock[0], &pState->macBlock[0] );
388
389
//
390
// Next we process the associated data
391
// See the CCM specs for the details
392
//
393
if( cbAuthData <= 0 )
394
{
395
//
396
// cbAuthData == 0, nothing needs to be done.
397
//
398
} else if( cbAuthData < AUTHDATA_16BIT_LIMIT )
399
{
400
//
401
// 16-bit length encoding.
402
//
403
SYMCRYPT_STORE_MSBFIRST16( &tmpBuf[0], (UINT16) cbAuthData );
404
SymCryptCcmAddMacData( pState, &tmpBuf[0], 2 );
405
} else if( fcbAuthDataLt32bitLimitStatic || cbAuthData < AUTHDATA_32BIT_LIMIT )
406
{
407
//
408
// 32-bit length
409
//
410
tmpBuf[0] = 0xff;
411
tmpBuf[1] = 0xfe; // Magic prefix as per SP 800-38c
412
SYMCRYPT_STORE_MSBFIRST32( &tmpBuf[2], (UINT32) cbAuthData );
413
SymCryptCcmAddMacData( pState, &tmpBuf[0], 2 + sizeof( UINT32 ) );
414
} else
415
{
416
//
417
// 64-bit length
418
//
419
tmpBuf[0] = 0xff;
420
tmpBuf[1] = 0xff; // Magic prefix as per SP 800-38c
421
SYMCRYPT_STORE_MSBFIRST64( &tmpBuf[2], cbAuthData );
422
SymCryptCcmAddMacData( pState, &tmpBuf[0], 2 + sizeof( UINT64 ) );
423
}
424
425
SymCryptCcmAddMacData( pState, pbAuthData, cbAuthData );
426
SymCryptCcmPadMacData( pState ); // Pad MAC data with zeroes until the next block size boundary
427
428
}
429
430
SYMCRYPT_NOINLINE
431
VOID
432
SYMCRYPT_CALL
433
SymCryptCcmEncryptPart(
434
_Inout_ PSYMCRYPT_CCM_STATE pState,
435
_In_reads_( cbData ) PCBYTE pbSrc,
436
_Out_writes_( cbData ) PBYTE pbDst,
437
SIZE_T cbData )
438
{
439
UINT64 bytesProcessedAfterThisCall;
440
441
SYMCRYPT_CHECK_MAGIC( pState );
442
443
bytesProcessedAfterThisCall = cbData + pState->bytesProcessed;
444
445
SYMCRYPT_ASSERT( bytesProcessedAfterThisCall >= cbData &&
446
bytesProcessedAfterThisCall <= pState->cbData );
447
448
//
449
// We are violating the read-once implementation rule here. We read the data twice:
450
// once for MACing and once for encryption.
451
// In this particular situation this is safe to do.
452
// We consider the read for the MAC operation as reading the 'real' value.
453
// The encryption code reads the data, but all it does is XOR the key stream into
454
// it. (CCM encryption uses CTR mode for the encryption part.)
455
// We don't care if the attacker modifies the data before the encryption.
456
// We are revealing the key stream anyway (from the plaintext and ciphertext) and
457
// the exact byte value that we xor the key stream into is irrelevant.
458
//
459
SymCryptCcmAddMacData( pState, pbSrc, cbData );
460
461
SymCryptCcmEncryptDecryptPart( pState, pbSrc, pbDst, cbData );
462
463
}
464
465
SYMCRYPT_NOINLINE
466
VOID
467
SYMCRYPT_CALL
468
SymCryptCcmEncryptFinal(
469
_Inout_ PSYMCRYPT_CCM_STATE pState,
470
_Out_writes_( cbTag ) PBYTE pbTag,
471
SIZE_T cbTag )
472
{
473
//
474
// Check invariants in checked builds
475
//
476
SYMCRYPT_CHECK_MAGIC( pState );
477
478
SYMCRYPT_ASSERT( cbTag == pState->cbTag && pState->bytesProcessed == pState->cbData );
479
480
481
SymCryptCcmPadMacData( pState );
482
483
//
484
// Set the counter value to zero to get the counter value that encrypts the tag,
485
// and then encrypt the tag.
486
// We reset bytesProcessed so that the partial encrypt/decrypt function will do the right thing
487
//
488
SymCryptWipe( &pState->counterBlock[1 + pState->cbNonce], pState->cbCounter );
489
490
pState->bytesProcessed = 0;
491
492
SymCryptCcmEncryptDecryptPart( pState, &pState->macBlock[0], &pState->macBlock[0], SYMCRYPT_CCM_BLOCK_SIZE );
493
494
memcpy( pbTag, &pState->macBlock[0], cbTag );
495
496
SymCryptWipeKnownSize( pState, sizeof( *pState ) );
497
SYMCRYPT_ASSERT( pState->bytesInMacBlock == 0 );
498
}
499
500
SYMCRYPT_NOINLINE
501
VOID
502
SYMCRYPT_CALL
503
SymCryptCcmDecryptPart(
504
_Inout_ PSYMCRYPT_CCM_STATE pState,
505
_In_reads_( cbData ) PCBYTE pbSrc,
506
_Out_writes_( cbData ) PBYTE pbDst,
507
SIZE_T cbData )
508
{
509
UINT64 bytesProcessedAfterThisCall;
510
511
SYMCRYPT_CHECK_MAGIC( pState );
512
513
bytesProcessedAfterThisCall = cbData + pState->bytesProcessed;
514
515
SYMCRYPT_ASSERT( bytesProcessedAfterThisCall >= cbData &&
516
bytesProcessedAfterThisCall <= pState->cbData );
517
518
519
//
520
// We are violating the read-once/write-once implementation rule here.
521
// We write the decrypted data and then read it back for the authentication function.
522
// In this particular situation this is safe to do.
523
//
524
// Anyone who can access the memory space that contains the source and destination of this
525
// function can recover the key stream used for this (key,nonce) combination.
526
// We can think of the decryption function as merely exposing the key stream, and then the
527
// caller picking the ciphertext (and by implication the plaintext) to be authenticated.
528
// Thus the data we read during authentication is the 'real' plaintext, and the
529
// decryption function merely made the key stream available.
530
//
531
// Note that this would not safe in general, it is only safe because CTR mode decryption already
532
// reveals the key stream.
533
//
534
SymCryptCcmEncryptDecryptPart( pState, pbSrc, pbDst, cbData );
535
SymCryptCcmAddMacData( pState, pbDst, cbData );
536
537
}
538
539
SYMCRYPT_NOINLINE
540
SYMCRYPT_ERROR
541
SYMCRYPT_CALL
542
SymCryptCcmDecryptFinal(
543
_Inout_ PSYMCRYPT_CCM_STATE pState,
544
_In_reads_( cbTag ) PCBYTE pbTag,
545
SIZE_T cbTag )
546
{
547
SYMCRYPT_ERROR status;
548
549
//
550
// Check invariants in checked builds
551
//
552
SYMCRYPT_CHECK_MAGIC( pState );
553
554
SYMCRYPT_ASSERT( cbTag == pState->cbTag && pState->bytesProcessed == pState->cbData );
555
556
SymCryptCcmPadMacData( pState );
557
558
//
559
// Set the counter value to zero to get the counter value that encrypts the tag,
560
// and then encrypt the tag
561
// We reset bytesProcessed so that the partial encrypt/decrypt function will do the right thing
562
//
563
SymCryptWipe( &pState->counterBlock[1 + pState->cbNonce], pState->cbCounter );
564
565
pState->bytesProcessed = 0;
566
567
SymCryptCcmEncryptDecryptPart( pState, &pState->macBlock[0], &pState->macBlock[0], SYMCRYPT_CCM_BLOCK_SIZE );
568
569
if( !SymCryptEqual( pbTag, &pState->macBlock[0], cbTag ) )
570
{
571
status = SYMCRYPT_AUTHENTICATION_FAILURE;
572
}
573
else
574
{
575
status = SYMCRYPT_NO_ERROR;
576
}
577
578
SymCryptWipeKnownSize( pState, sizeof( *pState ) );
579
SYMCRYPT_ASSERT( pState->bytesInMacBlock == 0 );
580
581
return status;
582
}
583
584
585
static const BYTE SymCryptCcmSelftestResult[3 + SYMCRYPT_AES_BLOCK_SIZE ] =
586
{
587
0x42, 0xd7, 0xda,
588
0x3d, 0x9e, 0x95, 0x82, 0x29, 0x3c, 0x10, 0x9c, 0xa3, 0x39, 0x31, 0x3f, 0x18, 0xf3, 0x10, 0xf6
589
};
590
591
VOID
592
SYMCRYPT_CALL
593
SymCryptCcmSelftest(void)
594
{
595
BYTE buf[ 3 + SYMCRYPT_AES_BLOCK_SIZE ];
596
SYMCRYPT_AES_EXPANDED_KEY key;
597
SYMCRYPT_ERROR err;
598
599
if( SymCryptAesExpandKey( &key, SymCryptTestKey32, 16 ) != SYMCRYPT_NO_ERROR )
600
{
601
SymCryptFatal( 'ccm0' );
602
}
603
604
SymCryptCcmEncrypt( SymCryptAesBlockCipher,
605
&key,
606
&SymCryptTestKey32[16], 12,
607
NULL, 0,
608
&SymCryptTestMsg3[0], buf, 3,
609
&buf[3], SYMCRYPT_AES_BLOCK_SIZE );
610
611
SymCryptInjectError( buf, sizeof( buf ) );
612
if( memcmp( buf, SymCryptCcmSelftestResult, sizeof( buf ) ) != 0 )
613
{
614
SymCryptFatal( 'ccm1' );
615
}
616
617
// inject error into the ciphertext or tag
618
SymCryptInjectError( buf, sizeof( buf ) );
619
620
err = SymCryptCcmDecrypt( SymCryptAesBlockCipher,
621
&key,
622
&SymCryptTestKey32[16], 12,
623
NULL, 0,
624
buf, buf, 3,
625
&buf[3], SYMCRYPT_AES_BLOCK_SIZE );
626
627
SymCryptInjectError( buf, 3 );
628
629
if( err != SYMCRYPT_NO_ERROR || memcmp( buf, SymCryptTestMsg3, 3 ) != 0 )
630
{
631
SymCryptFatal( 'ccm2' );
632
}
633
634
}
635
636