~zooko/cryptopp/trunk

« back to all changes in this revision

Viewing changes to secblock.h

  • Committer: weidai
  • Date: 2009-03-02 02:39:17 UTC
  • Revision ID: svn-v4:57ff6487-cd31-0410-9ec3-f628ee90f5f0:trunk/c5:433
changes for 5.6: 
    - added AuthenticatedSymmetricCipher interface class and Filter wrappers
    - added CCM, GCM (with SSE2 assembly), CMAC, and SEED
    - improved AES speed on x86 and x64
    - removed WORD64_AVAILABLE; compiler 64-bit int support is now required

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 
6
6
#include "config.h"
7
7
#include "misc.h"
8
 
#include <string.h>             // CodeWarrior doesn't have memory.h
9
8
#include <assert.h>
10
9
 
 
10
#if defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE) || defined(QNX)
 
11
        #include <malloc.h>
 
12
#else
 
13
        #include <stdlib.h>
 
14
#endif
 
15
 
11
16
NAMESPACE_BEGIN(CryptoPP)
12
17
 
13
18
// ************** secure memory allocation ***************
65
70
 
66
71
        if (preserve)
67
72
        {
68
 
                A b;
69
 
                typename A::pointer newPointer = b.allocate(newSize, NULL);
 
73
                typename A::pointer newPointer = a.allocate(newSize, NULL);
70
74
                memcpy_s(newPointer, sizeof(T)*newSize, p, sizeof(T)*STDMIN(oldSize, newSize));
71
75
                a.deallocate(p, oldSize);
72
 
                std::swap(a, b);
73
76
                return newPointer;
74
77
        }
75
78
        else
83
86
#pragma warning(pop)
84
87
#endif
85
88
 
86
 
template <class T>
 
89
template <class T, bool T_Align16 = false>
87
90
class AllocatorWithCleanup : public AllocatorBase<T>
88
91
{
89
92
public:
94
97
                CheckSize(n);
95
98
                if (n == 0)
96
99
                        return NULL;
97
 
                return new T[n];
 
100
 
 
101
                if (T_Align16 && n*sizeof(T) >= 16)
 
102
                {
 
103
                        byte *p;
 
104
                #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE
 
105
                        while (!(p = (byte *)_mm_malloc(sizeof(T)*n, 16)))
 
106
                #elif defined(CRYPTOPP_MEMALIGN_AVAILABLE)
 
107
                        while (!(p = (byte *)memalign(16, sizeof(T)*n)))
 
108
                #elif defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16)
 
109
                        while (!(p = (byte *)malloc(sizeof(T)*n)))
 
110
                #else
 
111
                        while (!(p = (byte *)malloc(sizeof(T)*n + 16)))
 
112
                #endif
 
113
                                CallNewHandler();
 
114
 
 
115
                #ifdef CRYPTOPP_NO_ALIGNED_ALLOC
 
116
                        size_t adjustment = 16-((size_t)p%16);
 
117
                        p += adjustment;
 
118
                        p[-1] = (byte)adjustment;
 
119
                #endif
 
120
 
 
121
                        assert(IsAlignedOn(p, 16));
 
122
                        return (pointer)p;
 
123
                }
 
124
 
 
125
                pointer p;
 
126
                while (!(p = (pointer)malloc(sizeof(T)*n)))
 
127
                        CallNewHandler();
 
128
                return p;
98
129
        }
99
130
 
100
131
        void deallocate(void *p, size_type n)
101
132
        {
102
 
                memset(p, 0, n*sizeof(T));
103
 
                delete [] (T *)p;
 
133
                memset_z(p, 0, n*sizeof(T));
 
134
 
 
135
                if (T_Align16 && n*sizeof(T) >= 16)
 
136
                {
 
137
                #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE
 
138
                        _mm_free(p);
 
139
                #elif defined(CRYPTOPP_NO_ALIGNED_ALLOC)
 
140
                        p = (byte *)p - ((byte *)p)[-1];
 
141
                        free(p);
 
142
                #else
 
143
                        free(p);
 
144
                #endif
 
145
                        return;
 
146
                }
 
147
 
 
148
                free(p);
104
149
        }
105
150
 
106
151
        pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve)
110
155
 
111
156
        // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a
112
157
        // template class member called rebind".
113
 
    template <class U> struct rebind { typedef AllocatorWithCleanup<U> other; };
 
158
    template <class U> struct rebind { typedef AllocatorWithCleanup<U, T_Align16> other; };
 
