SecBlock
Documentation |
#include <cryptopp/secblock.h>
|
The Crypto++ library uses SecBlock class to provide secure storage that is zeroized or wiped when the block is destroyed. The class should be used to hold keys, initialization vectors, and other security parameters. The SecBlock
class is fully featured and allows you to create, copy, assign and append data to a block.
SecBlock
is a template class, and you can have a block of any type using SecBlock<T>
. The type of T
includes byte
, word32
and word64
. When T = byte
then there is a SecByteBlock
typedef. The library makes frequent use of SecByteBlock
.
A SecBlock
can be aligned or unaligned. Alignment is indirectly specified through a template parameter for the allocator, called AllocatorWithCleanup
. When the SecBlock
is aligned the alignment is 16-bytes and used with SSE and POWER8 extensions. When unaligned the SecBlock
will use the natural alignment of the underlying type T
.
The SecBlock
class also allows you to easily acquire a block of uninitialized memory. STL container classes, like std::string
and std::vector
, always initialize their elements to a default value, even if the default value is unneeded.
Related topics are ByteQueue
and SecByteBlockSink
if you want to use a SecBlock
in a pipeline.
Constructors
template <class T, class A> SecBlock (size_type size=0)
T
the underlying type, like byte
, word32
or double
.
A
the allocator, like AllocatorWithCleanup
.
size
the size of the SecBlock
, in elements.
The constructor shown above provides you with a secure block of memory that will be zeroized upon destruction. The elements are not initialized.
template <class T, class A> SecBlock (const T *ptr, size_type len)
T
the underlying type, like byte
, word32
or double
.
A
the allocator, like AllocatorWithCleanup
.
ptr
a pointer to an array of T
.
len
the number of elements in the memory block.
This constructor shown above provides you with two choices, though it is not readily apparent. First, you can copy an existing block of memory into the SecBlock
. This is the typical use case, and it occurs when ptr
is not NULL
.
The second choice is an initialized array. When ptr
is NULL
and len
is valid, then a new block is allocated and the elements are initialized to the default value for the type.
Class Methods
The SecBlock
class has a lot of class methods. The list below is some of the more frequent ones. If you need a member function not listed then visit SecBlock
in the online manual or browse the secblock.h
source file.
data()
returns a pointer to the first element in the SecBlock
.
size()
returns the number of elements in the SecBlock
.
BytePtr()
returns a pointer to the first element in the SecBlock
cast to a byte*
.
SizeInBytes()
returns the number of bytes in the SecBlock
.
begin()
returns an iterator to the first element in the SecBlock
.
end()
returns an iterator to beyond the last element in the SecBlock
.
empty()
returns true
if the SecBlock
is empty.
swap()
exchanges two SecBlock
s.
operator=()
assigns to a SecBlock
.
operator+=()
appends to a SecBlock
.
operator==()
compares two SecBlock
in near-constant time using VerifyBufsEqual
.
operator!=()
compares two SecBlock
in near-constant time using VerifyBufsEqual
.
New()
change size without preserving contents.
Grow()
increase size and preserve contents. The new space is uninitialized. Grow
does not shrink an object; use resize()
instead.
CleanNew()
change size without preserving contents. The new space is initialized to 0.
CleanGrow()
increase size and preserve contents. The new space is initialized to 0. Grow
does not shrink an object; use resize()
instead.
Assign()
makes a SecBlock
from another SecBlock
or an array. The array must be distinct from the SecBlock
.
Append()
adds a SecBlock
from another SecBlock
or an array. The array must be distinct from the SecBlock
.
SetMark()
set the number of elements to zeroize. The number to zeroize may be fewer than are allocated or 0.
Alignment
The default allocator used for a SecBlock
is unaligned. You can switch to an aligned allocator that provides 16-byte alignment as shown below. The library uses an aligned allocator internally for buffers when working with SSE and POWER8 SIMD units. The syntax is a little ugly, and it is one of the reasons why there is a typedef for SecByteBlock
.
// An aligned SecByteBlock typedef SecBlock<byte, AllocatorWithCleanup<byte, true> > AlignedSecByteBlock; // An aligned block of word32 SecBlock<word32, AllocatorWithCleanup<word32, true> > block1; // An aligned block of double SecBlock<double, AllocatorWithCleanup<double, true> > block2;
You usually don't need to use an aligned allocator. You usually know when you need an aligned SecBlock
because you will experience a SIGBUS
on Linux. SIGBUS
is almost always indicative of a misaligned load or store and a SIMD unit.
Sometimes the library experiences a SIGBUS
that is not related to the SIMD unit. Most recently was on Sparc64 due to a bad cast. Also see Issue 597.
There are other type of allocators available for use with SecBlock
. If you think you need one of them browse the source file secblock.h
.
std::string
Sometimes you have data in a std::string
or std::vector
and you want to move it to a SecByteBlock
for ease of use with the library. And sometimes you have to move data from a SecByteBlock
to another container. A number of questions exist on Stack Overflow so it appears to be a frequent task.
If you have a std::string
or std::vector
then you can create a SecByteBlock
as shown below.
std::string str = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWV4oK8c/MZkCLk4qSCNjW0Zm6H0CBCtS" "YxkXkC9FBHehRANCAAQPldOnhO2/oXjdJD1dwlFPiNs6fcdoRgFu3/Z0iKj24SjTGyLRGAtYWLGXBZcD" "dPj3T2bJRHRVhE8Bc2AjkT7n"; SecByteBlock key(reinterpret_cast<const byte*>(&str[0]), str.size());
Taking the address of the first element of the std::string
yields a const char*
. The cast converts it to a const byte*
.
Moving from SecByteBlock
to a std::string
is similar to the other operation.
SecByteBlock key; // Assume key is populated std::string str(reinterpret_cast<const char*>(&key[0]), key.size()); std::vector vec(reinterpret_cast<const char*>(&key[0]), key.size());
A more interesting case is getting a non-const pointer. Below is the way to get a non-const pointer and avoid undefined behavior. You must take the address of element 0. You should not use str.data()
or cast it to a non-const pointer.
SecByteBlock key(...); // Assume key is populated std::string str; str.resize(key.size()); // Make room for elements std::memcpy(&str[0], &key[0], str.size());
AllocatorWithCleanup
The AllocatorWithCleanup
class is a C++ allocator. It is used by SecBlock
and typedefs like SecByteBlock
, and it can be used in C++ container classes.
AllocatorWithCleanup
is like a standard C++ allocator. There are no constructors of interest. The class provides three useful member functions for managing memroy.
allocate()
acquires a memory blockdeallocate()
releases a memory blockreallocate()
resizes a memory blockrebind()
switches to a different object type
Below are examples of using the allocator with std::string
and std::vector
.
typedef std::basic_string<char, std::char_traits<char>, AllocatorWithCleanup<char> > secure_string; typedef std::vector<int, AllocatorWithCleanup<int> > secure_vector;