You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
224 lines
10 KiB
224 lines
10 KiB
// 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: |
|
/// \brief The algorithm name |
|
/// \returns the algorithm name |
|
/// \details StaticAlgorithmName returns the algorithm's name as a static |
|
/// member function. |
|
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() |
|
{return "XTS";} |
|
|
|
virtual ~XTS_ModeBase() {} |
|
|
|
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 2*GetBlockCipher().GetValidKeyLength((n+1)/2);} |
|
bool IsValidKeyLength(size_t keylength) const |
|
{return keylength == GetValidKeyLength(keylength);} |
|
|
|
/// \brief Validates the key length |
|
/// \param length the size of the keying material, in bytes |
|
/// \throws InvalidKeyLength if the key length is invalid |
|
void ThrowIfInvalidKeyLength(size_t length); |
|
|
|
/// Provides the block size of the cipher |
|
/// \return the block size of the cipher, in bytes |
|
unsigned int BlockSize() const |
|
{return GetBlockCipher().BlockSize();} |
|
|
|
/// \brief Provides the input block size most efficient for this cipher |
|
/// \return The input block size that is most efficient for the cipher |
|
/// \details The base class implementation returns MandatoryBlockSize(). |
|
/// \note Optimal input length is |
|
/// <tt>n * OptimalBlockSize() - GetOptimalBlockSizeUsed()</tt> for |
|
/// any <tt>n \> 0</tt>. |
|
unsigned int GetOptimalBlockSize() const |
|
{return GetBlockCipher().BlockSize()*ParallelBlocks;} |
|
unsigned int MinLastBlockSize() const |
|
{return GetBlockCipher().BlockSize()+1;} |
|
unsigned int OptimalDataAlignment() const |
|
{return GetBlockCipher().OptimalDataAlignment();} |
|
|
|
/// \brief Validates the block size |
|
/// \param length the block size of the cipher, in bytes |
|
/// \throws InvalidArgument if the block size is invalid |
|
/// \details If <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is 0, |
|
/// then CIPHER must be a 16-byte block cipher. If |
|
/// <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is non-zero then |
|
/// CIPHER can be 16, 32, 64, or 128-byte block cipher. |
|
void ThrowIfInvalidBlockSize(size_t length); |
|
|
|
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 ProcessData(byte *outString, const byte *inString, size_t length); |
|
size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); |
|
|
|
/// \brief Resynchronize the cipher |
|
/// \param sector a 64-bit sector number |
|
/// \param order the endian order the word should be written |
|
/// \details The Resynchronize() overload was provided for API |
|
/// compatibility with the IEEE P1619 paper. |
|
void Resynchronize(word64 sector, ByteOrder order=BIG_ENDIAN_ORDER); |
|
|
|
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();} |
|
|
|
// Buffers are sized based on ParallelBlocks |
|
AlignedSecByteBlock m_xregister; |
|
AlignedSecByteBlock m_xworkspace; |
|
|
|
// Intel lacks the SSE registers to run 8 or 12 parallel blocks. |
|
// Do not change this value after compiling. It has no effect. |
|
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 |
|
enum {ParallelBlocks = 4}; |
|
#else |
|
enum {ParallelBlocks = 12}; |
|
#endif |
|
}; |
|
|
|
/// \brief XTS block cipher mode of operation implementation |
|
/// \tparam CIPHER BlockCipher derived class or type |
|
/// \details XTS_Final() provides access to CIPHER in base class XTS_ModeBase() |
|
/// through an interface. AccessBlockCipher() and AccessTweakCipher() allow |
|
/// the XTS_ModeBase() base class to access the user's block cipher without |
|
/// recompiling the library. |
|
/// \details If <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is 0, then CIPHER must |
|
/// be a 16-byte block cipher. If <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is |
|
/// non-zero then CIPHER can be 16, 32, 64, or 128-byte block cipher. |
|
/// 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> |
|
class CRYPTOPP_NO_VTABLE XTS_Final : public XTS_ModeBase |
|
{ |
|
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
|
|
|