159
#if _MSC_VER >= 1500
 
160
        AllocatorWithCleanup() {}
 
161
        template <class U, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<U, A> &) {}
 
162
#endif
114
163
};
115
164
 
116
165
CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
117
166
CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
118
167
CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
 
168
CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
 
169
#if CRYPTOPP_BOOL_X86
 
170
CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>;   // for Integer
 
171
#endif
119
172
 
120
173
template <class T>
121
174
class NullAllocator : public AllocatorBase<T>
140
193
// This allocator can't be used with standard collections because
141
194
// they require that all objects of the same allocator type are equivalent.
142
195
// So this is for use with SecBlock only.
143
 
template <class T, size_t S, class A = NullAllocator<T> >
 
196
template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false>
144
197
class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
145
198
{
146
199
public:
150
203
 
151
204
        pointer allocate(size_type n)
152
205
        {
 
206
                assert(IsAlignedOn(m_array, 8));
 
207
 
153
208
                if (n <= S && !m_allocated)
154
209
                {
155
210
                        m_allocated = true;
156
 
                        return m_array;
 
211
                        return GetAlignedArray();
157
212
                }
158
213
                else
159
214
                        return m_fallbackAllocator.allocate(n);
164
219
                if (n <= S && !m_allocated)
165
220
                {
166
221
                        m_allocated = true;
167
 
                        return m_array;
 
222
                        return GetAlignedArray();
168
223
                }
169
224
                else
170
225
                        return m_fallbackAllocator.allocate(n, hint);
172
227
 
173
228
        void deallocate(void *p, size_type n)
174
229
        {
175
 
                if (p == m_array)
 
230
                if (p == GetAlignedArray())
176
231
                {
177
232
                        assert(n <= S);
178
233
                        assert(m_allocated);
185
240
 
186
241
        pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve)
187
242
        {
188
 
                if (p == m_array && newSize <= S)
 
243
                if (p == GetAlignedArray() && newSize <= S)
189
244
                {
190
245
                        assert(oldSize <= S);
191
246
                        if (oldSize > newSize)
203
258
        size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
204
259
 
205
260
private:
 
261
#ifdef __BORLANDC__
 
262
        T* GetAlignedArray() {return m_array;}
206
263
        T m_array[S];
 
264
#else
 
265
        T* GetAlignedArray() {return T_Align16 ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;}
 
266
        CRYPTOPP_ALIGN_DATA(8) T m_array[T_Align16 ? S+8/sizeof(T) : S];
 
267
#endif
207
268
        A m_fallbackAllocator;
208
269
        bool m_allocated;
209
270
};
218
279
        typedef typename A::const_pointer const_iterator;
219
280
        typedef typename A::size_type size_type;
220
281
 
221
 
    explicit SecBlock(size_type size=0)
 
282
        explicit SecBlock(size_type size=0)
222
283
                : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
223
284
        SecBlock(const SecBlock<T, A> &t)
224
285
                : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));}
227
288
        {
228
289
                m_ptr = m_alloc.allocate(len, NULL);
229
290
                if (t == NULL)
230
 
                        memset(m_ptr, 0, len*sizeof(T));
 
291
                        memset_z(m_ptr, 0, len*sizeof(T));
231
292
                else
232
293
                        memcpy(m_ptr, t, len*sizeof(T));
233
294
        }
235
296
        ~SecBlock()
236
297
                {m_alloc.deallocate(m_ptr, m_size);}
237
298
 
 
299
#ifdef __BORLANDC__
 
300
        operator T *() const
 
301
                {return (T*)m_ptr;}
 
302
#else
238
303
        operator const void *() const
239
304
                {return m_ptr;}
240
305
        operator void *()
241
306
                {return m_ptr;}
242
 
#if defined(__GNUC__) && __GNUC__ < 3   // reduce warnings
243
 
        operator const void *()
244
 
                {return m_ptr;}
245
 
#endif
246
307
 
247
308
        operator const T *() const
248
309
                {return m_ptr;}
249
310
        operator T *()
250
311
                {return m_ptr;}
251
 
#if defined(__GNUC__) && __GNUC__ < 3   // reduce warnings
252
 
        operator const T *()
253
 
                {return m_ptr;}
254
312
#endif
255
313
 
256
314
//      T *operator +(size_type offset)
280
338
        size_type size() const {return m_size;}
281
339
        bool empty() const {return m_size == 0;}
282
340
 
 
341
        byte * BytePtr() {return (byte *)m_ptr;}
 
342
        const byte * BytePtr() const {return (const byte *)m_ptr;}
283
343
        size_type SizeInBytes() const {return m_size*sizeof(T);}
284
344
 
 
345
        //! set contents and size
285
346
        void Assign(const T *t, size_type len)
286
347
        {
287
348
                New(len);
288
349
                memcpy_s(m_ptr, m_size*sizeof(T), t, len*sizeof(T));
289
350
        }
290
351
 
 
352
        //! copy contents and size from another SecBlock
291
353
        void Assign(const SecBlock<T, A> &t)
292
354
        {
293
355
                New(t.m_size);
300
362
                return *this;
301
363
        }
302
364
 
 
365
        // append to this object
303
366
        SecBlock<T, A>& operator+=(const SecBlock<T, A> &t)
304
367
        {
305
368
                size_type oldSize = m_size;
308
371
                return *this;
309
372
        }
310
373
 
 
374
        // append operator
311
375
        SecBlock<T, A> operator+(const SecBlock<T, A> &t)
312
376
        {
313
377
                SecBlock<T, A> result(m_size+t.m_size);
318
382
 
319
383
        bool operator==(const SecBlock<T, A> &t) const
320
384
        {
321
 
                return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0;
 
385
                return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T));
322
386
        }
