⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xts.c

📁 功能强大的开源加密软件。使用最新ieee-p1619标准
💻 C
📖 第 1 页 / 共 2 页
字号:
// to the LAST 8 bytes of the buffer for the whitening values. Note that the generated 128-bit whitening values
// are stored in memory as a sequence of 64-bit integers in reverse order. For descriptions of the input
// parameters, see EncryptBufferXTS().
static void GenerateWhiteningValues (unsigned __int64 *bufPtr64,
							TC_LARGEST_COMPILER_UINT length,
							const UINT64_STRUCT *startDataUnitNo,
							unsigned int startBlock,
							unsigned __int8 *ks2,
							int cipher)
{
	unsigned int block;
	unsigned int endBlock;
	unsigned __int8 byteBufUnitNo [BYTES_PER_XTS_BLOCK];
	unsigned __int8 whiteningValue [BYTES_PER_XTS_BLOCK];
	unsigned __int64 *whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;
	unsigned __int8 finalCarry;
	unsigned __int64 *const finalInt64WhiteningValuePtr = whiteningValuePtr64 + sizeof (whiteningValue) / sizeof (*whiteningValuePtr64) - 1;
	TC_LARGEST_COMPILER_UINT blockCount, dataUnitNo;

	dataUnitNo = startDataUnitNo->Value;

	blockCount = length / BYTES_PER_XTS_BLOCK;

	// 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.
	*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	*((unsigned __int64 *) byteBufUnitNo + 1) = 0;

	// Generate the whitening values. 
	// When length > ENCRYPTION_DATA_UNIT_SIZE, this can be parallelized (one data unit per core)
	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);

		// Process all blocks in this data unit
		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				whiteningValuePtr64 = (unsigned __int64 *) whiteningValue;

				*bufPtr64-- = *whiteningValuePtr64++;
				*bufPtr64-- = *whiteningValuePtr64;

				blockCount--;
			}

			// Derive the next whitening value

			whiteningValuePtr64 = finalInt64WhiteningValuePtr;

#if BYTE_ORDER == LITTLE_ENDIAN

			// Little-endian platforms (Intel, AMD, etc.)

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

			*whiteningValuePtr64-- <<= 1;

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

			*whiteningValuePtr64 <<= 1;

#else
			// Big-endian platforms (PowerPC, Motorola, etc.)

			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;
		}

		startBlock = 0;

		dataUnitNo++;

		// Convert the 64-bit data unit number into a little-endian 16-byte array. 
		*((unsigned __int64 *) byteBufUnitNo) = LE64 (dataUnitNo);
	}

	FAST_ERASE64 (whiteningValue, sizeof(whiteningValue));
}
#endif	// #if 0


#else	// XTS_LOW_RESOURCE_VERSION


#if BYTE_ORDER == BIG_ENDIAN
#error XTS_LOW_RESOURCE_VERSION is not compatible with big-endian platforms
#endif 


// Increases a 64-bit value by one in a way compatible with non-64-bit environments/platforms
static void IncUint64Struct (UINT64_STRUCT *uint64Struct)
{
#ifdef TC_NO_COMPILER_INT64
	if (!++uint64Struct->LowPart)
	{
		uint64Struct->HighPart++;
	}
#else
	uint64Struct->Value++;
#endif
}


// Converts a 64-bit unsigned integer (passed as two 32-bit integers for compatibility with non-64-bit
// environments/platforms) into a little-endian 16-byte array.
static void Uint64ToLE16ByteArray (unsigned __int8 *byteBuf, unsigned __int32 highInt32, unsigned __int32 lowInt32)
{
	unsigned __int32 *bufPtr32 = (unsigned __int32 *) byteBuf;

	*bufPtr32++ = lowInt32;
	*bufPtr32++ = highInt32;

	// We're converting a 64-bit number into a little-endian 16-byte array so we can zero the last 8 bytes
	*bufPtr32++ = 0;
	*bufPtr32 = 0;
}


// Generates and XORs XTS whitening values into blocks in the buffer.
// For descriptions of the input parameters, see EncryptBufferXTS().
static void WhiteningPass (unsigned __int8 *buffer,
							TC_LARGEST_COMPILER_UINT length,
							const UINT64_STRUCT *startDataUnitNo,
							unsigned int startBlock,
							unsigned __int8 *ks2,
							int cipher)
{
	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 subsequent whitening values and XOR each whitening value into corresponding
		// ciphertext/plaintext block

		for (block = 0; block < endBlock; block++)
		{
			if (block >= startBlock)
			{
				whiteningValuePtr32 = (unsigned __int32 *) whiteningValue;

				// XOR the whitening value into this ciphertext/plaintext block
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32++;
				*bufPtr32++ ^= *whiteningValuePtr32;

				blockCount--;
			}

			// 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;
		}

		startBlock = 0;

		// Increase the data unit number by one
		IncUint64Struct (&dataUnitNo);

		// 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));
}


// length: number of bytes to encrypt; may be larger than one data unit and must be divisible by the cipher block size
// ks: the primary key schedule
// ks2: the secondary key schedule
// dataUnitNo: The sequential number of the data unit with which the buffer starts.
// startCipherBlockNo: The sequential number of the first plaintext block to encrypt inside the data unit dataUnitNo.
//                     When encrypting the data unit from its first block, startCipherBlockNo is 0. 
//                     The startCipherBlockNo value applies only to the first data unit in the buffer; each successive
//                     data unit is encrypted from its first block. The start of the buffer does not have to be
//                     aligned with the start of a data unit. If it is aligned, startCipherBlockNo must be 0; if it
//                     is not aligned, startCipherBlockNo must reflect the misalignment accordingly.
void EncryptBufferXTS (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *dataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	TC_LARGEST_COMPILER_UINT blockCount;
	unsigned __int8 *bufPtr = buffer;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	// Pre-whitening (all plaintext blocks in the buffer)
	WhiteningPass (buffer, length, dataUnitNo, startCipherBlockNo, ks2, cipher);

	// Encrypt all plaintext blocks in the buffer
	for (blockCount = 0; blockCount < length / BYTES_PER_XTS_BLOCK; blockCount++)
	{
		EncipherBlock (cipher, bufPtr, ks);
		bufPtr += BYTES_PER_XTS_BLOCK;
	}

	// Post-whitening (all ciphertext blocks in the buffer)
	WhiteningPass (buffer, length, dataUnitNo, startCipherBlockNo, ks2, cipher);
}


// For descriptions of the input parameters, see EncryptBufferXTS().
void DecryptBufferXTS (unsigned __int8 *buffer,
					   TC_LARGEST_COMPILER_UINT length,
					   const UINT64_STRUCT *dataUnitNo,
					   unsigned int startCipherBlockNo,
					   unsigned __int8 *ks,
					   unsigned __int8 *ks2,
					   int cipher)
{
	TC_LARGEST_COMPILER_UINT blockCount;
	unsigned __int8 *bufPtr = buffer;

	if (length % BYTES_PER_XTS_BLOCK)
		TC_THROW_FATAL_EXCEPTION;

	WhiteningPass (buffer, length, dataUnitNo, startCipherBlockNo, ks2, cipher);

	for (blockCount = 0; blockCount < length / BYTES_PER_XTS_BLOCK; blockCount++)
	{
		DecipherBlock (cipher, bufPtr, ks);
		bufPtr += BYTES_PER_XTS_BLOCK;
	}

	WhiteningPass (buffer, length, dataUnitNo, startCipherBlockNo, ks2, cipher);
}

#endif	// XTS_LOW_RESOURCE_VERSION

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -