#include "precomp.h"
extern SYMCRYPT_ALIGN_AT( 256) BYTE SymCryptAesInvSbox[256];
extern SYMCRYPT_ALIGN_AT(1024) BYTE SymCryptAesSboxMatrixMult[4][256][4];
extern SYMCRYPT_ALIGN_AT(1024) BYTE SymCryptAesInvSboxMatrixMult[4][256][4];
extern SYMCRYPT_ALIGN_AT(1024) BYTE SymCryptAesInvMatrixMult[4][256][4];
#define IS_UINT32_ALIGNED( __p ) ((((intptr_t)__p) & 3) == 0)
#define NEED_ALIGN (!(SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_ARM | SYMCRYPT_CPU_ARM64))
VOID
SYMCRYPT_CALL
SymCryptAes4SboxC(
_In_reads_(4) PCBYTE pIn,
_Out_writes_(4) PBYTE pOut )
{
pOut[0] = SymCryptAesSboxMatrixMult[0][pIn[0]][1];
pOut[1] = SymCryptAesSboxMatrixMult[0][pIn[1]][1];
pOut[2] = SymCryptAesSboxMatrixMult[0][pIn[2]][1];
pOut[3] = SymCryptAesSboxMatrixMult[0][pIn[3]][1];
}
VOID
SYMCRYPT_CALL
SymCryptAesCreateDecryptionRoundKeyC(
_In_reads_(16) PCBYTE pEncryptionRoundKey,
_Out_writes_(16) PBYTE pDecryptionRoundKey )
{
int i;
PBYTE p = pDecryptionRoundKey;
PCBYTE q = pEncryptionRoundKey;
for( i=0; i<4; i++ ) {
*(UINT32 *)p =
*(UINT32 *)SymCryptAesInvMatrixMult[0][q[0]] ^
*(UINT32 *)SymCryptAesInvMatrixMult[1][q[1]] ^
*(UINT32 *)SymCryptAesInvMatrixMult[2][q[2]] ^
*(UINT32 *)SymCryptAesInvMatrixMult[3][q[3]];
p += 4;
q += 4;
}
}
SYMCRYPT_NOINLINE
VOID
SYMCRYPT_CALL
SymCryptAesEncryptC(
_In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey,
_In_reads_(SYMCRYPT_AES_BLOCK_SIZE) PCBYTE pbPlaintext,
_Out_writes_(SYMCRYPT_AES_BLOCK_SIZE) PBYTE pbCiphertext )
{
SYMCRYPT_ALIGN BYTE state[4][4] = { 0 };
SYMCRYPT_ALIGN UINT32 state2[4] = { 0 };
const BYTE (*keyPtr)[4][4];
const BYTE (*keyLimit)[4][4];
#if NEED_ALIGN
SYMCRYPT_ALIGN BYTE alignBuffer[SYMCRYPT_AES_BLOCK_SIZE];
#endif
#if NEED_ALIGN
if( !(IS_UINT32_ALIGNED( pbPlaintext ) & IS_UINT32_ALIGNED( pbCiphertext )) ) {
memcpy( alignBuffer, pbPlaintext, SYMCRYPT_AES_BLOCK_SIZE );
SymCryptAesEncrypt( pExpandedKey, alignBuffer, alignBuffer );
memcpy( pbCiphertext, alignBuffer, SYMCRYPT_AES_BLOCK_SIZE );
SymCryptWipeKnownSize( alignBuffer, sizeof( alignBuffer ) );
return;
}
#endif
SYMCRYPT_CHECK_MAGIC( pExpandedKey );
keyPtr = &pExpandedKey->RoundKey[0];
keyLimit = &pExpandedKey->lastEncRoundKey[0];
*((UINT32 *) &state[0][0]) = *(UINT32 *) (*keyPtr)[0] ^ *(UINT32 *) &pbPlaintext[0];
*((UINT32 *) &state[1][0]) = *(UINT32 *) (*keyPtr)[1] ^ *(UINT32 *) &pbPlaintext[4];
*((UINT32 *) &state[2][0]) = *(UINT32 *) (*keyPtr)[2] ^ *(UINT32 *) &pbPlaintext[8];
*((UINT32 *) &state[3][0]) = *(UINT32 *) (*keyPtr)[3] ^ *(UINT32 *) &pbPlaintext[12];
keyPtr += 1;
while (keyPtr < keyLimit)
{
state2[0] = *((UINT32 *) &SymCryptAesSboxMatrixMult[0][ state[0][0] ]);
state2[3] = *((UINT32 *) &SymCryptAesSboxMatrixMult[1][ state[0][1] ]);
state2[2] = *((UINT32 *) &SymCryptAesSboxMatrixMult[2][ state[0][2] ]);
state2[1] = *((UINT32 *) &SymCryptAesSboxMatrixMult[3][ state[0][3] ]);
state2[1] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[0][ state[1][0] ]);
state2[0] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[1][ state[1][1] ]);
state2[3] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[2][ state[1][2] ]);
state2[2] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[3][ state[1][3] ]);
state2[2] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[0][ state[2][0] ]);
state2[1] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[1][ state[2][1] ]);
state2[0] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[2][ state[2][2] ]);
state2[3] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[3][ state[2][3] ]);
state2[3] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[0][ state[3][0] ]);
state2[2] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[1][ state[3][1] ]);
state2[1] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[2][ state[3][2] ]);
state2[0] ^= *((UINT32 *) &SymCryptAesSboxMatrixMult[3][ state[3][3] ]);
*((UINT32 *) &state[0][0]) = *(UINT32 *) (*keyPtr)[0] ^ state2[0];
*((UINT32 *) &state[1][0]) = *(UINT32 *) (*keyPtr)[1] ^ state2[1];
*((UINT32 *) &state[2][0]) = *(UINT32 *) (*keyPtr)[2] ^ state2[2];
*((UINT32 *) &state[3][0]) = *(UINT32 *) (*keyPtr)[3] ^ state2[3];
keyPtr += 1;
}
state2[0] = (UINT32) SymCryptAesSboxMatrixMult[0][ state[0][0] ][1];
state2[3] = (UINT32) SymCryptAesSboxMatrixMult[0][ state[0][1] ][1] << 8;
state2[2] = (UINT32) SymCryptAesSboxMatrixMult[0][ state[0][2] ][1] << 16;
state2[1] = (UINT32) SymCryptAesSboxMatrixMult[0][ state[0][3] ][1] << 24;
state2[1] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[1][0] ][1];
state2[0] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[1][1] ][1] << 8;
state2[3] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[1][2] ][1] << 16;
state2[2] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[1][3] ][1] << 24;
state2[2] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[2][0] ][1];
state2[1] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[2][1] ][1] << 8;
state2[0] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[2][2] ][1] << 16;
state2[3] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[2][3] ][1] << 24;
state2[3] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[3][0] ][1];
state2[2] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[3][1] ][1] << 8;
state2[1] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[3][2] ][1] << 16;
state2[0] |= (UINT32) SymCryptAesSboxMatrixMult[0][ state[3][3] ][1] << 24;
*((UINT32 *) &pbCiphertext[0 ]) = *(UINT32 *) (*keyPtr)[0] ^ state2[0];
*((UINT32 *) &pbCiphertext[4 ]) = *(UINT32 *) (*keyPtr)[1] ^ state2[1];
*((UINT32 *) &pbCiphertext[8 ]) = *(UINT32 *) (*keyPtr)[2] ^ state2[2];
*((UINT32 *) &pbCiphertext[12]) = *(UINT32 *) (*keyPtr)[3] ^ state2[3];
SymCryptWipeKnownSize( state, sizeof( state ) );
SymCryptWipeKnownSize( state2, sizeof( state2 ) );
return;
}
SYMCRYPT_NOINLINE
VOID
SYMCRYPT_CALL
SymCryptAesDecryptC(
_In_ PCSYMCRYPT_AES_EXPANDED_KEY pExpandedKey,
_In_reads_(SYMCRYPT_AES_BLOCK_SIZE) PCBYTE pbCiphertext,
_Out_writes_(SYMCRYPT_AES_BLOCK_SIZE) PBYTE pbPlaintext )
{
SYMCRYPT_ALIGN BYTE state[4][4] = { 0 };
SYMCRYPT_ALIGN UINT32 state2[4] = { 0 };
const BYTE (*keyPtr)[4][4];
const BYTE (*keyLimit)[4][4];
#if NEED_ALIGN
SYMCRYPT_ALIGN BYTE alignBuffer[SYMCRYPT_AES_BLOCK_SIZE];
#endif
#if NEED_ALIGN
if( !(IS_UINT32_ALIGNED( pbPlaintext ) & IS_UINT32_ALIGNED( pbCiphertext )) ) {
memcpy( alignBuffer, pbCiphertext, SYMCRYPT_AES_BLOCK_SIZE );
SymCryptAesDecrypt( pExpandedKey, alignBuffer, alignBuffer );
memcpy( pbPlaintext, alignBuffer, SYMCRYPT_AES_BLOCK_SIZE );
SymCryptWipeKnownSize( alignBuffer, sizeof( alignBuffer ) );
return;
}
#endif
SYMCRYPT_CHECK_MAGIC( pExpandedKey );
keyPtr = &pExpandedKey->lastEncRoundKey[0];
keyLimit = &pExpandedKey->lastDecRoundKey[0];
*((UINT32 *) &state[0][0]) = *(UINT32 *) (*keyPtr)[0] ^ *(UINT32 *) &pbCiphertext[0];
*((UINT32 *) &state[1][0]) = *(UINT32 *) (*keyPtr)[1] ^ *(UINT32 *) &pbCiphertext[4];
*((UINT32 *) &state[2][0]) = *(UINT32 *) (*keyPtr)[2] ^ *(UINT32 *) &pbCiphertext[8];
*((UINT32 *) &state[3][0]) = *(UINT32 *) (*keyPtr)[3] ^ *(UINT32 *) &pbCiphertext[12];
keyPtr += 1;
while (keyPtr < keyLimit)
{
state2[0] = *((UINT32 *) &SymCryptAesInvSboxMatrixMult[0][ state[0][0] ]);
state2[1] = *((UINT32 *) &SymCryptAesInvSboxMatrixMult[1][ state[0][1] ]);
state2[2] = *((UINT32 *) &SymCryptAesInvSboxMatrixMult[2][ state[0][2] ]);
state2[3] = *((UINT32 *) &SymCryptAesInvSboxMatrixMult[3][ state[0][3] ]);
state2[1] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[0][ state[1][0] ]);
state2[2] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[1][ state[1][1] ]);
state2[3] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[2][ state[1][2] ]);
state2[0] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[3][ state[1][3] ]);
state2[2] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[0][ state[2][0] ]);
state2[3] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[1][ state[2][1] ]);
state2[0] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[2][ state[2][2] ]);
state2[1] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[3][ state[2][3] ]);
state2[3] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[0][ state[3][0] ]);
state2[0] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[1][ state[3][1] ]);
state2[1] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[2][ state[3][2] ]);
state2[2] ^= *((UINT32 *) &SymCryptAesInvSboxMatrixMult[3][ state[3][3] ]);
*((UINT32 *) &state[0][0]) = *(UINT32 *) (*keyPtr)[0] ^ state2[0];
*((UINT32 *) &state[1][0]) = *(UINT32 *) (*keyPtr)[1] ^ state2[1];
*((UINT32 *) &state[2][0]) = *(UINT32 *) (*keyPtr)[2] ^ state2[2];
*((UINT32 *) &state[3][0]) = *(UINT32 *) (*keyPtr)[3] ^ state2[3];
keyPtr += 1;
}
state2[0] = (UINT32) SymCryptAesInvSbox[ state[0][0] ];
state2[1] = (UINT32) SymCryptAesInvSbox[ state[0][1] ] << 8;
state2[2] = (UINT32) SymCryptAesInvSbox[ state[0][2] ] << 16;
state2[3] = (UINT32) SymCryptAesInvSbox[ state[0][3] ] << 24;
state2[1] |= (UINT32) SymCryptAesInvSbox[ state[1][0] ];
state2[2] |= (UINT32) SymCryptAesInvSbox[ state[1][1] ] << 8;
state2[3] |= (UINT32) SymCryptAesInvSbox[ state[1][2] ] << 16;
state2[0] |= (UINT32) SymCryptAesInvSbox[ state[1][3] ] << 24;
state2[2] |= (UINT32) SymCryptAesInvSbox[ state[2][0] ];
state2[3] |= (UINT32) SymCryptAesInvSbox[ state[2][1] ] << 8;
state2[0] |= (UINT32) SymCryptAesInvSbox[ state[2][2] ] << 16;
state2[1] |= (UINT32) SymCryptAesInvSbox[ state[2][3] ] << 24;
state2[3] |= (UINT32) SymCryptAesInvSbox[ state[3][0] ];
state2[0] |= (UINT32) SymCryptAesInvSbox[ state[3][1] ] << 8;
state2[1] |= (UINT32) SymCryptAesInvSbox[ state[3][2] ] << 16;
state2[2] |= (UINT32) SymCryptAesInvSbox[ state[3][3] ] << 24;
*((UINT32 *) &pbPlaintext[0 ]) = *(UINT32 *) (*keyPtr)[0] ^ state2[0];
*((UINT32 *) &pbPlaintext[4 ]) = *(UINT32 *) (*keyPtr)[1] ^ state2[1];
*((UINT32 *) &pbPlaintext[8 ]) = *(UINT32 *) (*keyPtr)[2] ^ state2[2];
*((UINT32 *) &pbPlaintext[12]) = *(UINT32 *) (*keyPtr)[3] ^ state2[3];
SymCryptWipeKnownSize( state, sizeof( state ) );
SymCryptWipeKnownSize( state2, sizeof( state2 ) );
return;
}
VOID
SYMCRYPT_CALL
SymCryptAesEcbEncryptC(
_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 )
{
SymCryptAesEncryptC( pExpandedKey, pbSrc, pbDst );
pbSrc += SYMCRYPT_AES_BLOCK_SIZE;
pbDst += SYMCRYPT_AES_BLOCK_SIZE;
cbData -= SYMCRYPT_AES_BLOCK_SIZE;
}
}
VOID
SYMCRYPT_CALL
SymCryptAesEcbDecryptC(
_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 )
{
SymCryptAesDecryptC( pExpandedKey, pbSrc, pbDst );
pbSrc += SYMCRYPT_AES_BLOCK_SIZE;
pbDst += SYMCRYPT_AES_BLOCK_SIZE;
cbData -= SYMCRYPT_AES_BLOCK_SIZE;
}
}