Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:10

0001 // xts.h - written and placed in the public domain by Jeffrey Walton

0002 
0003 /// \file xts.h

0004 /// \brief Classes for XTS block cipher mode of operation

0005 /// \details XTS mode is a wide block mode defined by IEEE P1619-2008. NIST

0006 ///  SP-800-38E approves the mode for storage devices citing IEEE 1619-2007.

0007 ///  IEEE 1619-2007 provides both a reference implementation and test vectors.

0008 ///  The IEEE reference implementation fails to arrive at the expected result

0009 ///  for some test vectors.

0010 /// \sa <A HREF="http://www.cryptopp.com/wiki/Modes_of_Operation">Modes of

0011 ///  Operation</A> on the Crypto++ wiki, <A

0012 ///  HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf"> Evaluation of Some

0013 ///  Blockcipher Modes of Operation</A>, <A

0014 ///  HREF="https://csrc.nist.gov/publications/detail/sp/800-38e/final">Recommendation

0015 ///  for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on

0016 ///  Storage Devices</A>, <A

0017 ///  HREF="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE P1619-2007</A>

0018 ///  and <A HREF="https://crypto.stackexchange.com/q/74925/10496">IEEE P1619/XTS,

0019 ///  inconsistent reference implementation and test vectors</A>.

0020 /// \since Crypto++ 8.3

0021 
0022 #ifndef CRYPTOPP_XTS_MODE_H
0023 #define CRYPTOPP_XTS_MODE_H
0024 
0025 #include "cryptlib.h"
0026 #include "secblock.h"
0027 #include "modes.h"
0028 #include "misc.h"
0029 
0030 /// \brief Enable XTS for wide block ciphers

0031 /// \details XTS is only defined for AES. The library can support wide

0032 ///  block ciphers like Kaylna and Threefish since we know the polynomials.

0033 ///  To enable wide block ciphers define <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt>

0034 ///  to non-zero. Note this is a library compile time define.

0035 /// \details There is risk involved with using XTS with wider block ciphers.

0036 ///  According to Phillip Rogaway, "The narrow width of the underlying PRP and

0037 ///  the poor treatment of fractional final blocks are problems."

0038 /// \sa <A HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf">Evaluation

0039 ///  of Some Blockcipher Modes of Operation</A>

0040 /// \since Crypto++ 8.3

0041 #ifndef CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS
0042 # define CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS 0
0043 #endif  // CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS

0044 
0045 NAMESPACE_BEGIN(CryptoPP)
0046 
0047 /// \brief XTS block cipher mode of operation default implementation

0048 /// \since Crypto++ 8.3

