From d6933e03f6a499a3c9800a4b677e1b4795229990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mitch=20Lindgren=20=F0=9F=A6=8E?= Date: Tue, 31 Oct 2023 22:21:18 +0000 Subject: [PATCH] Merged PR 9746161: Support cbNonce != 12 for AES-GCM This change adds support for nonces larger or smaller than 12-bytes for AES-GCM (and GCM generally, if it's ever used with other block ciphers). It adds 32-bit CTR functions, as required in the GCM spec. Previously we used a 64-bit CTR function, which worked for 12-byte nonces because the counter block always started at 1 and the message length limit for GCM is 2^36 - 32 bytes, so the 32-bit counter would never overflow. Using a 64-bit counter does not work for non-12-byte nonces because the counter block starts at an arbitrary value computed by GHASHing the nonce. It also updates the "stitched" implementations of AES-GCM to use 32-bit addition intrinsics instead of 64-bit addition. Tested with unit tests: - AMD64 with all features enabled - AMD64 without aesni - AMD64 without pclmulqdq - AMD64 with everything disabled except for rdrand, rdseed, savexmmnofail - ARM64 hardware (Galaxy Book 2) + qemu (via pipeline) Related work items: #33824154 --- CHANGELOG.md | 1 + inc/symcrypt.h | 6 +- lib/aes-default.c | 53 ++- lib/aes-neon.c | 258 ++++----------- lib/aes-pattern.c | 344 ++++++++++++++++++++ lib/aes-xmm.c | 248 +++----------- lib/aes-ymm.c | 80 ++--- lib/blockciphermodes.c | 51 +++ lib/gcm.c | 152 +++++---- lib/ghash.c | 11 +- lib/sc_lib.h | 52 +++ unittest/kat_authenc.dat | 434 +++++++++++++++++++++++-- unittest/lib/cng_imp_authenc.cpp | 24 +- unittest/lib/rsa32_implementations.cpp | 13 + unittest/lib/sc_imp_pattern.cpp | 5 +- unittest/lib/testAuthEnc.cpp | 23 +- 16 files changed, 1191 insertions(+), 564 deletions(-) create mode 100644 lib/aes-pattern.c diff --git a/CHANGELOG.md b/CHANGELOG.md index d9e7b04..66d4900 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ prior to the creation of a new release, based on the changes contained in that r - Extended SymCrypt support for XTS-AES adding support for 128-bit tweak and ciphertext-stealing - Added support for salt length detection in RSA-PSS verification - Export various constant time operations from SymCrypt Linux modules +- Added support for nonce sizes other than 12 bytes for AES-GCM # Version 103.3.2 diff --git a/inc/symcrypt.h b/inc/symcrypt.h index 877629c..c83883c 100644 --- a/inc/symcrypt.h +++ b/inc/symcrypt.h @@ -3495,7 +3495,7 @@ SymCryptMarvin32Selftest(void); // for different block cipher computations as the expanded key is not modified once initialized. // // SymCryptXxxBlockCipher -// A SYMCRYPT_BLOCK_CIPHER structure that provides a description +// A SYMCRYPT_BLOCKCIPHER structure that provides a description // of the block cipher and its primary functions. This is used by cipher modes to pass // all the block-cipher specific information in a single structure. // @@ -4152,8 +4152,7 @@ SymCryptCtrMsb64( SIZE_T cbData ); // // This function implements the CTR cipher mode. -// It is not intended to be used as-is, rather it is a building block -// for modes like CCM and GCM. +// It is not intended to be used as-is, rather it is a building block for modes like CCM. // On some platforms we have optimized code for AES-CTR, on other platforms // we use this generic construction to achieve the same effect. // @@ -4174,7 +4173,6 @@ SymCryptCtrMsb64( // buffers may be the same or non-overlapping, but may not partially overlap. // - VOID SYMCRYPT_CALL SymCryptCfbEncrypt( diff --git a/lib/aes-default.c b/lib/aes-default.c index 900c565..6f65d3d 100644 --- a/lib/aes-default.c +++ b/lib/aes-default.c @@ -361,6 +361,51 @@ SymCryptAesCbcMac( #endif } +VOID +SYMCRYPT_CALL +SymCryptAesCtrMsb32( + _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, + _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbChainingValue, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData ) +{ +#if SYMCRYPT_CPU_AMD64 + if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_CODE ) ) + { + SymCryptAesCtrMsb32Xmm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData ); + } else { + SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE ); // keep Prefast happy + SymCryptCtrMsb32( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData ); + } + +#elif SYMCRYPT_CPU_X86 + SYMCRYPT_EXTENDED_SAVE_DATA SaveData; + + if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_CODE ) && + SymCryptSaveXmm( &SaveData ) == SYMCRYPT_NO_ERROR ) + { + SymCryptAesCtrMsb32Xmm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData ); + SymCryptRestoreXmm( &SaveData ); + } else { + SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE ); // keep Prefast happy + SymCryptCtrMsb32( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData ); + } + +#elif SYMCRYPT_CPU_ARM64 + if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) ) + { + SymCryptAesCtrMsb32Neon( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData ); + } else { + SymCryptCtrMsb32( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData ); + } + +#else + SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE ); // keep Prefast happy + SymCryptCtrMsb32( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData ); +#endif +} + VOID SYMCRYPT_CALL SymCryptAesCtrMsb64( @@ -529,7 +574,7 @@ SymCryptAesGcmEncryptPartOnePass( bytesToProcess ); #else - SymCryptAesCtrMsb64(&pState->pKey->blockcipherKey.aes, + SymCryptAesCtrMsb32(&pState->pKey->blockcipherKey.aes, &pState->counterBlock[0], pbSrc, pbDst, @@ -563,7 +608,7 @@ SymCryptAesGcmEncryptPartOnePass( SymCryptWipeKnownSize( &pState->keystreamBlock[0], SYMCRYPT_GCM_BLOCK_SIZE ); SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE ); - SymCryptAesCtrMsb64(&pState->pKey->blockcipherKey.aes, + SymCryptAesCtrMsb32(&pState->pKey->blockcipherKey.aes, &pState->counterBlock[0], &pState->keystreamBlock[0], &pState->keystreamBlock[0], @@ -712,7 +757,7 @@ SymCryptAesGcmDecryptPartOnePass( // This violates the read-once rule, but it is safe for the same reasons as above // in the encryption case. // - SymCryptAesCtrMsb64(&pState->pKey->blockcipherKey.aes, + SymCryptAesCtrMsb32(&pState->pKey->blockcipherKey.aes, &pState->counterBlock[0], pbSrc, pbDst, @@ -729,7 +774,7 @@ SymCryptAesGcmDecryptPartOnePass( SymCryptWipeKnownSize( &pState->keystreamBlock[0], SYMCRYPT_GCM_BLOCK_SIZE ); SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE ); - SymCryptAesCtrMsb64(&pState->pKey->blockcipherKey.aes, + SymCryptAesCtrMsb32(&pState->pKey->blockcipherKey.aes, &pState->counterBlock[0], &pState->keystreamBlock[0], &pState->keystreamBlock[0], diff --git a/lib/aes-neon.c b/lib/aes-neon.c index f717355..32b118b 100644 --- a/lib/aes-neon.c +++ b/lib/aes-neon.c @@ -769,172 +769,26 @@ SymCryptAesEcbEncryptNeon( #pragma warning( disable:4701 ) // "Use of uninitialized variable" #pragma runtime_checks( "u", off ) -VOID -SYMCRYPT_CALL -SymCryptAesCtrMsb64Neon( - _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, - _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbChainingValue, - _In_reads_( cbData ) PCBYTE pbSrc, - _Out_writes_( cbData ) PBYTE pbDst, - SIZE_T cbData ) -{ - __n128 chain = *(__n128 *)pbChainingValue; - const __n128 * pSrc = (const __n128 *) pbSrc; - __n128 * pDst = (__n128 *) pbDst; +#define SYMCRYPT_AesCtrMsbXxNeon SymCryptAesCtrMsb64Neon +#define VADDQ_UXX vaddq_u64 +#define VSUBQ_UXX vsubq_u64 - const __n128 chainIncrement1 = SYMCRYPT_SET_N128_U64( 0, 1 ); - const __n128 chainIncrement2 = SYMCRYPT_SET_N128_U64( 0, 2 ); - const __n128 chainIncrement8 = SYMCRYPT_SET_N128_U64( 0, 8 ); +#include "aes-pattern.c" - __n128 ctr0, ctr1, ctr2, ctr3, ctr4, ctr5, ctr6, ctr7; - __n128 c0, c1, c2, c3, c4, c5, c6, c7; +#undef VSUBQ_UXX +#undef VADDQ_UXX +#undef SYMCRYPT_AesCtrMsbXxNeon - cbData &= ~(SYMCRYPT_AES_BLOCK_SIZE - 1); +#define SYMCRYPT_AesCtrMsbXxNeon SymCryptAesCtrMsb32Neon +#define VADDQ_UXX vaddq_u32 +#define VSUBQ_UXX vsubq_u32 - // Our chain variable is in integer format, not the MSBfirst format loaded from memory. - ctr0 = vrev64q_u8( chain ); - ctr1 = vaddq_u64( ctr0, chainIncrement1 ); - ctr2 = vaddq_u64( ctr0, chainIncrement2 ); - ctr3 = vaddq_u64( ctr1, chainIncrement2 ); - ctr4 = vaddq_u64( ctr2, chainIncrement2 ); - ctr5 = vaddq_u64( ctr3, chainIncrement2 ); - ctr6 = vaddq_u64( ctr4, chainIncrement2 ); - ctr7 = vaddq_u64( ctr5, chainIncrement2 ); +#include "aes-pattern.c" -/* - while cbData >= 5 * block - generate 8 blocks of key stream - if cbData < 8 * block - break; - process 8 blocks - if cbData >= 5 * block - process 5-7 blocks - done - if cbData >= 2 * block - generate 4 blocks of key stream - process 2-4 blocks - done - if cbData == 1 block - generate 1 block of key stream - process block -*/ - while( cbData >= 5 * SYMCRYPT_AES_BLOCK_SIZE ) - { - c0 = vrev64q_u8( ctr0 ); - c1 = vrev64q_u8( ctr1 ); - c2 = vrev64q_u8( ctr2 ); - c3 = vrev64q_u8( ctr3 ); - c4 = vrev64q_u8( ctr4 ); - c5 = vrev64q_u8( ctr5 ); - c6 = vrev64q_u8( ctr6 ); - c7 = vrev64q_u8( ctr7 ); +#undef VSUBQ_UXX +#undef VADDQ_UXX +#undef SYMCRYPT_AesCtrMsbXxNeon - ctr0 = vaddq_u64( ctr0, chainIncrement8 ); - ctr1 = vaddq_u64( ctr1, chainIncrement8 ); - ctr2 = vaddq_u64( ctr2, chainIncrement8 ); - ctr3 = vaddq_u64( ctr3, chainIncrement8 ); - ctr4 = vaddq_u64( ctr4, chainIncrement8 ); - ctr5 = vaddq_u64( ctr5, chainIncrement8 ); - ctr6 = vaddq_u64( ctr6, chainIncrement8 ); - ctr7 = vaddq_u64( ctr7, chainIncrement8 ); - - AES_ENCRYPT_8( pExpandedKey, c0, c1, c2, c3, c4, c5, c6, c7 ); - - if( cbData < 8 * SYMCRYPT_AES_BLOCK_SIZE ) - { - break; - } - - pDst[0] = veorq_u64( pSrc[0], c0 ); - pDst[1] = veorq_u64( pSrc[1], c1 ); - pDst[2] = veorq_u64( pSrc[2], c2 ); - pDst[3] = veorq_u64( pSrc[3], c3 ); - pDst[4] = veorq_u64( pSrc[4], c4 ); - pDst[5] = veorq_u64( pSrc[5], c5 ); - pDst[6] = veorq_u64( pSrc[6], c6 ); - pDst[7] = veorq_u64( pSrc[7], c7 ); - - pDst += 8; - pSrc += 8; - cbData -= 8 * SYMCRYPT_AES_BLOCK_SIZE; - } - - // - // At this point we have one of the two following cases: - // - cbData >= 5 * 16 and we have 8 blocks of key stream in c0-c7. ctr0-ctr7 is set to (c0+8)-(c7+8) - // - cbData < 5 * 16 and we have no blocks of key stream, and ctr0-ctr7 set to the next 8 counters to use - // - - if( cbData >= SYMCRYPT_AES_BLOCK_SIZE ) // quick exit of function if the request was a multiple of 8 blocks - { - if( cbData >= 5 * SYMCRYPT_AES_BLOCK_SIZE ) - { - // - // We already have the key stream - // - pDst[0] = veorq_u64( pSrc[0], c0 ); - pDst[1] = veorq_u64( pSrc[1], c1 ); - pDst[2] = veorq_u64( pSrc[2], c2 ); - pDst[3] = veorq_u64( pSrc[3], c3 ); - pDst[4] = veorq_u64( pSrc[4], c4 ); - chain = vsubq_u64( ctr5, chainIncrement8 ); - - if( cbData >= 96 ) - { - chain = vsubq_u64( ctr6, chainIncrement8 ); - pDst[5] = veorq_u64( pSrc[5], c5 ); - if( cbData >= 112 ) - { - chain = vsubq_u64( ctr7, chainIncrement8 ); - pDst[6] = veorq_u64( pSrc[6], c6 ); - } - } - } - else if( cbData >= 2 * SYMCRYPT_AES_BLOCK_SIZE ) - { - // Produce 4 blocks of key stream - - chain = ctr2; // chain is only incremented by 2 for now - - c0 = vrev64q_u8( ctr0 ); - c1 = vrev64q_u8( ctr1 ); - c2 = vrev64q_u8( ctr2 ); - c3 = vrev64q_u8( ctr3 ); - - AES_ENCRYPT_4( pExpandedKey, c0, c1, c2, c3 ); - - pDst[0] = veorq_u64( pSrc[0], c0 ); - pDst[1] = veorq_u64( pSrc[1], c1 ); - if( cbData >= 48 ) - { - chain = ctr3; - pDst[2] = veorq_u64( pSrc[2], c2 ); - if( cbData >= 64 ) - { - chain = ctr4; - pDst[3] = veorq_u64( pSrc[3], c3 ); - } - } - } - else - { - // Exactly 1 block to process - chain = ctr1; - - c0 = vrev64q_u8( ctr0 ); - - AES_ENCRYPT_1( pExpandedKey, c0 ); - pDst[0] = veorq_u64( pSrc[0], c0 ); - } - } - else - { - chain = ctr0; - } - - chain = vrev64q_u8( chain ); - *(__n128 *)pbChainingValue = chain; -} #pragma runtime_checks( "u", restore ) #pragma warning(pop) @@ -1662,13 +1516,13 @@ SymCryptAesGcmEncryptStitchedNeon( // Our chain variable is in integer format, not the MSBfirst format loaded from memory. ctr0 = vrev64q_u8( chain ); - ctr1 = vaddq_u64( ctr0, chainIncrement1 ); - ctr2 = vaddq_u64( ctr0, chainIncrement2 ); - ctr3 = vaddq_u64( ctr1, chainIncrement2 ); - ctr4 = vaddq_u64( ctr2, chainIncrement2 ); - ctr5 = vaddq_u64( ctr3, chainIncrement2 ); - ctr6 = vaddq_u64( ctr4, chainIncrement2 ); - ctr7 = vaddq_u64( ctr5, chainIncrement2 ); + ctr1 = vaddq_u32( ctr0, chainIncrement1 ); + ctr2 = vaddq_u32( ctr0, chainIncrement2 ); + ctr3 = vaddq_u32( ctr1, chainIncrement2 ); + ctr4 = vaddq_u32( ctr2, chainIncrement2 ); + ctr5 = vaddq_u32( ctr3, chainIncrement2 ); + ctr6 = vaddq_u32( ctr4, chainIncrement2 ); + ctr7 = vaddq_u32( ctr5, chainIncrement2 ); state = *(__n128 *) pState; @@ -1689,14 +1543,14 @@ SymCryptAesGcmEncryptStitchedNeon( if ( cbData >= 8 * SYMCRYPT_AES_BLOCK_SIZE ) { - ctr0 = vaddq_u64( ctr0, chainIncrement8 ); - ctr1 = vaddq_u64( ctr1, chainIncrement8 ); - ctr2 = vaddq_u64( ctr2, chainIncrement8 ); - ctr3 = vaddq_u64( ctr3, chainIncrement8 ); - ctr4 = vaddq_u64( ctr4, chainIncrement8 ); - ctr5 = vaddq_u64( ctr5, chainIncrement8 ); - ctr6 = vaddq_u64( ctr6, chainIncrement8 ); - ctr7 = vaddq_u64( ctr7, chainIncrement8 ); + ctr0 = vaddq_u32( ctr0, chainIncrement8 ); + ctr1 = vaddq_u32( ctr1, chainIncrement8 ); + ctr2 = vaddq_u32( ctr2, chainIncrement8 ); + ctr3 = vaddq_u32( ctr3, chainIncrement8 ); + ctr4 = vaddq_u32( ctr4, chainIncrement8 ); + ctr5 = vaddq_u32( ctr5, chainIncrement8 ); + ctr6 = vaddq_u32( ctr6, chainIncrement8 ); + ctr7 = vaddq_u32( ctr7, chainIncrement8 ); // Encrypt first 8 blocks pDst[0] = veorq_u64( pSrc[0], c0 ); @@ -1723,14 +1577,14 @@ SymCryptAesGcmEncryptStitchedNeon( c6 = vrev64q_u8( ctr6 ); c7 = vrev64q_u8( ctr7 ); - ctr0 = vaddq_u64( ctr0, chainIncrement8 ); - ctr1 = vaddq_u64( ctr1, chainIncrement8 ); - ctr2 = vaddq_u64( ctr2, chainIncrement8 ); - ctr3 = vaddq_u64( ctr3, chainIncrement8 ); - ctr4 = vaddq_u64( ctr4, chainIncrement8 ); - ctr5 = vaddq_u64( ctr5, chainIncrement8 ); - ctr6 = vaddq_u64( ctr6, chainIncrement8 ); - ctr7 = vaddq_u64( ctr7, chainIncrement8 ); + ctr0 = vaddq_u32( ctr0, chainIncrement8 ); + ctr1 = vaddq_u32( ctr1, chainIncrement8 ); + ctr2 = vaddq_u32( ctr2, chainIncrement8 ); + ctr3 = vaddq_u32( ctr3, chainIncrement8 ); + ctr4 = vaddq_u32( ctr4, chainIncrement8 ); + ctr5 = vaddq_u32( ctr5, chainIncrement8 ); + ctr6 = vaddq_u32( ctr6, chainIncrement8 ); + ctr7 = vaddq_u32( ctr7, chainIncrement8 ); AES_GCM_ENCRYPT_8( pExpandedKey, c0, c1, c2, c3, c4, c5, c6, c7, pGhashSrc, 8, expandedKeyTable, todo, a0, a1, a2 ); @@ -1814,7 +1668,7 @@ SymCryptAesGcmEncryptStitchedNeon( // Encrypt 1-7 blocks with pre-generated AES-CTR blocks and GHASH the results while( nBlocks >= 2 ) { - ctr0 = vaddq_u64( ctr0, chainIncrement2 ); + ctr0 = vaddq_u32( ctr0, chainIncrement2 ); r0 = veorq_u64( pSrc[0], c0 ); r1 = veorq_u64( pSrc[1], c1 ); @@ -1845,7 +1699,7 @@ SymCryptAesGcmEncryptStitchedNeon( if( nBlocks > 0 ) { - ctr0 = vaddq_u64( ctr0, chainIncrement1 ); + ctr0 = vaddq_u32( ctr0, chainIncrement1 ); r0 = veorq_u64( pSrc[0], c0 ); pDst[0] = r0; @@ -1911,13 +1765,13 @@ SymCryptAesGcmDecryptStitchedNeon( // Our chain variable is in integer format, not the MSBfirst format loaded from memory. ctr0 = vrev64q_u8( chain ); - ctr1 = vaddq_u64( ctr0, chainIncrement1 ); - ctr2 = vaddq_u64( ctr0, chainIncrement2 ); - ctr3 = vaddq_u64( ctr1, chainIncrement2 ); - ctr4 = vaddq_u64( ctr2, chainIncrement2 ); - ctr5 = vaddq_u64( ctr3, chainIncrement2 ); - ctr6 = vaddq_u64( ctr4, chainIncrement2 ); - ctr7 = vaddq_u64( ctr5, chainIncrement2 ); + ctr1 = vaddq_u32( ctr0, chainIncrement1 ); + ctr2 = vaddq_u32( ctr0, chainIncrement2 ); + ctr3 = vaddq_u32( ctr1, chainIncrement2 ); + ctr4 = vaddq_u32( ctr2, chainIncrement2 ); + ctr5 = vaddq_u32( ctr3, chainIncrement2 ); + ctr6 = vaddq_u32( ctr4, chainIncrement2 ); + ctr7 = vaddq_u32( ctr5, chainIncrement2 ); state = *(__n128 *) pState; @@ -1937,14 +1791,14 @@ SymCryptAesGcmDecryptStitchedNeon( c6 = vrev64q_u8( ctr6 ); c7 = vrev64q_u8( ctr7 ); - ctr0 = vaddq_u64( ctr0, chainIncrement8 ); - ctr1 = vaddq_u64( ctr1, chainIncrement8 ); - ctr2 = vaddq_u64( ctr2, chainIncrement8 ); - ctr3 = vaddq_u64( ctr3, chainIncrement8 ); - ctr4 = vaddq_u64( ctr4, chainIncrement8 ); - ctr5 = vaddq_u64( ctr5, chainIncrement8 ); - ctr6 = vaddq_u64( ctr6, chainIncrement8 ); - ctr7 = vaddq_u64( ctr7, chainIncrement8 ); + ctr0 = vaddq_u32( ctr0, chainIncrement8 ); + ctr1 = vaddq_u32( ctr1, chainIncrement8 ); + ctr2 = vaddq_u32( ctr2, chainIncrement8 ); + ctr3 = vaddq_u32( ctr3, chainIncrement8 ); + ctr4 = vaddq_u32( ctr4, chainIncrement8 ); + ctr5 = vaddq_u32( ctr5, chainIncrement8 ); + ctr6 = vaddq_u32( ctr6, chainIncrement8 ); + ctr7 = vaddq_u32( ctr7, chainIncrement8 ); AES_GCM_ENCRYPT_8( pExpandedKey, c0, c1, c2, c3, c4, c5, c6, c7, pGhashSrc, 8, expandedKeyTable, todo, a0, a1, a2 ); @@ -1999,7 +1853,7 @@ SymCryptAesGcmDecryptStitchedNeon( // Decrypt 1-7 blocks with pre-generated AES-CTR blocks while( nBlocks >= 2 ) { - ctr0 = vaddq_u64( ctr0, chainIncrement2 ); + ctr0 = vaddq_u32( ctr0, chainIncrement2 ); pDst[0] = veorq_u64( pSrc[0], c0 ); pDst[1] = veorq_u64( pSrc[1], c1 ); @@ -2016,7 +1870,7 @@ SymCryptAesGcmDecryptStitchedNeon( if( nBlocks > 0 ) { - ctr0 = vaddq_u64( ctr0, chainIncrement1 ); + ctr0 = vaddq_u32( ctr0, chainIncrement1 ); pDst[0] = veorq_u64( pSrc[0], c0 ); } diff --git a/lib/aes-pattern.c b/lib/aes-pattern.c new file mode 100644 index 0000000..9afe2d8 --- /dev/null +++ b/lib/aes-pattern.c @@ -0,0 +1,344 @@ +// +// aes-pattern.c +// +// Copyright (c) Microsoft Corporation. Licensed under the MIT license. +// +// This file contains "pattern" code for AES-related functions. It's not intended to be compiled +// directly; rather it is included by other aes-*.c files which define the macros used here. +// + +#if SYMCRYPT_CPU_ARM64 + +VOID +SYMCRYPT_CALL +SYMCRYPT_AesCtrMsbXxNeon( + _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, + _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbChainingValue, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData ) +{ + __n128 chain = *(__n128 *)pbChainingValue; + const __n128 * pSrc = (const __n128 *) pbSrc; + __n128 * pDst = (__n128 *) pbDst; + + const __n128 chainIncrement1 = SYMCRYPT_SET_N128_U64( 0, 1 ); + const __n128 chainIncrement2 = SYMCRYPT_SET_N128_U64( 0, 2 ); + const __n128 chainIncrement8 = SYMCRYPT_SET_N128_U64( 0, 8 ); + + __n128 ctr0, ctr1, ctr2, ctr3, ctr4, ctr5, ctr6, ctr7; + __n128 c0, c1, c2, c3, c4, c5, c6, c7; + + cbData &= ~(SYMCRYPT_AES_BLOCK_SIZE - 1); + + // Our chain variable is in integer format, not the MSBfirst format loaded from memory. + ctr0 = vrev64q_u8( chain ); + ctr1 = VADDQ_UXX( ctr0, chainIncrement1 ); + ctr2 = VADDQ_UXX( ctr0, chainIncrement2 ); + ctr3 = VADDQ_UXX( ctr1, chainIncrement2 ); + ctr4 = VADDQ_UXX( ctr2, chainIncrement2 ); + ctr5 = VADDQ_UXX( ctr3, chainIncrement2 ); + ctr6 = VADDQ_UXX( ctr4, chainIncrement2 ); + ctr7 = VADDQ_UXX( ctr5, chainIncrement2 ); + +/* + while cbData >= 5 * block + generate 8 blocks of key stream + if cbData < 8 * block + break; + process 8 blocks + if cbData >= 5 * block + process 5-7 blocks + done + if cbData >= 2 * block + generate 4 blocks of key stream + process 2-4 blocks + done + if cbData == 1 block + generate 1 block of key stream + process block +*/ + while( cbData >= 5 * SYMCRYPT_AES_BLOCK_SIZE ) + { + c0 = vrev64q_u8( ctr0 ); + c1 = vrev64q_u8( ctr1 ); + c2 = vrev64q_u8( ctr2 ); + c3 = vrev64q_u8( ctr3 ); + c4 = vrev64q_u8( ctr4 ); + c5 = vrev64q_u8( ctr5 ); + c6 = vrev64q_u8( ctr6 ); + c7 = vrev64q_u8( ctr7 ); + + ctr0 = VADDQ_UXX( ctr0, chainIncrement8 ); + ctr1 = VADDQ_UXX( ctr1, chainIncrement8 ); + ctr2 = VADDQ_UXX( ctr2, chainIncrement8 ); + ctr3 = VADDQ_UXX( ctr3, chainIncrement8 ); + ctr4 = VADDQ_UXX( ctr4, chainIncrement8 ); + ctr5 = VADDQ_UXX( ctr5, chainIncrement8 ); + ctr6 = VADDQ_UXX( ctr6, chainIncrement8 ); + ctr7 = VADDQ_UXX( ctr7, chainIncrement8 ); + + AES_ENCRYPT_8( pExpandedKey, c0, c1, c2, c3, c4, c5, c6, c7 ); + + if( cbData < 8 * SYMCRYPT_AES_BLOCK_SIZE ) + { + break; + } + + pDst[0] = veorq_u64( pSrc[0], c0 ); + pDst[1] = veorq_u64( pSrc[1], c1 ); + pDst[2] = veorq_u64( pSrc[2], c2 ); + pDst[3] = veorq_u64( pSrc[3], c3 ); + pDst[4] = veorq_u64( pSrc[4], c4 ); + pDst[5] = veorq_u64( pSrc[5], c5 ); + pDst[6] = veorq_u64( pSrc[6], c6 ); + pDst[7] = veorq_u64( pSrc[7], c7 ); + + pDst += 8; + pSrc += 8; + cbData -= 8 * SYMCRYPT_AES_BLOCK_SIZE; + } + + // + // At this point we have one of the two following cases: + // - cbData >= 5 * 16 and we have 8 blocks of key stream in c0-c7. ctr0-ctr7 is set to (c0+8)-(c7+8) + // - cbData < 5 * 16 and we have no blocks of key stream, and ctr0-ctr7 set to the next 8 counters to use + // + + if( cbData >= SYMCRYPT_AES_BLOCK_SIZE ) // quick exit of function if the request was a multiple of 8 blocks + { + if( cbData >= 5 * SYMCRYPT_AES_BLOCK_SIZE ) + { + // + // We already have the key stream + // + pDst[0] = veorq_u64( pSrc[0], c0 ); + pDst[1] = veorq_u64( pSrc[1], c1 ); + pDst[2] = veorq_u64( pSrc[2], c2 ); + pDst[3] = veorq_u64( pSrc[3], c3 ); + pDst[4] = veorq_u64( pSrc[4], c4 ); + chain = VSUBQ_UXX( ctr5, chainIncrement8 ); + + if( cbData >= 96 ) + { + chain = VSUBQ_UXX( ctr6, chainIncrement8 ); + pDst[5] = veorq_u64( pSrc[5], c5 ); + if( cbData >= 112 ) + { + chain = VSUBQ_UXX( ctr7, chainIncrement8 ); + pDst[6] = veorq_u64( pSrc[6], c6 ); + } + } + } + else if( cbData >= 2 * SYMCRYPT_AES_BLOCK_SIZE ) + { + // Produce 4 blocks of key stream + + chain = ctr2; // chain is only incremented by 2 for now + + c0 = vrev64q_u8( ctr0 ); + c1 = vrev64q_u8( ctr1 ); + c2 = vrev64q_u8( ctr2 ); + c3 = vrev64q_u8( ctr3 ); + + AES_ENCRYPT_4( pExpandedKey, c0, c1, c2, c3 ); + + pDst[0] = veorq_u64( pSrc[0], c0 ); + pDst[1] = veorq_u64( pSrc[1], c1 ); + if( cbData >= 48 ) + { + chain = ctr3; + pDst[2] = veorq_u64( pSrc[2], c2 ); + if( cbData >= 64 ) + { + chain = ctr4; + pDst[3] = veorq_u64( pSrc[3], c3 ); + } + } + } + else + { + // Exactly 1 block to process + chain = ctr1; + + c0 = vrev64q_u8( ctr0 ); + + AES_ENCRYPT_1( pExpandedKey, c0 ); + pDst[0] = veorq_u64( pSrc[0], c0 ); + } + } + else + { + chain = ctr0; + } + + chain = vrev64q_u8( chain ); + *(__n128 *)pbChainingValue = chain; +} + +#endif // SYMCRYPT_CPU_ARM64 + +#if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64 + +VOID +SYMCRYPT_CALL +SYMCRYPT_AesCtrMsbXxXmm( + _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, + _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbChainingValue, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData ) +{ + __m128i chain = _mm_loadu_si128( (__m128i *) pbChainingValue ); + + __m128i BYTE_REVERSE_ORDER = _mm_set_epi8( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + + __m128i chainIncrement1 = _mm_set_epi32( 0, 0, 0, 1 ); + __m128i chainIncrement2 = _mm_set_epi32( 0, 0, 0, 2 ); + __m128i chainIncrement3 = _mm_set_epi32( 0, 0, 0, 3 ); + //__m128i chainIncrement8 = _mm_set_epi32( 0, 0, 0, 8 ); + + __m128i c0, c1, c2, c3, c4, c5, c6, c7; + + cbData &= ~(SYMCRYPT_AES_BLOCK_SIZE - 1); + + chain = _mm_shuffle_epi8( chain, BYTE_REVERSE_ORDER ); + +/* + while cbData >= 5 * block + generate 8 blocks of key stream + if cbData < 8 * block + break; + process 8 blocks + if cbData >= 5 * block + process 5-7 blocks + done + if cbData > 1 block + generate 4 blocks of key stream + process 2-4 blocks + done + if cbData == 1 block + generate 1 block of key stream + process block +*/ + while( cbData >= 5 * SYMCRYPT_AES_BLOCK_SIZE ) + { + c0 = chain; + c1 = MM_ADD_EPIXX( chain, chainIncrement1 ); + c2 = MM_ADD_EPIXX( chain, chainIncrement2 ); + c3 = MM_ADD_EPIXX( c1, chainIncrement2 ); + c4 = MM_ADD_EPIXX( c2, chainIncrement2 ); + c5 = MM_ADD_EPIXX( c3, chainIncrement2 ); + c6 = MM_ADD_EPIXX( c4, chainIncrement2 ); + c7 = MM_ADD_EPIXX( c5, chainIncrement2 ); + chain = MM_ADD_EPIXX( c6, chainIncrement2 ); + + c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); + c1 = _mm_shuffle_epi8( c1, BYTE_REVERSE_ORDER ); + c2 = _mm_shuffle_epi8( c2, BYTE_REVERSE_ORDER ); + c3 = _mm_shuffle_epi8( c3, BYTE_REVERSE_ORDER ); + c4 = _mm_shuffle_epi8( c4, BYTE_REVERSE_ORDER ); + c5 = _mm_shuffle_epi8( c5, BYTE_REVERSE_ORDER ); + c6 = _mm_shuffle_epi8( c6, BYTE_REVERSE_ORDER ); + c7 = _mm_shuffle_epi8( c7, BYTE_REVERSE_ORDER ); + + AES_ENCRYPT_8( pExpandedKey, c0, c1, c2, c3, c4, c5, c6, c7 ); + + if( cbData < 8 * SYMCRYPT_AES_BLOCK_SIZE ) + { + break; + } + + _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 16), _mm_xor_si128( c1, _mm_loadu_si128( ( __m128i * ) (pbSrc + 16 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 32), _mm_xor_si128( c2, _mm_loadu_si128( ( __m128i * ) (pbSrc + 32 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 48), _mm_xor_si128( c3, _mm_loadu_si128( ( __m128i * ) (pbSrc + 48 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 64), _mm_xor_si128( c4, _mm_loadu_si128( ( __m128i * ) (pbSrc + 64 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 80), _mm_xor_si128( c5, _mm_loadu_si128( ( __m128i * ) (pbSrc + 80 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 96), _mm_xor_si128( c6, _mm_loadu_si128( ( __m128i * ) (pbSrc + 96 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst +112), _mm_xor_si128( c7, _mm_loadu_si128( ( __m128i * ) (pbSrc +112 ) ) ) ); + pbDst += 8 * SYMCRYPT_AES_BLOCK_SIZE; + pbSrc += 8 * SYMCRYPT_AES_BLOCK_SIZE; + cbData -= 8 * SYMCRYPT_AES_BLOCK_SIZE; + } + + // + // At this point we have one of the two following cases: + // - cbData >= 5 * 16 and we have 8 blocks of key stream in c0-c7. chain is set to c7 + 1 + // - cbData < 5 * 16 and we have no blocks of key stream, with chain the next value to use + // + + if( cbData >= SYMCRYPT_AES_BLOCK_SIZE ) // quick exit of function if the request was a multiple of 8 blocks + { + if( cbData >= 5 * SYMCRYPT_AES_BLOCK_SIZE ) + { + // + // We already have the key stream + // + _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 16), _mm_xor_si128( c1, _mm_loadu_si128( ( __m128i * ) (pbSrc + 16 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 32), _mm_xor_si128( c2, _mm_loadu_si128( ( __m128i * ) (pbSrc + 32 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 48), _mm_xor_si128( c3, _mm_loadu_si128( ( __m128i * ) (pbSrc + 48 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 64), _mm_xor_si128( c4, _mm_loadu_si128( ( __m128i * ) (pbSrc + 64 ) ) ) ); + chain = MM_SUB_EPIXX( chain, chainIncrement3 ); + + if( cbData >= 96 ) + { + chain = MM_ADD_EPIXX( chain, chainIncrement1 ); + _mm_storeu_si128( (__m128i *) (pbDst + 80), _mm_xor_si128( c5, _mm_loadu_si128( ( __m128i * ) (pbSrc + 80 ) ) ) ); + if( cbData >= 112 ) + { + chain = MM_ADD_EPIXX( chain, chainIncrement1 ); + _mm_storeu_si128( (__m128i *) (pbDst + 96), _mm_xor_si128( c6, _mm_loadu_si128( ( __m128i * ) (pbSrc + 96 ) ) ) ); + } + } + } + else if( cbData >= 2 * SYMCRYPT_AES_BLOCK_SIZE ) + { + // Produce 4 blocks of key stream + + c0 = chain; + c1 = MM_ADD_EPIXX( chain, chainIncrement1 ); + c2 = MM_ADD_EPIXX( chain, chainIncrement2 ); + c3 = MM_ADD_EPIXX( c1, chainIncrement2 ); + chain = c2; // chain is only incremented by 2 for now + + c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); + c1 = _mm_shuffle_epi8( c1, BYTE_REVERSE_ORDER ); + c2 = _mm_shuffle_epi8( c2, BYTE_REVERSE_ORDER ); + c3 = _mm_shuffle_epi8( c3, BYTE_REVERSE_ORDER ); + + AES_ENCRYPT_4( pExpandedKey, c0, c1, c2, c3 ); + + _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0 ) ) ) ); + _mm_storeu_si128( (__m128i *) (pbDst + 16), _mm_xor_si128( c1, _mm_loadu_si128( ( __m128i * ) (pbSrc + 16 ) ) ) ); + if( cbData >= 48 ) + { + chain = MM_ADD_EPIXX( chain, chainIncrement1 ); + _mm_storeu_si128( (__m128i *) (pbDst + 32), _mm_xor_si128( c2, _mm_loadu_si128( ( __m128i * ) (pbSrc + 32 ) ) ) ); + if( cbData >= 64 ) + { + chain = MM_ADD_EPIXX( chain, chainIncrement1 ); + _mm_storeu_si128( (__m128i *) (pbDst + 48), _mm_xor_si128( c3, _mm_loadu_si128( ( __m128i * ) (pbSrc + 48 ) ) ) ); + } + } + } + else + { + // Exactly 1 block to process + c0 = chain; + chain = MM_ADD_EPIXX( chain, chainIncrement1 ); + + c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); + + AES_ENCRYPT_1( pExpandedKey, c0 ); + _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0 ) ) ) ); + } + } + + chain = _mm_shuffle_epi8( chain, BYTE_REVERSE_ORDER ); + _mm_storeu_si128( (__m128i *) pbChainingValue, chain ); +} + +#endif // SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64 \ No newline at end of file diff --git a/lib/aes-xmm.c b/lib/aes-xmm.c index 56b6dd5..bffcf99 100644 --- a/lib/aes-xmm.c +++ b/lib/aes-xmm.c @@ -727,166 +727,26 @@ SymCryptAesCbcMacXmm( #pragma warning( disable:4701 ) // "Use of uninitialized variable" #pragma runtime_checks( "u", off ) -VOID -SYMCRYPT_CALL -SymCryptAesCtrMsb64Xmm( - _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, - _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbChainingValue, - _In_reads_( cbData ) PCBYTE pbSrc, - _Out_writes_( cbData ) PBYTE pbDst, - SIZE_T cbData ) -{ - __m128i chain = _mm_loadu_si128( (__m128i *) pbChainingValue ); +#define SYMCRYPT_AesCtrMsbXxXmm SymCryptAesCtrMsb64Xmm +#define MM_ADD_EPIXX _mm_add_epi64 +#define MM_SUB_EPIXX _mm_sub_epi64 - __m128i BYTE_REVERSE_ORDER = _mm_set_epi8( - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); +#include "aes-pattern.c" - __m128i chainIncrement1 = _mm_set_epi32( 0, 0, 0, 1 ); - __m128i chainIncrement2 = _mm_set_epi32( 0, 0, 0, 2 ); - __m128i chainIncrement3 = _mm_set_epi32( 0, 0, 0, 3 ); - //__m128i chainIncrement8 = _mm_set_epi32( 0, 0, 0, 8 ); +#undef MM_SUB_EPIXX +#undef MM_ADD_EPIXX +#undef SYMCRYPT_AesCtrMsbXxXmm - __m128i c0, c1, c2, c3, c4, c5, c6, c7; +#define SYMCRYPT_AesCtrMsbXxXmm SymCryptAesCtrMsb32Xmm +#define MM_ADD_EPIXX _mm_add_epi32 +#define MM_SUB_EPIXX _mm_sub_epi32 - cbData &= ~(SYMCRYPT_AES_BLOCK_SIZE - 1); +#include "aes-pattern.c" - chain = _mm_shuffle_epi8( chain, BYTE_REVERSE_ORDER ); +#undef MM_SUB_EPIXX +#undef MM_ADD_EPIXX +#undef SYMCRYPT_AesCtrMsbXxXmm -/* - while cbData >= 5 * block - generate 8 blocks of key stream - if cbData < 8 * block - break; - process 8 blocks - if cbData >= 5 * block - process 5-7 blocks - done - if cbData > 1 block - generate 4 blocks of key stream - process 2-4 blocks - done - if cbData == 1 block - generate 1 block of key stream - process block -*/ - while( cbData >= 5 * SYMCRYPT_AES_BLOCK_SIZE ) - { - c0 = chain; - c1 = _mm_add_epi64( chain, chainIncrement1 ); - c2 = _mm_add_epi64( chain, chainIncrement2 ); - c3 = _mm_add_epi64( c1, chainIncrement2 ); - c4 = _mm_add_epi64( c2, chainIncrement2 ); - c5 = _mm_add_epi64( c3, chainIncrement2 ); - c6 = _mm_add_epi64( c4, chainIncrement2 ); - c7 = _mm_add_epi64( c5, chainIncrement2 ); - chain = _mm_add_epi64( c6, chainIncrement2 ); - - c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); - c1 = _mm_shuffle_epi8( c1, BYTE_REVERSE_ORDER ); - c2 = _mm_shuffle_epi8( c2, BYTE_REVERSE_ORDER ); - c3 = _mm_shuffle_epi8( c3, BYTE_REVERSE_ORDER ); - c4 = _mm_shuffle_epi8( c4, BYTE_REVERSE_ORDER ); - c5 = _mm_shuffle_epi8( c5, BYTE_REVERSE_ORDER ); - c6 = _mm_shuffle_epi8( c6, BYTE_REVERSE_ORDER ); - c7 = _mm_shuffle_epi8( c7, BYTE_REVERSE_ORDER ); - - AES_ENCRYPT_8( pExpandedKey, c0, c1, c2, c3, c4, c5, c6, c7 ); - - if( cbData < 8 * SYMCRYPT_AES_BLOCK_SIZE ) - { - break; - } - - _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 16), _mm_xor_si128( c1, _mm_loadu_si128( ( __m128i * ) (pbSrc + 16 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 32), _mm_xor_si128( c2, _mm_loadu_si128( ( __m128i * ) (pbSrc + 32 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 48), _mm_xor_si128( c3, _mm_loadu_si128( ( __m128i * ) (pbSrc + 48 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 64), _mm_xor_si128( c4, _mm_loadu_si128( ( __m128i * ) (pbSrc + 64 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 80), _mm_xor_si128( c5, _mm_loadu_si128( ( __m128i * ) (pbSrc + 80 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 96), _mm_xor_si128( c6, _mm_loadu_si128( ( __m128i * ) (pbSrc + 96 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst +112), _mm_xor_si128( c7, _mm_loadu_si128( ( __m128i * ) (pbSrc +112 ) ) ) ); - pbDst += 8 * SYMCRYPT_AES_BLOCK_SIZE; - pbSrc += 8 * SYMCRYPT_AES_BLOCK_SIZE; - cbData -= 8 * SYMCRYPT_AES_BLOCK_SIZE; - } - - // - // At this point we have one of the two following cases: - // - cbData >= 5 * 16 and we have 8 blocks of key stream in c0-c7. chain is set to c7 + 1 - // - cbData < 5 * 16 and we have no blocks of key stream, with chain the next value to use - // - - if( cbData >= SYMCRYPT_AES_BLOCK_SIZE ) // quick exit of function if the request was a multiple of 8 blocks - { - if( cbData >= 5 * SYMCRYPT_AES_BLOCK_SIZE ) - { - // - // We already have the key stream - // - _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 16), _mm_xor_si128( c1, _mm_loadu_si128( ( __m128i * ) (pbSrc + 16 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 32), _mm_xor_si128( c2, _mm_loadu_si128( ( __m128i * ) (pbSrc + 32 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 48), _mm_xor_si128( c3, _mm_loadu_si128( ( __m128i * ) (pbSrc + 48 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 64), _mm_xor_si128( c4, _mm_loadu_si128( ( __m128i * ) (pbSrc + 64 ) ) ) ); - chain = _mm_sub_epi64( chain, chainIncrement3 ); - - if( cbData >= 96 ) - { - chain = _mm_add_epi64( chain, chainIncrement1 ); - _mm_storeu_si128( (__m128i *) (pbDst + 80), _mm_xor_si128( c5, _mm_loadu_si128( ( __m128i * ) (pbSrc + 80 ) ) ) ); - if( cbData >= 112 ) - { - chain = _mm_add_epi64( chain, chainIncrement1 ); - _mm_storeu_si128( (__m128i *) (pbDst + 96), _mm_xor_si128( c6, _mm_loadu_si128( ( __m128i * ) (pbSrc + 96 ) ) ) ); - } - } - } - else if( cbData >= 2 * SYMCRYPT_AES_BLOCK_SIZE ) - { - // Produce 4 blocks of key stream - - c0 = chain; - c1 = _mm_add_epi64( chain, chainIncrement1 ); - c2 = _mm_add_epi64( chain, chainIncrement2 ); - c3 = _mm_add_epi64( c1, chainIncrement2 ); - chain = c2; // chain is only incremented by 2 for now - - c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); - c1 = _mm_shuffle_epi8( c1, BYTE_REVERSE_ORDER ); - c2 = _mm_shuffle_epi8( c2, BYTE_REVERSE_ORDER ); - c3 = _mm_shuffle_epi8( c3, BYTE_REVERSE_ORDER ); - - AES_ENCRYPT_4( pExpandedKey, c0, c1, c2, c3 ); - - _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0 ) ) ) ); - _mm_storeu_si128( (__m128i *) (pbDst + 16), _mm_xor_si128( c1, _mm_loadu_si128( ( __m128i * ) (pbSrc + 16 ) ) ) ); - if( cbData >= 48 ) - { - chain = _mm_add_epi64( chain, chainIncrement1 ); - _mm_storeu_si128( (__m128i *) (pbDst + 32), _mm_xor_si128( c2, _mm_loadu_si128( ( __m128i * ) (pbSrc + 32 ) ) ) ); - if( cbData >= 64 ) - { - chain = _mm_add_epi64( chain, chainIncrement1 ); - _mm_storeu_si128( (__m128i *) (pbDst + 48), _mm_xor_si128( c3, _mm_loadu_si128( ( __m128i * ) (pbSrc + 48 ) ) ) ); - } - } - } - else - { - // Exactly 1 block to process - c0 = chain; - chain = _mm_add_epi64( chain, chainIncrement1 ); - - c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); - - AES_ENCRYPT_1( pExpandedKey, c0 ); - _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0 ) ) ) ); - } - } - - chain = _mm_shuffle_epi8( chain, BYTE_REVERSE_ORDER ); - _mm_storeu_si128( (__m128i *) pbChainingValue, chain ); -} #pragma runtime_checks( "u", restore ) #pragma warning(pop) @@ -1558,13 +1418,13 @@ SymCryptAesGcmEncryptStitchedXmm( // Do 8 blocks of CTR either for tail (if total blocks <8) or for encryption of first 8 blocks c0 = chain; - c1 = _mm_add_epi64( chain, chainIncrement1 ); - c2 = _mm_add_epi64( chain, chainIncrement2 ); - c3 = _mm_add_epi64( c1, chainIncrement2 ); - c4 = _mm_add_epi64( c2, chainIncrement2 ); - c5 = _mm_add_epi64( c3, chainIncrement2 ); - c6 = _mm_add_epi64( c4, chainIncrement2 ); - c7 = _mm_add_epi64( c5, chainIncrement2 ); + c1 = _mm_add_epi32( chain, chainIncrement1 ); + c2 = _mm_add_epi32( chain, chainIncrement2 ); + c3 = _mm_add_epi32( c1, chainIncrement2 ); + c4 = _mm_add_epi32( c2, chainIncrement2 ); + c5 = _mm_add_epi32( c3, chainIncrement2 ); + c6 = _mm_add_epi32( c4, chainIncrement2 ); + c7 = _mm_add_epi32( c5, chainIncrement2 ); c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); c1 = _mm_shuffle_epi8( c1, BYTE_REVERSE_ORDER ); @@ -1580,7 +1440,7 @@ SymCryptAesGcmEncryptStitchedXmm( if( nBlocks >= 8 ) { // Encrypt first 8 blocks - update chain - chain = _mm_add_epi64( chain, chainIncrement8 ); + chain = _mm_add_epi32( chain, chainIncrement8 ); _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0) ) ) ); _mm_storeu_si128( (__m128i *) (pbDst + 16), _mm_xor_si128( c1, _mm_loadu_si128( ( __m128i * ) (pbSrc + 16) ) ) ); @@ -1598,14 +1458,14 @@ SymCryptAesGcmEncryptStitchedXmm( { // In this loop we always have 8 blocks to encrypt and we have already encrypted the previous 8 blocks ready for GHASH c0 = chain; - c1 = _mm_add_epi64( chain, chainIncrement1 ); - c2 = _mm_add_epi64( chain, chainIncrement2 ); - c3 = _mm_add_epi64( c1, chainIncrement2 ); - c4 = _mm_add_epi64( c2, chainIncrement2 ); - c5 = _mm_add_epi64( c3, chainIncrement2 ); - c6 = _mm_add_epi64( c4, chainIncrement2 ); - c7 = _mm_add_epi64( c5, chainIncrement2 ); - chain = _mm_add_epi64( c6, chainIncrement2 ); + c1 = _mm_add_epi32( chain, chainIncrement1 ); + c2 = _mm_add_epi32( chain, chainIncrement2 ); + c3 = _mm_add_epi32( c1, chainIncrement2 ); + c4 = _mm_add_epi32( c2, chainIncrement2 ); + c5 = _mm_add_epi32( c3, chainIncrement2 ); + c6 = _mm_add_epi32( c4, chainIncrement2 ); + c7 = _mm_add_epi32( c5, chainIncrement2 ); + chain = _mm_add_epi32( c6, chainIncrement2 ); c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); c1 = _mm_shuffle_epi8( c1, BYTE_REVERSE_ORDER ); @@ -1647,10 +1507,10 @@ SymCryptAesGcmEncryptStitchedXmm( if (nBlocks > 0) { c0 = chain; - c1 = _mm_add_epi64( chain, chainIncrement1 ); - c2 = _mm_add_epi64( chain, chainIncrement2 ); - c3 = _mm_add_epi64( c1, chainIncrement2 ); - c4 = _mm_add_epi64( c2, chainIncrement2 ); + c1 = _mm_add_epi32( chain, chainIncrement1 ); + c2 = _mm_add_epi32( chain, chainIncrement2 ); + c3 = _mm_add_epi32( c1, chainIncrement2 ); + c4 = _mm_add_epi32( c2, chainIncrement2 ); c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); c1 = _mm_shuffle_epi8( c1, BYTE_REVERSE_ORDER ); @@ -1660,8 +1520,8 @@ SymCryptAesGcmEncryptStitchedXmm( if (nBlocks > 4) { // Do 8 rounds of AES-CTR for tail in parallel with 8 rounds of GHASH - c5 = _mm_add_epi64( c4, chainIncrement1 ); - c6 = _mm_add_epi64( c4, chainIncrement2 ); + c5 = _mm_add_epi32( c4, chainIncrement1 ); + c6 = _mm_add_epi32( c4, chainIncrement2 ); c4 = _mm_shuffle_epi8( c4, BYTE_REVERSE_ORDER ); c5 = _mm_shuffle_epi8( c5, BYTE_REVERSE_ORDER ); @@ -1705,7 +1565,7 @@ SymCryptAesGcmEncryptStitchedXmm( // Encrypt 1-7 blocks with pre-generated AES-CTR blocks and GHASH the results while( nBlocks >= 2 ) { - chain = _mm_add_epi64( chain, chainIncrement2 ); + chain = _mm_add_epi32( chain, chainIncrement2 ); r0 = _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0) ) ); r1 = _mm_xor_si128( c1, _mm_loadu_si128( ( __m128i * ) (pbSrc + 16) ) ); @@ -1732,7 +1592,7 @@ SymCryptAesGcmEncryptStitchedXmm( if( nBlocks > 0 ) { - chain = _mm_add_epi64( chain, chainIncrement1 ); + chain = _mm_add_epi32( chain, chainIncrement1 ); r0 = _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0) ) ); @@ -1805,14 +1665,14 @@ SymCryptAesGcmDecryptStitchedXmm( { // In this loop we always have 8 blocks to decrypt and GHASH c0 = chain; - c1 = _mm_add_epi64( chain, chainIncrement1 ); - c2 = _mm_add_epi64( chain, chainIncrement2 ); - c3 = _mm_add_epi64( c1, chainIncrement2 ); - c4 = _mm_add_epi64( c2, chainIncrement2 ); - c5 = _mm_add_epi64( c3, chainIncrement2 ); - c6 = _mm_add_epi64( c4, chainIncrement2 ); - c7 = _mm_add_epi64( c5, chainIncrement2 ); - chain = _mm_add_epi64( c6, chainIncrement2 ); + c1 = _mm_add_epi32( chain, chainIncrement1 ); + c2 = _mm_add_epi32( chain, chainIncrement2 ); + c3 = _mm_add_epi32( c1, chainIncrement2 ); + c4 = _mm_add_epi32( c2, chainIncrement2 ); + c5 = _mm_add_epi32( c3, chainIncrement2 ); + c6 = _mm_add_epi32( c4, chainIncrement2 ); + c7 = _mm_add_epi32( c5, chainIncrement2 ); + chain = _mm_add_epi32( c6, chainIncrement2 ); c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); c1 = _mm_shuffle_epi8( c1, BYTE_REVERSE_ORDER ); @@ -1856,10 +1716,10 @@ SymCryptAesGcmDecryptStitchedXmm( // We have 1-7 blocks to GHASH and decrypt // Do the exact number of GHASH blocks we need in parallel with generating either 4 or 8 blocks of AES-CTR c0 = chain; - c1 = _mm_add_epi64( chain, chainIncrement1 ); - c2 = _mm_add_epi64( chain, chainIncrement2 ); - c3 = _mm_add_epi64( c1, chainIncrement2 ); - c4 = _mm_add_epi64( c2, chainIncrement2 ); + c1 = _mm_add_epi32( chain, chainIncrement1 ); + c2 = _mm_add_epi32( chain, chainIncrement2 ); + c3 = _mm_add_epi32( c1, chainIncrement2 ); + c4 = _mm_add_epi32( c2, chainIncrement2 ); c0 = _mm_shuffle_epi8( c0, BYTE_REVERSE_ORDER ); c1 = _mm_shuffle_epi8( c1, BYTE_REVERSE_ORDER ); @@ -1868,8 +1728,8 @@ SymCryptAesGcmDecryptStitchedXmm( if( nBlocks > 4 ) { - c5 = _mm_add_epi64( c4, chainIncrement1 ); - c6 = _mm_add_epi64( c4, chainIncrement2 ); + c5 = _mm_add_epi32( c4, chainIncrement1 ); + c6 = _mm_add_epi32( c4, chainIncrement2 ); c4 = _mm_shuffle_epi8( c4, BYTE_REVERSE_ORDER ); c5 = _mm_shuffle_epi8( c5, BYTE_REVERSE_ORDER ); @@ -1886,7 +1746,7 @@ SymCryptAesGcmDecryptStitchedXmm( // Decrypt 1-7 blocks with pre-generated AES-CTR blocks while( nBlocks >= 2 ) { - chain = _mm_add_epi64( chain, chainIncrement2 ); + chain = _mm_add_epi32( chain, chainIncrement2 ); _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0) ) ) ); _mm_storeu_si128( (__m128i *) (pbDst + 16), _mm_xor_si128( c1, _mm_loadu_si128( ( __m128i * ) (pbSrc + 16) ) ) ); @@ -1903,7 +1763,7 @@ SymCryptAesGcmDecryptStitchedXmm( if( nBlocks > 0 ) { - chain = _mm_add_epi64( chain, chainIncrement1 ); + chain = _mm_add_epi32( chain, chainIncrement1 ); _mm_storeu_si128( (__m128i *) (pbDst + 0), _mm_xor_si128( c0, _mm_loadu_si128( ( __m128i * ) (pbSrc + 0) ) ) ); } diff --git a/lib/aes-ymm.c b/lib/aes-ymm.c index 898bac7..fc0e979 100644 --- a/lib/aes-ymm.c +++ b/lib/aes-ymm.c @@ -497,14 +497,14 @@ SymCryptAesGcmEncryptStitchedYmm_2048( state = _mm_loadu_si128( (__m128i *) pState ); ctr0 = _mm256_insertf128_si256( _mm256_castsi128_si256( chain ), chain, 1); // AVX - ctr0 = _mm256_add_epi64( ctr0, chainIncrementUpper1 ); - ctr1 = _mm256_add_epi64( ctr0, chainIncrement2 ); - ctr2 = _mm256_add_epi64( ctr0, chainIncrement4 ); - ctr3 = _mm256_add_epi64( ctr1, chainIncrement4 ); - ctr4 = _mm256_add_epi64( ctr2, chainIncrement4 ); - ctr5 = _mm256_add_epi64( ctr3, chainIncrement4 ); - ctr6 = _mm256_add_epi64( ctr4, chainIncrement4 ); - ctr7 = _mm256_add_epi64( ctr5, chainIncrement4 ); + ctr0 = _mm256_add_epi32( ctr0, chainIncrementUpper1 ); + ctr1 = _mm256_add_epi32( ctr0, chainIncrement2 ); + ctr2 = _mm256_add_epi32( ctr0, chainIncrement4 ); + ctr3 = _mm256_add_epi32( ctr1, chainIncrement4 ); + ctr4 = _mm256_add_epi32( ctr2, chainIncrement4 ); + ctr5 = _mm256_add_epi32( ctr3, chainIncrement4 ); + ctr6 = _mm256_add_epi32( ctr4, chainIncrement4 ); + ctr7 = _mm256_add_epi32( ctr5, chainIncrement4 ); CLMUL_3( state, GHASH_H_POWER(expandedKeyTable, todo), GHASH_Hx_POWER(expandedKeyTable, todo), a0_xmm, a1_xmm, a2_xmm ); a0 = a1 = a2 = _mm256_setzero_si256(); @@ -518,14 +518,14 @@ SymCryptAesGcmEncryptStitchedYmm_2048( c6 = _mm256_shuffle_epi8( ctr6, BYTE_REVERSE_ORDER ); c7 = _mm256_shuffle_epi8( ctr7, BYTE_REVERSE_ORDER ); - ctr0 = _mm256_add_epi64( ctr0, chainIncrement16 ); - ctr1 = _mm256_add_epi64( ctr1, chainIncrement16 ); - ctr2 = _mm256_add_epi64( ctr2, chainIncrement16 ); - ctr3 = _mm256_add_epi64( ctr3, chainIncrement16 ); - ctr4 = _mm256_add_epi64( ctr4, chainIncrement16 ); - ctr5 = _mm256_add_epi64( ctr5, chainIncrement16 ); - ctr6 = _mm256_add_epi64( ctr6, chainIncrement16 ); - ctr7 = _mm256_add_epi64( ctr7, chainIncrement16 ); + ctr0 = _mm256_add_epi32( ctr0, chainIncrement16 ); + ctr1 = _mm256_add_epi32( ctr1, chainIncrement16 ); + ctr2 = _mm256_add_epi32( ctr2, chainIncrement16 ); + ctr3 = _mm256_add_epi32( ctr3, chainIncrement16 ); + ctr4 = _mm256_add_epi32( ctr4, chainIncrement16 ); + ctr5 = _mm256_add_epi32( ctr5, chainIncrement16 ); + ctr6 = _mm256_add_epi32( ctr6, chainIncrement16 ); + ctr7 = _mm256_add_epi32( ctr7, chainIncrement16 ); AES_ENCRYPT_YMM_2048( pExpandedKey, c0, c1, c2, c3, c4, c5, c6, c7 ); @@ -552,14 +552,14 @@ SymCryptAesGcmEncryptStitchedYmm_2048( c6 = _mm256_shuffle_epi8( ctr6, BYTE_REVERSE_ORDER ); c7 = _mm256_shuffle_epi8( ctr7, BYTE_REVERSE_ORDER ); - ctr0 = _mm256_add_epi64( ctr0, chainIncrement16 ); - ctr1 = _mm256_add_epi64( ctr1, chainIncrement16 ); - ctr2 = _mm256_add_epi64( ctr2, chainIncrement16 ); - ctr3 = _mm256_add_epi64( ctr3, chainIncrement16 ); - ctr4 = _mm256_add_epi64( ctr4, chainIncrement16 ); - ctr5 = _mm256_add_epi64( ctr5, chainIncrement16 ); - ctr6 = _mm256_add_epi64( ctr6, chainIncrement16 ); - ctr7 = _mm256_add_epi64( ctr7, chainIncrement16 ); + ctr0 = _mm256_add_epi32( ctr0, chainIncrement16 ); + ctr1 = _mm256_add_epi32( ctr1, chainIncrement16 ); + ctr2 = _mm256_add_epi32( ctr2, chainIncrement16 ); + ctr3 = _mm256_add_epi32( ctr3, chainIncrement16 ); + ctr4 = _mm256_add_epi32( ctr4, chainIncrement16 ); + ctr5 = _mm256_add_epi32( ctr5, chainIncrement16 ); + ctr6 = _mm256_add_epi32( ctr6, chainIncrement16 ); + ctr7 = _mm256_add_epi32( ctr7, chainIncrement16 ); AES_GCM_ENCRYPT_16_Ymm( pExpandedKey, c0, c1, c2, c3, c4, c5, c6, c7, pbGhashSrc, BYTE_REVERSE_ORDER, expandedKeyTable, todo, a0, a1, a2 ); @@ -694,14 +694,14 @@ SymCryptAesGcmDecryptStitchedYmm_2048( state = _mm_loadu_si128( (__m128i *) pState ); ctr0 = _mm256_insertf128_si256( _mm256_castsi128_si256( chain ), chain, 1); // AVX - ctr0 = _mm256_add_epi64( ctr0, chainIncrementUpper1 ); - ctr1 = _mm256_add_epi64( ctr0, chainIncrement2 ); - ctr2 = _mm256_add_epi64( ctr0, chainIncrement4 ); - ctr3 = _mm256_add_epi64( ctr1, chainIncrement4 ); - ctr4 = _mm256_add_epi64( ctr2, chainIncrement4 ); - ctr5 = _mm256_add_epi64( ctr3, chainIncrement4 ); - ctr6 = _mm256_add_epi64( ctr4, chainIncrement4 ); - ctr7 = _mm256_add_epi64( ctr5, chainIncrement4 ); + ctr0 = _mm256_add_epi32( ctr0, chainIncrementUpper1 ); + ctr1 = _mm256_add_epi32( ctr0, chainIncrement2 ); + ctr2 = _mm256_add_epi32( ctr0, chainIncrement4 ); + ctr3 = _mm256_add_epi32( ctr1, chainIncrement4 ); + ctr4 = _mm256_add_epi32( ctr2, chainIncrement4 ); + ctr5 = _mm256_add_epi32( ctr3, chainIncrement4 ); + ctr6 = _mm256_add_epi32( ctr4, chainIncrement4 ); + ctr7 = _mm256_add_epi32( ctr5, chainIncrement4 ); CLMUL_3( state, GHASH_H_POWER(expandedKeyTable, todo), GHASH_Hx_POWER(expandedKeyTable, todo), a0_xmm, a1_xmm, a2_xmm ); a0 = a1 = a2 = _mm256_setzero_si256(); @@ -717,14 +717,14 @@ SymCryptAesGcmDecryptStitchedYmm_2048( c6 = _mm256_shuffle_epi8( ctr6, BYTE_REVERSE_ORDER ); c7 = _mm256_shuffle_epi8( ctr7, BYTE_REVERSE_ORDER ); - ctr0 = _mm256_add_epi64( ctr0, chainIncrement16 ); - ctr1 = _mm256_add_epi64( ctr1, chainIncrement16 ); - ctr2 = _mm256_add_epi64( ctr2, chainIncrement16 ); - ctr3 = _mm256_add_epi64( ctr3, chainIncrement16 ); - ctr4 = _mm256_add_epi64( ctr4, chainIncrement16 ); - ctr5 = _mm256_add_epi64( ctr5, chainIncrement16 ); - ctr6 = _mm256_add_epi64( ctr6, chainIncrement16 ); - ctr7 = _mm256_add_epi64( ctr7, chainIncrement16 ); + ctr0 = _mm256_add_epi32( ctr0, chainIncrement16 ); + ctr1 = _mm256_add_epi32( ctr1, chainIncrement16 ); + ctr2 = _mm256_add_epi32( ctr2, chainIncrement16 ); + ctr3 = _mm256_add_epi32( ctr3, chainIncrement16 ); + ctr4 = _mm256_add_epi32( ctr4, chainIncrement16 ); + ctr5 = _mm256_add_epi32( ctr5, chainIncrement16 ); + ctr6 = _mm256_add_epi32( ctr6, chainIncrement16 ); + ctr7 = _mm256_add_epi32( ctr7, chainIncrement16 ); AES_GCM_ENCRYPT_16_Ymm( pExpandedKey, c0, c1, c2, c3, c4, c5, c6, c7, pbGhashSrc, BYTE_REVERSE_ORDER, expandedKeyTable, todo, a0, a1, a2 ); diff --git a/lib/blockciphermodes.c b/lib/blockciphermodes.c index 50101b1..cd9fb63 100644 --- a/lib/blockciphermodes.c +++ b/lib/blockciphermodes.c @@ -244,6 +244,57 @@ SymCryptCbcMac( SymCryptWipeKnownSize( buf, sizeof( buf )); } +VOID +SYMCRYPT_CALL +SymCryptCtrMsb32( + _In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, + _In_ PCVOID pExpandedKey, + _Inout_updates_( pBlockCipher->blockSize ) + PBYTE pbChainingValue, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData ) +{ + SYMCRYPT_ALIGN BYTE buf[2 * SYMCRYPT_MAX_BLOCK_SIZE]; + PBYTE count = &buf[0]; + PBYTE keystream= &buf[SYMCRYPT_MAX_BLOCK_SIZE]; + SIZE_T blockSize; + PCBYTE pbSrcEnd; + + blockSize = pBlockCipher->blockSize; + SYMCRYPT_ASSERT( blockSize <= SYMCRYPT_MAX_BLOCK_SIZE ); + + // + // Compute the end of the data, rounding the size down to a multiple of the block size. + // + pbSrcEnd = &pbSrc[ cbData & ~(blockSize - 1) ]; + + // + // We keep the chaining state in a local buffer to enforce the read-once write-once rule. + // It also improves memory locality. + // + #pragma warning(suppress: 22105) + memcpy( count, pbChainingValue, blockSize ); + while( pbSrc < pbSrcEnd ) + { + SYMCRYPT_ASSERT( pbSrc <= pbSrcEnd - blockSize ); // help PreFast + (*pBlockCipher->encryptFunc)( pExpandedKey, count, keystream ); + SymCryptXorBytes( keystream, pbSrc, pbDst, blockSize ); + + // + // We only need to increment the last 32 bits of the counter value. + // + SYMCRYPT_STORE_MSBFIRST32( &count[ blockSize-4 ], 1 + SYMCRYPT_LOAD_MSBFIRST32( &count[ blockSize-4 ] ) ); + + pbSrc += blockSize; + pbDst += blockSize; + } + + memcpy( pbChainingValue, count, blockSize ); + + SymCryptWipeKnownSize( buf, sizeof( buf )); +} + VOID SYMCRYPT_CALL SymCryptCtrMsb64( diff --git a/lib/gcm.c b/lib/gcm.c index 275c44c..862a016 100644 --- a/lib/gcm.c +++ b/lib/gcm.c @@ -6,7 +6,7 @@ #include "precomp.h" -#define GCM_REQUIRED_NONCE_SIZE (12) +#define GCM_MIN_NONCE_SIZE (1) #define GCM_MIN_TAG_SIZE (12) #define GCM_MAX_TAG_SIZE (16) @@ -26,9 +26,10 @@ SymCryptGcmValidateParameters( } // - // We only support 12-byte nonces, are per SP800-38D recommendations. + // SP800-38D specifies that the nonce must be at least one bit, but we operate on bytes, + // so the minimum is one byte. // - if( cbNonce != GCM_REQUIRED_NONCE_SIZE ) + if( cbNonce < GCM_MIN_NONCE_SIZE ) { return SYMCRYPT_WRONG_NONCE_SIZE; } @@ -161,21 +162,8 @@ SymCryptGcmEncryptDecryptPart( { bytesToProcess = cbData & SYMCRYPT_GCM_BLOCK_ROUND_MASK; - // - // We use the CTR mode function that increments 64 bits, rather than the 32 bits that GCM requires. - // As we only support 12-byte nonces, the 32-bit counter never overflows, and we can safely use - // the 64-bit incrementing primitive. - // If we ever support other nonce sizes this is going to be a big problem. - // You can't fake a 32-bit counter using a 64-bit counter function without side-channels that expose - // information about the current counter value. - // With other nonce sizes the actual counter value itself is not public, so we can't expose that. - // We can do two things: - // - create SymCryptCtrMsb32 - // - Accept that we leak information about the counter value; after all it is not treated as a - // secret when the nonce is 12 bytes. - // SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE ); - SymCryptCtrMsb64( pState->pKey->pBlockCipher, + SymCryptCtrMsb32( pState->pKey->pBlockCipher, &pState->pKey->blockcipherKey, &pState->counterBlock[0], pbSrc, @@ -192,7 +180,7 @@ SymCryptGcmEncryptDecryptPart( SymCryptWipeKnownSize( &pState->keystreamBlock[0], SYMCRYPT_GCM_BLOCK_SIZE ); SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE ); - SymCryptCtrMsb64( pState->pKey->pBlockCipher, + SymCryptCtrMsb32( pState->pKey->pBlockCipher, &pState->pKey->blockcipherKey, &pState->counterBlock[0], &pState->keystreamBlock[0], @@ -209,7 +197,25 @@ SymCryptGcmEncryptDecryptPart( } +FORCEINLINE +VOID +SYMCRYPT_CALL +SymCryptGcmResetCounterBlock( + _Inout_ PSYMCRYPT_GCM_STATE pState ) +{ + // Computing the tag for GCM requires invoking the GCTR function with the pre-counter + // block which was computed when the nonce was set. Historically, we only supported 12-byte + // nonces, so we could trivially reset the counter block by just setting the last 4 bytes to + // (DWORD) 1. With support for larger IVs, the pre-counter block is computed from a GHash of + // the nonce, and we don't store the value. Adding a field in the GCM struct to store the value + // would be ABI-breaking, so instead we can recompute the value by decrementing the last 32 bits + // of the counter block by the number of blocks that have been processed (since the counter is + // incremented once per block), plus one for the initial increment. + UINT32 preCounter32 = SYMCRYPT_LOAD_MSBFIRST32(&pState->counterBlock[12]) - + (UINT32) ((pState->cbData + SYMCRYPT_GCM_BLOCK_SIZE - 1) / SYMCRYPT_GCM_BLOCK_SIZE) - 1; + SYMCRYPT_STORE_MSBFIRST32(&pState->counterBlock[12], preCounter32); +} VOID SYMCRYPT_CALL @@ -218,7 +224,6 @@ SymCryptGcmComputeTag( _Out_writes_( SYMCRYPT_GCM_BLOCK_SIZE ) PBYTE pbTag ) { SYMCRYPT_ALIGN BYTE buf[2 * SYMCRYPT_GCM_BLOCK_SIZE]; - UINT64 cntLow; SYMCRYPT_STORE_MSBFIRST64( &buf[16], pState->cbAuthData * 8 ); SYMCRYPT_STORE_MSBFIRST64( &buf[24], pState->cbData * 8 ); @@ -238,19 +243,7 @@ SymCryptGcmComputeTag( SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[16], SYMCRYPT_GCM_BLOCK_SIZE ); } - // - // Set up the correct counter block value - // This is a bit tricky. Normally all we have to do is set the last - // 4 bytes to 00000001. But if the message is 2^36-32 bytes then - // our use of a 64-bit incrementing CTR function has incremented bytes - // 8-11 of the nonce. (The 4-byte counter has overflowed, and - // the carry went into the next byte(s).) - // We resolve this by decrementing the 8-byte value first, - // and then setting the proper bits. - // - cntLow = SYMCRYPT_LOAD_MSBFIRST64( &pState->counterBlock[8] ); - cntLow = ((cntLow - 1) & 0xffffffff00000000) | 1; - SYMCRYPT_STORE_MSBFIRST64( &pState->counterBlock[8], cntLow ); + SymCryptGcmResetCounterBlock(pState); // // Convert the GHash state to an array of bytes @@ -259,7 +252,7 @@ SymCryptGcmComputeTag( SYMCRYPT_STORE_MSBFIRST64( &buf[8], pState->ghashState.ull[0] ); SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE ); - SymCryptCtrMsb64( pState->pKey->pBlockCipher, + SymCryptCtrMsb32( pState->pKey->pBlockCipher, &pState->pKey->blockcipherKey, &pState->counterBlock[0], buf, @@ -269,7 +262,6 @@ SymCryptGcmComputeTag( SymCryptWipeKnownSize( buf, sizeof( buf ) ); } - SYMCRYPT_NOINLINE SYMCRYPT_ERROR SYMCRYPT_CALL @@ -337,7 +329,58 @@ SymCryptGcmKeyCopy( _In_ PCSYMCRYPT_GCM_EXPANDED_KEY pSrc, _Out_ PSYMCRYPT_GCM_E SYMCRYPT_ASSERT( status == SYMCRYPT_NO_ERROR ); } +VOID +SYMCRYPT_CALL +SymCryptGcmSetNonce( + _Out_ PSYMCRYPT_GCM_STATE pState, + _In_reads_( cbNonce ) PCBYTE pbNonce, + SIZE_T cbNonce ) +{ + SYMCRYPT_ASSERT( cbNonce >= GCM_MIN_NONCE_SIZE ); + // Handle the nonce depending on its size, as specified in NIST SP800-38D + if( cbNonce == 12 ) + { + // If len(nonce) = 96 bits (12 bytes), pre-counter block = nonce || (DWORD) 1 + memcpy( &pState->counterBlock[0], pbNonce, cbNonce ); + SymCryptWipeKnownSize( &pState->counterBlock[12], 4 ); + pState->counterBlock[15] = 1; + } + else + { + // If len(nonce) != 96 bits (12 bytes), + // pre-counter block = GHASH(nonce padded to a multiple of 128 bits || (QWORD) len(nonce)) + BYTE buf[SYMCRYPT_GF128_BLOCK_SIZE]; + SIZE_T cbNonceRemainder = cbNonce & 0xf; + + SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, pbNonce, + cbNonce - cbNonceRemainder ); + + // If the nonce length is not a multiple of 128 bits, it needs to be padded with zeros + // until it is, as GHASH is only defined on multiples of 128 bits. + if(cbNonceRemainder > 0) + { + SymCryptWipeKnownSize( buf, sizeof(buf) ); + memcpy(buf, pbNonce + cbNonce - cbNonceRemainder, cbNonceRemainder); + SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, buf, sizeof(buf) ); + } + + // Now we append the length of the nonce in bits. We take the length as a 64-bit integer, + // but it too must be padded to 128 bits for use in GHASH. + SymCryptWipeKnownSize( buf, 8 ); + SYMCRYPT_STORE_MSBFIRST64( &buf[8], cbNonce * 8 ); + SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, buf, sizeof(buf) ); + + SymCryptGHashResult( &pState->ghashState, pState->counterBlock ); + SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) ); + } + + // Increment the last 32 bits of the counter. We'll recalculate the pre-counter block later + // when computing the tag. + SYMCRYPT_STORE_MSBFIRST32( + &pState->counterBlock[12], + 1 + SYMCRYPT_LOAD_MSBFIRST32( &pState->counterBlock[12] ) ); +} SYMCRYPT_NOINLINE VOID @@ -350,8 +393,6 @@ SymCryptGcmInit( { UNREFERENCED_PARAMETER( cbNonce ); // It is used in an ASSERT, but only in CHKed builds. - SYMCRYPT_ASSERT( cbNonce == GCM_REQUIRED_NONCE_SIZE ); - SYMCRYPT_CHECK_MAGIC( pExpandedKey ); pState->pKey = pExpandedKey; @@ -360,12 +401,7 @@ SymCryptGcmInit( pState->bytesInMacBlock = 0; SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) ); - // - // Set up the counter block value - // - memcpy( &pState->counterBlock[0], pbNonce, GCM_REQUIRED_NONCE_SIZE ); - SymCryptWipeKnownSize( &pState->counterBlock[12], 4 ); - pState->counterBlock[15] = 2; + SymCryptGcmSetNonce(pState, pbNonce, cbNonce); SYMCRYPT_SET_MAGIC( pState ); } @@ -591,12 +627,11 @@ SymCryptGcmEncrypt( SYMCRYPT_ALIGN BYTE buf[2 * SYMCRYPT_GCM_BLOCK_SIZE]; SYMCRYPT_GCM_STATE state; PSYMCRYPT_GCM_STATE pState = &state; - UINT64 cntLow; // SymCryptGcmInit( &state, pExpandedKey, pbNonce, cbNonce ); UNREFERENCED_PARAMETER( cbNonce ); // It is used in an ASSERT, but only in CHKed builds. - SYMCRYPT_ASSERT( cbNonce == GCM_REQUIRED_NONCE_SIZE ); + SYMCRYPT_ASSERT( cbNonce >= GCM_MIN_NONCE_SIZE ); SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE ); SYMCRYPT_CHECK_MAGIC( pExpandedKey ); @@ -607,14 +642,7 @@ SymCryptGcmEncrypt( pState->bytesInMacBlock = 0; SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) ); - memcpy( &pState->counterBlock[0], pbNonce, GCM_REQUIRED_NONCE_SIZE ); - SymCryptWipeKnownSize( &pState->counterBlock[12], 4 ); - pState->counterBlock[15] = 1; - // Keep cntLow (for encrypting the tag) for later - cntLow = *((PUINT64) &pState->counterBlock[8]); - - pState->counterBlock[15] = 2; - + SymCryptGcmSetNonce( pState, pbNonce, cbNonce ); // SymCryptGcmAuthPart( &state, pbAuthData, cbAuthData ); pState->cbAuthData += cbAuthData; @@ -670,7 +698,8 @@ SymCryptGcmEncrypt( SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[16], SYMCRYPT_GCM_BLOCK_SIZE ); } - *((PUINT64) &pState->counterBlock[8]) = cntLow; + // Reset the counter block prior to computing the tag + SymCryptGcmResetCounterBlock( pState ); // // Convert the GHash state to an array of bytes @@ -679,7 +708,7 @@ SymCryptGcmEncrypt( SYMCRYPT_STORE_MSBFIRST64( &buf[8], pState->ghashState.ull[0] ); SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE ); - SymCryptCtrMsb64( pState->pKey->pBlockCipher, + SymCryptCtrMsb32( pState->pKey->pBlockCipher, &pState->pKey->blockcipherKey, &pState->counterBlock[0], buf, @@ -712,12 +741,11 @@ SymCryptGcmDecrypt( SYMCRYPT_ALIGN BYTE buf[2 * SYMCRYPT_GCM_BLOCK_SIZE]; SYMCRYPT_GCM_STATE state; PSYMCRYPT_GCM_STATE pState = &state; - UINT64 cntLow; // SymCryptGcmInit( &state, pExpandedKey, pbNonce, cbNonce ); UNREFERENCED_PARAMETER( cbNonce ); // It is used in an ASSERT, but only in CHKed builds. - SYMCRYPT_ASSERT( cbNonce == GCM_REQUIRED_NONCE_SIZE ); + SYMCRYPT_ASSERT( cbNonce >= GCM_MIN_NONCE_SIZE ); SYMCRYPT_ASSERT( cbTag >= GCM_MIN_TAG_SIZE && cbTag <= GCM_MAX_TAG_SIZE ); SYMCRYPT_CHECK_MAGIC( pExpandedKey ); @@ -728,13 +756,7 @@ SymCryptGcmDecrypt( pState->bytesInMacBlock = 0; SymCryptWipeKnownSize( &pState->ghashState, sizeof( pState->ghashState ) ); - memcpy( &pState->counterBlock[0], pbNonce, GCM_REQUIRED_NONCE_SIZE ); - SymCryptWipeKnownSize( &pState->counterBlock[12], 4 ); - pState->counterBlock[15] = 1; - // Keep cntLow (for encrypting the tag) for later - cntLow = *((PUINT64) &pState->counterBlock[8]); - - pState->counterBlock[15] = 2; + SymCryptGcmSetNonce( pState, pbNonce, cbNonce ); // SymCryptGcmAuthPart( &state, pbAuthData, cbAuthData ); pState->cbAuthData += cbAuthData; @@ -790,7 +812,7 @@ SymCryptGcmDecrypt( SymCryptGHashAppendData( &pState->pKey->ghashKey, &pState->ghashState, &buf[16], SYMCRYPT_GCM_BLOCK_SIZE ); } - *((PUINT64) &pState->counterBlock[8]) = cntLow; + SymCryptGcmResetCounterBlock( pState ); // // Convert the GHash state to an array of bytes @@ -799,7 +821,7 @@ SymCryptGcmDecrypt( SYMCRYPT_STORE_MSBFIRST64( &buf[8], pState->ghashState.ull[0] ); SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE ); - SymCryptCtrMsb64( pState->pKey->pBlockCipher, + SymCryptCtrMsb32( pState->pKey->pBlockCipher, &pState->pKey->blockcipherKey, &pState->counterBlock[0], buf, diff --git a/lib/ghash.c b/lib/ghash.c index 2e03894..463e443 100644 --- a/lib/ghash.c +++ b/lib/ghash.c @@ -59,11 +59,14 @@ SymCryptGHashExpandKeyC( VOID SYMCRYPT_CALL SymCryptGHashAppendDataC( - _In_reads_( SYMCRYPT_GF128_FIELD_SIZE ) PCSYMCRYPT_GF128_ELEMENT expandedKeyTable, - _Inout_ PSYMCRYPT_GF128_ELEMENT pState, - _In_reads_( cbData ) PCBYTE pbData, - _In_ SIZE_T cbData ) + _In_reads_( SYMCRYPT_GF128_FIELD_SIZE ) PCSYMCRYPT_GF128_ELEMENT expandedKeyTable, + _Inout_ PSYMCRYPT_GF128_ELEMENT pState, + _In_reads_( cbData ) PCBYTE pbData, + _In_range_( SYMCRYPT_GF128_BLOCK_SIZE, SIZE_T_MAX & ~0xf) SIZE_T cbData ) { + SYMCRYPT_ASSERT(cbData >= SYMCRYPT_GF128_BLOCK_SIZE); + SYMCRYPT_ASSERT((cbData & 0xf) == 0); + UINT64 R0, R1; UINT64 mask; SYMCRYPT_ALIGN UINT32 state32[4]; diff --git a/lib/sc_lib.h b/lib/sc_lib.h index 1b1210f..7add65c 100644 --- a/lib/sc_lib.h +++ b/lib/sc_lib.h @@ -1407,6 +1407,24 @@ SymCryptAesCtrMsb64Neon( _Out_writes_( cbData ) PBYTE pbDst, SIZE_T cbData ); +VOID +SYMCRYPT_CALL +SymCryptAesCtrMsb32Xmm( + _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, + _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbChainingValue, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData ); + +VOID +SYMCRYPT_CALL +SymCryptAesCtrMsb32Neon( + _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, + _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbChainingValue, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData ); + VOID SYMCRYPT_CALL SymCryptXtsAesEncryptDataUnitC( @@ -1645,6 +1663,40 @@ SymCryptGcmDecryptPartTwoPass( _Out_writes_( cbData ) PBYTE pbDst, SIZE_T cbData ); +VOID +SYMCRYPT_CALL +SymCryptCtrMsb32( + _In_ PCSYMCRYPT_BLOCKCIPHER pBlockCipher, + _In_ PCVOID pExpandedKey, + _Inout_updates_( pBlockCipher->blockSize ) + PBYTE pbChainingValue, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData ); +// +// SymCryptCtrMsb32 implements the CTR cipher mode with a 32-bit increment function. +// It is not intended to be used as-is, rather it is a building block for modes like GCM. +// See the description of SymCryptCtrMsb64 in symcrypt.h for more details. +// +// For now, this function is only intended for use with GCM, which specifies the use a +// 32-bit increment function. It's only used in cases where we can't use one of the optimized +// implementations (i.e. on ARM32 or x86[-64] without AESNI). Therefore, unlike the 64-bit version, +// there are no optimized implementations of the CTR function to call. If we ever need this +// functionality for other block cipher modes, this function will need to be updated and we'll +// need to add an additional pointer to SYMCRYPT_BLOCKCIPHER for the optimized CTR function. + +VOID +SYMCRYPT_CALL +SymCryptAesCtrMsb32( + _In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey, + _Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbChainingValue, + _In_reads_( cbData ) PCBYTE pbSrc, + _Out_writes_( cbData ) PBYTE pbDst, + SIZE_T cbData ); + +// SymCryptAesCtrMsb32 is a dispatch function for the optimized AES CTR implementations that use +//a 32-bit counter function (currently only relevant to GCM). + SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptParallelHashProcess_serial( diff --git a/unittest/kat_authenc.dat b/unittest/kat_authenc.dat index 5271cd6..b408bb8 100644 --- a/unittest/kat_authenc.dat +++ b/unittest/kat_authenc.dat @@ -16,107 +16,475 @@ # # test case 1 -key = 00000000000000000000000000000000 -nonce= 000000000000000000000000 +Key = 00000000000000000000000000000000 +Nonce= 000000000000000000000000 AuthData = "" Plaintext = "" Ciphertext = "" Tag = 58e2fccefa7e3061367f1d57a4e7455a # test case 2 -key = 00000000000000000000000000000000 -nonce= 000000000000000000000000 +Key = 00000000000000000000000000000000 +Nonce= 000000000000000000000000 AuthData = "" Plaintext = 00000000000000000000000000000000 Ciphertext = 0388dace60b6a392f328c2b971b2fe78 Tag = ab6e47d42cec13bdf53a67b21257bddf # test case 3 -key = feffe9928665731c6d6a8f9467308308 -nonce= cafebabefacedbaddecaf888 +Key = feffe9928665731c6d6a8f9467308308 +Nonce= cafebabefacedbaddecaf888 AuthData = "" Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985 Tag = 4d5c2af327cd64a62cf35abd2ba6fab4 # test case 4 -key = feffe9928665731c6d6a8f9467308308 -nonce= cafebabefacedbaddecaf888 +Key = feffe9928665731c6d6a8f9467308308 +Nonce= cafebabefacedbaddecaf888 AuthData = feedfacedeadbeeffeedfacedeadbeefabaddad2 Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091 Tag = 5bc94fbc3221a5db94fae95ae7121a47 # test case 7 -key = 000000000000000000000000000000000000000000000000 -nonce= 000000000000000000000000 +Key = 000000000000000000000000000000000000000000000000 +Nonce= 000000000000000000000000 AuthData = "" Plaintext = "" Ciphertext = "" Tag = cd33b28ac773f74ba00ed1f312572435 # test case 8 -key = 000000000000000000000000000000000000000000000000 -nonce= 000000000000000000000000 +Key = 000000000000000000000000000000000000000000000000 +Nonce= 000000000000000000000000 AuthData = "" Plaintext = 00000000000000000000000000000000 Ciphertext = 98e7247c07f0fe411c267e4384b0f600 Tag = 2ff58d80033927ab8ef4d4587514f0fb # test case 9 -key = feffe9928665731c6d6a8f9467308308feffe9928665731c -nonce= cafebabefacedbaddecaf888 +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c +Nonce= cafebabefacedbaddecaf888 AuthData = "" Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 Ciphertext = 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256 Tag = 9924a7c8587336bfb118024db8674a14 # test case 10 -key = feffe9928665731c6d6a8f9467308308feffe9928665731c -nonce= cafebabefacedbaddecaf888 +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c +Nonce= cafebabefacedbaddecaf888 AuthData = feedfacedeadbeeffeedfacedeadbeefabaddad2 Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 Ciphertext = 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710 Tag = 2519498e80f1478f37ba55bd6d27618c - # test case 13 -key = 0000000000000000000000000000000000000000000000000000000000000000 -nonce= 000000000000000000000000 +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Nonce= 000000000000000000000000 AuthData = "" Plaintext = "" Ciphertext = "" Tag = 530f8afbc74536b9a963b4f1c4cb738b # test case 14 -key = 0000000000000000000000000000000000000000000000000000000000000000 -nonce= 000000000000000000000000 +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Nonce= 000000000000000000000000 AuthData = "" Plaintext = 00000000000000000000000000000000 Ciphertext = cea7403d4d606b6e074ec5d3baf39d18 Tag = d0d1c8a799996bf0265b98b5d48ab919 # test case 15 -key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 -nonce= cafebabefacedbaddecaf888 +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +Nonce= cafebabefacedbaddecaf888 AuthData = "" Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad Tag = b094dac5d93471bdec1a502270e3cc6c # test case 16 -key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 -nonce= cafebabefacedbaddecaf888 +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +Nonce= cafebabefacedbaddecaf888 AuthData = feedfacedeadbeeffeedfacedeadbeefabaddad2 Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662 Tag = 76fc6ece0f4e1768cddf8853bb2d551b +# +# Test cases from NIST: # https://csrc.nist.gov/Projects/cryptographic-algorithm-validation-program/cavp-testing-block-cipher-modes#GCMVS +# + +# test case 17 +Key = 88768354df414ce4097f4d357837116685beee0d93aab343576b893088256260 +Nonce = f649d375e4e896397a8a96cbb847fbf45cb54132c76baf814f4e35e9f7737f16d5cd710370f143612b46724bbdded2a26264b90a91f5ed425d08d317f49a56828fcfeb9ebe1bc53117bb4156c2e99d70b238dd9166cc05906719818022c75957d25ad9c36c93ce2626248c783e0207c35db74996f47d096c3cafe701a38154ce +AuthData = "" +Plaintext = "" +Ciphertext = "" +Tag = 905b22cd3fe77645e6a217dd1f993ec4 + +# test case 18 +Key = f43e7ecc3634beccb40763b6fd5344957597ea1aa831753a0c3a56fe6f4b7c5a +Nonce = 2d80ad96187ed28295fcaf6f780765a1df7aea9d1203844c03416c9d4867fb06ad5461ffbccf691141d5f37d408c54c4f973393c77c1edfa1004acaaeb6cdddd97b00b8e04e58f1324090e369d3149f20df143da68c521dc552ef4edba016133d040bdc331b703225de6927a3735a98750b5d4c7e968d16b55843f9f4f341c42 +AuthData = 2acd2a55be81b12763aa9803b5a835b6 +Plaintext = "" +Ciphertext = "" +Tag = b619670f80a37317eb99d7c2f41de176 + +# test case 19 +Key = d0c267c19f30d80b8914bbbfb72f73b8d3cd5f6a787015848a7b30e38f16f18b +Nonce = b6dcda95ac99777625ae87f8a3a9dd64d79bbd5f4a0e54ca1a9fa2e3f45f5fc2cea7b614126ff0affd3e17356ea01609dda13fd8ddf3df4fcb1849b8b3692c5d4fad309108bcbe24010fbe9cfb4f5d197f4c53b09590ac7b1f7ba099e1f34854d0fca9cc91f81f9b6c9ae0dc63ea7d2a4a7da5ed6857276b68e0f2b851508d3d +AuthData = "" +Plaintext = b8b6883644e234df243291074fe36f81 +Ciphertext = ff4fb3f3f9a251d482c2bef3e2d0eced +Tag = bd063809f7e1c4720ef2ea63db996c21 + +# test case 20 +Key = 62405e8a2442edd5d45ac903d83558a7df8b5dc19e4b5fa449ef35a86eac7584 +Nonce = fbe247a5ca5306eaf065a8c236329c6292c95893aecc309cd8130dfcd6ba6c4b87fdff92a206c511e93c0b1b111cd69ba1c86d510aa80b8e895a525e155a1b0b71d8961a42f7ef87cc08de7aa8f797195e6947c3cf3a120cf15cd587b3341a1d12b23ee71eeda30362fd72fe87a80253d059d0775033d0f3b6a4579824ff5207 +AuthData = 75ca67e0f038d9beab8ee21f2d0472c1b0d05c402b50b8fc1c1d2fedf21aec776ec671adc1d599c4c7a30a2552246c12 +Plaintext = 196ce0f275803a406b5c1bc601e75a8c +Ciphertext = 0e894fc7c27698a8ce690a6cb4e31dbf +Tag = 7c3f82d3cbe2c75dd15c50e5c6ff3858 + +# test case 21 +Key = aa319f8c3003f21631148a2c5098935f5a800e475e9275349ee911c029f766b2 +Nonce = 1e352b49ed652ef8ee5ee52f9ba21f5a782012d48e1d47c51bb1193c936893eedc3c015c29cb4d1fb1fb8c6241993cc9a8318288c349fcd39a7aafb651b7486b85f1331cb1d662e7e0395b3a78b05f346d1c5119949b81878ab1dc2e82683ff644f33d91087afd80d190407226603f6aab09d07e9ac994d073607567a2010675 +AuthData = 21c0610c3b80cce66ef76260bdddefda910558cc94b659262fc1648df01d6f9bfc2be0a36944d5d5ed66c2e2fe7cad261c65314a94484e0d22a72716318597641d775679965857fbe19eea6c5465e12e5a53458b0d0b775e642f +Plaintext = 7b2c94e55b3de0b5a83869a678c5ae51 +Ciphertext = 65e98a2a6fb052d6950337b30e2d8db4 +Tag = b075b860f6cabfd85994512a8a8506f2 + +# test case 22 +Key = 474b0d4d76b17b43084fc0df7890d8c8a8b17eb49b59eb73 +Nonce = 21f9fe1e94d3e570b05b395645f2d31d57505e364b17ea5ec0efc85a9f6a2b27d8f7ecb03886b89ebaa963e2724d2e0609b59382a1e5684102e505dd0a18e799cf97ff01b5a7ca5dfc21c022abb868e4c5b4729688e7b5319b631eae78371f1eb7949bdc3c63f271a66a7abf949fb32babfacf787dc28ff6b77a77e1584b0f28 +AuthData = "" +Plaintext = fdf3277bf48759ee5f3d567668a073c3 +Ciphertext = bb5c33e74c7d243c3d90b5f5e422b145 +Tag = 322632b89bcdccf6f4248f6209105e + +# test case 23 +Key = 725befd9ff5c57ea57571af21bed7b73ceeea6f94a02a59b +Nonce = b0ad393fe9dc1ef0c05fdeeb187cdfcd796c69b9a56951497a05fff9c3013455c543bf4a7f51b28f63503af87ea6d331033a29f623d0bbd0227cfacdb3cb1f8f8af2a08bc508c68410c5f3aff0aa45a060ad238cdf66ac0b0d8aa7f1835b44bf59e324b8620a11f923d3e50c3184db1cd0c9ccc9357a475f162990e0e1790244 +AuthData = 329b45fd5a7253e562a4db8b40c597c1 +Plaintext = 1421f49ee1eba002402e86fbfc19cbc4 +Ciphertext = 3206a10bcaf76562939c4f6f3a206fdf +Tag = 0f1f909cceb234df0f8618c3dc054dc3 + +# test case 24 +Key = d8a2c8bbac785f20003416804acaba3d51a293f41935641e +Nonce = a13fd29fb79b4a078e1dd4568c67afe29003565cb864aa7e78b48765b98a4ffda3de8163de39e21fbf832f250f23d0e688f9afbc6fb16d89cfed8da4707b9bd2620fd4c4d0f2bbd1b38aa9e1e3d8148650bc746299e34d5f602f455c97213c777f50abb2c6aa500da5b5916a166f8050bb56a4922bb41a27bfd212792dd02bb7 +AuthData = "" +Plaintext = 9413325bf2c0a3c23bbb70f547 +Ciphertext = 9589c64389826275ce2641e9e9 +Tag = b797881186afabc8ca1c778b8c98c83e + +# test case 25 +Key = 8f19c98b33dbdee176f5d0209ad68b14 +Nonce = 3ee882ecb113d979ac3614df51292c3c50e38e33e6952bbfc4c8f1710ef721adb4378d2ffa3de722f365803ba4dcd4e35dab8517f06b63d4c1167e4df5636de36b49e9236c21f0cc925dd116b45a3b7461d43443736f96bced8c12733a85a76f3df81ca35b1f56ffd2ee2caeb1a5aedb067b5972aa5169f5acc852adde6ce3c1 +AuthData = 9e916c13708a6e252f15de528a3424def62f863f1333cf0695eb51654ba0e95b5fd906d953b06fc27b77559ca5090cd09d65b18a2b1fb40e8f7d655b93fd87ad1cf3a07f7350fe55eb2387e1d795eac9d50d7808dc85014fc130 +Plaintext = c9acb7f4d6cf74137b8c65fee6dff725a8210245da9eab5dc5552f62da221be2 +Ciphertext = 1cfb6d58588202a88bfdd3c15d4f5f9c6ab985be88aa927bd1d96a41a22399a1 +Tag = 14b87a0b659ca53fc8846cda + +# test case 26 +Key = 705f69e89bcaba68c4c26a9f7bf6944c +Nonce = 15b3bea26780db690eb2f78354207209c6c6f70a1d18cb5ed654a81a6da3300d653cfb54b5ce8c324f5e78474d80de9380ca77a8037c2a7a160ff38a8b23a20a688fd8a5d1ffce5af7ba371e94de38b6658471d2ccaf684fad7aeae8b80df1a0956b1c767de3d686ef56ab7741b5f15bbf7bb0024b362ea97940d69378a9b1e4 +AuthData = "" +Plaintext = 6a0006a35f11510d13fee5822bda908576ee9743b95eea9eaba2c457a8a5838e56f6ea6b85d332849dc66a02dec292556428af +Ciphertext = 8cfaaf97ff27aa73fdbabd03879b937f668dba79ed9d73c7ca46317516617c9b384d9338b1a087b2688765a0dde6387f6350c0 +Tag = 17cf37639932f4ce0e42df066353756c + +# test case 27 +Key = fcbc7eb62716dc7f792b6194d26d6d569eaee07a9d3c37ca42854090661e1845 +Nonce = 4c8c4624279b23b495c788844c76d225ebf23826599c3e1cf4db1da2d65a7f7544d8e86fcc33fb113d3174b8c7903122cb5967f6107382cc5ac6e7a0e4ca4f08de3e911d483e68253d3f886cfe349bf93299a28e665bc096a51ce84ce6940b34a037722483b96a7b25507f5a04643c6730faaab618e6231a727714d6f366fa9b +AuthData = 3c182af19c46ff4acbdacecf70b42fb5 +Plaintext = 22144fc12f7bc5522b88b76c8ded1c76 +Ciphertext = c8d98107c0cb3c0fd2189ae97280d562 +Tag = 2906772330ecd9a3b8a82876a4ebdeea + +# test case 28 +Key = aa319f8c3003f21631148a2c5098935f5a800e475e9275349ee911c029f766b2 +Nonce = 1e352b49ed652ef8ee5ee52f9ba21f5a782012d48e1d47c51bb1193c936893eedc3c015c29cb4d1fb1fb8c6241993cc9a8318288c349fcd39a7aafb651b7486b85f1331cb1d662e7e0395b3a78b05f346d1c5119949b81878ab1dc2e82683ff644f33d91087afd80d190407226603f6aab09d07e9ac994d073607567a2010675 +AuthData = 21c0610c3b80cce66ef76260bdddefda910558cc94b659262fc1648df01d6f9bfc2be0a36944d5d5ed66c2e2fe7cad261c65314a94484e0d22a72716318597641d775679965857fbe19eea6c5465e12e5a53458b0d0b775e642f +Plaintext = 7b2c94e55b3de0b5a83869a678c5ae51 +Ciphertext = 65e98a2a6fb052d6950337b30e2d8db4 +Tag = b075b860f6cabfd85994512a8a8506f2 + +# test case 29 +Key = 7c73a4164f5e1d4a08d9fbdc3b1995eb +Nonce = b92bac3289295dfc93215b70 +AuthData = 5cdb7a60e1830c0cf8175c12e279f9c867d7c82d +Plaintext = 2ec786bdd99d5b28d8c15375bea6f438 +Ciphertext = 18451efba2f5a0daaae48637984ab5f7 +Tag = a9e9b0a20257f2be56e881cf02 + +# +# Additional test cases for various nonce sizes, generated using alternative implementation +# + +# test case 30 +Key = 864dca30175769c5e7a4cd6a3ddf4e1a7ca4e1a091c4f3cd27b6aa87736da99e +Nonce = de +AuthData = 67c04bbe19b4466132232874d6c6e68b +Plaintext = 66790e3bec6dbd94fcbd04ca96e4c1ec119d03239f0322285aeae2eeed83c598a968ac8e08dda5c897da20c7b0f8bc46a9effa4ef5e4128e03dd6343d3a448bdcfc080c75e6cf9ed64e4c412fa8839b07375cefd38d1fbeca2222eb125fb12acfea1e3e2fc9d4460bd9ca06e4f4adabeacc60dbda2e55c74c3ae1b9b8db53f9d +Ciphertext = 387bb82cf0d691c2832c79bc87742a369dee6c35a812aec892c4d632c607e918c1e189671fd49f437dd1d46d4e861961d78abc992ab3f8803049ea3d8908a9a6dbf120cb9ef56445acf1922759dac4a1abec3c60cfa82d2f70eb9b424ed678a5dbcd15cff3613c31c40f1c35c470454c52403046dbe1786f50eec05711f678e8 +Tag = 861c14c07219aaa3f5616df48ef066e2 + +# test case 31 +Key = e0c29c3758c480413757edf6f0ff14e0d29900fd2bc5853a91145762f68e3cba +Nonce = ff07 +AuthData = 24bd685f32680753bfc2ae4be1755847 +Plaintext = 5156d837709285a25f263ae79c6ac2f401c39845b440adfa314d4a8d6ed23441cfdf2ee2322da93c962d640a08504cdb3e5506f229222e7468806c9acf5b6c57e6ea2aecf9f11bc83c62f2a1139e5778f2417da350ba652a14c81f61d53e093a6dd34a6e01bdee4fb29eff191a260ab57ec1dc6460121ec916c8603758565ce8 +Ciphertext = c26cf7bc7059b233e0ab61951e5ca6c44f1025a82a747e4453350fb6a5f82d6f9e2f2d3aeb65089debce680b1b6f2fff8873a37f33ea1ba6023d3ee909db04060ecd45bf4aefeed87cf1bf462111c65695e19494ed93ee50aff3b318ec970b5ce4699771ad312b582dda741407665d5c834971e69af67e22afbfc5414edd4d26 +Tag = 3de49bef5754c1ed694da788e69fe07a + +# test case 32 +Key = 10b38335db2b48860531c845700c2c48790654da1ef0c4620d0773c50542932d +Nonce = b083aa +AuthData = a973bb7d63f74fd33a1e43d671d9d72e +Plaintext = 3b2a93c34405bc5442370b6680ff49a787d6446557949af70a6cd5ab06caafa96d9393cb4d7530d2caae1fbf5782fe38a43cfd7c6c5f75b298ac7feb5003a57dd1db8ab6ee9c67cf7206fae2b6b58fbdc48ebb0e454b50598b1361765e58b0e8aabc20d71d72dc5d32e72a5cd86c0b98428d9f57190558d07df0fffc383b568f +Ciphertext = 3229e79c64eb1d1761a9f464b8bee6b3e121b3a0c101e147903693f027b26e3864ea2b76a233f069ef20bdf9d90f21316258df47e9fa55861ddbb23f96090c9f5c36712365dbf869eb69b548e32d17d8a6687f594f36e637d405f49b06cb8fe9c25be011ed1ab0c1856eb5008f7d9863fbed8faa58eed1cb940f863156ca0cdf +Tag = 8ebda6353e189227c90fcb8dc35a838a + +# test case 33 +Key = d74fab478674037a30d178b47115d5c52d9a37abbccaba58979c212f325ed8c8 +Nonce = 6b0767bb +AuthData = 1b0aeef4a51949ca93439b3a81c2fdb2 +Plaintext = 3b6f6bd8e80c82a6f2be0b076dbb3c73fcc49e064d19d1d4a0084c94b84a1fe1f9b1411a2959c74f70a1fa74f994924c93e5be6363bc31f208231f290d05b3c0ce32bbe52967ffa0e8957ac234438acfd4fcd5c1c42e132747a800a2cc6096c39210f97224bd000388b1696d8aebef79ede4b633ce079ced5af31a0e014a7ba5 +Ciphertext = 13d4199408804c2e093275f55ae68c36f863754d0caea9914251ee1f7466c8d37a9e153da2b307e0a6998439b540231aa5874f738a665e83cfe69663506ccf4115438e51a8e902d7c9b47a3cb113daf8a6eea10b91419b9b0f2c8fbcbd92e34abcaebd88f9d229bff4745dc8d4a1416d2447340ff42970e87ac851d218b8f937 +Tag = 11e7d66b4940afdb20d537f2946f725e + +# test case 34 +Key = a8a11ff40303ea7db2f8bbdb904363b2a90998decb55fdff058dadb4c38c4cdb +Nonce = 82c061347b +AuthData = 8b7bf81df3341fa4fdcdbe19f761ff04 +Plaintext = 8f931ef323facbcde363fb21c5d98de232318c9b95de876c1b5d89f3c81ace22bab7a909b8d725088491ca7b5c3df9cc0663da43384c11989fcdcf2abdb21761b00cd7b126fa6cfce6c4095d94f4ba57aaccd868b4e8f55d4c59ec9ec4006989c8539643be05fc01234f8433fdbb8fadb4bc3ded536646d5c5acf449e03b1449 +Ciphertext = d80772be2c3536d42157b0765b828fed66080141fe4b2df24490b26b372036b27363f58122a10c5ec4b0cb11151abc5bff3668b9ce8bf44cebf61d01b9fce7ea0bd641a17a167fc8a0d89da6ad02dcac3d840041f27be8269e4508b782b02a44fc5290459238b4f571ecff530fe1bbeb0433de18c80fed1ef145ae5f4bae62f2 +Tag = f3439c39ea24b024fd22d0e39d9b24d1 + +# test case 35 +Key = 2d6eca9e7f93f08abe5d1b1f1768084a2f3bf510fc49aaf54cdd9684c7361c29 +Nonce = d63d39def06a +AuthData = fea5206e93226a00dc530d31e9b8e5f8 +Plaintext = c69b0c78f72a581befaf878e29d9c151b0b38f28a5a849225d22b753df6a10f871a6bbb59b279cf08c982dc00a5b7a0a534b06f91ea465dd549e57ad9526c122a5755684389008479d67f721521bb7d6b377b291cc8c36aa739a7826ade9591cdd0c1317b4921c6b5983fb9cf9bdbe95147806f67b4d8727b457fe7b81a1b273 +Ciphertext = 2547efa00cf89e98196ace298fb2f0e8fb1ca3d69c61e382f1928f8d22d902e075812093617fd6e8eae94ffae2a34b1e6851754211ec38c78ff92d48995b1ea051b7806b477c07103c2bf0dd996e5b7fd6b0963ecd43899dfb1453756c0d7bcd546ab243176849ce6eb16548dcde6a3e9ffff3778095ab0465632d2357aa4bc7 +Tag = d59debf3164bbe91edce368ea4e3d5a9 + +# test case 36 +Key = f11c56ce4111544f1e3a4c7b5643f0d0c61aa60a79154eea6c63b350a8c354e0 +Nonce = 2ac71c97624dc9 +AuthData = 3f112dbfe7d3cb0f55c2f2ed6fc17196 +Plaintext = 92e46f8f665c8c0349ea8799684084b2fa6cdf314fa7174349c52812387e29eed017c506776e1e58207c9f0569f846cd89ca4d7f1e7ddc232069bda237ffd3f535fb83827a52c2f5fed8f290cb27528a7e4b1fb94a1cf699383208e44614d9389d7f2ad0a9a87c9ee9cd67b241241dfff9cfca5bbaf33a7b2c9acd5e5f6f8f6d +Ciphertext = 187b0895ad985826ceb61514edca174ebd84765be5daefd4f2ef4ff63b4b52b190773f2a47a53cd387a480d9ad43f81a3b9d1bdfd5e284afa9856f98bce327ead5a13504f6c579c9084f34b081c03f4c11b63a6450db4ee5837ae5b580f5b433cf75b4405066e21f28f97eb6d3507eff83fcc473f7521a2cf36f02a15c8003ec +Tag = 01b43be23f352baf9af30f53d05d2f29 + +# test case 37 +Key = 19f44a589cad46ad1e544775e97d09cdafa99a1918adcc62b8b27b3056c92b81 +Nonce = d2ee02987dc64b98 +AuthData = 4cee592a85b169bbb85b11e01cc79c15 +Plaintext = 78dc729ee2e0cff343155c87d381c38bd259b9ae358d17fde57e54a8f1942430bec55fe1cf3c034e16c6e727fbdf006659c0fd53d56630236432c3e005ce351b42290b13cba740aa67b52a7cc727da5a2571e7b2971e76d1b8658c3c452a50bc601525ea6e738c2a14d03c0c94fb0bf225e3e194ebc4eb79c1fdc6e03716d191 +Ciphertext = 83d3b77c4f71226b858d6341a1a9fe7526f307de00fdce667cb572de10255abb499c53444de51cf31aadef37add8091646273838578740a0a1831999a5fd420e07169ce0dc6136ce3ec33a2bf5af33223ee609677351115142f9949cadc92698631ea71a937ef1aaf65b3dca25c87283d70ec0baa92c4284c399881739b80f4d +Tag = 05d8bffec0289dddeb23ae7882444a80 + +# test case 38 +Key = 5eedef269b573041c91641a563fcfa159a49722c2aaf8aba5f5efa765f07c18d +Nonce = 59ae56c7dc4e3ca9a9 +AuthData = 4d1fd6da995749271e7cab865c81da36 +Plaintext = 0166f9c71ba273dbcd96a1ac74b208af3590599841ff8c702f30f0ccbc6dbd829086f8292125a6ea8ba80b849068eb5cbd8ef9295f7ba95aa05b2e8b8b0bfb2f2e6983d95b118f2a238b4522c0faf840a9b0e22572e29a348b9a876d9a0c7ce0d7849b2f9a1476b5419d2f99cb912cc3e444da47656b0257aab4f17fb17d28ab +Ciphertext = 3bac281ddeb7f65ed2a81368fb026c8aaa00cd28b77162be97eb30f743b5746759120aea3537bb9bfbc3dd5c7bbb1aff267e66abd28796e5be50078899014558b1ab9f0e5b63766a6d8ee01430d7dd78c7b7e88d603a6510cc98fb942cc0597728c54ab84a122623d926803c04e5802dd8e58695d6eb0344e706ba74d1f07ea1 +Tag = d267e1494b153393ffaf202ff91a6876 + +# test case 39 +Key = 173215ac35f98b0453a382922b89bf72086aae58895a0547c354a397d7b1736a +Nonce = 7de8f3c93619c7b7a054 +AuthData = d71b1f1c731c33389605a313ea175cb9 +Plaintext = 677b7c55c048b3bc32aa332cd8ef8ec0ef6b46fbbcc9641012595f3b90a3625c8dec4dc1e803764e54d3df57cc9e0738c3a7d7136de60bf7c6ff0bd5719bccb506f86183aa34aec91160164f7416daa7adc3a09fca085ea855da6be59b388c07592053c1dcf07d3092232264bcd382b823a870c7353e8d3eb279fc803d250b48 +Ciphertext = 3449c261373acbd14f71250e201f641cdbc5b9927e52de05f801c3feed630176065e3d0633fb55bbcd8fdf4374b653c371bb810f98273a3fcc21396dc606901af1b716361bfc2ac5658643aa5ecbc8d74742ac50d59d80735701be33f48c2ba0886e9868fb8086941eb45dd09b1b3c4c50addd811a4a4eed6969a6d6092fb91d +Tag = a48d37e5ea4f7313aa30842c0a539ed2 + +# test case 40 +Key = 885247b0b29f5e268ac661200b5777ba9c56366c06b530cfd70270abf8665ae2 +Nonce = 4aa7658bd86001e11c2a55 +AuthData = d93170fa7d30525813b62bfcc4e84541 +Plaintext = 1490d4b63045a797436439293a0665677e944e792a02ec13671088bc937d93f42b320a4d9fea3726ce75bc41c0a308354ad54de7c46ec14fa30def0db264262b0d076345d8a698e5708e37f255c857f63cfab5d5cf53d24e1ec21eb109fe79f1de2b721e9fa10b5bba941869aa54a81a124c5ceb4d4df274a4fd8b539c545fba +Ciphertext = 4bfb54458fdcbbf18e6b83451a9e7a121d38cd89d1d6eebb34fa67a0870578bc20e438614a9413e8c8394471448bf10318944d22045883a9f693fb49825508443530153946cde04d3c4dd61738156787e234d1abf672dabf15736c74e81ddcccc18d527f8c9d2268f63c1cd1547f1b3bb8abfd8cfa671daa85a96786bb691727 +Tag = 6fd3d53757b942a3e204766097083ecb + +# test case 41 +Key = d62e6c7ebc0db2d7750c08c9269ced82741bd20576adda87fc17766635260ed1 +Nonce = df7fea81f51410a7cece8f188f +AuthData = abd4d7273682ec7c1be61615101c65c2 +Plaintext = fde9f66ae3e07c8c6992ca23d010c9c9d485965c76cd8c793d4f9d6de7dd2f164ca68c4e6898f3de561444eb4fc5a309ffb9366b8667e6ea9dcfe1e25af952e97bbef43dd084e163cf6f486fa39003f28f9a75a66ce415ebdd44b9849b4e20f97de7a831d983a4b7fe328825fb8416dc20e3c1d72c672f4f5ab8aa9ad504b921 +Ciphertext = 25679fbdb10210ad751d27ab09a2b589e49d43b8fe7b92c218f2edeefa6d9acb276f0e1adc268665c361da66c943b1aa47e8590dddd7345de3b0dc41c97259659564994bf0883e7503b39a10d23059479f68921c4721d2debe06501c6f45938468f61c28750d1270362703a9eecae8c63d79690d6f5bb98762fe4e57ef13afda +Tag = a3de4286e35ca74698a192cfeb4d3d25 + +# test case 42 +Key = 56b89a4f466e532bee466eb87d469eff489e92d1f0fd8bfaf4443aa083d0e8b4 +Nonce = 7f5ea0711d18bd341876f3c376a5 +AuthData = 07e248773b5f68fafb209874cb1b82c6 +Plaintext = fc3d4b29e73efff67093d140a0b8b4aed55c3715a0373668d23f847dac39e3ee235320802c23e35d029f567dc2ab86c8235d1b9b7673c319fbe4343e8c88778ab03949f71212b7233b5cf06a6d24dd5b36067ece5cc31aed41c0fd90ddf4d89a477a11cc52764163f8f8a716ad4c2df12333212fe68e1da2847e3b6d1ed1cc97 +Ciphertext = a421fb71f55fe99e462a837dbb78f7d95845eb6c2a875dc6f1fa6cbd58e0f7c073612161ce7ae3b45bd8fd53cbd79095b47d6cf743e0b4e2be42af797733195aa34b2bacea12795038ecfffda2c3c22e2e19ac87c614874b6e97e80b44c88f77752f4609b040bbc4b60b6a0800c8d3ce6a8624e5ecb71e64d7817edc6a32371a +Tag = 39b23a275966db0853836d84b80aa448 + +# test case 43 +Key = 546fee1572043ef1ef22988ea20904cd1b9a89700b4227ccee71f07d8eae24ce +Nonce = 3ec0994255b0459c24f670eec9e804 +AuthData = 4a5b1b382f0790f10a25ddca82335f8c +Plaintext = 0203db516f05d24d321a306cfda8d6c841befbf0aedf51a42f157398625f8a158183011c6562b0c63848d99f5fe08fd152abf3b7030c435761f722b295d68d7928387f833e785c3bf1c1219f98239cf50528d5497e56b707e5a2162fb3d25a8637a3080a597cb08c81350b668a291fc2192674597c8a62ffad9562e86b367f84 +Ciphertext = 2fad65b72d4cfcd20f77588bf73f0683a063198586e66272095e35602353df2885a5a17bf64d1829ee0275553753dfaeb92ff839499f01796959808358bef29a94588c629daeed791207ff8e312aeeaa6d65893ad84a8743826288c6b858fcc91dd1d3bde7a00a5813d7acb293fe5a9eda5365ba199bdfaffb4e89dd41beaadd +Tag = cf713d805f1d936f8542024c49e14a15 + +# test case 44 +Key = 163c013f1ea0819b286bb89cb9603276e57cc2941f6111ddaafd174f2221b5c1 +Nonce = ab8cc60e49962adf6c66269b49113c45 +AuthData = 6ab43661b504263eec416fb7ce1e2325 +Plaintext = 85e24d1c58756da9c05034dcebf0b95e55f4632ee3545338596a43e30163b3e4e7c3c4d177fbc5f08dc9b010afd49f1835ac2e03378957c1e5607ecb45e966396e4f5e22f8c5b2593ec939f550ffdd9e2f96d48b37e9a7351cfff2823952d1cb6e8e69ffc5614a82d57e158fe09b92baf176672529c77fe5241fb6480939531e +Ciphertext = 69e4a43c349badbcc0aeb53868cabaab5f69f64eb3658f758db248d046bc8bc97fb522c0bad0839a33d1c3d629090426a3e47ae9a6698de9371eee25a9e5757d1fe70370f199d764d9bc394d240586bfbedcde1027b94716b4ff2fd2643326480704a3742b3ce15a4743c764bc9afa06380e63bd0d460386c627ac9235c6376c +Tag = 4fbaf01ee16cde4d05e284ad91e273d2 + +# test case 45 +Key = 497c52407808936daee1eaad3cfdded0ac3718b8ea1c7c251b20faf1e819b956 +Nonce = 7f931578f0fab0665b96ef69711d04a34f +AuthData = b8ca47045001f9d1ce4289a5539005c7 +Plaintext = f24e7823b2e63f0a078b116cbe2a6bfd04f0413c0d92d42b84398c2e9f8d2bfbf30b010795139aadf189295532ee6587364ddaa32b3fce221fa1addb18628f07f8fee69e83e31da53061c3a2429db73d94d7f352133b98297d01461246b1cee3d94d6ffb629c68d6e2bf54061aea711b5fc0db64bc322d23ea117fd37eaff165 +Ciphertext = 7a360790c56266310dc659acee1d1ef04065d1b719598cc17ead1f951698609d2d30a0922ed7ae1482a87b59d1d6652fd52b1e58d4a011f230addf507bc1ae68c334d0c090ff5f0bf2e4c35e790e83de7f45b4c973dc515a58e7a91138fb20743d4708dd3fb09437b9485443d238fe311e693180e35fd9ccd6771cadfb8aada6 +Tag = 31447df48c9064c86911b9cdeb7091e5 + +# test case 46 +Key = a0fb940140222a6bfcf5da7eceaec57e7a5bb1c73f1a6810239bf88ad3d86768 +Nonce = d9bd6588b1a6e7ad4c0151c69f461a516ee5 +AuthData = 02d14097b24bbff2c5a74fd2fac627e8 +Plaintext = 02e5d8b683d0bde2cd0a6ba887d23c397eef6728f4b641b2eda551230b3030b1dfdafdaa9a350afda7612c91d0520e995cde1c626c372e64e0802b02e797a15c3264bc21b20b912b8cdaec84c18e93374e5e7b19e4891c7f433d8c24f6400a385af789d10adc16dd0592e92f7ecc1148b7832d9ac9e9adf3738bc53990a24300 +Ciphertext = 74119bb4ba3cd5909f96f17dd4a41b5d9dddf098a54a57627860006d86f52ae62776a5b205bb0acf0624c7607d467ba3e8ee5721468be38783c4440458967e2330711baf362b1b0b4f2b3468ed496df95f97ddef30115dd900c1f5f846e29cdf87e6f085cbec30c065d82dc9dd71b66a3ad59cb7d4a7d7caa7dffb844610c4f9 +Tag = 37048b5a1dec46c2bf549fd8135b3482 + +# test case 47 +Key = d0ed91d834414b3d9c76221b895473d54b280804a3973c7b5e03da4adb2049b5 +Nonce = 0aa342efea4add0fe389c7a974be54a1229248 +AuthData = edd37da595f3157d388c9d4b857e1421 +Plaintext = 6613642c829f7c50b4523f814c2ff1add119e529303117b0da71aaab9066ac647f7a09dd0f40d0340d93cb186694c4fab35ccba7906e90536ea052210e3d663d66fe323a194ba49ae9b3442c1115f22399e8732e5bd34f991d7e3b8414d6d1f58abe00a969200c36230aca16fd39328f63977e078148030e72ea68cfb63652dd +Ciphertext = 42be769cb8af4eec7a85ea43f93dd03780854703a6cd4236ee8e6ddc431823e98db6818fdd164ff2f2a7d329bade57bb28d81f9a69ab2a3d2694dcd8cbe0ea0b94921a12ee902ea3ae5ad917cae15c82d18a5f061e29f06cbd7f2e5def06a8cf97bece2155dd2f0933f65a4a6a9b822778d7170337c1c371abef153e4fd0a9a7 +Tag = d06c44c421f84bc913624f9c2b3861c4 + +# test case 48 +Key = 4751aefbf26690638998c8367b263d9e2b9892a03cfa64d6298caedd7e6c65c8 +Nonce = 2434dab556b2d2dc9765b845e4f8417010fbb395 +AuthData = d1fe877b1cfa35005b1140e6bbe33b9b +Plaintext = 6980e2b79e7025c4c0d36a4701de8d52e75aa66e0b1b54a615e376903778848001f3f2a476e9cc4a629883407798c3ccaa0e1b72b66b245e35676cc560fb2666855bef2f76005a4a3c9ccb5e4b9c9a91cddc3eb822a159c5a47ce87bc5001e02c0127b00ad788d3423b6c0a481c4c44b3e76b7f089d7406dd3e2e928aa56d104 +Ciphertext = 674c1a431b357f721d5808e4743d35557aa8e543aaa39475f5e99006b1f685e0dd1c46aeb561e936502642cd8d916d499242e3c4adc8621d56df74ee65a7d2c182f5332eda3a18a61fdbd13fae56b87d22b89c9d66f7b8b00a878d0cf9f36f3e22b2953a923e74e05ca96c92a05ae4fb85a8adc2b3d65d3b4b33c7437e902ba8 +Tag = e4799497bdf7e75d6448ab4d61b05586 + +# test case 49 +Key = 427d2dde665b291ae2239178c276924c8ab3b9073242ca7c745a536db5047a5d +Nonce = 0e90a50fe1670bcc7bcb044631db573ad61d625747 +AuthData = 57f9ab2622ee36a2c0848b72df7688ba +Plaintext = 4796d4c9b5ea2996d667690dcf4f814ce36f59f6041afaf249c519fe9bc0f17de9085363c5efd3a4574b55159755fa41d5847417661ff73074f2df4ba56bfd8a1c60af0df42b26a1bd6f495baecb2e864a6e0397e2982891b87e5016b0e4332d3fe29c7f0c6ebaa85ebd6c8b8a99a46b833e203b1b438ba8d2cfe2ddd67e50d4 +Ciphertext = 0be77d425da311fb0955718ba33eb05538eb987ac92966347cfae0f7bedadeb0b014804f4063eb4a73d759f33b40debc749b40e6a0324a670e64d2cd60d9d6b354de76a1b28c299b9d705005504c243b73d9df77ae3c229b1e50d72eb92c3d548a3b4c1d36d0aa18da124ad2569bdaf754fff1df1e08054307b61a9e6ee3a707 +Tag = 4e857a5c9238e71e16869d4a8ee84312 + +# test case 50 +Key = ab693a84b5403c1d23a37b48f676d1736d9f84279e64c36206c8b0ac76511bff +Nonce = 039a03f796ea36f7f3a6dae4c78d0009ae1877012bf2 +AuthData = 2ea5cf4e976bc0a79f9e91156e2558b3 +Plaintext = 86873b0a6b4c5b711203bb6dad0543d6078cf570b5be67603002ceea5ba9717dae0a84314a0c91c5048710bb23fc2bd19132c80745b697e00bfd9f0b2573474ddd0eb196cadb1e03554c8c0e43cec128194be7ffeb0f9b9b66c838f7e09dfc5438355e3f34319013a9db8e67b79422a9dc8ea9f99117378f74f56b26ec5d2632 +Ciphertext = 665b9954a814d5b3aca3db0c30730d5813a6d585efb5fb72337057bc07f24a8277c107f4974c356b70cca7259cba19cc1c61a0f7c4183429b6716eb8a2bb4171469a18ac87a2025a5694ed874e2e81c1cdccef9ea9bf182125eb4cb23b11d107df30f7cb7bd56018ac1224e5fb7e44671e5515a365b42869f03cdbe515638250 +Tag = 4c637ce548b236189c61523649e6ea0c + +# test case 51 +Key = 570b9219c3b71ddb6fbaa128945aca00bb18f6df6836b2b534011f2bbc000303 +Nonce = df97b22873e77fbac26503c57aa64b9fb14f01501fe744 +AuthData = d650f40f65a398083fd2b5786b34fcb4 +Plaintext = da5ecb22a6040573161bd5f7e18d10badc465a72cd0b2d8c8d16a72abcfc2fbfc61e3922ec6774bd232d81e657c8cb26fdc8f0bef25702326a7d138aec1236fdb0c1a2e95a5b5d68a77b7c757b61506a478029fe92921994f894f8bb34c02840bc4a851bdaf7c767a716907e1b8a6f6bbc131ec0093e5f6c07adcfba26cf75f3 +Ciphertext = 28ac5122dfc81971685685766d836e40545ecec6b143e291a5ce327ba903bd094cabd56ea68a0eab949f1bdb5a370621c13eb67ed8732484498aa185af04020029b8622301eb03b11d17bb9df091e41757472cdb869e2604120599fac6bd72f49137514ed2e1f648f192faa99d00e11ff0cb8dedaa2d2f8614f0e700a7a72492 +Tag = 17bb8a888a30380ccc26c1ccf335e3ee + +# test case 52 +Key = de4c8997d260f1e4b51fce782bd5714bdffb5222b72aa8acb4c91f7264ab4fea +Nonce = a9c789ca4fddda7289e1cdbb26adc05b49857c71005936e8 +AuthData = a8c6e7b745805fda7d299bdab9053b38 +Plaintext = 1d44fa67ec10c8ef14c8508c59323da4ee977ec920cb4f7821965785361adc110e95e742be176694a6053403f67505e36e3ff9e93826444d7276f21c8c6bf6ee488982d069a54e2a42b32db02bf125d98344a7a0033d6df99b92a1f576363fd0127106b699feab85f84436d7c50fc251b4233027870f295c7fe7276462810b03 +Ciphertext = 1fa8ff8ab3f22067a9bf92e212dd63607058feda7f5e659521c289769337559e9598234f1aed2cda3d3c1a2fbf5f3ce031607605281fd6bf64b4380f213c206d855bf031c41853bfbda0aacfd9d03d99eb55525ed2f74bd66725dbe2d99b3660ac6c4071b052ddd62165fabae91e8ccf1fbb1a87457eb9dc439636051909fba1 +Tag = f241f0c684e90302dbc4b7167513af01 + +# test case 53 +Key = 6980b58c7e99d6d0a4dbe23855e3a8478ea8780d7ae166061128a65c2b1529b9 +Nonce = 71642d25089c7b2197a90d678d26c6b677da82fa6c3aaed02e +AuthData = 4521ec63d0e9a92bd529217abf136528 +Plaintext = e711a697a8f30fd98afb751b2925b0dcfcf1d106408f0e0ce0e00b40fe178a805abd128f7dedf86a2400df8e55e503fa75be054466509822b3464b77e96040797a3c83918fd17f0fc84c957910aac4d416df39e8679787d107aa25596148f884054d9b82ed35cc945488242775fb5b981d23ffc1afb9118c4ff367cf16277c87 +Ciphertext = ae081f9fb5c416fe13700da5c7ab0aa5f029287614b7b674e15b0c603505d506176c0ee7cf73776feeb6a4a283c62fe9ad832ef84f7a4c4bf80e73bd09daadbbd004e1cdac6e84cbba9cd607d83dff05efbca17a4cbba1bf499797ef34fb6ca11c75269c0b679c0b05c2be87c5938b63e44435650ff8a4620f249c8770b8a050 +Tag = 6048295ec36d2b046d282af9d3ca14f6 + +# test case 54 +Key = 386dbb6ff4fb2d04833e2f8abdc8904307c75bb0ae8158f8acf3d66cff74a9f2 +Nonce = ae123a575be7618553cebd97eda5d09cf150660332fa7d63a09a +AuthData = a99549155f3efb88ee388f6f59a48a4e +Plaintext = 60dbc5ba8398e7c623e720a7b24f2be416707588f3f83e55dcbaec5ad7d672d477b51785cba65b52525ea6090bb980e297c0c81a81deccda602e6cd4c285b3bf025a5333a15779529a2c461bad25b6ba0b0308afe81efb936c59b3529498f734a1398fddd1d06c1ae17f5bddebfee66d054c5dc04898fd68ee11ea025ad740f3 +Ciphertext = 889f430d6bdee4604602759a9299be12f362ef5b16f5d78d025062a5eb2bf0116cdf3972e0465a41b5a1bba9c65792e441b402b591915ddcb92d37d0565b7d347875e446d148b54622144df0464f3f8b1649fc4e289ff826742e792f0fe645770477699d0ccf03993821c67498d30f769f196d2a0b9d178b733d84085fc931a1 +Tag = fcd4236ba4b21b5a8f3dd59ac22286bf + +# test case 55 +Key = c4da9c299a24d3c08614d6548ef61d806a089af3e9857fabccb9951bc540d595 +Nonce = 6eba8315b9fe341f6b6fb3eb2379abad13cf12c8c2cc0430fee18f +AuthData = 4b998f3095f96a3d6a8b6327e600b703 +Plaintext = d3f94cd1a06f308326ad0d67a8e26de81b9dd5f70ea7a0fe860cf78b4546797a4a7169d8fdefd9cbc30b63f095bec622514604faae6077aea99afd993f3677f65fc4e2e2d0d15024ae3a29703d4847814e1e4966c0b46d0f0d9f4c843becf015b4d69814a4d329582e01d242c1b184de4ce2107c64b2bd48fd11fe334778c96f +Ciphertext = 059bb134bf7ba4b838db8f67d43534b998caa5542752ef4a1e7ace8f2a690fed32062b84c1bf3a2f187ad1a110a1df223aedb378592f78e24cbb2c39b01c61edeb2c97040fc7a24b8b9e0dbddea1d5b74192df1ca8675999ff1521e07d0fd90967bc64314af9927c0c33a5749aa6bd783bd5aa8af08a5e5c7d97d54817e5feea +Tag = 5b7966e628e357990f815ea554c9dc37 + +# test case 56 +Key = b9b4b64b3cbb57b956819fa6b7793d9a9b1c5ca66ed3d376dd679b7cc644a48c +Nonce = aa49c7f27733890031bd184159a33a75d7373b0ad9d26dcde56a8873 +AuthData = 4fa05e0690a3f0e0e3270833e193236c +Plaintext = dc9c30532d0e96c62286c60e70077cbbcf5b1ba88c22538453199d939dd661d35779b879b3f3791b630c60378672dfb2a29b09092b5f0f7453a696881b93bbc2ad2516e89fec7e0123f7faf6ac78001008c7f5cfc5f2f2fb881a179306f4cb8065f9adb403858b13f2af89ef8712cb985eedda5453959f312e7c14a231e0df07 +Ciphertext = f7eea9b06aa8753a26061afd7d0c712a0114e579107f14a042fb617c3d6a65a1b8d26b7bdf15aad0b9812bf21a010dddb488792480e60fec75574d4df235894653e8887ac8525a12654e96b978dffe596e31329ce84c69ef196a8448f68ea9a6bd4968636a6a6c61e5323a7805849383f21f7c62f0aa3552d6bca2ac219685a4 +Tag = 747ce8534a550684b5f68e3f65a04967 + +# test case 57 +Key = 23403011150256c3e0d8bd49375f14454f9dee3f8b3f5d169f7ab6a833936504 +Nonce = a744314004b7e29b4dbd17d8b91f211d8031fad3dd65183426734e101d +AuthData = 0b7b5dd4f9ff302a176b67cb912b426f +Plaintext = 042647a32de034497b41ca3826709ea6a5a956e94d7464362a42b74fea2609646d04a7aec214f34df451996c1adb89ecd68d4002d51d1746dcf3f3827897bca54633ae0cd07fe2b52216410e385a90be47d9f405065737d6a38bb6bc73a0421ba51f93020f3cefe6d05f7166ce7383511b66b85b61b70db795a7d56f4b95cd8a +Ciphertext = b0215463ce80fb0aab53bf7b8837279b6feb1fd0064bfadbe91110e7a3d1b6514c8a5ff270e3bbea6a770302e2a8557a425bb84ca32e4776d761e79c023723b2c229529ce51980d005a26445a59ca0dbb2c8faf89238df669f8c9ef2ca1c1f20446feda1d934297a304eb6d07e5598dbaa0bcfa8adfefdf3a2e4c5cebad85583 +Tag = fb9a5e7f7e4311065f71e8c4608f06a9 + +# test case 58 +Key = 752e346f7a38575c30126ff5ed003e6d9834079e5bf23809ad23e82ca791e104 +Nonce = f524b8a65a700a04609937cc1c36dd7ef5f71811a6d809d32507d6c19148 +AuthData = b057258685f11d03d22302cc90227ddc +Plaintext = 1fd72a3b508bd7e6cecfa187d264cc4129d734231f641eb3cedeb5d7b06a3aa3d9c8656cbff30ea4faa8e9a9d8e96859d04cd3c86cdbd8d9c35020d9d803d24b637a200c41e3b9422c60669d3841ce2cf80868ca61065f0363f9ffa9d83eaf70fef22c79c770020216f46dc7fdb9670473a43c27b4e70a2d3451c4967a27bc00 +Ciphertext = 6c2cb9903d65c0a34896994cd3911211c2bf67a37a12c902fb9eb237d53369e624addd564563f4771d4a0bb61862b1e188dce30ad44f43634d10114ec4454fb106ad4ea74fe3a0977fead85208d1f06a0dfdc45e33344a301c7d94a08dd0a0e4064865e5c5683f97d40ccb7ad83420c363464bc96875a2445a3a3ba03fb2ec2c +Tag = dfb93a5567a2cc368e52a57c35ecbbb4 + +# test case 59 +Key = 16c7857b187e9e2fabb665cbd9688b2016bd2b4634bc71f107aed37e400bdbc8 +Nonce = b31fa0112550cb8e7fe2f41abd1e6e638361d4a00b5b2b6280125c6f6509f4 +AuthData = c3bde200bdf254715d13c9c24ff8df57 +Plaintext = 11f8b35fe9caa9b1e4fc73f9228a54b6ef72d3480d7a21d16b8dc24a124434efe946ac24c455641dc60a9868ee66cd75b30c44900ed2c708dc5e02b4706d757ed76a52d222affc5096a540c1f35814db15d858dae516decab716a4c3e7937619520248ece55271a49bac60a241ff17c05aa396dc42e7a87251bd90fa7da58784 +Ciphertext = c86293c7344b9dacb8402b1aa67aa4f5aa28015ad5e70a5eeca7d175c04bb7d8fabc616943e98ecba93e21316a863486db5629f4a09dc84cc4a1f2164a82ac99a9344e41247e10fe7ebfda386dcf30ac5ea9f6da6a9c9b6fe2d4a9c495506d4bd46440d4c50756c7956810a4b8d980a3000398cd33a2c4309848e2be5e45f8e1 +Tag = 2fce1f4137692b592a8bf95cf3f59b7c + +# test case 60 +Key = 0efa9cb15b0e2267c5707ba4204dd85cf147e72d1bac2fb7dbc7d24d9e482a2c +Nonce = 621854f949699f8880083bef8c8a30c1a266d6f1ca99caf725e63c8973a66ce2 +AuthData = 45e9525b071e5cdbbfba1ac0fdd75bd5 +Plaintext = 4f1473fd09899bcc15fd2c31d75fa1a29ff4b0461e26858578e4349e3911ba0473c5b8022ed00a341c84ca60996b7eac497751111490eb724a2af6e0cc31799a8d4c66f42c185715e03f96ece2e9b83967b7531dad7e267debb194621a2650a4e14c2dd3d0099fb647397785ad6d98658a66613535900aaecb363f3d6366c38d +Ciphertext = ab15fd59a32fb7db18e26d65afbb8df4a8d22d030d8c7e682e7a668158ac2e2a738b439f30edb69d57f46b55c1c628f7081bd8bd4b3504832c3e98eea8cffd99ce31ffaf31f5a1f20c989982d4e64dbda71ba2a7be8dc8b53e2d801e6af4ce4a20aff3a45416011689339e5accb079e15aa34a339c50894ecd344a3851ae87b0 +Tag = 3cffaaaf0a16a9778690498387292ac9 + +# test case 61 +# this tests overflow of the 32-bit counter using a nonce that results in a high counter value +# (0xffffff35) along with a ciphertext that is 224 blocks long +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Nonce = dc71bc1b2c5507d3456b76a39485b31d +AuthData = cea03889c61605da63da57b57615a704 +Plaintext = 247964023b6e44730a7bc1c1d6aa23d89bea03e6cfa7cbfbcb33b85b37e7e0a2f5b76abcdf68f40faf151598a576df00993e2c37993e7b72aeec7fa7b293b63dda5c785ed35eb95a51719e8bddc2436bf661701e4438d24bb5160f4479ed064c0db7a4725131af6b84de86401d77b0fc25b6923366e7b5c9f53867512c9ed40a8574d14690e34fd9564cfea6dbb447cd7cc039626480a3cac2cee799370ff06d2c34ca7edba7820b0b0b4e1e51802bb4d120686fafcbe1109180394abf79bc90ff3d4476030ac3c7456e1e6a8c7e5d0228c7f848af6e1bf8a9efe0a1cb606e958a254b14ecc4d6cccdc8912386be8f19608816d719e22a7e66d149a267bde5961011cd430775cc933127c96d5712d476e77677b847afcbc2939bc6af6e22bf8f54ab48582deb4ef96575744501e5ee60d5918ffdacc01cfa5006cf4445e984f6eef0afa6b730c80d4b4365a95df83bf3e4def6d045e43112591b8741ed0dde5bf7e33166a0c361f278ecd8bd2d3ab4948e88d640cf31c678d01296967e49d2f61a4457a6f18c01f22631656e4f2cea910742965d4ad85cc818fb17cc65ba4f4c73b79dc6b401e69ea1eba49728a5d3ac6851ce094662a1238cf1e68e060c7d5c754039ff438754a7749adbbda92dae519a77a12647fa3d1a3a23236df9e52778bd7aacb4abcef2b01fb3ebd858d33e0c9852031c2dcac8fe9cd0e9f559b219d495d6fa65f7559aa6fb5167286442ba9f048ff30783cb16fcb2f84f1892cf254034d50e3da45931ea06039ecb0f4b82f064630c1f5a63db6450e33c9e74045c06b726218ee5bff593a6f280fda00c8384315610f68fd2b58276febf3476ab76949ec70992e2055abe246d86462df92dc536f7c5bd38a673c2870e7cb0e45cf5efb9817320273f6554fd0a85d93b8b4fcb464aee9c19a5e06329407b4f545e54c8c902e0a8237bd99716032f8e183e9f41e975b96c1911b34932a568b075ead499a2cc3ed5560cf9775cfdd20d8d880e9e7bbbff8ff1292ee47e0859c6d6a70844cb52549af767a63d4bf5646c5881a32088a4c37aeab06e1a04d4090fa2482d608db89942c2d1ad94738f9d309e5fbedc6d7d4ceaafd74ee4d33dd0dbd27d475742242398610f5eaa93143d84146ab9e81505b95fa40b533a6369439100c31fc66fdbcd750caaa4fce307e1f00b4656300cca5972f148859490aa5fc9e44598b9c41e6c6016b9266962c25ca6af66e3de4ef6dedfbe605ba3b1885981890dceb20cc97b615da84e2afba83357933a8e89421d36c6b0ab5d1245846b207102249b527c9e28f2631f50dae7809f3b84de8c6f4ee341c2eacdd275f4f4061c9361f6a21c46b94de75eea5997f4567cc146a4a518a38b46355af93c97222bdb7c0f88ac8ca62b420151705738cc0ad05524527e34722c38afad8b5fd781cb96af73fcaaee0844cb9f7306a62096d1e8f68c7f2baa5fb5d7c29782e75d8a71d4e296e776ca3e42dac931d9d7ec3e3039c0f37bdc93d6ba0aefebe71ed800efb1559fdab6e457fd4e4db71be88cd6e8fefa444031209257b2d3ca1558c0146b31c07309ba92421c8c72b0a80074f0b0f261d7c1207609abc7a90d4ec03b26cc0e12007fb40982d0578b5f849d1efda4bdc991a6bc2349c4fdc4bf6c9c8a59761efd986c84e24f174b06fcdf7d4c91381c997db9bee2c231b53812dced2977dcb396eab6c5f997d21ce1b68638c3bcc0845392004dc535cf8dd6f1d835599755e887e0ec00b6e33a1726cbb7bb2fc5d68947e0d558680f9bc9a11a81d69497ba8513d4521d7550ed3ae405ecafa19f63a3d26e08fc1a4ddeb026ccaf6a300c756736424ba37ab99d73a9562f1d37cc6c3937b26aa2bd0da461065a40e2bea5341eeea9a891ce987fa85c2042b42e4abf022cd1a6de28938305600d8fd48589f9a845775228790bc11dfcc7cbaa82288f8d65482de3217526c481876d142c1c2eb2ad6accd1f9605fc6adaba106f96408b64c4a2432993d2a2b03bcac851494f91783d0660cad808339a13470ab52a2bfcc9f98c5da9364bf8b68719d16146f0fe0cd0de35dbfc6d5e0f65424664ee62bd71b4cfd31b399902ef0bf8ac2ee39d108516396f2c018bb25d1ad9000ff3b9d6d713ec216d88b08a44b6bd26901a7ef0745ea21b61c6457df973dc282dea09e7262f5be59fee08aa905d85b8ed78726f591d2862ce75c7233f2da240ff1f28abd9361e03f9f39bf3d945014181ad19e8581b3a9d930049b4ec09618b7b0a26a3a63c82f59cdb7c2980b36d9752143eca7228e610abd882ed11f29aa6859d6ccfe8ffad7f2fadb67aaec5c9fcb5b17921cad4530b9eac964a7d27ac96da2bc3f3c7694d4f0417b4a74b8fc0dd8a823eb75856e0fd7805ac1533c492e43dc86017044ccc91ae44e367f9f5ad2eec9813685acdc0f12675f62af6f5f2aaf1ba4603e92f96b35634eb16b1389cf6a02114ec6839bb145282855a991c57a61f41e1b36b5f3362b8d6be2a67221f4ea0c1daa5697979de342d606151e7c7bfbaa3c2d2b717ce0ad0869df742574808643385d827f52aaddac89a740284431b7048983aabbcca6184cd2525379593da45724dc04eed5ccf39de857df3ab15627f2a56ad6f4cce90e924a2b1b284f48928b46f69242deb2d69c7af73ff67d77b8468f15d4c7f2785e3bde07a85863e9c1e6b917c57c8c84aabc5c5f2fa38e0c1bc5c7d6566f14eceebbcf85cc941be1d093d8440c1358fc306552ba4dc865f3c4a4227091c57aab5503e6f5a4a76a0ae0087eb710ee6527ff3010638bf01fe272f7c2b4a8fe268704df362da110bb4da59b1cf8f8235ccbd29293e5c4cfb84afba44d5c08ee631f7b3b6d3fbf6897f615395265ca217d7c4c7f10f03d9e525e4900a382a6012083ea2a89d33181d8dd17d62761eed36227f1b324935581ed25fc16ea7aa62088fe1deef73fe53ecf499e3bedca7ff0d85e91f7729d4fb8b1274ed19f131c2b5c4c0cb27010364f7e602d6c5634cb9fd0e052e3e28c6272a2a0705828fc4917d675c68cd8c82bb8618f4c92b4bdd11a1cbaf1865618241f5d24be73fddb1a151f5b5937baeea3771ca9bd1032ada5cf2abbd2649b0f271c24c0a04fb7ee7acd51abbc066fe6f74c73ef911135c8510add5982d4286bf19ff862513c48568bef4a86f731f8b1df2b05010214f88652a750dacb802d7e94f17617c31e6c42c27be4cd9df9f8c500232fa5c11fd2ce2327c3d91c4bb8c269aea06c6eaa0a0758f175ab3a74cab934120d3f6cddfc16b71395c74b061d94e30538d6b9518d4b4d7bb037751184edd96f8dfd4597ea51a72dab955ce69a3034de4d8382df2148e1b398f1d071ec163a04636b30da71b0d7c524f571f50b683e249a43d316ce4acb7b770970b154d51d3d73dcce4b6d0f8b306f0d5f674ae1f250d09099789c6f8b53e745efd06eb09911c2754b6bff1ed5d8da7d5d9e3f6a9173bfb5f8e729679c041319b9783c92a604a01a1303d7c15c48a5a9f1f8c3e38408e399e8e6f4356364f9495adefd98816a4f0e1d13fe6d505af32864f3803bad9604557823e40fe12775b9fe70b3941a0cf45ef666000790cde37bdc5d7ade86cb0ee21347105d4c78cc5b68d1e74a91cfefc0027b9348b469e24e1c01eabf1c4e1cd84ccec4fd1382f73234a296ddde14757104539d6534923ca23dbba51ecc46900f7a27baee29c7869cf98396ba3db4532ae643f3f65e35aec209c88be34a481fd94184545ae86a4eeca7aed5a470d21604a19e2bfeddd7edf5207d90ffc747559c1ae33a3800001aa6bc1a5d761490ca32e601544641b2d207bba5e62b87541df526335d0a594cd2d17b32c02147556f1ae758bf62c44aa21d7612a33ec36ebf8702cf2972ca59b1ca750925c5fc46500479dd38ee791d9262f3a10d8b4b5a7aa6f762ffa51f8767153c87fa482e11a9414641ee2ea547cdbf6043096fb5b628a189e3a2cc6f84b903c2dc932709165f765a990bc4b26ce7264bdc6682cbd78b4312b4d2c60a3579b0c435579daa8cc72aa6fa8b1436c4cab56a95b5f41b5d36bd7afeaeb73582d3f8fba9fc11ea62a0995793970d2e97d0bb8e8dc8aca0ac68361b74b182ee079dca24e9290fcb7cf10d8cfad0889140f456d93f2db25d0ff63735ad651bef3b1be271b92e3d05913ee458c869befcc11a6a3c20f524e9eac8d44f897b815eb497e3822b09288cbcda4685e3cb3bbcec0e7ec48a4b367f2301a43fabfc1827451f5b8f8e0b1209d5df9c46fce564b34dcfd94d6fc2ade951f921fdf5c8571cb39c5ba4d030bdbf53a9dfdff15ebf23d569a8be38cb589ad01e2496aabe885042c6df303c02aa256d2dc4df30f9d5f9b7c53b3cc5304ff5ccb28c41763e41e4fa016ea0f8ceef7c4c6444e1729402d2b8d47a125efed946614f3d58f046501772e5e687223e194a8ea844a2db44193dae94227bd60391189d0dccc4da44125b9960995545505ea39fe5b68af3459af5772275822aa03d9768c4f6f602b1256f0c40d3cad1f63230d9fa89b9534d73edabb9fe52bd2fdb9f2e882a5ff53122128b7e6ed24d35236783bdc21718f3747653ba7d20649a6aa211afcb2ab9775ea870a6e1a2ba9a9cc76717a27cdb12397b326961e605923ed7a857ef0d3e3f226fcfcc68af7a6fa9b70f67bf4cd5eed8d6bb98368a0b6078c8a5d1bf7b2a320973f0322ed279789e7bff7e689a51e448719e0def4507f52302b5e9cc43fc2859e4c8b75e627837f8914b9aab22f57431d50abb68596c5329f52a2702eb2b48d08d57098dd1de87a5fd323d27da92c3788557338a78e47cd9a3385e411c4f7e4884d85dc2c3da7acdd76b5b9970442b5a2c63863e4def3b12e2be849acdc86f5cd9bcc82ba65302ee5e972bcf963ca65f81f1e7d36abeed479206f3c7a88c2b8eae18840866ef8f4fac2984aa8ce93a8a8db46d56a0970fd71a8c92e3bdaf5a090d4a4b745ec016a679f8ca1d7d95b64684a5c090e0a7911cd01059b97ba986200f188a4a509a89773181e4b3eca29551ff9129c3 +Ciphertext = 066f41b75ce25ac456dc0e4c0aea74aaf821461e8c8f9951303b2e0061ee8ebfa2228cbb509eb3f0d4f73d35ad834d9a36ba7342df4a1af4755d82dae663f737ae1ee128d91d18b462826d19cb12f376075878f9fc85a89640f6a6ffacd1b69c2db92abc119c8f2f52ffe273b173ae6b620e4ef32c9f2139d93adb61de450b516a6607fb34dc1fb0a85fd9e7f844967a1a5de2050c46ab328865ba1d3cb79f6405cb1a4c9b9507e35fc42583fa8c74869cfc6d58f6b444f49ac997d268474c6f35314b9ad1a4ded5a41aa1ce4a40b1aeecfaaea72c5041f5b971fcf601813e63a07a8171e1afe62681c5d5e5c40a67fb8569caf2061bd00ec899441cb67eb27c240b0c2cd0fba7efcc574af20f15d28f727056918c5aba21a3f18e404b6fd12406ed0d1e329fb42bf0d4ef11ef1ed00eb6325e897ecc88be1984c5bca0ceae2fe2d5cca7b870d98c5d21163e64923c7bfe4a8565f0eeba25b53834633de56fa4f77e817f80a53f486f62410dd42fc3e1e45fe2800ad84be21312e01b7357b4cfbf79e8abf4cff9e5585bd2ac83586dfc7736ef0609dde12abd2df0b63b2b589781a334c085d04ed3704f6d9cca4dedb645986cb401b9f7e07a9b8249cb25d705910f1ddacf64cbba4e305732680606f84e5f7ef7e1f04bfff97e4ef1849d737cccfa636c2fdc19b1b7dce37a2f30500ba3615b2e8ca8b4aedcabcaf876dc65867f033345f89bcb68f86c2a18b03bc97ed9c47ed052128df84ba3cb08d36e3f2772a1e54db768987ec076989d6d4c1a052f5a12db53dae79b4461e3978d0dfb0a3a8e65e1f26f33271679d5789fc5176d3715fed46ba7270830038cf791d42a032547bd8bd3e7f2fe8882eccd55d53b4779645e5b4e819f3076c128617e3889dee15259f05d3b1841cb793815760eb715f8a3bf476d8a618f41b94424e9ed863d25f1ecb026cc18479696cf5a5214ba8a30e538fa7038760e26743a16d19612e9fcf02d287f8de28e3ad95ae825778385ac0bb2c8965e90b33221cf43bb6c7cc557651c06d60ba184deead44b1199a6d10483538c2a3a37560ada56308574f89552a63374a2c0f3caee712b7fd32d57a753eb8af40f9702537d3e39fbff78bed8655383bdee688b9155605cd92ad11d97f188f69ebf138fd982da743b7991953c05dc2a01cb52a8061af15f222bd234be2bcea1b9262ff466d9a0d0b6078ca360f522a3573f47356db02de7442dd9f2e8c38028b58e713d10f03e58c5a6250b3a5b4a312ba8f6dc67c344beea1b89a0bcfaf405f55e9b189a2ff75c9005ecfc613edf1656386ebe1cd5b34830ac467748095d6ae00f1e0c9db613f03c1f7174e07e9bb0cefba362b21e1e1105ab3828924d690cbfb04af5717fbd70a06f13592eee6bb26aab84ae30e3ca2def416fe3d2c958b74a73536751bde703415913cbdb8f02285cfc93502b5d3e7ea13d435ed9ea2997e974bb35d02248f96114c3e1e78e1ddae703904278cc71ed86db3e7ff1940730fc56d699901b0a9c50865cbe228d4455396c1daac5f6fb5fc8adbcc4e9c2732d1aa8cf95a2c08696fbbd45594f7d5716bf0840eb4108a817f5d4d7fa23ad37a5fb12419c10d5f24def5b1bc767f9d8b0a7d104a5f2161a78644f608cdcf14bd7c39aa2397cfb9ad3ef2768ac550092505280139c7ecf5b8839f4d781fdf454fec0444aafd5071ca455c84b1a069c6e16d87f28b8aed2d067c5b5ef06600dd81b7a6a09f5d3da7589ae7b6cc5123730e34ec2203b547703785e480b86176de6b8c8f5a7e5e21b03349db2f8b3a67a26d305eec63cca3070d089702791b5ea386a2979bcc7bb82b9b0fdaf019fabb659bb3883cb706431f8f008a9019aba14e6f3a56e4cf58d514564dc316697083d787fa9a461af032a95a92667f315738108c534b596e2d8637fdac2f10b5de7646d53a9a454a4c0b39200f1f515c7359cbf13bec6a8d79ddf3ecb7586ca87f9de1201ae8a60ffc4d015fdcff31be7c3b228d45b231bbd29c4b433ca22526f8bb36317d08b84aa02b5ae909260a50f384938bffb225ecec157511a7ab90b6ff584a0dcd4218e3c886ee774bb7281d9144ace0f9bef99dcee60622ed879ffc843c7cc22f44a1e37c1e415c8984c44bb73bf21f9a04455ab9b5cbb9f357549989e7d885ec47ec140488f587090ab049ac39b80b320666374fd7b3851f6744b88719cad12ee9c9013a30ede58b74da4fd2b93ba286977deb6ffc1ed609659d18a817028b6a73559d5a418a5d12b7761c48880d0f1ba56c2d3cb88b9429f4ebe7281049224714b9e67db185c932fbab04f7af0f62b59529f95334861fc04f7bcdd76a62e6025767df06fffdd083264b7e2dbf63419f4806431232976a5538a1205fa95c051e0d8de4874675649b9adac2fe6887c5751a94e74ae0763d1abe58933ccf3549f9d9f84883757ef4736333cffa2be54446f43fec2d330b9e27957cb4c4f66e7b67734b1a56744c554199fcbbe10d055867be33570a38da81d23985cb673b21c6aa318b2c092e09a36e022aec43d147e9500d67b157b73d3e10937214be952600e78bcbbf2a9add8065b8cc860246a0c147c56db3fb11d803a70b932020f10c93b468ba621719b1e838dd63fdb4f4a44bd9d9587c37263e15052f586cc0e1e32c63148c3126a9b8fc2c2e4850689e70618c12d1e4feaa3598256527bf30e571f58b4a71840d149e84553e10919fba5732e4b46ee4e5be49abb78a5bf6fad070fa47b4f4e043e1db8145beb3d3fce4416b5d9a3edca1eb23704b901585cee8a69aa446e035d945ea4e2cb5834eecf6045e6ba08a83da6e74229b2b44d1979f774958f189ceeedb290cc7879144207fb84aa9c4e156852caf09f08395c7e84cce19a6772db50f21d985d1fe1a8e852b5941bff04ad5d5be44720557b7d0c96d7170be59e26418137a0aef3414a3564497a11568234abf7ba67229a94fde532550ac695a860e73c4164243a4278b4e87dfa26d459382d77bcc65b568a8e456dc0383f7685f552b253b65aa61e11e454a28e30731ec9df60d18e827142a9aaf9e515abb4fb32d00e46cd57f3a39729426c073c21967fb873604cffc7179bbca214bbd4291582c0bf18d85acc51a963ae00cff500d475f37219932347129f2ee10d0fafbef391e7b54e9fd5792b5ce6f692f02052f635e9058c25ab3f973d74df8f5ba11001aa423fe7b1f9a45ec77fc7fd0a3670dab26c97e538438b92d7d4a640d17bc3512c854f2970a9f6a901e6cbbb19553f0208585dc11fe776b815460c167ff48605d6638d2abd87563463f04a10c2693971c1c957b27ab7c0e14b9764d8e2e64877300ab1dcb1fae42ef21c24c555507f99d1ae56c4148937c1dee59c27c6bda0e4c8df7c7866c251e101729fa4fa3f335b2d92c39d4d2d766ab51d4e99d3eea6393208abdfce2bfe2cd840b5030acdecb3a6d1aeb64236e9684818d5303c4a0eb9cdf38baeef8b8653d70cfd0f821fec496e76ed5de1ef05182d52c982b184268a28eaa5d39e88d9dea760a9a5d7a9e7b56b2062d1d4deaa871a229643f9af3ac26f015ae9d6bb959d54943445a506aeaad11e8ef312f07ad617285b743867937bf379b61c96e938cdf5bd321418acdec8bcbd8dc0d25a98c03e5f150808932cb64e048c44f4acdaa5eef521182b1802b5fd72af85058aa2e51a5cb8f389a4ae7416c228742149ecf1817a51b969821890aaf4b289fa643a615e6b6b7b8ed3cd4ee9141617f0eef2c8526a141d28c88604f8211e7cc549ac477030be67fcd71fcac613738d8f4287fe3eefffbbf934cc7761810bbd352f630a37c4c8060ad4c4261598458a70eb3c062d9ad2af88afbb5dd1456b25ee3c896be06f4f12a5a32d6b72a84e932a3aa70d42f35f7d8e5c465377efdfa0730c6591042b7466c45306d266c24a357df69e8e035540e91370cd67126d73604c3dd779201f7711af94e0729b1559d6777ea851855585aa5f7781cedf394913536fcdc2f594d4fe042db5f6e673a015de17d6c8f38ffcb6f7c1298721d6671d54dc564e81d5d1710cefbde0d2683aa38b62d64d289d076c53a837c29c85b48f39f7c1c5c77c51dc8f77bfe0ab40aa08d8ddc6e2bf9c3bfce07f865e9aec625b74100ef3eb6ddc572f8ea9f4addf074860fe5e03130cc15ea5afcbee3bd3d312f7ed67f53640431834a3246346253ee8ac71bde098a1141e705c43220436843c1d760544b552f7586c21833759f26e1cb9c00f544cb3dea46bfcbbe2150eaf0218b48a521f17baed6d7beed52486737c15d55f22248e0e96757c36b365d36db1548288871eb0f91b6c1228e9bfc9045dda8cfbcf3fad91b62e4f088b9bd780899a3e59138a9a3ec21f1220ae99597a4a59b2c27698887c7c6e4dc1c0fc387d5e365bd87187a4f4dce32f53febdf54721b42379450598493a7468aff41973fdabbb1acf2db2407f3954c3b07a1a841e4ca3c6992a6de1493c21d5b91ad5231af8e79c60873542df11437072c61abb0d9073a11db5fb03875d7e06117fe359b67709930e08e7d6b2163358cca0e6fcf234d0abf91936df7cf7e2035dfa35f17e11d9bd772b68a2657a707a20a606dfd7a3d89d4ad7512eda4fe4889b06bf7aed1b491f4afdf3ebabcee7431db4d15a820f3505ff7b45afc5e182449e3083b825f11d8a589b307feb818ecc9b20c57aa350b29a87a6702ac66331970a399e0712d471ee25ae4fc50e70ac900a8d6dba0473bb2311c405dec66e05e4fe61a6fba6abc3c616ec716409ade1d1ad8c26bc49c1676fedb04b5cf577c8a4cee885fe6b28a933e2dbe62856f4c81a5cb579dba920da86dce737ea3fc25019cd0d6c7c8c8adaef6f288a9dc4ae5aa465c1447572e4b4bf5e41be34ca8fe32b0f691eb8aaec2a969dc057744aced6d0e8e143768d4685c717e777555f176b3c038c749d0f4fba76bcfad668ba95d29607965f947769ee02ad8cb4b717b0b4449e1df6e80036adc7a1e81645e388af2914fa1416a54fe701c1ce1916669151da98327b0af9675a5fdfdbdc7915 +Tag = 2c75bf81d73c9e44bee5e3ab74be1df5 + +# test case 62 (pseudorandom inputs) partial = 1 -rrep = 1000 -rnd = f05d1f02827dc7a10c7db69614ad4fd7 - - +rrep = 10000 +rnd = 55c73321b33ec311f61145a0b612c469 [AesCcm] @@ -160,7 +528,7 @@ Tag = b4ac6bec93e8598e7f0dadbcea5b partial = 1 rrep = 1000 -rnd = ce7c7df92c0bfc567814477cbfe48588 +rnd = 90c1d23c66d83a0441e2309999822879 @@ -168,8 +536,8 @@ rnd = ce7c7df92c0bfc567814477cbfe48588 # test case from RFC 8439 2.8.2 # test case 1 -key = 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f -nonce = 070000004041424344454647 +Key = 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +Nonce = 070000004041424344454647 AuthData = 50515253c0c1c2c3c4c5c6c7 Plaintext = 4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e Ciphertext = d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116 @@ -177,4 +545,4 @@ Tag = 1ae10b594f09e26a7e902ecbd0600691 partial = 0 rrep = 1000 -rnd = 57bada7066d2febeba29b0ec55a32659 +rnd = 693a22c9e85dc3b2bbdb76204ea4056e diff --git a/unittest/lib/cng_imp_authenc.cpp b/unittest/lib/cng_imp_authenc.cpp index 08fe0ea..535adac 100644 --- a/unittest/lib/cng_imp_authenc.cpp +++ b/unittest/lib/cng_imp_authenc.cpp @@ -344,6 +344,13 @@ AuthEncImp::encrypt( return status; } + auto nonceSizes = getNonceSizes(); + if( nonceSizes.find( cbNonce ) == nonceSizes.end() ) + { + status = STATUS_NOT_SUPPORTED; + return status; + } + if( !state.inComputation ) { // Only init the authInfo if we are starting a new computation @@ -385,7 +392,6 @@ AuthEncImp::encrypt( return status; } - template<> NTSTATUS AuthEncImp::decrypt( @@ -408,20 +414,23 @@ AuthEncImp::decrypt( if( flags != 0 ) { status = STATUS_NOT_SUPPORTED; - goto cleanup; + return status; } + auto nonceSizes = getNonceSizes(); + if( nonceSizes.find( cbNonce ) == nonceSizes.end() ) + { + status = STATUS_NOT_SUPPORTED; + return status; + } + + authInfo.pbNonce = (PBYTE) pbNonce; authInfo.cbNonce = (ULONG) cbNonce; authInfo.pbAuthData = (PBYTE) pbAuthData; authInfo.cbAuthData = (ULONG) cbAuthData; authInfo.pbTag = (PBYTE) pbTag; authInfo.cbTag = (ULONG) cbTag; - //authInfo.pbMacContext = NULL; - //authInfo.cbMacContext = 0; - //authInfo.cbAAD = 0; - //authInfo.cbData = 0; - //authInfo.dwFlags = 0; ULONG res; status = CngDecryptFn( state.hKey, (PBYTE) pbSrc, (ULONG) cbData, &authInfo, NULL, 0, pbDst, (ULONG) cbData, &res, 0 ); @@ -438,7 +447,6 @@ AuthEncImp::decrypt( CHECK( res == cbData, "?" ); } -cleanup: return status; } diff --git a/unittest/lib/rsa32_implementations.cpp b/unittest/lib/rsa32_implementations.cpp index af8279d..99e243e 100644 --- a/unittest/lib/rsa32_implementations.cpp +++ b/unittest/lib/rsa32_implementations.cpp @@ -2945,6 +2945,12 @@ AuthEncImp::encrypt( goto cleanup; } + if( cbNonce != 12 ) + { + status = STATUS_NOT_SUPPORTED; + goto cleanup; + } + status = AesGcm ( &state.key, NULL, 16, @@ -2953,6 +2959,7 @@ AuthEncImp::encrypt( (PBYTE) pbAuthData, (ULONG) cbAuthData, pbTag, (ULONG) cbTag, ENCRYPT ); + CHECK( NT_SUCCESS( status ), "GCM encrypt failure" ); cleanup: @@ -2982,6 +2989,12 @@ AuthEncImp::decrypt( goto cleanup; } + if( cbNonce != 12 ) + { + status = STATUS_NOT_SUPPORTED; + goto cleanup; + } + status = AesGcm ( &state.key, NULL, 16, diff --git a/unittest/lib/sc_imp_pattern.cpp b/unittest/lib/sc_imp_pattern.cpp index 47357d6..1cf9204 100644 --- a/unittest/lib/sc_imp_pattern.cpp +++ b/unittest/lib/sc_imp_pattern.cpp @@ -874,7 +874,10 @@ AuthEncImp::getNonceSizes() { std::set res; - res.insert( 12 ); + for(int i = 1; i <= 256; ++i) + { + res.insert( i ); + } return res; } diff --git a/unittest/lib/testAuthEnc.cpp b/unittest/lib/testAuthEnc.cpp index 70b840f..fc7fb85 100644 --- a/unittest/lib/testAuthEnc.cpp +++ b/unittest/lib/testAuthEnc.cpp @@ -270,7 +270,7 @@ katAuthEncSingle( SIZE_T cbTag, ULONGLONG line) { - BYTE bufData[512]; + BYTE bufData[4096]; BYTE bufTag[32]; NTSTATUS status; @@ -333,24 +333,27 @@ testAuthEncRandom( AuthEncMultiImp * pImp, int rrep, PCBYTE pbResult, SIZE_T cbR std::sort( nonceSizes.begin(), nonceSizes.end() ); std::sort( tagSizes.begin(), tagSizes.end() ); - //iprint( "# sizes: %d, %d, %d\n", keySizes.size(), nonceSizes.size(), tagSizes.size() ); - // - //for( int i=0; i< tagSizes.size(); i++ ) - //{ - // iprint( "tag %d: %d\n", i, tagSizes[i] ); - //} - memset( buf, 0, sizeof( buf ) ); - for( int i=0; im_algorithmName == "AesGcm" && (rng.byte() & 1) ) + { + cbNonce = 12; + } + CHECK( cbKey <= bufSize && cbNonce <= bufSize && cbTag <= sizeof( tagBuf ), "??" ); + SIZE_T keyIdx = rng.sizet( bufSize - cbKey ); SIZE_T nonceIdx = rng.sizet( bufSize - cbNonce ); SIZE_T tagIdx = rng.sizet( bufSize - cbTag ); @@ -363,6 +366,8 @@ testAuthEncRandom( AuthEncMultiImp * pImp, int rrep, PCBYTE pbResult, SIZE_T cbR rng.randomSubRange( bufSize, &srcIdx, &cbData ); SIZE_T dstIdx = rng.sizet( bufSize - cbData ); + pImp->setKey( &buf[keyIdx], cbKey ); + pImp->encrypt( &buf[nonceIdx], cbNonce, &buf[authDataIdx], cbAuthData, &buf[srcIdx], tmp1, cbData,