#include "precomp.h"
const SYMCRYPT_BLOCKCIPHER SymCryptAesBlockCipherNoOpt = {
&SymCryptAesExpandKey,
#if SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_ARM
&SymCryptAesEncryptAsm,
&SymCryptAesDecryptAsm,
#else
&SymCryptAesEncryptC,
&SymCryptAesDecryptC,
#endif
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
SYMCRYPT_AES_BLOCK_SIZE,
sizeof( SYMCRYPT_AES_EXPANDED_KEY ),
};
VOID
SYMCRYPT_CALL
SymCryptAes4Sbox( _In_reads_(4) PCBYTE pIn, _Out_writes_(4) PBYTE pOut, BOOL UseSimd )
{
#if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64
if( UseSimd )
{
SymCryptAes4SboxXmm( pIn, pOut );
} else {
SymCryptAes4SboxC( pIn, pOut );
}
#elif SYMCRYPT_CPU_ARM64
if( UseSimd )
{
SymCryptAes4SboxNeon( pIn, pOut );
} else {
SymCryptAes4SboxC( pIn, pOut );
}
#else
UNREFERENCED_PARAMETER( UseSimd );
SymCryptAes4SboxC( pIn, pOut );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesCreateDecryptionRoundKey(
_In_reads_(16) PCBYTE pEncryptionRoundKey,
_Out_writes_(16) PBYTE pDecryptionRoundKey,
BOOL UseSimd )
{
#if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64
if( UseSimd )
{
SymCryptAesCreateDecryptionRoundKeyXmm( pEncryptionRoundKey, pDecryptionRoundKey );
} else {
SymCryptAesCreateDecryptionRoundKeyC( pEncryptionRoundKey, pDecryptionRoundKey );
}
#elif SYMCRYPT_CPU_ARM64
if( UseSimd )
{
SymCryptAesCreateDecryptionRoundKeyNeon( pEncryptionRoundKey, pDecryptionRoundKey );
} else {
SymCryptAesCreateDecryptionRoundKeyC( pEncryptionRoundKey, pDecryptionRoundKey );
}
#else
UNREFERENCED_PARAMETER( UseSimd );
SymCryptAesCreateDecryptionRoundKeyC( pEncryptionRoundKey, pDecryptionRoundKey );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesEncrypt(
_In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey,
_In_reads_(SYMCRYPT_AES_BLOCK_SIZE) PCBYTE pbSrc,
_Out_writes_(SYMCRYPT_AES_BLOCK_SIZE) PBYTE pbDst )
{
#if SYMCRYPT_CPU_AMD64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_CODE ) )
{
SymCryptAesEncryptXmm( pExpandedKey, pbSrc, pbDst );
} else {
SymCryptAesEncryptAsm( pExpandedKey, pbSrc, pbDst );
}
#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 )
{
SymCryptAesEncryptXmm( pExpandedKey, pbSrc, pbDst );
SymCryptRestoreXmm( &SaveData );
} else {
SymCryptAesEncryptAsm( pExpandedKey, pbSrc, pbDst );
}
#elif SYMCRYPT_CPU_ARM
SymCryptAesEncryptAsm( pExpandedKey, pbSrc, pbDst );
#elif SYMCRYPT_CPU_ARM64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) )
{
SymCryptAesEncryptNeon( pExpandedKey, pbSrc, pbDst );
} else {
SymCryptAesEncryptC( pExpandedKey, pbSrc, pbDst );
}
#else
SymCryptAesEncryptC( pExpandedKey, pbSrc, pbDst );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesDecrypt(
_In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey,
_In_reads_(SYMCRYPT_AES_BLOCK_SIZE) PCBYTE pbSrc,
_Out_writes_(SYMCRYPT_AES_BLOCK_SIZE) PBYTE pbDst )
{
#if SYMCRYPT_CPU_AMD64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_CODE ) )
{
SymCryptAesDecryptXmm( pExpandedKey, pbSrc, pbDst );
} else {
SymCryptAesDecryptAsm( pExpandedKey, pbSrc, pbDst );
}
#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 )
{
SymCryptAesDecryptXmm( pExpandedKey, pbSrc, pbDst );
SymCryptRestoreXmm( &SaveData );
} else {
SymCryptAesDecryptAsm( pExpandedKey, pbSrc, pbDst );
}
#elif SYMCRYPT_CPU_ARM
SymCryptAesDecryptAsm( pExpandedKey, pbSrc, pbDst );
#elif SYMCRYPT_CPU_ARM64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) )
{
SymCryptAesDecryptNeon( pExpandedKey, pbSrc, pbDst );
} else {
SymCryptAesDecryptC( pExpandedKey, pbSrc, pbDst );
}
#else
SymCryptAesDecryptC( pExpandedKey, pbSrc, pbDst );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesCbcEncrypt(
_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 ) )
{
SymCryptAesCbcEncryptXmm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
} else {
SymCryptAesCbcEncryptAsm( 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 )
{
SymCryptAesCbcEncryptXmm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
SymCryptRestoreXmm( &SaveData );
} else {
SymCryptAesCbcEncryptAsm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
}
#elif SYMCRYPT_CPU_ARM
SymCryptAesCbcEncryptAsm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
#elif SYMCRYPT_CPU_ARM64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) )
{
SymCryptAesCbcEncryptNeon( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
} else {
SymCryptCbcEncrypt( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
}
#else
SymCryptCbcEncrypt( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesCbcDecrypt(
_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 ) )
{
SymCryptAesCbcDecryptXmm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
} else {
SymCryptAesCbcDecryptAsm( 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 )
{
SymCryptAesCbcDecryptXmm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
SymCryptRestoreXmm( &SaveData );
} else {
SymCryptAesCbcDecryptAsm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
}
#elif SYMCRYPT_CPU_ARM
SymCryptAesCbcDecryptAsm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
#elif SYMCRYPT_CPU_ARM64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) )
{
SymCryptAesCbcDecryptNeon( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
} else {
SymCryptCbcDecrypt( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
}
#else
SymCryptCbcDecrypt( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesEcbEncrypt(
_In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey,
_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 ) )
{
SymCryptAesEcbEncryptXmm( pExpandedKey, pbSrc, pbDst, cbData );
} else {
SymCryptAesEcbEncryptAsm( pExpandedKey, 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 )
{
SymCryptAesEcbEncryptXmm( pExpandedKey, pbSrc, pbDst, cbData );
SymCryptRestoreXmm( &SaveData );
} else {
SymCryptAesEcbEncryptAsm( pExpandedKey, pbSrc, pbDst, cbData );
}
#elif SYMCRYPT_CPU_ARM
SymCryptAesEcbEncryptAsm( pExpandedKey, pbSrc, pbDst, cbData );
#elif SYMCRYPT_CPU_ARM64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) )
{
SymCryptAesEcbEncryptNeon( pExpandedKey, pbSrc, pbDst, cbData );
} else {
SymCryptAesEcbEncryptC( pExpandedKey, pbSrc, pbDst, cbData );
}
#else
SymCryptAesEcbEncryptC( pExpandedKey, pbSrc, pbDst, cbData );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesEcbDecrypt(
_In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey,
_In_reads_( cbData ) PCBYTE pbSrc,
_Out_writes_( cbData ) PBYTE pbDst,
SIZE_T cbData )
{
while( cbData >= SYMCRYPT_AES_BLOCK_SIZE )
{
SymCryptAesDecrypt( pExpandedKey, pbSrc, pbDst );
pbSrc += SYMCRYPT_AES_BLOCK_SIZE;
pbDst += SYMCRYPT_AES_BLOCK_SIZE;
cbData -= SYMCRYPT_AES_BLOCK_SIZE;
}
}
VOID
SYMCRYPT_CALL
SymCryptAesCbcMac(
_In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey,
_Inout_updates_( SYMCRYPT_AES_BLOCK_SIZE ) PBYTE pbChainingValue,
_In_reads_( cbData ) PCBYTE pbData,
SIZE_T cbData )
{
#if SYMCRYPT_CPU_AMD64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_CODE ) )
{
SymCryptAesCbcMacXmm( pExpandedKey, pbChainingValue, pbData, cbData );
} else {
SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE );
SymCryptCbcMac( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbData, 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 )
{
SymCryptAesCbcMacXmm( pExpandedKey, pbChainingValue, pbData, cbData );
SymCryptRestoreXmm( &SaveData );
} else {
SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE );
SymCryptCbcMac( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbData, cbData );
}
#elif SYMCRYPT_CPU_ARM64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) )
{
SymCryptAesCbcMacNeon( pExpandedKey, pbChainingValue, pbData, cbData );
} else {
SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE );
SymCryptCbcMac( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbData, cbData );
}
#else
SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE );
SymCryptCbcMac( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbData, cbData );
#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 );
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 );
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 );
SymCryptCtrMsb32( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesCtrMsb64(
_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 ) )
{
SymCryptAesCtrMsb64Xmm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
} else {
SymCryptAesCtrMsb64Asm( 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 )
{
SymCryptAesCtrMsb64Xmm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
SymCryptRestoreXmm( &SaveData );
} else {
SymCryptAesCtrMsb64Asm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
}
#elif SYMCRYPT_CPU_ARM
SymCryptAesCtrMsb64Asm( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
#elif SYMCRYPT_CPU_ARM64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES ) )
{
SymCryptAesCtrMsb64Neon( pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
} else {
SymCryptCtrMsb64( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
}
#else
SYMCRYPT_ASSERT( SymCryptAesBlockCipherNoOpt.blockSize == SYMCRYPT_AES_BLOCK_SIZE );
SymCryptCtrMsb64( &SymCryptAesBlockCipherNoOpt, pExpandedKey, pbChainingValue, pbSrc, pbDst, cbData );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesGcmEncryptPartOnePass(
_Inout_ PSYMCRYPT_GCM_STATE pState,
_In_reads_( cbData ) PCBYTE pbSrc,
_Out_writes_( cbData ) PBYTE pbDst,
SIZE_T cbData )
{
SIZE_T bytesToProcess;
#if SYMCRYPT_CPU_AMD64
SYMCRYPT_EXTENDED_SAVE_DATA SaveData;
#endif
SYMCRYPT_ASSERT( (pState->cbData & SYMCRYPT_GCM_BLOCK_MOD_MASK) == pState->bytesInMacBlock );
SYMCRYPT_ASSERT( pState->cbData + cbData <= SYMCRYPT_GCM_MAX_DATA_SIZE );
pState->cbData += cbData;
if( pState->bytesInMacBlock > 0 )
{
bytesToProcess = SYMCRYPT_MIN( cbData, SYMCRYPT_GCM_BLOCK_SIZE - pState->bytesInMacBlock );
SymCryptXorBytes(
pbSrc,
&pState->keystreamBlock[pState->bytesInMacBlock],
&pState->macBlock[pState->bytesInMacBlock],
bytesToProcess );
memcpy( pbDst, &pState->macBlock[pState->bytesInMacBlock], bytesToProcess );
pbSrc += bytesToProcess;
pbDst += bytesToProcess;
cbData -= bytesToProcess;
pState->bytesInMacBlock += bytesToProcess;
if( pState->bytesInMacBlock == SYMCRYPT_GCM_BLOCK_SIZE )
{
SymCryptGHashAppendData( &pState->pKey->ghashKey,
&pState->ghashState,
&pState->macBlock[0],
SYMCRYPT_GCM_BLOCK_SIZE );
pState->bytesInMacBlock = 0;
}
}
if( cbData >= SYMCRYPT_GCM_BLOCK_SIZE )
{
bytesToProcess = cbData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
#if SYMCRYPT_CPU_AMD64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_VAES_256_CODE ) &&
(bytesToProcess >= GCM_YMM_MINBLOCKS * SYMCRYPT_GCM_BLOCK_SIZE) &&
SymCryptSaveYmm( &SaveData ) == SYMCRYPT_NO_ERROR )
{
SymCryptAesGcmEncryptStitchedYmm_2048(
&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
&pState->pKey->ghashKey.table[0],
&pState->ghashState,
pbSrc,
pbDst,
bytesToProcess );
SymCryptRestoreYmm( &SaveData );
} else {
SymCryptAesGcmEncryptStitchedXmm(
&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
&pState->pKey->ghashKey.table[0],
&pState->ghashState,
pbSrc,
pbDst,
bytesToProcess );
}
#elif SYMCRYPT_CPU_X86
SymCryptAesGcmEncryptStitchedXmm(
&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
(PSYMCRYPT_GF128_ELEMENT)&pState->pKey->ghashKey.tableSpace[pState->pKey->ghashKey.tableOffset],
&pState->ghashState,
pbSrc,
pbDst,
bytesToProcess );
#elif SYMCRYPT_CPU_ARM64
SymCryptAesGcmEncryptStitchedNeon(
&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
&pState->pKey->ghashKey.table[0],
&pState->ghashState,
pbSrc,
pbDst,
bytesToProcess );
#else
SymCryptAesCtrMsb32(&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
pbSrc,
pbDst,
cbData );
SymCryptGHashAppendData(&pState->pKey->ghashKey,
&pState->ghashState,
pbDst,
cbData );
#endif
pbSrc += bytesToProcess;
pbDst += bytesToProcess;
cbData -= bytesToProcess;
}
if( cbData > 0 )
{
SymCryptWipeKnownSize( &pState->keystreamBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
SymCryptAesCtrMsb32(&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
&pState->keystreamBlock[0],
&pState->keystreamBlock[0],
SYMCRYPT_GCM_BLOCK_SIZE );
SymCryptXorBytes( &pState->keystreamBlock[0], pbSrc, &pState->macBlock[0], cbData );
memcpy( pbDst, &pState->macBlock[0], cbData );
pState->bytesInMacBlock = cbData;
}
}
VOID
SYMCRYPT_CALL
SymCryptAesGcmDecryptPartOnePass(
_Inout_ PSYMCRYPT_GCM_STATE pState,
_In_reads_( cbData ) PCBYTE pbSrc,
_Out_writes_( cbData ) PBYTE pbDst,
SIZE_T cbData )
{
SIZE_T bytesToProcess;
#if SYMCRYPT_CPU_AMD64
SYMCRYPT_EXTENDED_SAVE_DATA SaveData;
#endif
SYMCRYPT_ASSERT( (pState->cbData & SYMCRYPT_GCM_BLOCK_MOD_MASK) == pState->bytesInMacBlock );
SYMCRYPT_ASSERT( pState->cbData + cbData <= SYMCRYPT_GCM_MAX_DATA_SIZE );
pState->cbData += cbData;
if( pState->bytesInMacBlock > 0 )
{
bytesToProcess = SYMCRYPT_MIN( cbData, SYMCRYPT_GCM_BLOCK_SIZE - pState->bytesInMacBlock );
memcpy( &pState->macBlock[pState->bytesInMacBlock], pbSrc, bytesToProcess );
SymCryptXorBytes(
&pState->keystreamBlock[pState->bytesInMacBlock],
&pState->macBlock[pState->bytesInMacBlock],
pbDst,
bytesToProcess );
pbSrc += bytesToProcess;
pbDst += bytesToProcess;
cbData -= bytesToProcess;
pState->bytesInMacBlock += bytesToProcess;
if( pState->bytesInMacBlock == SYMCRYPT_GCM_BLOCK_SIZE )
{
SymCryptGHashAppendData( &pState->pKey->ghashKey,
&pState->ghashState,
&pState->macBlock[0],
SYMCRYPT_GCM_BLOCK_SIZE );
pState->bytesInMacBlock = 0;
}
}
if( cbData >= SYMCRYPT_GCM_BLOCK_SIZE )
{
bytesToProcess = cbData & SYMCRYPT_GCM_BLOCK_ROUND_MASK;
SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
#if SYMCRYPT_CPU_AMD64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_VAES_256_CODE ) &&
(bytesToProcess >= GCM_YMM_MINBLOCKS * SYMCRYPT_GCM_BLOCK_SIZE) &&
SymCryptSaveYmm( &SaveData ) == SYMCRYPT_NO_ERROR )
{
SymCryptAesGcmDecryptStitchedYmm_2048(
&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
&pState->pKey->ghashKey.table[0],
&pState->ghashState,
pbSrc,
pbDst,
bytesToProcess );
SymCryptRestoreYmm( &SaveData );
} else {
SymCryptAesGcmDecryptStitchedXmm(
&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
&pState->pKey->ghashKey.table[0],
&pState->ghashState,
pbSrc,
pbDst,
bytesToProcess );
}
#elif SYMCRYPT_CPU_X86
SymCryptAesGcmDecryptStitchedXmm(
&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
(PSYMCRYPT_GF128_ELEMENT)&pState->pKey->ghashKey.tableSpace[pState->pKey->ghashKey.tableOffset],
&pState->ghashState,
pbSrc,
pbDst,
bytesToProcess );
#elif SYMCRYPT_CPU_ARM64
SymCryptAesGcmDecryptStitchedNeon(
&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
&pState->pKey->ghashKey.table[0],
&pState->ghashState,
pbSrc,
pbDst,
bytesToProcess );
#else
SymCryptGHashAppendData(&pState->pKey->ghashKey,
&pState->ghashState,
pbSrc,
cbData );
SymCryptAesCtrMsb32(&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
pbSrc,
pbDst,
cbData );
#endif
pbSrc += bytesToProcess;
pbDst += bytesToProcess;
cbData -= bytesToProcess;
}
if( cbData > 0 )
{
SymCryptWipeKnownSize( &pState->keystreamBlock[0], SYMCRYPT_GCM_BLOCK_SIZE );
SYMCRYPT_ASSERT( pState->pKey->pBlockCipher->blockSize == SYMCRYPT_GCM_BLOCK_SIZE );
SymCryptAesCtrMsb32(&pState->pKey->blockcipherKey.aes,
&pState->counterBlock[0],
&pState->keystreamBlock[0],
&pState->keystreamBlock[0],
SYMCRYPT_GCM_BLOCK_SIZE );
memcpy( &pState->macBlock[0], pbSrc, cbData );
SymCryptXorBytes(
&pState->keystreamBlock[0],
&pState->macBlock[0],
pbDst,
cbData );
pState->bytesInMacBlock = cbData;
}
}
VOID
SYMCRYPT_CALL
SymCryptAesGcmEncryptPart(
_Inout_ PSYMCRYPT_GCM_STATE pState,
_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_PCLMULQDQ_CODE ) )
{
SymCryptAesGcmEncryptPartOnePass( pState, pbSrc, pbDst, cbData );
} else {
SymCryptGcmEncryptPartTwoPass( pState, pbSrc, pbDst, cbData );
}
#elif SYMCRYPT_CPU_X86
SYMCRYPT_EXTENDED_SAVE_DATA SaveData;
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_PCLMULQDQ_CODE ) &&
SymCryptSaveXmm( &SaveData ) == SYMCRYPT_NO_ERROR )
{
SymCryptAesGcmEncryptPartOnePass( pState, pbSrc, pbDst, cbData );
SymCryptRestoreXmm( &SaveData );
} else {
SymCryptGcmEncryptPartTwoPass( pState, pbSrc, pbDst, cbData );
}
#elif SYMCRYPT_CPU_ARM64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES | SYMCRYPT_CPU_FEATURE_NEON_PMULL ) )
{
SymCryptAesGcmEncryptPartOnePass( pState, pbSrc, pbDst, cbData );
} else {
SymCryptGcmEncryptPartTwoPass( pState, pbSrc, pbDst, cbData );
}
#else
SymCryptGcmEncryptPartTwoPass( pState, pbSrc, pbDst, cbData );
#endif
}
VOID
SYMCRYPT_CALL
SymCryptAesGcmDecryptPart(
_Inout_ PSYMCRYPT_GCM_STATE pState,
_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_PCLMULQDQ_CODE ) )
{
SymCryptAesGcmDecryptPartOnePass( pState, pbSrc, pbDst, cbData );
} else {
SymCryptGcmDecryptPartTwoPass( pState, pbSrc, pbDst, cbData );
}
#elif SYMCRYPT_CPU_X86
SYMCRYPT_EXTENDED_SAVE_DATA SaveData;
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURES_FOR_AESNI_PCLMULQDQ_CODE ) &&
SymCryptSaveXmm( &SaveData ) == SYMCRYPT_NO_ERROR )
{
SymCryptAesGcmDecryptPartOnePass( pState, pbSrc, pbDst, cbData );
SymCryptRestoreXmm( &SaveData );
} else {
SymCryptGcmDecryptPartTwoPass( pState, pbSrc, pbDst, cbData );
}
#elif SYMCRYPT_CPU_ARM64
if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_AES | SYMCRYPT_CPU_FEATURE_NEON_PMULL ) )
{
SymCryptAesGcmDecryptPartOnePass( pState, pbSrc, pbDst, cbData );
} else {
SymCryptGcmDecryptPartTwoPass( pState, pbSrc, pbDst, cbData );
}
#else
SymCryptGcmDecryptPartTwoPass( pState, pbSrc, pbDst, cbData );
#endif
}