Ejemplo n.º 1
0
void DecryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo)
{
	/* Deprecated/legacy */

	int cipher = EAGetFirstCipher (cryptoInfo->ea);
	int cipherCount = EAGetCipherCount (cryptoInfo->ea);
	unsigned __int8 *p = buffer;
	unsigned __int8 *ks = cryptoInfo->ks;
	unsigned __int8 i[8];
	unsigned __int8 t[16];
	unsigned __int64 b;

	*(unsigned __int64 *)i = BE64(blockIndex);

	if (length % 16)
		GST_THROW_FATAL_EXCEPTION;

	// Note that the maximum supported volume size is 8589934592 GB  (i.e., 2^63 bytes).

	for (b = 0; b < length >> 4; b++)
	{
		Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx);
		Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t);

		if (cipherCount > 1)
		{
			// Cipher cascade
			ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea);

			for (cipher = EAGetLastCipher (cryptoInfo->ea);
				cipher != 0;
				cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher))
			{
				ks -= CipherGetKeyScheduleSize (cipher);
				DecipherBlock (cipher, p, ks);
			}
		}
		else
		{
			DecipherBlock (cipher, p, ks);
		}

		Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t);

		p += 16;

		if (i[7] != 0xff)
			i[7]++;
		else
			*(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 );
	}

	FAST_ERASE64 (t, sizeof(t));
}
Ejemplo n.º 2
0
void DecryptBufferLRW64 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo)
{
	/* Deprecated/legacy */

	int cipher = EAGetFirstCipher (cryptoInfo->ea);
	unsigned __int8 *p = buffer;
	unsigned __int8 *ks = cryptoInfo->ks;
	unsigned __int8 i[8];
	unsigned __int8 t[8];
	unsigned __int64 b;

	*(unsigned __int64 *)i = BE64(blockIndex);

	if (length % 8)
		GST_THROW_FATAL_EXCEPTION;

	for (b = 0; b < length >> 3; b++)
	{
		Gf64MulTab (i, t, &cryptoInfo->gf_ctx);
		Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t);

		DecipherBlock (cipher, p, ks);

		Xor64 ((unsigned __int64 *)p, (unsigned __int64 *)t);

		p += 8;

		if (i[7] != 0xff)
			i[7]++;
		else
			*(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 );
	}

	FAST_ERASE64 (t, sizeof(t));
}
Ejemplo n.º 3
0
void DecipherBlocks (int cipher, void *dataPtr, void *ks, size_t blockCount)
{
	byte *data = dataPtr;
	size_t blockSize = CipherGetBlockSize (cipher);
	while (blockCount-- > 0)
	{
		DecipherBlock (cipher, data, ks);
		data += blockSize;
	}
}
Ejemplo n.º 4
0
void DecipherBlocks (int cipher, void *dataPtr, void *ks, size_t blockCount)
{
	byte *data = dataPtr;
#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
	KFLOATING_SAVE floatingPointState;
#endif

	if (cipher == AES
		&& (blockCount & (32 - 1)) == 0
		&& IsAesHwCpuSupported()
#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
		&& NT_SUCCESS (KeSaveFloatingPointState (&floatingPointState))
#endif
		)
	{
		while (blockCount > 0)
		{
			aes_hw_cpu_decrypt_32_blocks ((byte *) ks + sizeof (aes_encrypt_ctx), data);

			data += 32 * 16;
			blockCount -= 32;
		}

#if defined (TC_WINDOWS_DRIVER) && !defined (_WIN64)
		KeRestoreFloatingPointState (&floatingPointState);
#endif
	}
	else
	{
		size_t blockSize = CipherGetBlockSize (cipher);
		while (blockCount-- > 0)
		{
			DecipherBlock (cipher, data, ks);
			data += blockSize;
		}
	}
}
Ejemplo n.º 5
0
static void
DecryptBufferCBC (unsigned __int32 *data,
		 unsigned int len,
		 unsigned __int8 *ks,
		 unsigned __int32 *iv,
 		 unsigned __int32 *whitening,
		 int ea,
		 int cipher)
{

	/* IMPORTANT: This function has been deprecated (legacy) */

	unsigned __int32 bufIV[4];
	unsigned __int64 i;
	unsigned __int32 ct[4];
	int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher);

	if (len % blockSize)
		GST_THROW_FATAL_EXCEPTION;

	//  IV
	bufIV[0] = iv[0];
	bufIV[1] = iv[1];
	if (blockSize == 16)
	{
		bufIV[2] = iv[2];
		bufIV[3] = iv[3];
	}

	// Decrypt each block
	for (i = 0; i < len/blockSize; i++)
	{
		// Dewhitening
		data[0] ^= whitening[0];
		data[1] ^= whitening[1];
		if (blockSize == 16)
		{
			data[2] ^= whitening[0];
			data[3] ^= whitening[1];
		}

		// CBC
		ct[0] = data[0];
		ct[1] = data[1];
		if (blockSize == 16)
		{
			ct[2] = data[2];
			ct[3] = data[3];
		}

		if (ea != 0)
		{
			// Outer-CBC
			ks += EAGetKeyScheduleSize (ea);
			for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher))
			{
				ks -= CipherGetKeyScheduleSize (cipher);
				DecipherBlock (cipher, data, ks);
			}
		}
		else
		{
			// CBC/inner-CBC
			DecipherBlock (cipher, data, ks);
		}

		// CBC
		data[0] ^= bufIV[0];
		data[1] ^= bufIV[1];
		bufIV[0] = ct[0];
		bufIV[1] = ct[1];
		if (blockSize == 16)
		{
			data[2] ^= bufIV[2];
			data[3] ^= bufIV[3];
			bufIV[2] = ct[2];
			bufIV[3] = ct[3];
		}

		data += blockSize / sizeof(*data);
	}
}
Ejemplo n.º 6
0
// Encrypts or decrypts all blocks in the buffer in XTS mode. For descriptions of the input parameters,
// see the 64-bit version of EncryptBufferXTS().
static void EncryptDecryptBufferXTS32 (const unsigned __int8 *buffer,
							TC_LARGEST_COMPILER_UINT length,
							const UINT64_STRUCT *startDataUnitNo,
							unsigned int startBlock,
							unsigned __int8 *ks,
							unsigned __int8 *ks2,
							int cipher,
							BOOL decryption)
{
	TC_LARGEST_COMPILER_UINT blockCount;
	UINT64_STRUCT dataUnitNo;
	unsigned int block;
	unsigned int endBlock;
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int32 *bufPtr32 = (unsigned __int32 *) buffer;
	unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
	unsigned __int8 finalCarry;
	unsigned __int32 *const finalDwordWhiteningValuePtr = whiteningValuePtr32 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr32) - 1;

	// Store the 64-bit data unit number in a way compatible with non-64-bit environments/platforms
	dataUnitNo.HighPart = startDataUnitNo->HighPart;
	dataUnitNo.LowPart = startDataUnitNo->LowPart;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// (Passed as two 32-bit integers for compatibility with non-64-bit environments/platforms.)
	Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);

	// Generate whitening values for all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		memcpy (whiteningValue, byteBufUnitNo, BYTES_PER_XTS_BLOCK);
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate (and apply) subsequent whitening values for blocks in this data unit and
		// encrypt/decrypt all relevant blocks in this data unit
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;

				// Whitening
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32 ^= *whiteningValuePtr32;

				bufPtr32 -= BYTES_PER_XTS_BLOCK / sizeof (*bufPtr32) - 1;

				// Actual encryption/decryption
				if (decryption)
					DecipherBlock (cipher, bufPtr32, ks);
				else
					EncipherBlock (cipher, bufPtr32, ks);

				whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;

				// Whitening
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32;
			}

			// Derive the next whitening value

			finalCarry = 0;

			for (whiteningValuePtr32 = finalDwordWhiteningValuePtr;
				whiteningValuePtr32 >= (unsigned __int32 *) whiteningValue;
				whiteningValuePtr32--)
			{
				if (*whiteningValuePtr32 & 0x80000000)	// If the following shift results in a carry
				{
					if (whiteningValuePtr32 != finalDwordWhiteningValuePtr)	// If not processing the highest double word
					{
						// A regular carry
						*(whiteningValuePtr32 + 1) |= 1;
					}
					else 
					{
						// The highest byte shift will result in a carry
						finalCarry = 135;
					}
				}

				*whiteningValuePtr32 <<= 1;
			}

			whiteningValue[0] ^= finalCarry;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;

		// Increase the data unit number by one
		if (!++dataUnitNo.LowPart)
		{
			dataUnitNo.HighPart++;
		}

		// Convert the 64-bit data unit number into a little-endian 16-byte array. 
		Uint64ToLE16ByteArray (byteBufUnitNo, dataUnitNo.HighPart, dataUnitNo.LowPart);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
}
Ejemplo n.º 7
0
// Optimized for encryption algorithms not supporting intra-data-unit parallelization
static void DecryptBufferXTSNonParallel (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *startDataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
	unsigned __int64 *bufPtr = (unsigned __int64 *) buffer;
	unsigned int startBlock = startCipherBlockNo, endBlock, block;
	TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;

	// Convert the 64-bit data unit number into a little-endian 16-byte array. 
	// Note that as we are converting a 64-bit number into a 16-byte array we can always zero the last 8 bytes.
	dataUnitNo = startDataUnitNo->Value;
	*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	*((unsigned __int64 *) byteBufUnitNo + 1) = 0;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// Process all blocks in the buffer
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT)
			endBlock = startBlock + (unsigned int) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT;

		whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;

		// Encrypt the data unit number using the secondary key (in order to generate the first 
		// whitening value for this data unit)
		*whiteningValuePtr64 = *((unsigned __int64 *) byteBufUnitNo);
		*(whiteningValuePtr64 + 1) = 0;
		EncipherBlock (cipher, whiteningValue, ks2);

		// Generate (and apply) subsequent whitening values for blocks in this data unit and
		// decrypt all relevant blocks in this data unit
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				// Post-whitening
				*bufPtr++ ^= *whiteningValuePtr64++;
				*bufPtr-- ^= *whiteningValuePtr64--;

				// Actual decryption
				DecipherBlock (cipher, bufPtr, ks);

				// Pre-whitening
				*bufPtr++ ^= *whiteningValuePtr64++;
				*bufPtr++ ^= *whiteningValuePtr64;
			}
			else
				whiteningValuePtr64++;

			// Derive the next whitening value

