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
39using namespace CryptoPP;
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)
63 CRYPTOPP_ASSERT(count >= 16 && (count % 16 == 0));
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)
70 _mm_storeu_si128(M128_CAST(output+i),
72 _mm_loadu_si128(CONST_M128_CAST(input+i)),
73 _mm_loadu_si128(CONST_M128_CAST(mask+i))));
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)
81 VecStore(VecXor(VecLoad(input+i), VecLoad(mask+i)), output+i);
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)
100 x = GetWord<word128>(
false, LITTLE_ENDIAN_ORDER, in+idx);
101 word128 y = (x >> 127); x = (x << 1) + carry;
102 PutWord<word128>(
false, LITTLE_ENDIAN_ORDER, out+idx, x);
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)
109 x = GetWord<word64>(
false, LITTLE_ENDIAN_ORDER, in+idx);
110 word64 y = (x >> 63); x = (x << 1) + carry;
111 PutWord<word64>(
false, LITTLE_ENDIAN_ORDER, out+idx, x);
116 for (
size_t i=0, idx=0; i<len/4; ++i, idx+=4)
118 x = GetWord<word32>(
false, LITTLE_ENDIAN_ORDER, in+idx);
119 word32 y = (x >> 31); x = (x << 1) + carry;
120 PutWord<word32>(
false, LITTLE_ENDIAN_ORDER, out+idx, x);
125#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
128 CRYPTOPP_ASSERT(len >= 16);
129 CRYPTOPP_ASSERT(len <= 128);
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;
175 CRYPTOPP_ASSERT(len == 16);
186inline void GF_Double(
byte *inout,
unsigned int len)
188 GF_Double(inout, inout, len);
191ANONYMOUS_NAMESPACE_END
193NAMESPACE_BEGIN(CryptoPP)
197#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
198 CRYPTOPP_ASSERT(length >= 16 && length <= 128 &&
IsPowerOf2(length));
199 if (length < 16 || length > 128 || !
IsPowerOf2(length))
200 throw InvalidArgument(AlgorithmName() +
": block size of underlying block cipher is not valid");
202 CRYPTOPP_ASSERT(length == 16);
204 throw InvalidArgument(AlgorithmName() +
": block size of underlying block cipher is not 16");
210 CRYPTOPP_ASSERT(length % 2 == 0);
220 const size_t klen = length/2;
221 AccessBlockCipher().
SetKey(key+0, klen, params);
222 AccessTweakCipher().
SetKey(key+klen, klen, params);
234 std::memcpy(m_xregister, m_register, ivLength);
240 SecByteBlock iv(GetTweakCipher().
BlockSize());
241 PutWord<word64>(
false, order, iv, sector);
242 std::memset(iv+8, 0x00, iv.size()-8);
245 std::memcpy(m_xregister, iv, iv.size());
249void XTS_ModeBase::ResizeBuffers()
251 BlockOrientedCipherModeBase::ResizeBuffers();
252 m_xworkspace.New(GetBlockCipher().
BlockSize()*ParallelBlocks);
253 m_xregister.New(GetBlockCipher().
BlockSize()*ParallelBlocks);
264 CRYPTOPP_ASSERT(length %
BlockSize() == 0);
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);
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);
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);
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);
362 XorBuffer(outString, m_xworkspace, m_xregister, blockSize);
365 GF_Double(m_xregister, blockSize);
367 inString += blockSize;
368 outString += blockSize;
376 CRYPTOPP_ASSERT(inLength >=
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)
390 CRYPTOPP_ASSERT(outLength >= 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);
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);
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)
455 CRYPTOPP_ASSERT(outLength >= 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);
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);
516 XorBuffer(outString, m_xworkspace, poly1, blockSize);
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.
const byte * GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size)
Retrieves and validates the IV.
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.
void ThrowIfInvalidBlockSize(size_t length)
Validates the block size.
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
void ThrowIfInvalidKeyLength(size_t length)
Validates the key length.
std::string AlgorithmName() const
Provides the name of this algorithm.
unsigned int word32
32-bit unsigned datatype
Functions for CPU features and intrinsics.
ByteOrder
Provides the byte ordering.
Utility functions for the Crypto++ library.
bool IsPowerOf2(const T &value)
Tests whether a value is a power of 2.
Classes for block cipher modes of operation.
Support functions for PowerPC and vector operations.
Classes for the Threefish block cipher.
Classes for XTS block cipher mode of operation.