~zooko/cryptopp/trunk

« back to all changes in this revision

Viewing changes to modes.h

  • Committer: weidai
  • Date: 2010-06-18 01:52:34 UTC
  • Revision ID: svn-v4:57ff6487-cd31-0410-9ec3-f628ee90f5f0:trunk/c5:485
avoid SecBlock of arrays

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
 
14
14
NAMESPACE_BEGIN(CryptoPP)
15
15
 
16
 
//! Cipher mode documentation. See NIST SP 800-38A for definitions of these modes.
 
16
//! Cipher modes documentation. See NIST SP 800-38A for definitions of these modes. See AuthenticatedSymmetricCipherDocumentation for authenticated encryption modes.
17
17
 
18
18
/*! Each class derived from this one defines two types, Encryption and Decryption, 
19
19
        both of which implement the SymmetricCipher interface.
37
37
        size_t GetValidKeyLength(size_t n) const {return m_cipher->GetValidKeyLength(n);}
38
38
        bool IsValidKeyLength(size_t n) const {return m_cipher->IsValidKeyLength(n);}
39
39
 
40
 
        void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs);
41
 
 
42
 
        unsigned int OptimalDataAlignment() const {return BlockSize();}
 
40
        unsigned int OptimalDataAlignment() const {return m_cipher->OptimalDataAlignment();}
43
41
 
44
42
        unsigned int IVSize() const {return BlockSize();}
45
 
        void GetNextIV(byte *IV);
46
43
        virtual IV_Requirement IVRequirement() const =0;
47
44
 
 
45
        void SetCipher(BlockCipher &cipher)
 
46
        {
 
47
                this->ThrowIfResynchronizable();
 
48
                this->m_cipher = &cipher;
 
49
                this->ResizeBuffers();
 
50
        }
 
51
 
 
52
        void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
 
53
        {
 
54
                this->ThrowIfInvalidIV(iv);
 
55
                this->m_cipher = &cipher;
 
56
                this->ResizeBuffers();
 
57
                this->SetFeedbackSize(feedbackSize);
 
58
                if (this->IsResynchronizable())
 
59
                        this->Resynchronize(iv);
 
60
        }
 
61
 
48
62
protected:
 
63
        CipherModeBase() : m_cipher(NULL) {}
49
64
        inline unsigned int BlockSize() const {assert(m_register.size() > 0); return (unsigned int)m_register.size();}
50
65
        virtual void SetFeedbackSize(unsigned int feedbackSize)
51
66
        {
56
71
        {
57
72
                m_register.New(m_cipher->BlockSize());
58
73
        }
59
 
        virtual void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv) =0;
60
74
 
61
75
        BlockCipher *m_cipher;
62
 
        SecByteBlock m_register;
 
76
        AlignedSecByteBlock m_register;
63
77
};
64
78
 
65
79
template <class POLICY_INTERFACE>
66
80
class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
67
81
{
68
 
        unsigned int GetAlignment() const {return m_cipher->BlockAlignment();}
 
82
        unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
69
83
        void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
70
84
};
71
85
 
87
101
protected:
88
102
        unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
89
103
        byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
90
 
        void TransformRegister()
91
 
        {
92
 
                m_cipher->ProcessBlock(m_register, m_temp);
93
 
                unsigned int updateSize = BlockSize()-m_feedbackSize;
94
 
                memmove_s(m_register, m_register.size(), m_register+m_feedbackSize, updateSize);
95
 
                memcpy_s(m_register+updateSize, m_register.size()-updateSize, m_temp, m_feedbackSize);
96
 
        }
97
 
        void CipherResynchronize(const byte *iv)
98
 
        {
99
 
                memcpy_s(m_register, m_register.size(), iv, BlockSize());
100
 
                TransformRegister();
101
 
        }
102
 
        void SetFeedbackSize(unsigned int feedbackSize)
103
 
        {
104
 
                if (feedbackSize > BlockSize())
105
 
                        throw InvalidArgument("CFB_Mode: invalid feedback size");
106
 
                m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
107
 
        }
108
 
        void ResizeBuffers()
109
 
        {
110
 
                CipherModeBase::ResizeBuffers();
111
 
                m_temp.New(BlockSize());
112
 
        }
 
104
        bool CanIterate() const {return m_feedbackSize == BlockSize();}
 
105
        void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount);
 
106
        void TransformRegister();
 
107
        void CipherResynchronize(const byte *iv, size_t length);
 
108
        void SetFeedbackSize(unsigned int feedbackSize);
 
109
        void ResizeBuffers();
113
110
 
114
111
        SecByteBlock m_temp;
115
112
        unsigned int m_feedbackSize;
126
123
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
127
124
{
128
125
public:
129
 
        bool IsRandomAccess() const {return false;}
130
 
        IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
 
126
        bool CipherIsRandomAccess() const {return false;}
 
127
        IV_Requirement IVRequirement() const {return UNIQUE_IV;}
131
128
        static const char * CRYPTOPP_API StaticAlgorithmName() {return "OFB";}
132
129
 
133
130
private:
134
131
        unsigned int GetBytesPerIteration() const {return BlockSize();}
135
 
        unsigned int GetIterationsToBuffer() const {return 1;}
136
 
        void WriteKeystream(byte *keystreamBuffer, size_t iterationCount)
137
 
        {
138
 
                assert(iterationCount == 1);
139
 
                m_cipher->ProcessBlock(keystreamBuffer);
140
 
                memcpy_s(m_register, m_register.size(), keystreamBuffer, BlockSize());
141
 
        }
142
 
        void CipherResynchronize(byte *keystreamBuffer, const byte *iv)
143
 
        {
144
 
                CopyOrZero(keystreamBuffer, iv, BlockSize());
145
 
        }
 
132
        unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
 
133
        void WriteKeystream(byte *keystreamBuffer, size_t iterationCount);
 
134
        void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
146
135
};
147
136
 
148
137
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
149
138
{
150
139
public:
151
 
        bool IsRandomAccess() const {return true;}
152
 
        IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
153
 
        void GetNextIV(byte *IV);
 
140
        bool CipherIsRandomAccess() const {return true;}
 
141
        IV_Requirement IVRequirement() const {return RANDOM_IV;}
154
142
        static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";}
155
143
 
156
 
private:
 
144
protected:
 
145
        virtual void IncrementCounterBy256();
 
146
 
 
147
        unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
157
148
        unsigned int GetBytesPerIteration() const {return BlockSize();}
158
149
        unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
159
150
        void WriteKeystream(byte *buffer, size_t iterationCount)
160
151
                {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
161
152
        bool CanOperateKeystream() const {return true;}
162
153
        void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
163
 
        void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
 
154
        void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
164
155
        void SeekToIteration(lword iterationCount);
165
156
 
166
 
        inline void ProcessMultipleBlocks(byte *output, const byte *input, size_t n);
167
 
 
168
 
        SecByteBlock m_counterArray;
 
157
        AlignedSecByteBlock m_counterArray;
169
158
};
170
159
 
171
160
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase
172
161
{
173
162
public:
174
 
        void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv);
 
163
        void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
175
164
        unsigned int MandatoryBlockSize() const {return BlockSize();}
176
165
        bool IsRandomAccess() const {return false;}
177
166
        bool IsSelfInverting() const {return false;}
178
167
        bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
179
 
        void Resynchronize(const byte *iv) {memcpy_s(m_register, m_register.size(), iv, BlockSize());}
180
 
        void ProcessData(byte *outString, const byte *inString, size_t length);
 
168
        void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));}
181
169
 
182
170
protected:
183
171
        bool RequireAlignedInput() const {return true;}
184
 
        virtual void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks) =0;
185
172
        void ResizeBuffers()
186
173
        {
187
174
                CipherModeBase::ResizeBuffers();
194
181
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase
195
182
{
196
183
public:
 
184
        void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs)
 
185
                {m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();}
197
186
        IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
198
187
        unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
199
 
        void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
200
 
                {m_cipher->ProcessAndXorMultipleBlocks(inString, NULL, outString, numberOfBlocks);}
 
188
        void ProcessData(byte *outString, const byte *inString, size_t length);
201
189
        static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECB";}
202
190
};
203
191
 
213
201
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase
214
202
{
215
203
public:
216
 
        void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks);
 
204
        void ProcessData(byte *outString, const byte *inString, size_t length);
217
205
};
218
206
 
219
207
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption
225
213
        static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC/CTS";}
226
214
 
227
215
protected:
228
 
        void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv)
 
216
        void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
229
217
        {
230
 
                CBC_Encryption::UncheckedSetKey(params, key, length, iv);
 
218
                CBC_Encryption::UncheckedSetKey(key, length, params);
231
219
                m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL);
232
220
        }
233
221
 
237
225
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase
238
226
{
239
227
public:
240
 
        void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks);
 
228
        void ProcessData(byte *outString, const byte *inString, size_t length);
241
229
        
242
230
protected:
243
231
        void ResizeBuffers()
245
233
                BlockOrientedCipherModeBase::ResizeBuffers();
246
234
                m_temp.New(BlockSize());
247
235
        }
248
 
        SecByteBlock m_temp;
 
236
        AlignedSecByteBlock m_temp;
249
237
};
250
238
 
251
239
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption
273
261
        CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv)
274
262
        {
275
263
                this->m_cipher = &this->m_object;
276
 
                this->SetKey(key, length, MakeParameters(Name::IV(), iv));
 
264
                this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize())));
277
265
        }
278
266
        CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv, int feedbackSize)
279
267
        {
280
268
                this->m_cipher = &this->m_object;
281
 
                this->SetKey(key, length, MakeParameters(Name::IV(), iv)(Name::FeedbackSize(), feedbackSize));
 
269
                this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))(Name::FeedbackSize(), feedbackSize));
282
270
        }
283
271
 
284
272
        static std::string CRYPTOPP_API StaticAlgorithmName()
292
280
public:
293
281
        CipherModeFinalTemplate_ExternalCipher() {}
294
282
        CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher)
295
 
                {SetCipher(cipher);}
 
283
                {this->SetCipher(cipher);}
296
284
        CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
297
 
                {SetCipherWithIV(cipher, iv, feedbackSize);}
 
285
                {this->SetCipherWithIV(cipher, iv, feedbackSize);}
298
286
 
299
 
        void SetCipher(BlockCipher &cipher);
300
 
        void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0);
 
287
        std::string AlgorithmName() const
 
288
                {return (this->m_cipher ? this->m_cipher->AlgorithmName() + "/" : std::string("")) + BASE::StaticAlgorithmName();}
301
289
};
302
290
 
303
 
template <class BASE>
304
 
void CipherModeFinalTemplate_ExternalCipher<BASE>::SetCipher(BlockCipher &cipher)
305
 
{
306
 
        this->ThrowIfResynchronizable();
307
 
        this->m_cipher = &cipher;
308
 
        this->ResizeBuffers();
309
 
}
310
 
 
311
 
template <class BASE>
312
 
void CipherModeFinalTemplate_ExternalCipher<BASE>::SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize)
313
 
{
314
 
        this->ThrowIfInvalidIV(iv);
315
 
        this->m_cipher = &cipher;
316
 
        this->ResizeBuffers();
317
 
        this->SetFeedbackSize(feedbackSize);
318
 
        if (this->IsResynchronizable())
319
 
                this->Resynchronize(iv);
320
 
}
321
 
 
322
291
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
323
292
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
324
293
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;