#if BYTE_ORDER == LITTLE_ENDIAN

			// Little-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x8000000000000000) ?
				135 : 0;

			*whiteningValuePtr64-- <<= 1;

			if (*whiteningValuePtr64 & 0x8000000000000000)
				*(whiteningValuePtr64 + 1) |= 1;	

			*whiteningValuePtr64 <<= 1;

#else
			// Big-endian platforms

			finalCarry = 
				(*whiteningValuePtr64 & 0x80) ?
				135 : 0;

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);

			whiteningValuePtr64--;

			if (*whiteningValuePtr64 & 0x80)
				*(whiteningValuePtr64 + 1) |= 0x0100000000000000;	

			*whiteningValuePtr64 = LE64 (LE64 (*whiteningValuePtr64) << 1);
#endif

			whiteningValue[0] ^= finalCarry;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;
		dataUnitNo++;
		*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	}

	FAST_ERASE64 (whiteningValue, sizeof (whiteningValue));
}
Ejemplo n.º 8
0
static void DecryptBufferXTS8Byte (unsigned __int8 *buffer,
					GST_LARGEST_COMPILER_UINT length,
					const UINT64_STRUCT *startDataUnitNo,
					unsigned int startCipherBlockNo,
					unsigned __int8 *ks,
					unsigned __int8 *ks2,
					int cipher)
{
	unsigned __int8 finalCarry;
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK_SMALL];
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK_SMALL];
	unsigned __int32 *whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;
	unsigned __int32 *bufPtr = (unsigned __int32 *) buffer;
	unsigned __int32 startBlock = startCipherBlockNo, endBlock, block;
	GST_LARGEST_COMPILER_UINT blockCount;
	UINT64_STRUCT dataUnitNo;
	unsigned __int8 xor_ks[MAX_EXPANDED_KEY];

	dataUnitNo.LowPart = startDataUnitNo->LowPart;
	dataUnitNo.HighPart = startDataUnitNo->HighPart;

	*((unsigned __int32 *) byteBufUnitNo) = (unsigned __int32) LE32 (dataUnitNo.LowPart);
	*((unsigned __int32 *) byteBufUnitNo + 1) = (unsigned __int32) LE32 (dataUnitNo.HighPart);

	if (length % BYTES_PER_XTS_BLOCK_SMALL)
		GST_THROW_FATAL_EXCEPTION;

	blockCount = length / BYTES_PER_XTS_BLOCK_SMALL;

	memcpy(xor_ks, ks, CipherGetKeyScheduleSize(cipher));
	
	while (blockCount > 0)
	{
		if (blockCount < BLOCKS_PER_XTS_DATA_UNIT_SMALL)
			endBlock = startBlock + (unsigned __int32) blockCount;
		else
			endBlock = BLOCKS_PER_XTS_DATA_UNIT_SMALL;

		whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;

		//Encrypt data unit using the second key to generate the first whitening value
		*whiteningValuePtr32 = *((unsigned __int32 *) byteBufUnitNo);
		*(whiteningValuePtr32+1) = *((unsigned __int32 *) byteBufUnitNo+1);
		EncipherBlock (cipher, whiteningValue, ks2);

		//XOR ks with the current DataUnitNo
		XorKeySchedule(cipher, ks, xor_ks, byteBufUnitNo, 8);

		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				//Post-whitening
				*bufPtr++ ^= *whiteningValuePtr32++;
				*bufPtr-- ^= *whiteningValuePtr32--;

				//Actual decryption
				DecipherBlock (cipher, bufPtr, xor_ks);

				//Pre-whitening
				*bufPtr++ ^= *whiteningValuePtr32++;
				*bufPtr++ ^= *whiteningValuePtr32;
			}
			else
				whiteningValuePtr32++;

			//Derive the next whitening value

