Line | Count | Source (jump to first uncovered line) |
1 | | // xts.h - written and placed in the public domain by Jeffrey Walton |
2 | | |
3 | | /// \file xts.h |
4 | | /// \brief Classes for XTS block cipher mode of operation |
5 | | /// \details XTS mode is a wide block mode defined by IEEE P1619-2008. NIST |
6 | | /// SP-800-38E approves the mode for storage devices citing IEEE 1619-2007. |
7 | | /// IEEE 1619-2007 provides both a reference implementation and test vectors. |
8 | | /// The IEEE reference implementation fails to arrive at the expected result |
9 | | /// for some test vectors. |
10 | | /// \sa <A HREF="http://www.cryptopp.com/wiki/Modes_of_Operation">Modes of |
11 | | /// Operation</A> on the Crypto++ wiki, <A |
12 | | /// HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf"> Evaluation of Some |
13 | | /// Blockcipher Modes of Operation</A>, <A |
14 | | /// HREF="https://csrc.nist.gov/publications/detail/sp/800-38e/final">Recommendation |
15 | | /// for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on |
16 | | /// Storage Devices</A>, <A |
17 | | /// HREF="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE P1619-2007</A> |
18 | | /// and <A HREF="https://crypto.stackexchange.com/q/74925/10496">IEEE P1619/XTS, |
19 | | /// inconsistent reference implementation and test vectors</A>. |
20 | | /// \since Crypto++ 8.3 |
21 | | |
22 | | #ifndef CRYPTOPP_XTS_MODE_H |
23 | | #define CRYPTOPP_XTS_MODE_H |
24 | | |
25 | | #include "cryptlib.h" |
26 | | #include "secblock.h" |
27 | | #include "modes.h" |
28 | | #include "misc.h" |
29 | | |
30 | | /// \brief Enable XTS for wide block ciphers |
31 | | /// \details XTS is only defined for AES. The library can support wide |
32 | | /// block ciphers like Kaylna and Threefish since we know the polynomials. |
33 | | /// To enable wide block ciphers define <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> |
34 | | /// to non-zero. Note this is a library compile time define. |
35 | | /// \details There is risk involved with using XTS with wider block ciphers. |
36 | | /// According to Phillip Rogaway, "The narrow width of the underlying PRP and |
37 | | /// the poor treatment of fractional final blocks are problems." |
38 | | /// \sa <A HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf">Evaluation |
39 | | /// of Some Blockcipher Modes of Operation</A> |
40 | | /// \since Crypto++ 8.3 |
41 | | #ifndef CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS |
42 | | # define CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS 0 |
43 | | #endif // CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS |
44 | | |
45 | | NAMESPACE_BEGIN(CryptoPP) |
46 | | |
47 | | /// \brief XTS block cipher mode of operation default implementation |
48 | | /// \since Crypto++ 8.3 |
49 | | class CRYPTOPP_NO_VTABLE XTS_ModeBase : public BlockOrientedCipherModeBase |
50 | | { |
51 | | public: |
52 | | /// \brief The algorithm name |
53 | | /// \return the algorithm name |
54 | | /// \details StaticAlgorithmName returns the algorithm's name as a static |
55 | | /// member function. |
56 | | CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() |
57 | 2 | {return "XTS";} |
58 | | |
59 | 8 | virtual ~XTS_ModeBase() {} |
60 | | |
61 | | std::string AlgorithmName() const |
62 | 0 | {return GetBlockCipher().AlgorithmName() + "/XTS";} |
63 | | std::string AlgorithmProvider() const |
64 | 0 | {return GetBlockCipher().AlgorithmProvider();} |
65 | | |
66 | | size_t MinKeyLength() const |
67 | 0 | {return GetBlockCipher().MinKeyLength()*2;} |
68 | | size_t MaxKeyLength() const |
69 | 0 | {return GetBlockCipher().MaxKeyLength()*2;} |
70 | | size_t DefaultKeyLength() const |
71 | 0 | {return GetBlockCipher().DefaultKeyLength()*2;} |
72 | | size_t GetValidKeyLength(size_t n) const |
73 | 0 | {return 2*GetBlockCipher().GetValidKeyLength((n+1)/2);} |
74 | | bool IsValidKeyLength(size_t keylength) const |
75 | 0 | {return keylength == GetValidKeyLength(keylength);} |
76 | | |
77 | | /// \brief Validates the key length |
78 | | /// \param length the size of the keying material, in bytes |
79 | | /// \throw InvalidKeyLength if the key length is invalid |
80 | | void ThrowIfInvalidKeyLength(size_t length); |
81 | | |
82 | | /// Provides the block size of the cipher |
83 | | /// \return the block size of the cipher, in bytes |
84 | | unsigned int BlockSize() const |
85 | 0 | {return GetBlockCipher().BlockSize();} |
86 | | |
87 | | /// \brief Provides the input block size most efficient for this cipher |
88 | | /// \return The input block size that is most efficient for the cipher |
89 | | /// \details The base class implementation returns MandatoryBlockSize(). |
90 | | /// \note Optimal input length is |
91 | | /// <tt>n * OptimalBlockSize() - GetOptimalBlockSizeUsed()</tt> for |
92 | | /// any <tt>n \> 0</tt>. |
93 | | unsigned int GetOptimalBlockSize() const |
94 | 0 | {return GetBlockCipher().BlockSize()*ParallelBlocks;} |
95 | | unsigned int MinLastBlockSize() const |
96 | 0 | {return GetBlockCipher().BlockSize()+1;} |
97 | | unsigned int OptimalDataAlignment() const |
98 | 0 | {return GetBlockCipher().OptimalDataAlignment();} |
99 | | |
100 | | /// \brief Validates the block size |
101 | | /// \param length the block size of the cipher, in bytes |
102 | | /// \throw InvalidArgument if the block size is invalid |
103 | | /// \details If <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is 0, |
104 | | /// then CIPHER must be a 16-byte block cipher. If |
105 | | /// <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is non-zero then |
106 | | /// CIPHER can be 16, 32, 64, or 128-byte block cipher. |
107 | | void ThrowIfInvalidBlockSize(size_t length); |
108 | | |
109 | | void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs); |
110 | 0 | IV_Requirement IVRequirement() const {return UNIQUE_IV;} |
111 | | void Resynchronize(const byte *iv, int ivLength=-1); |
112 | | void ProcessData(byte *outString, const byte *inString, size_t length); |
113 | | size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); |
114 | | |
115 | | /// \brief Resynchronize the cipher |
116 | | /// \param sector a 64-bit sector number |
117 | | /// \param order the endian order the word should be written |
118 | | /// \details The Resynchronize() overload was provided for API |
119 | | /// compatibility with the IEEE P1619 paper. |
120 | | void Resynchronize(word64 sector, ByteOrder order=BIG_ENDIAN_ORDER); |
121 | | |
122 | | protected: |
123 | | virtual void ResizeBuffers(); |
124 | | |
125 | | inline size_t ProcessLastPlainBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); |
126 | | inline size_t ProcessLastCipherBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); |
127 | | |
128 | | virtual BlockCipher& AccessBlockCipher() = 0; |
129 | | virtual BlockCipher& AccessTweakCipher() = 0; |
130 | | |
131 | | const BlockCipher& GetBlockCipher() const |
132 | 14 | {return const_cast<XTS_ModeBase*>(this)->AccessBlockCipher();} |
133 | | const BlockCipher& GetTweakCipher() const |
134 | 0 | {return const_cast<XTS_ModeBase*>(this)->AccessTweakCipher();} |
135 | | |
136 | | // Buffers are sized based on ParallelBlocks |
137 | | AlignedSecByteBlock m_xregister; |
138 | | AlignedSecByteBlock m_xworkspace; |
139 | | |
140 | | // Intel lacks the SSE registers to run 8 or 12 parallel blocks. |
141 | | // Do not change this value after compiling. It has no effect. |
142 | | #if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X86 |
143 | | enum {ParallelBlocks = 4}; |
144 | | #else |
145 | | enum {ParallelBlocks = 12}; |
146 | | #endif |
147 | | }; |
148 | | |
149 | | /// \brief XTS block cipher mode of operation implementation |
150 | | /// \tparam CIPHER BlockCipher derived class or type |
151 | | /// \details XTS_Final() provides access to CIPHER in base class XTS_ModeBase() |
152 | | /// through an interface. AccessBlockCipher() and AccessTweakCipher() allow |
153 | | /// the XTS_ModeBase() base class to access the user's block cipher without |
154 | | /// recompiling the library. |
155 | | /// \details If <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is 0, then CIPHER must |
156 | | /// be a 16-byte block cipher. If <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> is |
157 | | /// non-zero then CIPHER can be 16, 32, 64, or 128-byte block cipher. |
158 | | /// There is risk involved with using XTS with wider block ciphers. |
159 | | /// According to Phillip Rogaway, "The narrow width of the underlying PRP and |
160 | | /// the poor treatment of fractional final blocks are problems." To enable |
161 | | /// wide block cipher support define <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> to |
162 | | /// non-zero. |
163 | | /// \sa <A HREF="http://www.cryptopp.com/wiki/Modes_of_Operation">Modes of |
164 | | /// Operation</A> on the Crypto++ wiki, <A |
165 | | /// HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf"> Evaluation of Some |
166 | | /// Blockcipher Modes of Operation</A>, <A |
167 | | /// HREF="https://csrc.nist.gov/publications/detail/sp/800-38e/final">Recommendation |
168 | | /// for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on |
169 | | /// Storage Devices</A>, <A |
170 | | /// HREF="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE P1619-2007</A> |
171 | | /// and <A HREF="https://crypto.stackexchange.com/q/74925/10496">IEEE P1619/XTS, |
172 | | /// inconsistent reference implementation and test vectors</A>. |
173 | | /// \since Crypto++ 8.3 |
174 | | template <class CIPHER> |
175 | | class CRYPTOPP_NO_VTABLE XTS_Final : public XTS_ModeBase |
176 | | { |
177 | | protected: |
178 | | BlockCipher& AccessBlockCipher() |
179 | 14 | {return *m_cipher;} |
180 | | BlockCipher& AccessTweakCipher() |
181 | 0 | {return m_tweaker;} |
182 | | |
183 | | protected: |
184 | | typename CIPHER::Encryption m_tweaker; |
185 | | }; |
186 | | |
187 | | /// \brief XTS block cipher mode of operation |
188 | | /// \tparam CIPHER BlockCipher derived class or type |
189 | | /// \details XTS mode is a wide block mode defined by IEEE P1619-2008. NIST |
190 | | /// SP-800-38E approves the mode for storage devices citing IEEE 1619-2007. |
191 | | /// IEEE 1619-2007 provides both a reference implementation and test vectors. |
192 | | /// The IEEE reference implementation fails to arrive at the expected result |
193 | | /// for some test vectors. |
194 | | /// \details XTS is only defined for AES. The library can support wide |
195 | | /// block ciphers like Kaylna and Threefish since we know the polynomials. |
196 | | /// There is risk involved with using XTS with wider block ciphers. |
197 | | /// According to Phillip Rogaway, "The narrow width of the underlying PRP and |
198 | | /// the poor treatment of fractional final blocks are problems." To enable |
199 | | /// wide block cipher support define <tt>CRYPTOPP_XTS_WIDE_BLOCK_CIPHERS</tt> to |
200 | | /// non-zero. |
201 | | /// \sa <A HREF="http://www.cryptopp.com/wiki/Modes_of_Operation">Modes of |
202 | | /// Operation</A> on the Crypto++ wiki, <A |
203 | | /// HREF="https://web.cs.ucdavis.edu/~rogaway/papers/modes.pdf"> Evaluation of Some |
204 | | /// Blockcipher Modes of Operation</A>, <A |
205 | | /// HREF="https://csrc.nist.gov/publications/detail/sp/800-38e/final">Recommendation |
206 | | /// for Block Cipher Modes of Operation: The XTS-AES Mode for Confidentiality on |
207 | | /// Storage Devices</A>, <A |
208 | | /// HREF="http://libeccio.di.unisa.it/Crypto14/Lab/p1619.pdf">IEEE P1619-2007</A> |
209 | | /// and <A HREF="https://crypto.stackexchange.com/q/74925/10496">IEEE P1619/XTS, |
210 | | /// inconsistent reference implementation and test vectors</A>. |
211 | | /// \since Crypto++ 8.3 |
212 | | template <class CIPHER> |
213 | | struct XTS : public CipherModeDocumentation |
214 | | { |
215 | | typedef CipherModeFinalTemplate_CipherHolder<typename CIPHER::Encryption, XTS_Final<CIPHER> > Encryption; |
216 | | typedef CipherModeFinalTemplate_CipherHolder<typename CIPHER::Decryption, XTS_Final<CIPHER> > Decryption; |
217 | | }; |
218 | | |
219 | | // C++03 lacks the mechanics to typedef a template |
220 | | #define XTS_Mode XTS |
221 | | |
222 | | NAMESPACE_END |
223 | | |
224 | | #endif // CRYPTOPP_XTS_MODE_H |