323
387
 
324
388
        bool operator!=(const SecBlock<T, A> &t) const
326
390
                return !operator==(t);
327
391
        }
328
392
 
 
393
        //! change size, without preserving contents
329
394
        void New(size_type newSize)
330
395
        {
331
396
                m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
332
397
                m_size = newSize;
333
398
        }
334
399
 
 
400
        //! change size and set contents to 0
335
401
        void CleanNew(size_type newSize)
336
402
        {
337
403
                New(newSize);
338
404
                memset(m_ptr, 0, m_size*sizeof(T));
339
405
        }
340
406
 
 
407
        //! change size only if newSize > current size. contents are preserved
341
408
        void Grow(size_type newSize)
342
409
        {
343
410
                if (newSize > m_size)
347
414
                }
348
415
        }
349
416
 
 
417
        //! change size only if newSize > current size. contents are preserved and additional area is set to 0
350
418
        void CleanGrow(size_type newSize)
351
419
        {
352
420
                if (newSize > m_size)
357
425
                }
358
426
        }
359
427
 
 
428
        //! change size and preserve contents
360
429
        void resize(size_type newSize)
361
430
        {
362
431
                m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
363
432
                m_size = newSize;
364
433
        }
365
434
 
 
435
        //! swap contents and size with another SecBlock
366
436
        void swap(SecBlock<T, A> &b)
367
437
        {
368
438
                std::swap(m_alloc, b.m_alloc);
377
447
};
378
448
 
379
449
typedef SecBlock<byte> SecByteBlock;
 
450
typedef SecBlock<byte, AllocatorWithCleanup<byte, CRYPTOPP_BOOL_X86 | CRYPTOPP_BOOL_X64> > AlignedSecByteBlock;
380
451
typedef SecBlock<word> SecWordBlock;
381
452
 
 
453
//! a SecBlock with fixed size, allocated statically
382
454
template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
383
455
class FixedSizeSecBlock : public SecBlock<T, A>
384
456
{
386
458
        explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
387
459
};
388
460
 
 
461
template <class T, unsigned int S, bool T_Align16 = CRYPTOPP_BOOL_X86 | CRYPTOPP_BOOL_X64>
 
462
class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<word32>, T_Align16> >
 
463
{
 
464
};
 
465
 
 
466
//! a SecBlock that preallocates size S statically, and uses the heap when this size is exceeded
389
467
template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
390
468
class SecBlockWithHint : public SecBlock<T, A>
391
469
{
393
471
        explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
394
472
};
395
473
 
396
 
template<class T, class U>
397
 
inline bool operator==(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (true);}
398
 
template<class T, class U>
399
 
inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (false);}
 
474
template<class T, bool A, class U, bool B>
 
475
inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (true);}
 
476
template<class T, bool A, class U, bool B>
 
477
inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (false);}
400
478
 
401
479
NAMESPACE_END
402
480
 
407
485
        a.swap(b);
408
486
}
409
487
 
410
 
#if defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)
 
488
#if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES))
 
489
// working for STLport 5.1.3 and MSVC 6 SP5
411
490
template <class _Tp1, class _Tp2>
412
491
inline CryptoPP::AllocatorWithCleanup<_Tp2>&
413
492
__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)