#if BYTE_ORDER == LITTLE_ENDIAN

			//Little-endian platforms

			finalCarry = (*whiteningValuePtr32 & 0x80000000) ? 135 : 0;

			*whiteningValuePtr32-- <<= 1;

			if (*whiteningValuePtr32 & 0x80000000)
				*(whiteningValuePtr32 + 1) |= 1;

			*whiteningValuePtr32 <<= 1;
#else
			//Big-endian platforms
			finalCarry = (*whiteningValuePtr32 & 0x80) ? 135 : 0);

			*whiteningValuePtr32 = LE32 (LE32 (*whiteningValuePtr32) << 1);

			whiteningValuePtr32--;

			if (*whiteningValuePtr32 & 0x80)
				*(whiteningValuePtr32 + 1) |= 0x1000000;

			*whiteningValuePtr32 = LE32 (LE32 (*whiteningValuePtr32) << 1);
#endif

			whiteningValue[0] ^= finalCarry;
		}

		blockCount -= endBlock - startBlock;
		startBlock = 0;
		if (!++dataUnitNo.LowPart)
			dataUnitNo.HighPart++;
		*((unsigned __int32 *) byteBufUnitNo) = (unsigned __int32) LE32 (dataUnitNo.LowPart);
		*((unsigned __int32 *) byteBufUnitNo+1) = (unsigned __int32) LE32 (dataUnitNo.HighPart);
	}

	FAST_ERASE32 (whiteningValue, sizeof (whiteningValue));
}