0049 class CRYPTOPP_NO_VTABLE XTS_ModeBase : public BlockOrientedCipherModeBase
0050 {
0051 public:
0052     /// \brief The algorithm name

0053     /// \return the algorithm name

0054     /// \details StaticAlgorithmName returns the algorithm's name as a static

0055     ///  member function.

0056     CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName()
0057         {return "XTS";}
0058 
0059     virtual ~XTS_ModeBase() {}
0060 
0061     std::string AlgorithmName() const
0062         {return GetBlockCipher().AlgorithmName() + "/XTS";}
0063     std::string AlgorithmProvider() const
0064         {return GetBlockCipher().AlgorithmProvider();}
0065 
0066     size_t MinKeyLength() const
0067         {return GetBlockCipher().MinKeyLength()*2;}
0068     size_t MaxKeyLength() const
0069         {return GetBlockCipher().MaxKeyLength()*2;}
0070     size_t DefaultKeyLength() const
0071         {return GetBlockCipher().DefaultKeyLength()*2;}
0072     size_t GetValidKeyLength(size_t n) const
0073         {return 2*GetBlockCipher().GetValidKeyLength((n+1)/2);}
0074     bool IsValidKeyLength(size_t keylength) const
0075         {return keylength == GetValidKeyLength(keylength);}
0076 
0077     /// \brief Validates the key length

0078     /// \param length the size of the keying material, in bytes

0079     /// \throw InvalidKeyLength if the key length is invalid

0080     void ThrowIfInvalidKeyLength(size_t length);
0081 
0082     /// Provides the block size of the cipher

0083     /// \return the block size of the cipher, in bytes

0084     unsigned int BlockSize() const
0085         {return GetBlockCipher().BlockSize();}
0086 
0087     /// \brief Provides the input block size most efficient for this cipher

0088     /// \return The input block size that is most efficient for the cipher

0089     /// \details The base class implementation returns MandatoryBlockSize().

0090     /// \note Optimal input length is

0091     ///  <tt>n * OptimalBlockSize() - GetOptimalBlockSizeUsed()</tt> for

0092     ///  any <tt>n \> 0</tt>.

0093     unsigned int GetOptimalBlockSize() const
0094         {return GetBlockCipher().BlockSize()*ParallelBlocks;}
0095     unsigned int MinLastBlockSize() const
0096         {return GetBlockCipher().BlockSize()+1;}
0097     unsigned int OptimalDataAlignment() const
0098         {return GetBlockCipher().OptimalDataAlignment();}
0099 
0100     /// \brief Validates the block size

0101     /// \param length the block size of the cipher, in bytes

0102     /// \throw InvalidArgument if the block size is invalid

0103     /// \details If <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is 0,

0104     ///  then CIPHER must be a 16-byte block cipher. If

0105     ///  <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is non-zero then

0106     ///  CIPHER can be 16, 32, 64, or 128-byte block cipher.

0107     void ThrowIfInvalidBlockSize(size_t length);
0108 
0109     void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs);
0110     IV_Requirement IVRequirement() const {return UNIQUE_IV;}
0111     void Resynchronize(const byte *iv, int ivLength=-1);
0112     void ProcessData(byte *outString, const byte *inString, size_t length);
0113     size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength);
0114 
0115     /// \brief Resynchronize the cipher

0116     /// \param sector a 64-bit sector number

0117     /// \param order the endian order the word should be written

0118     /// \details The Resynchronize() overload was provided for API

0119     ///  compatibility with the IEEE P1619 paper.

0120     void Resynchronize(word64 sector, ByteOrder order=BIG_ENDIAN_ORDER);
0121 
0122 protected:
0123     virtual void ResizeBuffers();
0124 
0125     inline size_t ProcessLastPlainBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength);
0126     inline size_t ProcessLastCipherBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength);
0127 
0128     virtual BlockCipher& AccessBlockCipher() = 0;
0129     virtual BlockCipher& AccessTweakCipher() = 0;
0130 
0131     const BlockCipher& GetBlockCipher() const
0132         {return const_cast<XTS_ModeBase*>(this)->AccessBlockCipher();}
0133     const BlockCipher& GetTweakCipher() const
0134         {return const_cast<XTS_ModeBase*>(this)->AccessTweakCipher();}
0135 
0136     // Buffers are sized based on ParallelBlocks

0137     AlignedSecByteBlock m_xregister;
0138     AlignedSecByteBlock m_xworkspace;
0139 
0140     // Intel lacks the SSE registers to run 8 or 12 parallel blocks.

0141     // Do not change this value after compiling. It has no effect.

0142 #if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86
0143     enum {ParallelBlocks = 4};
0144 #else
0145     enum {ParallelBlocks = 12};
0146 #endif
0147 };
0148 
0149 /// \brief XTS block cipher mode of operation implementation

0150 /// \tparam CIPHER BlockCipher derived class or type

0151 /// \details XTS_Final() provides access to CIPHER in base class XTS_ModeBase()

0152 ///  through an interface. AccessBlockCipher() and AccessTweakCipher() allow

0153 ///  the XTS_ModeBase() base class to access the user's block cipher without

0154 ///  recompiling the library.

0155 /// \details If <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is 0, then CIPHER must

0156 ///  be a 16-byte block cipher. If <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is

