11#ifndef __DECAF_SECURE_BUFFER_HXX__
12#define __DECAF_SECURE_BUFFER_HXX__ 1
23#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno)
27#if __cplusplus >= 201103L
28#define DECAF_NOEXCEPT noexcept
29#define DECAF_DELETE = delete
31#define DECAF_NOEXCEPT throw()
41static inline void really_bzero(
void *data,
size_t size) {
decaf_bzero(data,size); }
50 typedef const T* const_pointer;
52 typedef const T& const_reference;
53 typedef size_t size_type;
54 typedef std::ptrdiff_t difference_type;
62 inline T* address(T& r)
const DECAF_NOEXCEPT {
return &r; }
63 inline const T* address(
const T& r)
const DECAF_NOEXCEPT {
return &r; }
66 typename std::allocator<void>::const_pointer = 0
68 inline void deallocate(T* p,
size_t size) DECAF_NOEXCEPT;
69 inline size_t max_size()
const DECAF_NOEXCEPT {
return std::numeric_limits<size_t>::max() /
sizeof(T); }
70 inline void construct(T* p,
const T& t) {
new(p) T(t); }
71 inline void destroy(T* p) { p->~T(); }
79typedef std::vector<unsigned char, SanitizingAllocator<unsigned char, 0> >
SecureBuffer;
82template<
class T,
class U,
class V,
class W>
83inline bool memeq(
const std::vector<T,U> &a,
const std::vector<V,W> &b) {
84 if (a.size() != b.size())
return false;
92 inline size_t ser_size() const DECAF_NOEXCEPT {
return static_cast<const Base*
>(
this)->
ser_size(); }
107#if __cplusplus >= 201103L
122 virtual const char *
what() const DECAF_NOEXCEPT {
return "CryptoException"; }
129 virtual const char *
what() const DECAF_NOEXCEPT {
return "LengthException"; }
162 unsigned char *data_;
164 const bool zero_on_destroy_;
169 inline Block() : data_(NULL), size_(0), zero_on_destroy_(false) {}
172 inline Block(
const char *
data) DECAF_NOEXCEPT : data_((
unsigned char *)
data),
173 size_(strlen(
data)), zero_on_destroy_(
false) {}
176 inline Block(
const unsigned char *
data,
size_t size,
bool zero_on_destroy=
false) DECAF_NOEXCEPT : data_((
unsigned char *)
data),
177 size_(
size), zero_on_destroy_(zero_on_destroy) {}
180 inline Block(
const std::string &s) : data_(
181#if __cplusplus >= 201103L
182 ((unsigned char *)(s.
data()))
184 ((unsigned char *)&(s)[0])
186 ), size_(s.
size()), zero_on_destroy_(false) {}
189 template<
class alloc>
inline Block(
const std::vector<unsigned char,alloc> &s)
191#if __cplusplus >= 201103L
192 ((unsigned char *)(s.
data()))
194 ((unsigned char *)&(s)[0])
196 ), size_(s.
size()), zero_on_destroy_(false) {}
199 inline const unsigned char *
data() const DECAF_NOEXCEPT {
return data_; }
203 if (off >=
size())
throw(std::out_of_range(
"decaf::Block"));
208 inline size_t size() const DECAF_NOEXCEPT {
return size_; }
212 return std::string((
const char *)data_,size_);
223 if (b.size() !=
size())
return false;
233 inline void zeroize() DECAF_NOEXCEPT { really_bzero(data_,
size()); }
237 if (name) printf(
"%s = ", name);
238 for (
size_t s = 0; s <
size(); s++) printf(
"%02x", data_[s]);
244 inline decaf_bool_t operator>=(
const Block &b)
const DECAF_NOEXCEPT DECAF_DELETE;
245 inline decaf_bool_t operator<=(
const Block &b)
const DECAF_NOEXCEPT DECAF_DELETE;
246 inline decaf_bool_t operator> (
const Block &b)
const DECAF_NOEXCEPT DECAF_DELETE;
247 inline decaf_bool_t operator< (
const Block &b)
const DECAF_NOEXCEPT DECAF_DELETE;
248 inline void operator= (
const Block &b)
const DECAF_NOEXCEPT DECAF_DELETE;
261 template<
class alloc>
inline FixedBlock(
const std::vector<unsigned char,alloc> &s) :
Block(s) {
279 template<
class alloc>
inline Buffer(std::vector<unsigned char,alloc> &s) :
Block(s) {}
282 inline const unsigned char *
data() const DECAF_NOEXCEPT {
return data_; }
285 inline unsigned char*
data() DECAF_NOEXCEPT {
return data_; }
292 if (off >=
size())
throw(std::out_of_range(
"decaf::Buffer"));
304 inline void operator= (
const Block &b)
const DECAF_NOEXCEPT DECAF_DELETE;
323 inline explicit FixedBuffer(uint8_t dat[Size],
bool zero_on_destroy =
false) DECAF_NOEXCEPT :
Buffer(dat,Size,zero_on_destroy) {}
332 inline void operator= (
const Block &b)
const DECAF_NOEXCEPT DECAF_DELETE;
339 uint8_t storage[Size];
354 memcpy(storage,b.data(),Size);
359 memcpy(storage,b.data(),Size);
return *
this;
364 memcpy(storage,b.data(),Size);
return *
this;
375 memcpy(storage,b.
data(),Size);
380 memcpy(storage,b.data(),Size);
389 if (off >
size() || length >
size() - off)
throw LengthException();
402template <
class T,
class Wrapped>
403class OwnedOrUnowned {
407 const Wrapped *yours;
411 inline void clear() DECAF_NOEXCEPT {
413 really_bzero(ours.mine, T::size());
415 _aligned_free(ours.mine);
419 ours.yours = T::default_value();
423 inline void alloc() {
425 int ret = posix_memalign((
void**)&ours.mine, T::alignment(), T::size());
426 if (ret || !ours.mine) {
428 throw std::bad_alloc();
432 inline const Wrapped *get() const DECAF_NOEXCEPT {
return is_mine ? ours.mine : ours.yours; }
434 inline OwnedOrUnowned(
435 const Wrapped &yours = *T::default_value()
444 inline T &operator=(
const OwnedOrUnowned &it) {
445 if (
this == &it)
return *(T*)
this;
448 memcpy(ours.mine,it.ours.mine,T::size());
451 ours.yours = it.ours.yours;
453 is_mine = it.is_mine;
457#if __cplusplus >= 201103L
458 inline T &operator=(OwnedOrUnowned &&it) DECAF_NOEXCEPT {
459 if (
this == &it)
return *(T*)
this;
462 is_mine = it.is_mine;
464 it.ours.yours = T::default_value;
476template<
typename T,
size_t alignment>
477T* SanitizingAllocator<T,alignment>::allocate (
479 typename std::allocator<void>::const_pointer
484 if (alignment) ret = posix_memalign(&v, alignment, cnt *
sizeof(T));
485 else v = malloc(cnt *
sizeof(T));
487 if (ret || v==NULL)
throw(std::bad_alloc());
488 return reinterpret_cast<T*
>(v);
491template<
typename T,
size_t alignment>
492void SanitizingAllocator<T,alignment>::deallocate(T* p,
size_t size) DECAF_NOEXCEPT {
494 really_bzero(
reinterpret_cast<void*
>(p), size);
497 _aligned_free(
reinterpret_cast<void*
>(p));
500 free(
reinterpret_cast<void*
>(p));
A reference to a block of data, which (when accessed through this base class) is const.
Definition: secure_buffer.hxx:159
Block(const std::vector< unsigned char, alloc > &s)
Block from std::vector.
Definition: secure_buffer.hxx:189
Block(const unsigned char *data, size_t size, bool zero_on_destroy=false) DECAF_NOEXCEPT
Unowned init.
Definition: secure_buffer.hxx:176
const unsigned char * data() const DECAF_NOEXCEPT
Get const data.
Definition: secure_buffer.hxx:199
Block(const char *data) DECAF_NOEXCEPT
Init from C string.
Definition: secure_buffer.hxx:172
Block()
Null initialization.
Definition: secure_buffer.hxx:169
void zeroize() DECAF_NOEXCEPT
Securely set the buffer to 0.
Definition: secure_buffer.hxx:233
decaf_bool_t contents_equal(const Block &b) const DECAF_NOEXCEPT
Content-wise comparison; constant-time if they are the same length.
Definition: secure_buffer.hxx:222
size_t size() const DECAF_NOEXCEPT
Get the size.
Definition: secure_buffer.hxx:208
Block(const std::string &s)
Block from std::string.
Definition: secure_buffer.hxx:180
void debug_print_hex(const char *name=NULL)
Debugging print in hex.
Definition: secure_buffer.hxx:236
std::string get_string() const
Convert to C++ string.
Definition: secure_buffer.hxx:211
const unsigned char & operator[](size_t off) const
Subscript.
Definition: secure_buffer.hxx:202
Block slice(size_t off, size_t length) const
Slice the buffer.
Definition: secure_buffer.hxx:216
A reference to a writable block of data.
Definition: secure_buffer.hxx:270
unsigned char & operator[](size_t off)
Subscript.
Definition: secure_buffer.hxx:291
unsigned char * data() DECAF_NOEXCEPT
Cast to unsigned char.
Definition: secure_buffer.hxx:285
const unsigned char * data() const DECAF_NOEXCEPT
Get const data.
Definition: secure_buffer.hxx:282
Buffer() DECAF_NOEXCEPT
Null init.
Definition: secure_buffer.hxx:273
Buffer(std::vector< unsigned char, alloc > &s)
Block from std::vector.
Definition: secure_buffer.hxx:279
Buffer slice(size_t off, size_t length)
Slice the buffer.
void assign(const Block b)
Copy from another block.
Definition: secure_buffer.hxx:297
Buffer(unsigned char *data, size_t size, bool zero_on_destroy=false) DECAF_NOEXCEPT
Unowned init.
Definition: secure_buffer.hxx:276
An exception for when crypto (ie point decode) has failed.
Definition: secure_buffer.hxx:119
virtual const char * what() const DECAF_NOEXCEPT
Definition: secure_buffer.hxx:122
A fixed-size stack-allocated buffer (for DECAF_NOEXCEPT semantics)
Definition: secure_buffer.hxx:337
FixedArrayBuffer(Rng &r) DECAF_NOEXCEPT
New random buffer.
Definition: secure_buffer.hxx:350
FixedArrayBuffer() DECAF_NOEXCEPT
New buffer initialized to zero.
Definition: secure_buffer.hxx:344
FixedArrayBuffer & operator=(const Block &b)
Copy operator.
Definition: secure_buffer.hxx:368
FixedArrayBuffer & operator=(const FixedBlock< Size > &b) DECAF_NOEXCEPT
Copy operator.
Definition: secure_buffer.hxx:358
FixedArrayBuffer(const FixedBlock< Size > &b) DECAF_NOEXCEPT
Copy constructor.
Definition: secure_buffer.hxx:353
FixedArrayBuffer(const NOINIT &) DECAF_NOEXCEPT
New uninitialized buffer.
Definition: secure_buffer.hxx:347
FixedArrayBuffer(const Block &b)
Copy constructor.
Definition: secure_buffer.hxx:373
FixedArrayBuffer & operator=(const FixedArrayBuffer< Size > &b) DECAF_NOEXCEPT
Copy operator.
Definition: secure_buffer.hxx:363
FixedArrayBuffer(const FixedArrayBuffer< Size > &b) DECAF_NOEXCEPT
Copy constructor.
Definition: secure_buffer.hxx:379
~FixedArrayBuffer() DECAF_NOEXCEPT
Destroy the buffer.
Definition: secure_buffer.hxx:384
A fixed-size block.
Definition: secure_buffer.hxx:253
FixedBlock(const Block &b)
Check a block's length.
Definition: secure_buffer.hxx:256
FixedBlock(const uint8_t data[Size]) DECAF_NOEXCEPT
Explicitly pass a C buffer.
Definition: secure_buffer.hxx:266
FixedBlock(const std::vector< unsigned char, alloc > &s)
Block from std::vector.
Definition: secure_buffer.hxx:261
A fixed-size block.
Definition: secure_buffer.hxx:310
FixedBuffer(Buffer b)
Check a block's length.
Definition: secure_buffer.hxx:313
FixedBuffer(uint8_t dat[Size], bool zero_on_destroy=false) DECAF_NOEXCEPT
Explicitly pass a C buffer.
Definition: secure_buffer.hxx:323
FixedBuffer(SecureBuffer &b)
Check a block's length.
Definition: secure_buffer.hxx:318
An exception for when crypto (ie point decode) has failed.
Definition: secure_buffer.hxx:126
virtual const char * what() const DECAF_NOEXCEPT
Definition: secure_buffer.hxx:129
Prototype of a random number generator.
Definition: secure_buffer.hxx:138
SecureBuffer read(size_t length)
Read into a SecureBuffer.
Rng()
Empty initializer.
Definition: secure_buffer.hxx:141
Rng(const Rng &) DECAF_DELETE
Not copyable.
Rng & operator=(const Rng &) DECAF_DELETE
Not copyable.
virtual void read(Buffer buffer) DECAF_NOEXCEPT=0
Read into a Buffer.
An allocator which zeros its memory on free.
Definition: secure_buffer.hxx:44
Base class of objects which support serialization.
Definition: secure_buffer.hxx:89
size_t ser_size() const DECAF_NOEXCEPT
Return the number of bytes needed to serialize this object.
Definition: secure_buffer.hxx:92
void serialize_into(unsigned char *buf) const DECAF_NOEXCEPT
Serialize this object into a buffer.
Definition: secure_buffer.hxx:95
SecureBuffer serialize() const
Serialize this object into a SecureBuffer and return it.
Definition: secure_buffer.hxx:100
void DECAF_API_VIS decaf_bzero(void *data, size_t size) DECAF_NONNULL
Overwrite data with zeros.
decaf_bool_t DECAF_API_VIS decaf_memeq(const void *data1, const void *data2, size_t size) DECAF_NONNULL DECAF_WARN_UNUSED
Compare two buffers, returning DECAF_TRUE if they are equal.
uint32_t decaf_bool_t
"Boolean" type, will be set to all-zero or all-one (i.e.
Definition: common.h:89
Namespace for all C++ decaf objects.
Definition: decaf.hxx:22
bool memeq(const std::vector< T, U > &a, const std::vector< V, W > &b)
Constant-time compare two buffers.
Definition: secure_buffer.hxx:83
std::vector< unsigned char, SanitizingAllocator< unsigned char, 0 > > SecureBuffer
A variant of std::vector which securely zerozes its state when destructed.
Definition: secure_buffer.hxx:79
Passed to constructors to avoid (conservative) initialization.
Definition: secure_buffer.hxx:133