I am using Crypto++ library to decrypt files with AES algorithm in CBC mode. I came across SecByteBlock
class in sample code of AES which says
The key is declared on the stack using a SecByteBlock to ensure the sensitive material is zeroized.
Can someone please explain me when the contents of SecByteBlock
will get cleared and what advantages this class offer over char*
.
Thanks In Advance
[title] Advantages of SecByteBlock class from Crypto++
The advantage of using SecByteBlock
is you get the managed buffer with zeroization. Zeroization is often a compliance item. For example, FIPS 140-2 requires it, even at Level 1 validations.
A second, non obvious benefit is the allocator does not initialize POD memory - it returns a raw block. That makes a lot of sense since you often take a 0-value initialized and then overwrite the contents with data. There's no sense in intializing it, and it saves a lot of time.
You can get SecBlock
to provide a 0-value initialized block. Here's how to do both:
SecByteBlock block1(32);
SecByteBlock block2(NULL, 32);
block1
is 32-bytes in size, uninitialized and its contents will be garbage.
block2
is also 32-bytes in size, but it uses the (ptr, size)
overload. The overload will either copy-in the block pointed to by ptr
, or it will write 0's if its NULL
.
For completeness and reference, a SecByteBlock
is just a typedef for SecBlock<byte>
. SecBlock<T>
is the class of interest, and the library frequently uses SecBlock<byte>
, SecBlock<word32>
, SecBlock<word64>
, etc.
Here's the Doxygen generated manual page for SecBlock
: SecBlock< T, A > Class Template Reference. And here's the header file for secblock.h (its a header only implementation).
Can someone please explain me when the contents of
SecByteBlock
will get cleared ...
The contents of SecByteBlock
are cleared under the obvious case of object destruction. That is, the memory allocated to the SecBlock
are cleared with a pattern of 0's when the destructor runs.
There's a non obvious case, and that's when resize
is called to shrink one. In this case, the extra space being returned to the OS is wiped, too.
You can see the wiping in the source code. For example, from Crypto++ 5.6.4 secblock.h:
187 //! \brief Deallocates a block of memory
188 //! \param ptr the pointer for the allocation
189 //! \param size the size of the allocation, in elements
190 //! \details Internally, SecureWipeArray() is called before deallocating the memory.
191 //! Once the memory block is wiped or zeroized, AlignedDeallocate() or
192 //! UnalignedDeallocate() is called.
193 //! \details AlignedDeallocate() is used if T_Align16 is true.
194 //! UnalignedDeallocate() used if T_Align16 is false.
195 void deallocate(void *ptr, size_type size)
196 {
197 CRYPTOPP_ASSERT((ptr && size) || !(ptr || size));
198 SecureWipeArray((pointer)ptr, size);
199
200 #if CRYPTOPP_BOOL_ALIGN16
201 if (T_Align16 && size*sizeof(T) >= 16)
202 return AlignedDeallocate(ptr);
203 #endif
204
205 UnalignedDeallocate(ptr);
206 }
what advantages this class offer over char*.
Well, the SecBlock<byte>
is a class that manages a buffer. char*
is just a type and there's not much to it. You have to managed the buffer that the char*
is pointing to.
You can use something like a std::string
, but you will not get overflow detection (only std::vector
is required to check for it) and you will not get zeroization.
With that said, you can do both of these:
typdef SecBlock<char> SecCharBlock
typedef std::basic_string<char, std::char_traits<char>, AllocatorWithCleanup<char> > secure_string
The second one is kind of cool. You can do it because secblock.h provides a secure allocator that's compatible with the standard library. SecBlock<T>
uses the secure allocator internally, and its called an AllocatiorWithCleanup<T>
.
OpenSSL's wiki page on EVP Symmetric Encryption and Decryption | C++ Progams uses a similar allocator to supply a secure_string
class in their example. OpenSS:'s zallocator
calls OpenSSL_cleanse
.
From Crypto++ 5.6.4 secblock.h:
141 //! \class AllocatorWithCleanup
142 //! \brief Allocates a block of memory with cleanup
143 //! \tparam T class or type
144 //! \tparam T_Align16 boolean that determines whether allocations should be aligned on 16-byte boundaries
145 //! \details If T_Align16 is true, then AllocatorWithCleanup calls AlignedAllocate()
146 //! for memory allocations. If T_Align16 is false, then AllocatorWithCleanup() calls
147 //! UnalignedAllocate() for memory allocations.
148 //! \details Template parameter T_Align16 is effectively controlled by cryptlib.h and mirrors
149 //! CRYPTOPP_BOOL_ALIGN16. CRYPTOPP_BOOL_ALIGN16 is often used as the template parameter.
150 template <class T, bool T_Align16 = false>
151 class AllocatorWithCleanup : public AllocatorBase<T>
152 {
153 public:
154 CRYPTOPP_INHERIT_ALLOCATOR_TYPES
155
156 //! \brief Allocates a block of memory
157 //! \param ptr the size of the allocation
158 //! \param size the size of the allocation, in elements
159 //! \returns a memory block
160 //! \throws InvalidArgument
161 //! \details allocate() first checks the size of the request. If it is non-0
162 //! and less than max_size(), then an attempt is made to fulfill the request
163 //! using either AlignedAllocate() or UnalignedAllocate().
164 //! \details AlignedAllocate() is used if T_Align16 is true.
165 //! UnalignedAllocate() used if T_Align16 is false.
166 //! \details This is the C++ *Placement New* operator. ptr is not used, and the function
167 //! CRYPTOPP_ASSERTs in Debug builds if ptr is non-NULL.
168 //! \sa CallNewHandler() for the methods used to recover from a failed
169 //! allocation attempt.
170 //! \note size is the count of elements, and not the number of bytes
171 pointer allocate(size_type size, const void *ptr = NULL)
172 {
173 CRYPTOPP_UNUSED(ptr); CRYPTOPP_ASSERT(ptr == NULL);
174 this->CheckSize(size);
175 if (size == 0)
176 return NULL;
177
178 #if CRYPTOPP_BOOL_ALIGN16
179 // TODO: should this need the test 'size*sizeof(T) >= 16'?
180 if (T_Align16 && size*sizeof(T) >= 16)
181 return (pointer)AlignedAllocate(size*sizeof(T));
182 #endif
183
184 return (pointer)UnalignedAllocate(size*sizeof(T));
185 }
186 ...
241 };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With