ReactOS 0.4.17-dev-1005-g171e1de
ccm.c File Reference
#include "precomp.h"
Include dependency graph for ccm.c:

Go to the source code of this file.

Macros

#define CCM_MIN_NONCE_SIZE   (7)
 
#define CCM_MAX_NONCE_SIZE   (13)
 
#define CCM_MIN_TAG_SIZE   (4)
 
#define CCM_MAX_TAG_SIZE   (16)
 
#define CCM_MAX_COUNTER_SIZE   (SYMCRYPT_CCM_BLOCK_SIZE - 1 - CCM_MIN_NONCE_SIZE)
 
#define AUTHDATA_16BIT_LIMIT   ((1<<16) - (1<<8))
 
#define AUTHDATA_32BIT_LIMIT   (1ull << 32)
 
#define CCM_BLOCK_MOD_MASK   (SYMCRYPT_CCM_BLOCK_SIZE - 1)
 
#define CCM_BLOCK_ROUND_MASK   (~CCM_BLOCK_MOD_MASK)
 

Functions

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCcmValidateParameters (_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ SIZE_T cbNonce, _In_ SIZE_T cbAssociatedData, _In_ UINT64 cbData, _In_ SIZE_T cbTag)
 
VOID SYMCRYPT_CALL SymCryptCcmEncryptDecryptPart (_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
 
VOID SYMCRYPT_CALL SymCryptCcmAddMacData (_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
 
VOID SYMCRYPT_CALL SymCryptCcmPadMacData (_Inout_ PSYMCRYPT_CCM_STATE pState)
 
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmEncrypt (_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID 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)
 
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCcmDecrypt (_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID 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)
 
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmInit (_Out_ PSYMCRYPT_CCM_STATE pState, _In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, UINT64 cbData, SIZE_T cbTag)
 
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmEncryptPart (_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
 
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmEncryptFinal (_Inout_ PSYMCRYPT_CCM_STATE pState, _Out_writes_(cbTag) PBYTE pbTag, SIZE_T cbTag)
 
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmDecryptPart (_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
 
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCcmDecryptFinal (_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbTag) PCBYTE pbTag, SIZE_T cbTag)
 
VOID SYMCRYPT_CALL SymCryptCcmSelftest (void)
 

Variables

const BOOL fcbAuthDataLt32bitLimitStatic = SIZE_T_MAX < AUTHDATA_32BIT_LIMIT
 
static const BYTE SymCryptCcmSelftestResult [3+SYMCRYPT_AES_BLOCK_SIZE]
 

Macro Definition Documentation

◆ AUTHDATA_16BIT_LIMIT

#define AUTHDATA_16BIT_LIMIT   ((1<<16) - (1<<8))

Definition at line 16 of file ccm.c.

◆ AUTHDATA_32BIT_LIMIT

#define AUTHDATA_32BIT_LIMIT   (1ull << 32)

Definition at line 17 of file ccm.c.

◆ CCM_BLOCK_MOD_MASK

#define CCM_BLOCK_MOD_MASK   (SYMCRYPT_CCM_BLOCK_SIZE - 1)

Definition at line 23 of file ccm.c.

◆ CCM_BLOCK_ROUND_MASK

#define CCM_BLOCK_ROUND_MASK   (~CCM_BLOCK_MOD_MASK)

Definition at line 24 of file ccm.c.

◆ CCM_MAX_COUNTER_SIZE

#define CCM_MAX_COUNTER_SIZE   (SYMCRYPT_CCM_BLOCK_SIZE - 1 - CCM_MIN_NONCE_SIZE)

Definition at line 14 of file ccm.c.

◆ CCM_MAX_NONCE_SIZE

#define CCM_MAX_NONCE_SIZE   (13)

Definition at line 10 of file ccm.c.

◆ CCM_MAX_TAG_SIZE

#define CCM_MAX_TAG_SIZE   (16)

Definition at line 12 of file ccm.c.

◆ CCM_MIN_NONCE_SIZE

#define CCM_MIN_NONCE_SIZE   (7)

Definition at line 9 of file ccm.c.

◆ CCM_MIN_TAG_SIZE

#define CCM_MIN_TAG_SIZE   (4)

Definition at line 11 of file ccm.c.

Function Documentation

◆ SymCryptCcmAddMacData()

VOID SYMCRYPT_CALL SymCryptCcmAddMacData ( _Inout_ PSYMCRYPT_CCM_STATE  pState,
_In_reads_(cbData) PCBYTE  pbData,
SIZE_T  cbData 
)

Definition at line 164 of file ccm.c.

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
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}
#define CCM_BLOCK_ROUND_MASK
Definition: ccm.c:24
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
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
VOID SYMCRYPT_CALL SymCryptCbcMac(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _Inout_updates_(pBlockCipher->blockSize) PBYTE pbChainingValue, _In_reads_(cbData) PCBYTE pbSrc, SIZE_T cbData)
#define SYMCRYPT_CCM_BLOCK_SIZE
#define SYMCRYPT_MIN(_a, _b)
PCBYTE PBYTE SIZE_T cbData
PSYMCRYPT_COMMON_HASH_STATE pState
PCBYTE pbData
ULONG_PTR SIZE_T
Definition: typedefs.h:80

Referenced by SymCryptCcmDecryptPart(), SymCryptCcmEncryptPart(), and SymCryptCcmInit().

◆ SymCryptCcmDecrypt()

SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCcmDecrypt ( _In_ PCSYMCRYPT_BLOCKCIPHER  pBlockCipher,
_In_ PCVOID  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 at line 257 of file ccm.c.

269{
272
276 pbNonce, cbNonce,
277 pbAuthData, cbAuthData,
278 cbData, cbTag );
279
280
282
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 {
292 }
293
294 return status;
295}
static int state
Definition: maze.c:121
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmDecryptPart(_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: ccm.c:503
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCcmDecryptFinal(_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbTag) PCBYTE pbTag, SIZE_T cbTag)
Definition: ccm.c:542
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmInit(_Out_ PSYMCRYPT_CCM_STATE pState, _In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID pExpandedKey, _In_reads_(cbNonce) PCBYTE pbNonce, SIZE_T cbNonce, _In_reads_opt_(cbAuthData) PCBYTE pbAuthData, SIZE_T cbAuthData, UINT64 cbData, SIZE_T cbTag)
Definition: ccm.c:300
Definition: ps.c:97
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
SYMCRYPT_ERROR
Definition: symcrypt.h:227
SIZE_T cbTag
PCBYTE pbSrc
UINT64 cbAuthData
SYMCRYPT_MAGIC_FIELD SYMCRYPT_CCM_STATE
PCSYMCRYPT_BLOCKCIPHER pBlockCipher
PCBYTE PBYTE pbDst
SIZE_T cbNonce
PCVOID pExpandedKey

Referenced by SymCryptCcmSelftest().

◆ SymCryptCcmDecryptFinal()

SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCcmDecryptFinal ( _Inout_ PSYMCRYPT_CCM_STATE  pState,
_In_reads_(cbTag) PCBYTE  pbTag,
SIZE_T  cbTag 
)

Definition at line 542 of file ccm.c.

546{
548
549 //
550 // Check invariants in checked builds
551 //
553
554 SYMCRYPT_ASSERT( cbTag == pState->cbTag && pState->bytesProcessed == pState->cbData );
555
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
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}
VOID SYMCRYPT_CALL SymCryptCcmPadMacData(_Inout_ PSYMCRYPT_CCM_STATE pState)
Definition: ccm.c:209
VOID SYMCRYPT_CALL SymCryptCcmEncryptDecryptPart(_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: ccm.c:93
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
BOOLEAN SYMCRYPT_CALL SymCryptEqual(_In_reads_(cbBytes) PCBYTE pbSrc1, _In_reads_(cbBytes) PCBYTE pbSrc2, SIZE_T cbBytes)
Definition: equal.c:11
#define SYMCRYPT_CHECK_MAGIC(p)

Referenced by SymCryptCcmDecrypt().

◆ SymCryptCcmDecryptPart()

SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmDecryptPart ( _Inout_ PSYMCRYPT_CCM_STATE  pState,
_In_reads_(cbData) PCBYTE  pbSrc,
_Out_writes_(cbData) PBYTE  pbDst,
SIZE_T  cbData 
)

Definition at line 503 of file ccm.c.

508{
509 UINT64 bytesProcessedAfterThisCall;
510
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 //
536
537}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
VOID SYMCRYPT_CALL SymCryptCcmAddMacData(_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: ccm.c:164

Referenced by SymCryptCcmDecrypt().

◆ SymCryptCcmEncrypt()

SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmEncrypt ( _In_ PCSYMCRYPT_BLOCKCIPHER  pBlockCipher,
_In_ PCVOID  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 at line 227 of file ccm.c.

239{
241
245 pbNonce, cbNonce,
246 pbAuthData, cbAuthData,
247 cbData, cbTag );
248
250
252}
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmEncryptPart(_Inout_ PSYMCRYPT_CCM_STATE pState, _In_reads_(cbData) PCBYTE pbSrc, _Out_writes_(cbData) PBYTE pbDst, SIZE_T cbData)
Definition: ccm.c:433
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmEncryptFinal(_Inout_ PSYMCRYPT_CCM_STATE pState, _Out_writes_(cbTag) PBYTE pbTag, SIZE_T cbTag)
Definition: ccm.c:468

Referenced by SymCryptCcmSelftest().

◆ SymCryptCcmEncryptDecryptPart()

VOID SYMCRYPT_CALL SymCryptCcmEncryptDecryptPart ( _Inout_ PSYMCRYPT_CCM_STATE  pState,
_In_reads_(cbData) PCBYTE  pbSrc,
_Out_writes_(cbData) PBYTE  pbDst,
SIZE_T  cbData 
)

Definition at line 93 of file ccm.c.

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 //
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],
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}
#define CCM_BLOCK_MOD_MASK
Definition: ccm.c:23
VOID SYMCRYPT_CALL SymCryptCtrMsb64(_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)

Referenced by SymCryptCcmDecryptFinal(), SymCryptCcmDecryptPart(), SymCryptCcmEncryptFinal(), and SymCryptCcmEncryptPart().

◆ SymCryptCcmEncryptFinal()

SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmEncryptFinal ( _Inout_ PSYMCRYPT_CCM_STATE  pState,
_Out_writes_(cbTag) PBYTE  pbTag,
SIZE_T  cbTag 
)

Definition at line 468 of file ccm.c.

472{
473 //
474 // Check invariants in checked builds
475 //
477
478 SYMCRYPT_ASSERT( cbTag == pState->cbTag && pState->bytesProcessed == pState->cbData );
479
480
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
493
494 memcpy( pbTag, &pState->macBlock[0], cbTag );
495
496 SymCryptWipeKnownSize( pState, sizeof( *pState ) );
497 SYMCRYPT_ASSERT( pState->bytesInMacBlock == 0 );
498}
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878

Referenced by SymCryptCcmEncrypt().

◆ SymCryptCcmEncryptPart()

SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmEncryptPart ( _Inout_ PSYMCRYPT_CCM_STATE  pState,
_In_reads_(cbData) PCBYTE  pbSrc,
_Out_writes_(cbData) PBYTE  pbDst,
SIZE_T  cbData 
)

Definition at line 433 of file ccm.c.

438{
439 UINT64 bytesProcessedAfterThisCall;
440
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 //
460
462
463}

Referenced by SymCryptCcmEncrypt().

◆ SymCryptCcmInit()

SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmInit ( _Out_ PSYMCRYPT_CCM_STATE  pState,
_In_ PCSYMCRYPT_BLOCKCIPHER  pBlockCipher,
_In_ PCVOID  pExpandedKey,
_In_reads_(cbNonce) PCBYTE  pbNonce,
SIZE_T  cbNonce,
_In_reads_opt_(cbAuthData) PCBYTE  pbAuthData,
SIZE_T  cbAuthData,
UINT64  cbData,
SIZE_T  cbTag 
)

Definition at line 300 of file ccm.c.

310{
311 BYTE flags;
314
316
317 //
318 // Validate parameters in checked builds
319 //
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 //
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 //
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 //
404 SymCryptCcmAddMacData( pState, &tmpBuf[0], 2 );
406 {
407 //
408 // 32-bit length
409 //
410 tmpBuf[0] = 0xff;
411 tmpBuf[1] = 0xfe; // Magic prefix as per SP 800-38c
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
422 SymCryptCcmAddMacData( pState, &tmpBuf[0], 2 + sizeof( UINT64 ) );
423 }
424
426 SymCryptCcmPadMacData( pState ); // Pad MAC data with zeroes until the next block size boundary
427
428}
unsigned short UINT16
Definition: actypes.h:129
GLbitfield flags
Definition: glext.h:7161
#define AUTHDATA_16BIT_LIMIT
Definition: ccm.c:16
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCcmValidateParameters(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ SIZE_T cbNonce, _In_ SIZE_T cbAssociatedData, _In_ UINT64 cbData, _In_ SIZE_T cbTag)
Definition: ccm.c:28
const BOOL fcbAuthDataLt32bitLimitStatic
Definition: ccm.c:21
#define AUTHDATA_32BIT_LIMIT
Definition: ccm.c:17
PSYMCRYPT_BLOCKCIPHER_CRYPT encryptFunc
#define SYMCRYPT_STORE_MSBFIRST16(p, v)
Definition: symcrypt.h:310
#define SYMCRYPT_STORE_MSBFIRST32(p, v)
Definition: symcrypt.h:311
#define SYMCRYPT_STORE_MSBFIRST64(p, v)
Definition: symcrypt.h:312
#define SYMCRYPT_SET_MAGIC(p)
SIZE_T cbCounter
uint32_t UINT32
Definition: typedefs.h:59
unsigned char BYTE
Definition: xxhash.c:193

Referenced by SymCryptCcmDecrypt(), and SymCryptCcmEncrypt().

◆ SymCryptCcmPadMacData()

VOID SYMCRYPT_CALL SymCryptCcmPadMacData ( _Inout_ PSYMCRYPT_CCM_STATE  pState)

Definition at line 209 of file ccm.c.

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}

Referenced by SymCryptCcmDecryptFinal(), SymCryptCcmEncryptFinal(), and SymCryptCcmInit().

◆ SymCryptCcmSelftest()

VOID SYMCRYPT_CALL SymCryptCcmSelftest ( void  )

Definition at line 593 of file ccm.c.

594{
598
599 if( SymCryptAesExpandKey( &key, SymCryptTestKey32, 16 ) != SYMCRYPT_NO_ERROR )
600 {
601 SymCryptFatal( 'ccm0' );
602 }
603
605 &key,
606 &SymCryptTestKey32[16], 12,
607 NULL, 0,
608 &SymCryptTestMsg3[0], buf, 3,
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
621 &key,
622 &SymCryptTestKey32[16], 12,
623 NULL, 0,
624 buf, buf, 3,
626
628
629 if( err != SYMCRYPT_NO_ERROR || memcmp( buf, SymCryptTestMsg3, 3 ) != 0 )
630 {
631 SymCryptFatal( 'ccm2' );
632 }
633
634}
#define NULL
Definition: types.h:112
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#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
static const BYTE SymCryptCcmSelftestResult[3+SYMCRYPT_AES_BLOCK_SIZE]
Definition: ccm.c:585
SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCcmDecrypt(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID 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: ccm.c:257
SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptCcmEncrypt(_In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, _In_ PCVOID 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: ccm.c:227
Definition: copy.c:22
const PCSYMCRYPT_BLOCKCIPHER SymCryptAesBlockCipher
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptAesExpandKey(_Out_ PSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, _In_reads_(cbKey) PCBYTE pbKey, SIZE_T cbKey)
Definition: aes-key.c:219
#define SYMCRYPT_AES_BLOCK_SIZE
Definition: symcrypt.h:4255
SYMCRYPT_MAGIC_FIELD SYMCRYPT_AES_EXPANDED_KEY

◆ SymCryptCcmValidateParameters()

SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCcmValidateParameters ( _In_ PCSYMCRYPT_BLOCKCIPHER  pBlockCipher,
_In_ SIZE_T  cbNonce,
_In_ SIZE_T  cbAssociatedData,
_In_ UINT64  cbData,
_In_ SIZE_T  cbTag 
)

Definition at line 28 of file ccm.c.

35{
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 //
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 ||
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}
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define CCM_MAX_TAG_SIZE
Definition: ccm.c:12
#define CCM_MIN_TAG_SIZE
Definition: ccm.c:11
#define CCM_MAX_NONCE_SIZE
Definition: ccm.c:10

Referenced by SymCryptCcmInit().

Variable Documentation

◆ fcbAuthDataLt32bitLimitStatic

const BOOL fcbAuthDataLt32bitLimitStatic = SIZE_T_MAX < AUTHDATA_32BIT_LIMIT

Definition at line 21 of file ccm.c.

Referenced by SymCryptCcmInit().

◆ SymCryptCcmSelftestResult

const BYTE SymCryptCcmSelftestResult[3+SYMCRYPT_AES_BLOCK_SIZE]
static
Initial value:
=
{
0x42, 0xd7, 0xda,
0x3d, 0x9e, 0x95, 0x82, 0x29, 0x3c, 0x10, 0x9c, 0xa3, 0x39, 0x31, 0x3f, 0x18, 0xf3, 0x10, 0xf6
}

Definition at line 585 of file ccm.c.

Referenced by SymCryptCcmSelftest().