17#if defined(CRYPTOPP_DEBUG)
23#if defined(__SSE2__) || defined(_M_X64)
24# include <emmintrin.h>
27#if defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
28# if (CRYPTOPP_ARM_NEON_HEADER) || (CRYPTOPP_ARM_ASIMD_AVAILABLE)
33#if defined(__ALTIVEC__)
37ANONYMOUS_NAMESPACE_BEGIN
41#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
44using CryptoPP::XTS_Mode;
45using CryptoPP::Threefish512;
47void Modes_TestInstantiations()
49 XTS_Mode<AES>::Encryption m0;
50 XTS_Mode<AES>::Decryption m1;
51 XTS_Mode<AES>::Encryption m2;
52 XTS_Mode<AES>::Decryption m3;
54#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
55 XTS_Mode<Threefish512>::Encryption m4;
56 XTS_Mode<Threefish512>::Decryption m5;
61inline void XorBuffer(
byte *output,
const byte *input,
const byte *mask,
size_t count)
65#if defined(CRYPTOPP_DISABLE_ASM)
66 xorbuf(output, input, mask, count);
68#elif defined(__SSE2__) || defined(_M_X64)
69 for (
size_t i=0; i<count; i+=16)
75#elif defined(__aarch32__) || defined(__aarch64__) || defined(_M_ARM64)
76 for (
size_t i=0; i<count; i+=16)
77 vst1q_u8(output+i, veorq_u8(vld1q_u8(input+i), vld1q_u8(mask+i)));
79#elif defined(__ALTIVEC__)
80 for (
size_t i=0; i<count; i+=16)
84 xorbuf(output, input, mask, count);
88inline void XorBuffer(
byte *buf,
const byte *mask,
size_t count)
90 XorBuffer(buf, buf, mask, count);
94inline void GF_Double(
byte *out,
const byte* in,
unsigned int len)
96#if defined(CRYPTOPP_WORD128_AVAILABLE)
98 for (
size_t i=0, idx=0; i<len/16; ++i, idx+=16)
101 word128 y = (x >> 127); x = (x << 1) + carry;
105#elif defined(_M_X64) || defined(_M_ARM64) || defined(_LP64) || defined(__LP64__)
107 for (
size_t i=0, idx=0; i<len/8; ++i, idx+=8)
110 word64 y = (x >> 63); x = (x << 1) + carry;
116 for (
size_t i=0, idx=0; i<len/4; ++i, idx+=4)
119 word32 y = (x >> 31); x = (x << 1) + carry;
125#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
138 const size_t LEIDX = 16-1;
146 const size_t LEIDX = 32-1;
155 const size_t LEIDX = 64-1;
164 const size_t LEIDX = 128-1;
166 k[LEIDX-126] ^= 0x00;
167 k[LEIDX-127] ^= 0x43;
186inline void GF_Double(
byte *inout,
unsigned int len)
188 GF_Double(inout, inout, len);
191ANONYMOUS_NAMESPACE_END
197#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
199 if (length < 16 || length > 128 || !
IsPowerOf2(length))
200 throw InvalidArgument(AlgorithmName() +
": block size of underlying block cipher is not valid");
204 throw InvalidArgument(AlgorithmName() +
": block size of underlying block cipher is not 16");
220 const size_t klen = length/2;
221 AccessBlockCipher().
SetKey(key+0, klen, params);
222 AccessTweakCipher().
SetKey(key+klen, klen, params);
227 const byte *iv = GetIVAndThrowIfInvalid(params, ivLength);
234 std::memcpy(m_xregister, m_register, ivLength);
235 GetTweakCipher().ProcessBlock(m_xregister);
241 PutWord<word64>(
false, order, iv, sector);
242 std::memset(iv+8, 0x00, iv.
size()-8);
245 std::memcpy(m_xregister, iv, iv.
size());
246 GetTweakCipher().ProcessBlock(m_xregister);
249void XTS_ModeBase::ResizeBuffers()
251 BlockOrientedCipherModeBase::ResizeBuffers();
252 m_xworkspace.
New(GetBlockCipher().
BlockSize()*ParallelBlocks);
253 m_xregister.
New(GetBlockCipher().
BlockSize()*ParallelBlocks);
266 enum { lastParallelBlock = ParallelBlocks-1 };
267 const unsigned int blockSize = GetBlockCipher().BlockSize();
268 const size_t parallelSize = blockSize*ParallelBlocks;
271 while (length >= parallelSize)
274 GF_Double(m_xregister+1*blockSize, m_xregister+0*blockSize, blockSize);
275 GF_Double(m_xregister+2*blockSize, m_xregister+1*blockSize, blockSize);
276 GF_Double(m_xregister+3*blockSize, m_xregister+2*blockSize, blockSize);
278 if (ParallelBlocks > 4)
280 GF_Double(m_xregister+4*blockSize, m_xregister+3*blockSize, blockSize);
281 GF_Double(m_xregister+5*blockSize, m_xregister+4*blockSize, blockSize);
282 GF_Double(m_xregister+6*blockSize, m_xregister+5*blockSize, blockSize);
283 GF_Double(m_xregister+7*blockSize, m_xregister+6*blockSize, blockSize);
285 if (ParallelBlocks > 8)
287 GF_Double(m_xregister+8*blockSize, m_xregister+7*blockSize, blockSize);
288 GF_Double(m_xregister+9*blockSize, m_xregister+8*blockSize, blockSize);
289 GF_Double(m_xregister+10*blockSize, m_xregister+9*blockSize, blockSize);
290 GF_Double(m_xregister+11*blockSize, m_xregister+10*blockSize, blockSize);
294 XorBuffer(m_xworkspace, inString, m_xregister, parallelSize);
297 GetBlockCipher().AdvancedProcessBlocks(m_xworkspace, m_xregister,
301 GF_Double(m_xregister+0, m_xregister+lastParallelBlock*blockSize, blockSize);
303 inString += parallelSize;
304 outString += parallelSize;
305 length -= parallelSize;
309 while (ParallelBlocks == 12 && length >= blockSize*4)
312 GF_Double(m_xregister+1*blockSize, m_xregister+0*blockSize, blockSize);
313 GF_Double(m_xregister+2*blockSize, m_xregister+1*blockSize, blockSize);
314 GF_Double(m_xregister+3*blockSize, m_xregister+2*blockSize, blockSize);
317 XorBuffer(m_xworkspace, inString, m_xregister, blockSize*4);
320 GetBlockCipher().AdvancedProcessBlocks(m_xworkspace, m_xregister,
324 GF_Double(m_xregister+0, m_xregister+3*blockSize, blockSize);
326 inString += blockSize*4;
327 outString += blockSize*4;
328 length -= blockSize*4;
332 while (ParallelBlocks == 8 && length >= blockSize*2)
335 GF_Double(m_xregister+1*blockSize, m_xregister+0*blockSize, blockSize);
338 XorBuffer(m_xworkspace, inString, m_xregister, blockSize*2);
341 GetBlockCipher().AdvancedProcessBlocks(m_xworkspace, m_xregister,
345 GF_Double(m_xregister+0, m_xregister+1*blockSize, blockSize);
347 inString += blockSize*2;
348 outString += blockSize*2;
349 length -= blockSize*2;
356 XorBuffer(m_xworkspace, inString, m_xregister, blockSize);
359 GetBlockCipher().ProcessBlock(m_xworkspace);
362 XorBuffer(outString, m_xworkspace, m_xregister, blockSize);
365 GF_Double(m_xregister, blockSize);
367 inString += blockSize;
368 outString += blockSize;
379 throw InvalidArgument(
"XTS: message is too short for ciphertext stealing");
382 return ProcessLastPlainBlock(outString, outLength, inString, inLength);
384 return ProcessLastCipherBlock(outString, outLength, inString, inLength);
387size_t XTS_ModeBase::ProcessLastPlainBlock(
byte *outString,
size_t outLength,
const byte *inString,
size_t inLength)
392 const unsigned int blockSize = GetBlockCipher().BlockSize();
393 const size_t blocks = inLength / blockSize;
394 const size_t tail = inLength % blockSize;
395 outLength = inLength;
406 const size_t head = (blocks-1)*blockSize;
410 inString += head; inLength -= head;
416 XorBuffer(m_xworkspace, inString, m_xregister, blockSize);
419 GetBlockCipher().ProcessBlock(m_xworkspace);
422 XorBuffer(outString, m_xworkspace, m_xregister, blockSize);
425 GF_Double(m_xregister, blockSize);
429 inString += blockSize;
430 outString += blockSize;
431 const size_t len = inLength-blockSize;
434 std::memcpy(m_xworkspace, inString, len);
436 std::memcpy(outString, outString-blockSize, len);
438 std::memcpy(m_xworkspace+len, outString-blockSize+len, blockSize-len);
441 XorBuffer(m_xworkspace, m_xregister, blockSize);
444 GetBlockCipher().ProcessBlock(m_xworkspace);
447 XorBuffer(outString-blockSize, m_xworkspace, m_xregister, blockSize);
452size_t XTS_ModeBase::ProcessLastCipherBlock(
byte *outString,
size_t outLength,
const byte *inString,
size_t inLength)
457 const unsigned int blockSize = GetBlockCipher().BlockSize();
458 const size_t blocks = inLength / blockSize;
459 const size_t tail = inLength % blockSize;
460 outLength = inLength;
471 const size_t head = (blocks-1)*blockSize;
475 inString += head; inLength -= head;
478 #define poly1 (m_xregister+0*blockSize)
479 #define poly2 (m_xregister+1*blockSize)
480 GF_Double(poly2, poly1, blockSize);
484 inString += blockSize;
485 outString += blockSize;
486 const size_t len = inLength-blockSize;
489 XorBuffer(m_xworkspace, inString-blockSize, poly2, blockSize);
492 GetBlockCipher().ProcessBlock(m_xworkspace);
495 XorBuffer(m_xworkspace, poly2, blockSize);
498 std::memcpy(outString-blockSize, inString, len);
500 std::memcpy(outString, m_xworkspace, len);
502 std::memcpy(outString-blockSize+len, m_xworkspace+len, blockSize-len);
506 inString -= blockSize;
507 outString -= blockSize;
510 XorBuffer(m_xworkspace, outString, poly1, blockSize);
513 GetBlockCipher().ProcessBlock(m_xworkspace);
516 XorBuffer(outString, m_xworkspace, poly1, blockSize);
#define M128_CAST(x)
Clang workaround.
#define CONST_M128_CAST(x)
Clang workaround.
Class file for the AES cipher (Rijndael)
bool IsForwardTransformation() const
Determines if the cipher is being operated in its forward direction.
void Resynchronize(const byte *iv, int length=-1)
Resynchronize with an IV.
An invalid argument was detected.
Exception thrown when an invalid key length is encountered.
Interface for retrieving values given their names.
void New(size_type newSize)
Change size without preserving contents.
size_type size() const
Provides the count of elements in the SecBlock.
virtual void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms=g_nullNameValuePairs)
Sets or reset the key of this object.
XTS block cipher mode of operation default implementation.
bool IsValidKeyLength(size_t keylength) const
Returns whether keylength is a valid key length.
void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms=g_nullNameValuePairs)
Sets or reset the key of this object.
void ProcessData(byte *outString, const byte *inString, size_t length)
Encrypt or decrypt an array of bytes.
void Resynchronize(const byte *iv, int ivLength=-1)
Resynchronize with an IV.
size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength)
Encrypt or decrypt the last block of data.
unsigned int BlockSize() const
Provides the block size of the cipher.
void ThrowIfInvalidKeyLength(size_t length)
Validates the key length.
void ThrowIfInvalidBlockSize(size_t length)
Validates the block size.
std::string AlgorithmName() const
Provides the name of this algorithm.
__uint128_t word128
128-bit unsigned datatype
unsigned int word32
32-bit unsigned datatype
unsigned long long word64
64-bit unsigned datatype
Functions for CPU features and intrinsics.
ByteOrder
Provides the byte ordering.
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Utility functions for the Crypto++ library.
bool IsPowerOf2(const T &value)
Tests whether a value is a power of 2.
CRYPTOPP_DLL void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Classes for block cipher modes of operation.
Crypto++ library namespace.
Support functions for PowerPC and vector operations.
T1 VecXor(const T1 vec1, const T2 vec2)
XOR two vectors.
void VecStore(const T data, byte dest[16])
Stores a vector to a byte array.
uint32x4_p VecLoad(const byte src[16])
Loads a vector from a byte array.
Classes for the Threefish block cipher.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Classes for XTS block cipher mode of operation.