mirror of
https://github.com/shadps4-emu/ext-cryptopp.git
synced 2024-11-23 01:49:41 +00:00
parent
85ecff4609
commit
76c29eadaf
@ -410,6 +410,8 @@ xtr.cpp
|
||||
xtr.h
|
||||
xtrcrypt.cpp
|
||||
xtrcrypt.h
|
||||
xts.cpp
|
||||
xts.h
|
||||
zdeflate.cpp
|
||||
zdeflate.h
|
||||
zinflate.cpp
|
||||
@ -576,6 +578,7 @@ TestVectors/vmac.txt
|
||||
TestVectors/wake.txt
|
||||
TestVectors/whrlpool.txt
|
||||
TestVectors/xchacha.txt
|
||||
TestVectors/xts.txt
|
||||
TestPrograms/test_32bit.cxx
|
||||
TestPrograms/test_64bit.cxx
|
||||
TestPrograms/test_arm_acle.cxx
|
||||
|
8204
TestVectors/xts.txt
Normal file
8204
TestVectors/xts.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -167,6 +167,9 @@ void Benchmark2(double t, double hertz)
|
||||
BenchMarkByName<SymmetricCipher>("AES/CBC", 16);
|
||||
BenchMarkByName<SymmetricCipher>("AES/CBC", 24);
|
||||
BenchMarkByName<SymmetricCipher>("AES/CBC", 32);
|
||||
BenchMarkByName<SymmetricCipher>("AES/XTS", 32);
|
||||
BenchMarkByName<SymmetricCipher>("AES/XTS", 48);
|
||||
BenchMarkByName<SymmetricCipher>("AES/XTS", 64);
|
||||
BenchMarkByName<SymmetricCipher>("AES/OFB", 16);
|
||||
BenchMarkByName<SymmetricCipher>("AES/CFB", 16);
|
||||
BenchMarkByName<SymmetricCipher>("AES/ECB", 16);
|
||||
|
33
cmac.cpp
33
cmac.cpp
@ -5,14 +5,17 @@
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#include "cmac.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
ANONYMOUS_NAMESPACE_BEGIN
|
||||
|
||||
static void MulU(byte *k, unsigned int length)
|
||||
using CryptoPP::byte;
|
||||
using CryptoPP::IsPowerOf2;
|
||||
|
||||
void MulU(byte *k, unsigned int len)
|
||||
{
|
||||
byte carry = 0;
|
||||
|
||||
for (int i=length-1; i>=1; i-=2)
|
||||
for (int i=len-1; i>=1; i-=2)
|
||||
{
|
||||
byte carry2 = k[i] >> 7;
|
||||
k[i] += k[i] + carry;
|
||||
@ -20,9 +23,22 @@ static void MulU(byte *k, unsigned int length)
|
||||
k[i-1] += k[i-1] + carry2;
|
||||
}
|
||||
|
||||
#ifndef CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS
|
||||
CRYPTOPP_ASSERT(len == 16);
|
||||
|
||||
if (carry)
|
||||
{
|
||||
switch (length)
|
||||
k[15] ^= 0x87;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
CRYPTOPP_ASSERT(IsPowerOf2(len));
|
||||
CRYPTOPP_ASSERT(len >= 8);
|
||||
CRYPTOPP_ASSERT(len <= 128);
|
||||
|
||||
if (carry)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 8:
|
||||
k[7] ^= 0x1b;
|
||||
@ -50,11 +66,16 @@ static void MulU(byte *k, unsigned int length)
|
||||
k[127] ^= 0x43;
|
||||
break;
|
||||
default:
|
||||
throw InvalidArgument("CMAC: " + IntToString(length) + " is not a supported cipher block size");
|
||||
CRYPTOPP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
#endif // CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS
|
||||
}
|
||||
|
||||
ANONYMOUS_NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
|
||||
{
|
||||
BlockCipher &cipher = AccessCipher();
|
||||
|
8
cmac.h
8
cmac.h
@ -10,6 +10,13 @@
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
/// \brief Enable CMAC and wide block ciphers
|
||||
/// \details CMAC is only defined for AES. The library can support wide
|
||||
/// block ciphers like Kaylna and Threefish since we know the polynomials.
|
||||
#ifndef CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS
|
||||
# define CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS 1
|
||||
#endif // CRYPTOPP_CMAC_WIDE_BLOCK_CIPHERS
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// \brief CMAC base implementation
|
||||
@ -19,7 +26,6 @@ class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCo
|
||||
public:
|
||||
|
||||
virtual ~CMAC_Base() {}
|
||||
|
||||
CMAC_Base() : m_counter(0) {}
|
||||
|
||||
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms);
|
||||
|
@ -83,7 +83,7 @@ LIB_SRCS = \
|
||||
sm4_simd.cpp sosemanuk.cpp speck.cpp speck128_simd.cpp speck64_simd.cpp \
|
||||
square.cpp squaretb.cpp sse_simd.cpp strciphr.cpp tea.cpp tftables.cpp \
|
||||
threefish.cpp tiger.cpp tigertab.cpp ttmac.cpp tweetnacl.cpp twofish.cpp \
|
||||
vmac.cpp wake.cpp whrlpool.cpp xed25519.cpp xtr.cpp xtrcrypt.cpp \
|
||||
vmac.cpp wake.cpp whrlpool.cpp xed25519.cpp xtr.cpp xtrcrypt.cpp xts.cpp \
|
||||
zdeflate.cpp zinflate.cpp zlib.cpp
|
||||
|
||||
LIB_OBJS = \
|
||||
@ -114,7 +114,7 @@ LIB_OBJS = \
|
||||
sm4_simd.obj sosemanuk.obj speck.obj speck128_simd.obj speck64_simd.obj \
|
||||
square.obj squaretb.obj sse_simd.obj strciphr.obj tea.obj tftables.obj \
|
||||
threefish.obj tiger.obj tigertab.obj ttmac.obj tweetnacl.obj twofish.obj \
|
||||
vmac.obj wake.obj whrlpool.obj xed25519.obj xtr.obj xtrcrypt.obj \
|
||||
vmac.obj wake.obj whrlpool.obj xed25519.obj xtr.obj xtrcrypt.obj xts.obj \
|
||||
zdeflate.obj zinflate.obj zlib.obj
|
||||
|
||||
ASM_OBJS = \
|
||||
|
@ -346,6 +346,7 @@
|
||||
<ClCompile Include="xed25519.cpp" />
|
||||
<ClCompile Include="xtr.cpp" />
|
||||
<ClCompile Include="xtrcrypt.cpp" />
|
||||
<ClCompile Include="xts.cpp" />
|
||||
<ClCompile Include="zdeflate.cpp" />
|
||||
<ClCompile Include="zinflate.cpp" />
|
||||
<ClCompile Include="zlib.cpp" />
|
||||
@ -568,6 +569,7 @@
|
||||
<ClInclude Include="xed25519.h" />
|
||||
<ClInclude Include="xtr.h" />
|
||||
<ClInclude Include="xtrcrypt.h" />
|
||||
<ClInclude Include="xts.h" />
|
||||
<ClInclude Include="zdeflate.h" />
|
||||
<ClInclude Include="zinflate.h" />
|
||||
<ClInclude Include="zlib.h" />
|
||||
|
@ -518,6 +518,9 @@
|
||||
<ClCompile Include="xtrcrypt.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="xts.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="zdeflate.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1053,6 +1056,9 @@
|
||||
<ClInclude Include="xtrcrypt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="xts.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="zdeflate.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -213,7 +213,7 @@ size_t CBC_CTS_Encryption::ProcessLastBlock(byte *outString, size_t outLength, c
|
||||
const size_t used = inLength;
|
||||
const unsigned int blockSize = BlockSize();
|
||||
|
||||
if (inLength <= BlockSize())
|
||||
if (inLength <= blockSize)
|
||||
{
|
||||
if (!m_stolenIV)
|
||||
throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
|
||||
|
6
modes.h
6
modes.h
@ -255,8 +255,10 @@ public:
|
||||
unsigned int MandatoryBlockSize() const {return BlockSize();}
|
||||
bool IsRandomAccess() const {return false;}
|
||||
bool IsSelfInverting() const {return false;}
|
||||
bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
|
||||
void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));}
|
||||
bool IsForwardTransformation() const
|
||||
{return m_cipher->IsForwardTransformation();}
|
||||
void Resynchronize(const byte *iv, int length=-1)
|
||||
{memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));}
|
||||
|
||||
protected:
|
||||
bool RequireAlignedInput() const {return true;}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "ccm.h"
|
||||
#include "gcm.h"
|
||||
#include "eax.h"
|
||||
#include "xts.h"
|
||||
#include "twofish.h"
|
||||
#include "serpent.h"
|
||||
#include "cast.h"
|
||||
@ -67,6 +68,7 @@ void RegisterFactories4()
|
||||
RegisterSymmetricCipherDefaultFactories<CFB_Mode<AES> >();
|
||||
RegisterSymmetricCipherDefaultFactories<OFB_Mode<AES> >();
|
||||
RegisterSymmetricCipherDefaultFactories<CTR_Mode<AES> >();
|
||||
RegisterSymmetricCipherDefaultFactories<XTS_Mode<AES> >("AES/XTS");
|
||||
|
||||
RegisterAuthenticatedSymmetricCipherDefaultFactories<CCM<AES> >();
|
||||
RegisterAuthenticatedSymmetricCipherDefaultFactories<GCM<AES> >();
|
||||
|
20
test.cpp
20
test.cpp
@ -1010,15 +1010,17 @@ bool Validate(int alg, bool thorough)
|
||||
case 80: result = ValidateVMAC(); break;
|
||||
case 81: result = ValidateCCM(); break;
|
||||
case 82: result = ValidateGCM(); break;
|
||||
case 83: result = ValidateCMAC(); break;
|
||||
case 84: result = ValidateSM3(); break;
|
||||
case 85: result = ValidateBLAKE2s(); break;
|
||||
case 86: result = ValidateBLAKE2b(); break;
|
||||
case 87: result = ValidatePoly1305(); break;
|
||||
case 88: result = ValidateSipHash(); break;
|
||||
case 89: result = ValidateHashDRBG(); break;
|
||||
case 90: result = ValidateHmacDRBG(); break;
|
||||
case 91: result = ValidateNaCl(); break;
|
||||
case 83: result = ValidateXTS(); break;
|
||||
case 84: result = ValidateCMAC(); break;
|
||||
case 85: result = ValidateSM3(); break;
|
||||
case 86: result = ValidateBLAKE2s(); break;
|
||||
case 87: result = ValidateBLAKE2b(); break;
|
||||
case 88: result = ValidatePoly1305(); break;
|
||||
case 89: result = ValidateSipHash(); break;
|
||||
case 90: result = ValidateHashDRBG(); break;
|
||||
case 91: result = ValidateHmacDRBG(); break;
|
||||
case 92: result = ValidateNaCl(); break;
|
||||
|
||||
case 100: result = ValidateCHAM(); break;
|
||||
case 101: result = ValidateSIMECK(); break;
|
||||
case 102: result = ValidateSIMON(); break;
|
||||
|
@ -171,6 +171,7 @@ bool ValidateAll(bool thorough)
|
||||
pass=ValidateVMAC() && pass;
|
||||
pass=ValidateCCM() && pass;
|
||||
pass=ValidateGCM() && pass;
|
||||
pass=ValidateXTS() && pass;
|
||||
pass=ValidateCMAC() && pass;
|
||||
pass=RunTestDataFile("TestVectors/eax.txt") && pass;
|
||||
|
||||
|
@ -1860,6 +1860,12 @@ bool ValidateGCM()
|
||||
return RunTestDataFile("TestVectors/gcm.txt", MakeParameters(Name::TableSize(), (int)64*1024)) && pass;
|
||||
}
|
||||
|
||||
bool ValidateXTS()
|
||||
{
|
||||
std::cout << "\nAES/XTS validation suite running...\n";
|
||||
return RunTestDataFile("TestVectors/xts.txt");
|
||||
}
|
||||
|
||||
bool ValidateCMAC()
|
||||
{
|
||||
std::cout << "\nCMAC validation suite running...\n";
|
||||
|
@ -117,6 +117,7 @@ bool ValidateSosemanuk();
|
||||
bool ValidateVMAC();
|
||||
bool ValidateCCM();
|
||||
bool ValidateGCM();
|
||||
bool ValidateXTS();
|
||||
bool ValidateCMAC();
|
||||
|
||||
bool ValidateBBS();
|
||||
|
336
xts.cpp
Normal file
336
xts.cpp
Normal file
@ -0,0 +1,336 @@
|
||||
// xts.cpp - written and placed in the public domain by Jeffrey Walton
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "xts.h"
|
||||
#include "misc.h"
|
||||
#include "modes.h"
|
||||
|
||||
#if defined(CRYPTOPP_DEBUG)
|
||||
# include "aes.h"
|
||||
# include "threefish.h"
|
||||
#endif
|
||||
|
||||
ANONYMOUS_NAMESPACE_BEGIN
|
||||
|
||||
using CryptoPP::byte;
|
||||
using CryptoPP::word32;
|
||||
using CryptoPP::word64;
|
||||
using CryptoPP::GetWord;
|
||||
using CryptoPP::PutWord;
|
||||
using CryptoPP::IsPowerOf2;
|
||||
using CryptoPP::BIG_ENDIAN_ORDER;
|
||||
using CryptoPP::LITTLE_ENDIAN_ORDER;
|
||||
|
||||
// Borrowed from CMAC, but little-endian representation
|
||||
inline void GF_Double(byte *k, unsigned int len)
|
||||
{
|
||||
#if defined(_LP64) || defined(__LP64__)
|
||||
word64 carry = 0, x;
|
||||
for (size_t i=0, idx=0; i<len/8; ++i, idx+=8)
|
||||
{
|
||||
x = GetWord<word64>(false, LITTLE_ENDIAN_ORDER, k+idx);
|
||||
word64 y = (x >> 63); x = (x << 1) + carry;
|
||||
PutWord<word64>(false, LITTLE_ENDIAN_ORDER, k+idx, x);
|
||||
carry = y;
|
||||
}
|
||||
#else
|
||||
word32 carry = 0, x;
|
||||
for (size_t i=0, idx=0; i<len/4; ++i, idx+=4)
|
||||
{
|
||||
x = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, k+idx);
|
||||
word32 y = (x >> 31); x = (x << 1) + carry;
|
||||
PutWord<word32>(false, LITTLE_ENDIAN_ORDER, k+idx, x);
|
||||
carry = y;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
|
||||
|
||||
CRYPTOPP_ASSERT(IsPowerOf2(len));
|
||||
CRYPTOPP_ASSERT(len >= 8);
|
||||
CRYPTOPP_ASSERT(len <= 128);
|
||||
|
||||
// Special case the dominant case
|
||||
if (carry && len == 16)
|
||||
{
|
||||
k[0] ^= 0x87;
|
||||
return;
|
||||
}
|
||||
|
||||
if (carry)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 8:
|
||||
{
|
||||
const size_t LEIDX = 8-1;
|
||||
k[LEIDX-7] ^= 0x1b;
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
const size_t LEIDX = 16-1;
|
||||
k[LEIDX-15] ^= 0x87;
|
||||
break;
|
||||
}
|
||||
case 32:
|
||||
{
|
||||
// https://crypto.stackexchange.com/q/9815/10496
|
||||
// Polynomial x^256 + x^10 + x^5 + x^2 + 1
|
||||
const size_t LEIDX = 32-1;
|
||||
k[LEIDX-30] ^= 4;
|
||||
k[LEIDX-31] ^= 0x25;
|
||||
break;
|
||||
}
|
||||
case 64:
|
||||
{
|
||||
// https://crypto.stackexchange.com/q/9815/10496
|
||||
// Polynomial x^512 + x^8 + x^5 + x^2 + 1
|
||||
const size_t LEIDX = 64-1;
|
||||
k[LEIDX-62] ^= 1;
|
||||
k[LEIDX-63] ^= 0x25;
|
||||
break;
|
||||
}
|
||||
case 128:
|
||||
{
|
||||
// https://crypto.stackexchange.com/q/9815/10496
|
||||
// Polynomial x^1024 + x^19 + x^6 + x + 1
|
||||
const size_t LEIDX = 128-1;
|
||||
k[LEIDX-125] ^= 8;
|
||||
k[LEIDX-126] ^= 0x00;
|
||||
k[LEIDX-127] ^= 0x43;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CRYPTOPP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
CRYPTOPP_ASSERT(len == 16);
|
||||
|
||||
if (carry)
|
||||
{
|
||||
k[0] ^= 0x87;
|
||||
return;
|
||||
}
|
||||
#endif // CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
|
||||
}
|
||||
|
||||
#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
|
||||
|
||||
using CryptoPP::AES;
|
||||
using CryptoPP::XTS_Mode;
|
||||
using CryptoPP::Threefish512;
|
||||
|
||||
void Modes_TestInstantiations()
|
||||
{
|
||||
XTS_Mode<AES>::Encryption m0;
|
||||
XTS_Mode<AES>::Decryption m1;
|
||||
XTS_Mode<AES>::Encryption m2;
|
||||
XTS_Mode<AES>::Decryption m3;
|
||||
|
||||
#if CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
|
||||
XTS_Mode<Threefish512>::Encryption m4;
|
||||
XTS_Mode<Threefish512>::Decryption m5;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
ANONYMOUS_NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void XTS_ModeBase::SetKey(const byte *key, size_t length, const NameValuePairs ¶ms)
|
||||
{
|
||||
CRYPTOPP_ASSERT(length % 2 == 0);
|
||||
|
||||
const size_t klen = length/2;
|
||||
AccessBlockCipher().SetKey(key+0, klen, params);
|
||||
AccessTweakCipher().SetKey(key+klen, klen, params);
|
||||
|
||||
ResizeBuffers();
|
||||
|
||||
size_t ivLength;
|
||||
const byte *iv = GetIVAndThrowIfInvalid(params, ivLength);
|
||||
Resynchronize(iv, (int)ivLength);
|
||||
}
|
||||
|
||||
void XTS_ModeBase::Resynchronize(const byte *iv, int ivLength)
|
||||
{
|
||||
BlockOrientedCipherModeBase::Resynchronize(iv, ivLength);
|
||||
GetTweakCipher().ProcessBlock(m_register);
|
||||
}
|
||||
|
||||
void XTS_ModeBase::Resynchronize(word64 sector, ByteOrder order)
|
||||
{
|
||||
SecByteBlock iv(GetTweakCipher().BlockSize());
|
||||
PutWord<word64>(false, order, iv, sector);
|
||||
std::memset(iv+8, 0x00, iv.size()-8);
|
||||
|
||||
BlockOrientedCipherModeBase::Resynchronize(iv, iv.size());
|
||||
GetTweakCipher().ProcessBlock(m_register);
|
||||
}
|
||||
|
||||
void XTS_ModeBase::ResizeBuffers()
|
||||
{
|
||||
BlockOrientedCipherModeBase::ResizeBuffers();
|
||||
m_workspace.New(GetBlockCipher().BlockSize());
|
||||
}
|
||||
|
||||
void XTS_ModeBase::ProcessData(byte *outString, const byte *inString, size_t length)
|
||||
{
|
||||
const unsigned int blockSize = GetBlockCipher().BlockSize();
|
||||
|
||||
// data unit is multiple of 16 bytes
|
||||
CRYPTOPP_ASSERT(length % blockSize == 0);
|
||||
|
||||
// now encrypt the data unit, AES_BLK_BYTES at a time
|
||||
for (size_t i=0; i<length; i+=blockSize)
|
||||
{
|
||||
// merge the tweak into the input block
|
||||
xorbuf(m_workspace, inString+i, m_register, blockSize);
|
||||
|
||||
// encrypt one block, merge the tweak into the output block
|
||||
GetBlockCipher().AdvancedProcessBlocks(m_workspace, m_register, outString+i, blockSize, 0);
|
||||
|
||||
// Multiply T by alpha
|
||||
GF_Double(m_register, m_register.size());
|
||||
}
|
||||
}
|
||||
|
||||
size_t XTS_ModeBase::ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength)
|
||||
{
|
||||
if (IsForwardTransformation())
|
||||
return ProcessLastPlainBlock(outString, outLength, inString, inLength);
|
||||
else
|
||||
return ProcessLastCipherBlock(outString, outLength, inString, inLength);
|
||||
}
|
||||
|
||||
size_t XTS_ModeBase::ProcessLastPlainBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength)
|
||||
{
|
||||
// ensure output buffer is large enough
|
||||
CRYPTOPP_ASSERT(outLength >= inLength);
|
||||
// need at least a full AES block
|
||||
CRYPTOPP_ASSERT(inLength >= BlockSize());
|
||||
|
||||
const unsigned int blockSize = GetBlockCipher().BlockSize();
|
||||
const unsigned int blocks = inLength / blockSize;
|
||||
const unsigned int tail = inLength % blockSize;
|
||||
const size_t length = inLength;
|
||||
|
||||
if (tail == 0)
|
||||
{
|
||||
// Allow ProcessData to handle all the full blocks
|
||||
ProcessData(outString, inString, inLength);
|
||||
return inLength;
|
||||
}
|
||||
else if (blocks > 1)
|
||||
{
|
||||
// Allow ProcessData to handle full blocks except one
|
||||
const size_t head = (blocks-1)*blockSize;
|
||||
ProcessData(outString, inString, inLength-head);
|
||||
|
||||
outString += head; outLength -= head;
|
||||
inString += head; inLength -= head;
|
||||
}
|
||||
|
||||
///// handle the full block /////
|
||||
|
||||
// merge the tweak into the input block
|
||||
xorbuf(m_workspace, inString, m_register, blockSize);
|
||||
|
||||
// encrypt one block, merge the tweak into the output block
|
||||
GetBlockCipher().AdvancedProcessBlocks(m_workspace, m_register, outString, blockSize, 0);
|
||||
|
||||
// Multiply T by alpha
|
||||
GF_Double(m_register, m_register.size());
|
||||
|
||||
///// handle final partial block /////
|
||||
|
||||
inString += blockSize;
|
||||
outString += blockSize;
|
||||
const size_t len = inLength-blockSize;
|
||||
|
||||
// copy in the final plaintext bytes
|
||||
std::memcpy(m_workspace, inString, len);
|
||||
// and copy out the final ciphertext bytes
|
||||
std::memcpy(outString, outString-blockSize, len);
|
||||
// "steal" ciphertext to complete the block
|
||||
std::memcpy(m_workspace+len, outString-blockSize+len, blockSize-len);
|
||||
|
||||
// merge the tweak into the input block
|
||||
xorbuf(m_workspace, m_register, blockSize);
|
||||
|
||||
// encrypt the final block, merge the tweak into the output block
|
||||
GetBlockCipher().AdvancedProcessBlocks(m_workspace, m_register, outString-blockSize, blockSize, 0);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
size_t XTS_ModeBase::ProcessLastCipherBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength)
|
||||
{
|
||||
// ensure output buffer is large enough
|
||||
CRYPTOPP_ASSERT(outLength >= inLength);
|
||||
// need at least a full AES block
|
||||
CRYPTOPP_ASSERT(inLength >= BlockSize());
|
||||
|
||||
const unsigned int blockSize = GetBlockCipher().BlockSize();
|
||||
const unsigned int blocks = inLength / blockSize;
|
||||
const unsigned int tail = inLength % blockSize;
|
||||
const size_t length = inLength;
|
||||
|
||||
if (tail == 0)
|
||||
{
|
||||
// Allow ProcessData to handle all the full blocks
|
||||
ProcessData(outString, inString, inLength);
|
||||
return inLength;
|
||||
}
|
||||
else if (blocks > 1)
|
||||
{
|
||||
// Allow ProcessData to handle full blocks except one
|
||||
const size_t head = (blocks-1)*blockSize;
|
||||
ProcessData(outString, inString, inLength-head);
|
||||
|
||||
outString += head; outLength -= head;
|
||||
inString += head; inLength -= head;
|
||||
}
|
||||
|
||||
SecByteBlock poly1(m_register);
|
||||
SecByteBlock poly2(m_register);
|
||||
GF_Double(poly2, poly2.size());
|
||||
|
||||
///// handle final partial block /////
|
||||
|
||||
inString += blockSize;
|
||||
outString += blockSize;
|
||||
const size_t len = inLength-blockSize;
|
||||
|
||||
// merge the tweak into the input block
|
||||
xorbuf(m_workspace, inString-blockSize, poly2, blockSize);
|
||||
|
||||
// encrypt one block, merge the tweak into the output block
|
||||
GetBlockCipher().AdvancedProcessBlocks(m_workspace, poly2, m_workspace, blockSize, 0);
|
||||
|
||||
// copy in the final plaintext bytes
|
||||
std::memcpy(outString-blockSize, inString, len);
|
||||
// and copy out the final ciphertext bytes
|
||||
std::memcpy(outString, m_workspace, len);
|
||||
// "steal" ciphertext to complete the block
|
||||
std::memcpy(outString-blockSize+len, m_workspace+len, blockSize-len);
|
||||
|
||||
///// handle the full previous block /////
|
||||
|
||||
inString -= blockSize;
|
||||
outString -= blockSize;
|
||||
|
||||
// merge the tweak into the output block
|
||||
xorbuf(m_workspace, outString, poly1, blockSize);
|
||||
|
||||
// encrypt one block, merge the tweak into the input block
|
||||
GetBlockCipher().AdvancedProcessBlocks(m_workspace, poly1, outString, blockSize, 0);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
156
xts.h
Normal file
156
xts.h
Normal file
@ -0,0 +1,156 @@
|
||||
// xts.h - written and placed in the public domain by Jeffrey Walton
|
||||
|
||||
/// \file xts.h
|
||||
/// \brief Classes for XTS block cipher mode of operation
|
||||
/// \details XTS mode is a wide block mode defined by IEEE P1619-2008. NIST
|
||||
/// SP-800-38E approves the mode for storage devices citing IEEE 1619-2007.
|
||||
/// IEEE 1619-2007 provides both a reference implementation and test vectors.
|
||||
/// The IEEE reference implementation fails to arrive at the expected result
|
||||
/// for some test vectors.
|
||||
/// \sa <A HREF="http://www.cryptopp.com/wiki/Modes_of_Operation">Modes of
|
||||
/// Operation</A> on the Crypto++ wiki, <A
|
||||
/// HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf"> Evaluation of Some
|
||||
/// Blockcipher Modes of Operation</A>, <A
|
||||
/// HREF="https://csrc.nist.gov/publications/detail/sp/800-38e/final">Recommendation
|
||||
/// for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on
|
||||
/// Storage Devices</A>, <A
|
||||
/// HREF="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE P1619-2007</A>
|
||||
/// and <A HREF="https://crypto.stackexchange.com/q/74925/10496">IEEE P1619/XTS,
|
||||
/// inconsistent reference implementation and test vectors</A>.
|
||||
/// \since Crypto++ 8.3
|
||||
|
||||
#ifndef CRYPTOPP_XTS_MODE_H
|
||||
#define CRYPTOPP_XTS_MODE_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "secblock.h"
|
||||
#include "modes.h"
|
||||
#include "misc.h"
|
||||
|
||||
/// \brief Enable XTS for wide block ciphers
|
||||
/// \details XTS is only defined for AES. The library can support wide
|
||||
/// block ciphers like Kaylna and Threefish since we know the polynomials.
|
||||
/// To enable wide block ciphers define <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt>
|
||||
/// to non-zero. Note this is a library compile time define.
|
||||
/// \details There is risk involved with using XTS with wider block ciphers.
|
||||
/// According to Phillip Rogaway, "The narrow width of the underlying PRP and
|
||||
/// the poor treatment of fractional final blocks are problems."
|
||||
/// \sa <A HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf">Evaluation
|
||||
/// of Some Blockcipher Modes of Operation</A>
|
||||
/// \since Crypto++ 8.3
|
||||
#ifndef CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
|
||||
# define CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS 0
|
||||
#endif // CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// \brief XTS block cipher mode of operation default implementation
|
||||
/// \since Crypto++ 8.3
|
||||
class CRYPTOPP_NO_VTABLE XTS_ModeBase : public BlockOrientedCipherModeBase
|
||||
{
|
||||
public:
|
||||
std::string AlgorithmName() const
|
||||
{return GetBlockCipher().AlgorithmName() + "/XTS";}
|
||||
std::string AlgorithmProvider() const
|
||||
{return GetBlockCipher().AlgorithmProvider();}
|
||||
|
||||
size_t MinKeyLength() const
|
||||
{return GetBlockCipher().MinKeyLength()*2;}
|
||||
size_t MaxKeyLength() const
|
||||
{return GetBlockCipher().MaxKeyLength()*2;}
|
||||
size_t DefaultKeyLength() const
|
||||
{return GetBlockCipher().DefaultKeyLength()*2;}
|
||||
size_t GetValidKeyLength(size_t n) const
|
||||
{return GetBlockCipher().GetValidKeyLength((n+1)/2);}
|
||||
bool IsValidKeyLength(size_t keylength) const
|
||||
{return keylength == GetValidKeyLength(keylength);}
|
||||
|
||||
unsigned int BlockSize() const
|
||||
{return GetBlockCipher().BlockSize();}
|
||||
unsigned int MinLastBlockSize() const
|
||||
{return GetBlockCipher().BlockSize()+1;}
|
||||
unsigned int OptimalDataAlignment() const
|
||||
{return GetBlockCipher().OptimalDataAlignment();}
|
||||
|
||||
void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs);
|
||||
IV_Requirement IVRequirement() const {return UNIQUE_IV;}
|
||||
void Resynchronize(const byte *iv, int ivLength=-1);
|
||||
void Resynchronize(word64 sector, ByteOrder order=BIG_ENDIAN_ORDER);
|
||||
void ProcessData(byte *outString, const byte *inString, size_t length);
|
||||
size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength);
|
||||
|
||||
protected:
|
||||
virtual void ResizeBuffers();
|
||||
|
||||
inline size_t ProcessLastPlainBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength);
|
||||
inline size_t ProcessLastCipherBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength);
|
||||
|
||||
virtual BlockCipher& AccessBlockCipher() = 0;
|
||||
virtual BlockCipher& AccessTweakCipher() = 0;
|
||||
|
||||
const BlockCipher& GetBlockCipher() const
|
||||
{return const_cast<XTS_ModeBase*>(this)->AccessBlockCipher();}
|
||||
const BlockCipher& GetTweakCipher() const
|
||||
{return const_cast<XTS_ModeBase*>(this)->AccessTweakCipher();}
|
||||
|
||||
SecByteBlock m_workspace;
|
||||
};
|
||||
|
||||
/// \brief XTS block cipher mode of operation implementation details
|
||||
/// \tparam CIPHER BlockCipher derived class or type
|
||||
/// \since Crypto++ 8.3
|
||||
template <class CIPHER>
|
||||
class CRYPTOPP_NO_VTABLE XTS_Final : public XTS_ModeBase
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_STATIC_CONSTEXPR std::string CRYPTOPP_API StaticAlgorithmName()
|
||||
{return std::string(CIPHER::StaticAlgorithmName()) + "/XTS";}
|
||||
|
||||
protected:
|
||||
BlockCipher& AccessBlockCipher()
|
||||
{return *m_cipher;}
|
||||
BlockCipher& AccessTweakCipher()
|
||||
{return m_tweaker;}
|
||||
|
||||
protected:
|
||||
typename CIPHER::Encryption m_tweaker;
|
||||
};
|
||||
|
||||
/// \brief XTS block cipher mode of operation
|
||||
/// \tparam CIPHER BlockCipher derived class or type
|
||||
/// \details XTS mode is a wide block mode defined by IEEE P1619-2008. NIST
|
||||
/// SP-800-38E approves the mode for storage devices citing IEEE 1619-2007.
|
||||
/// IEEE 1619-2007 provides both a reference implementation and test vectors.
|
||||
/// The IEEE reference implementation fails to arrive at the expected result
|
||||
/// for some test vectors.
|
||||
/// \details XTS is only defined for AES. The library can support wide
|
||||
/// block ciphers like Kaylna and Threefish since we know the polynomials.
|
||||
/// There is risk involved with using XTS with wider block ciphers.
|
||||
/// According to Phillip Rogaway, "The narrow width of the underlying PRP and
|
||||
/// the poor treatment of fractional final blocks are problems." To enable
|
||||
/// wide block cipher support define <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> to
|
||||
/// non-zero.
|
||||
/// \sa <A HREF="http://www.cryptopp.com/wiki/Modes_of_Operation">Modes of
|
||||
/// Operation</A> on the Crypto++ wiki, <A
|
||||
/// HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf"> Evaluation of Some
|
||||
/// Blockcipher Modes of Operation</A>, <A
|
||||
/// HREF="https://csrc.nist.gov/publications/detail/sp/800-38e/final">Recommendation
|
||||
/// for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on
|
||||
/// Storage Devices</A>, <A
|
||||
/// HREF="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE P1619-2007</A>
|
||||
/// and <A HREF="https://crypto.stackexchange.com/q/74925/10496">IEEE P1619/XTS,
|
||||
/// inconsistent reference implementation and test vectors</A>.
|
||||
/// \since Crypto++ 8.3
|
||||
template <class CIPHER>
|
||||
struct XTS : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_CipherHolder<typename CIPHER::Encryption, XTS_Final<CIPHER> > Encryption;
|
||||
typedef CipherModeFinalTemplate_CipherHolder<typename CIPHER::Decryption, XTS_Final<CIPHER> > Decryption;
|
||||
};
|
||||
|
||||
// C++03 lacks the mechanics to typedef a template
|
||||
#define XTS_Mode XTS
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // CRYPTOPP_XTS_MODE_H
|
Loading…
Reference in New Issue
Block a user