0157 ///  non-zero then CIPHER can be 16, 32, 64, or 128-byte block cipher.

0158 ///  There is risk involved with using XTS with wider block ciphers.

0159 ///  According to Phillip Rogaway, "The narrow width of the underlying PRP and

0160 ///  the poor treatment of fractional final blocks are problems." To enable

0161 ///  wide block cipher support define <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> to

0162 ///  non-zero.

0163 /// \sa <A HREF="http://www.cryptopp.com/wiki/Modes_of_Operation">Modes of

0164 ///  Operation</A> on the Crypto++ wiki, <A

0165 ///  HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf"> Evaluation of Some

0166 ///  Blockcipher Modes of Operation</A>, <A

0167 ///  HREF="https://csrc.nist.gov/publications/detail/sp/800-38e/final">Recommendation

0168 ///  for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on

0169 ///  Storage Devices</A>, <A

0170 ///  HREF="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE P1619-2007</A>

0171 ///  and <A HREF="https://crypto.stackexchange.com/q/74925/10496">IEEE P1619/XTS,

0172 ///  inconsistent reference implementation and test vectors</A>.

0173 /// \since Crypto++ 8.3

0174 template <class CIPHER>
0175 class CRYPTOPP_NO_VTABLE XTS_Final : public XTS_ModeBase
0176 {
0177 protected:
0178     BlockCipher& AccessBlockCipher()
0179         {return *m_cipher;}
0180     BlockCipher& AccessTweakCipher()
0181         {return m_tweaker;}
0182 
0183 protected:
0184     typename CIPHER::Encryption m_tweaker;
0185 };
0186 
0187 /// \brief XTS block cipher mode of operation

0188 /// \tparam CIPHER BlockCipher derived class or type

0189 /// \details XTS mode is a wide block mode defined by IEEE P1619-2008. NIST

0190 ///  SP-800-38E approves the mode for storage devices citing IEEE 1619-2007.

0191 ///  IEEE 1619-2007 provides both a reference implementation and test vectors.

0192 ///  The IEEE reference implementation fails to arrive at the expected result

0193 ///  for some test vectors.

0194 /// \details XTS is only defined for AES. The library can support wide

0195 ///  block ciphers like Kaylna and Threefish since we know the polynomials.

0196 ///  There is risk involved with using XTS with wider block ciphers.

0197 ///  According to Phillip Rogaway, "The narrow width of the underlying PRP and

0198 ///  the poor treatment of fractional final blocks are problems." To enable

0199 ///  wide block cipher support define <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> to

0200 ///  non-zero.

0201 /// \sa <A HREF="http://www.cryptopp.com/wiki/Modes_of_Operation">Modes of

0202 ///  Operation</A> on the Crypto++ wiki, <A

0203 ///  HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf"> Evaluation of Some

0204 ///  Blockcipher Modes of Operation</A>, <A

0205 ///  HREF="https://csrc.nist.gov/publications/detail/sp/800-38e/final">Recommendation

0206 ///  for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on

0207 ///  Storage Devices</A>, <A

0208 ///  HREF="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE P1619-2007</A>

0209 ///  and <A HREF="https://crypto.stackexchange.com/q/74925/10496">IEEE P1619/XTS,

0210 ///  inconsistent reference implementation and test vectors</A>.

0211 /// \since Crypto++ 8.3

0212 template <class CIPHER>
0213 struct XTS : public CipherModeDocumentation
0214 {
0215     typedef CipherModeFinalTemplate_CipherHolder<typename CIPHER::Encryption, XTS_Final<CIPHER> > Encryption;
0216     typedef CipherModeFinalTemplate_CipherHolder<typename CIPHER::Decryption, XTS_Final<CIPHER> > Decryption;
0217 };
0218 
0219 // C++03 lacks the mechanics to typedef a template

0220 #define XTS_Mode XTS
0221 
0222 NAMESPACE_END
0223 
0224 #endif  // CRYPTOPP_XTS_MODE_H