Browse Source

switch SecureBuffer to vector

master
Michael Hamburg 9 years ago
parent
commit
4dd77e0149
7 changed files with 203 additions and 245 deletions
  1. +10
    -12
      src/public_include/decaf/crypto.hxx
  2. +23
    -13
      src/public_include/decaf/decaf_255.hxx
  3. +23
    -18
      src/public_include/decaf/decaf_448.hxx
  4. +114
    -137
      src/public_include/decaf/secure_buffer.hxx
  5. +19
    -51
      src/public_include/decaf/shake.hxx
  6. +8
    -8
      test/bench_decaf.cxx
  7. +6
    -6
      test/test_decaf.cxx

+ 10
- 12
src/public_include/decaf/crypto.hxx View File

@@ -57,7 +57,7 @@ public:
inline explicit PublicKey(const PrivateKey<Group> &priv) NOEXCEPT;
/** @brief Read a private key from a string*/
inline explicit PublicKey(const FixedBlock<Group::Point::SER_BYTES> b) NOEXCEPT : ser(b) {}
inline explicit PublicKey(const FixedBlock<Group::Point::SER_BYTES> &b) NOEXCEPT : ser(b) {}
/** @brief Return the corresponding EC point */
inline typename Group::Point point() const throw(CryptoException) {
@@ -68,11 +68,10 @@ public:
inline void verify_shake(const SHAKE<SHAKE_BITS> &ctx_, const FixedBlock<SIG_BYTES> &sig) throw(CryptoException) {
SHAKE<SHAKE_BITS> ctx(ctx_);
ctx << ser << sig.slice(0,Group::Point::SER_BYTES);
FixedBuffer<CHALLENGE_BYTES> challenge(ctx.output(CHALLENGE_BYTES));
challenge.debug_print("ch ver ");
SecureBuffer challenge(ctx.output(CHALLENGE_BYTES));
const typename Group::Point combo = point().non_secret_combo_with_base(
challenge,
typename Group::Scalar(challenge),
sig.slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES)
);
if (combo != typename Group::Point(sig.slice(0,Group::Point::SER_BYTES)))
@@ -128,9 +127,9 @@ public:
/** @brief Uncompressed representation */
inline SecureBuffer ser_uncompressed() const throw(std::bad_alloc) {
SecureBuffer b(SYM_BYTES + Group::Scalar::SER_BYTES + Group::Point::SER_BYTES);
b.slice(0,SYM_BYTES).assign(sym);
b.slice(SYM_BYTES,Group::Scalar::SER_BYTES).assign(scalar);
b.slice(SYM_BYTES+Group::Scalar::SER_BYTES,Group::Point::SER_BYTES).assign(pub_.ser);
Buffer(b).slice(0,SYM_BYTES).assign(sym);
Buffer(b).slice(SYM_BYTES,Group::Scalar::SER_BYTES).assign(scalar);
Buffer(b).slice(SYM_BYTES+Group::Scalar::SER_BYTES,Group::Point::SER_BYTES).assign(pub_.ser);
return b;
}
@@ -143,13 +142,12 @@ public:
ctx = ctx_;
ctx << pub_.ser << g_nonce;
FixedBuffer<PublicKey<Group>::CHALLENGE_BYTES> challenge(ctx.output(PublicKey<Group>::CHALLENGE_BYTES));
challenge.debug_print("ch sign");
SecureBuffer response(nonce - scalar * challenge);
SecureBuffer challenge(ctx.output(PublicKey<Group>::CHALLENGE_BYTES));
SecureBuffer response((nonce - scalar * typename Group::Scalar(challenge)).encode());
SecureBuffer ret(PublicKey<Group>::SIG_BYTES);
ret.slice(0,Group::Point::SER_BYTES).assign(g_nonce);
ret.slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES).assign(response);
Buffer(ret).slice(0,Group::Point::SER_BYTES).assign(g_nonce);
Buffer(ret).slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES).assign(response);
return ret;
}


+ 23
- 13
src/public_include/decaf/decaf_255.hxx View File

@@ -130,7 +130,7 @@ public:
static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
Scalar &sc, const FixedBlock<SER_BYTES> buffer
) NOEXCEPT {
return decaf_255_scalar_decode(sc.s,buffer);
return decaf_255_scalar_decode(sc.s,buffer.data());
}
/** @brief Encode to fixed-length string */
@@ -140,7 +140,12 @@ public:
/** @brief Encode to fixed-length buffer */
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT{
decaf_255_scalar_encode(buffer, s);
decaf_255_scalar_encode(buffer.data(), s);
}

/** @brief Encode to fixed-length buffer */
inline SecureBuffer encode() const throw(std::bad_alloc) {
SecureBuffer buffer(SER_BYTES); encode(buffer); return buffer;
}
/** Add. */
@@ -293,15 +298,15 @@ public:
if (s.size() < HASH_BYTES) {
SecureBuffer b(HASH_BYTES);
memcpy(b.data(), s.data(), s.size());
decaf_255_point_from_hash_nonuniform(p,b);
decaf_255_point_from_hash_nonuniform(p,b.data());
} else if (s.size() == HASH_BYTES) {
decaf_255_point_from_hash_nonuniform(p,s);
decaf_255_point_from_hash_nonuniform(p,s.data());
} else if (s.size() < 2*HASH_BYTES) {
SecureBuffer b(2*HASH_BYTES);
memcpy(b.data(), s.data(), s.size());
decaf_255_point_from_hash_uniform(p,b);
decaf_255_point_from_hash_uniform(p,b.data());
} else {
decaf_255_point_from_hash_uniform(p,s);
decaf_255_point_from_hash_uniform(p,s.data());
}
}
@@ -316,7 +321,12 @@ public:
* @brief Encode to a C buffer. The identity encodes to all zeros.
*/
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT {
decaf_255_point_encode(buffer, p);
decaf_255_point_encode(buffer.data(), p);
}

/** @brief Encode to fixed-length buffer */
inline SecureBuffer encode() const throw(std::bad_alloc) {
SecureBuffer buffer(SER_BYTES); encode(buffer); return buffer;
}
/** @brief Point add. */
@@ -394,7 +404,7 @@ public:
/** @brief Return a point equal to *this, whose internal data has a modified representation. */
inline Point debugging_pscale(const FixedBlock<SER_BYTES> factor) const NOEXCEPT {
Point q; decaf_255_point_debugging_pscale(q.p,p,factor); return q;
Point q; decaf_255_point_debugging_pscale(q.p,p,factor.data()); return q;
}
/** @brief Return a point equal to *this, whose internal data has a randomized representation. */
@@ -407,11 +417,11 @@ public:
* or leave buf unmodified and return false.
*/
inline bool invert_elligator (
Buffer &buf, uint16_t hint
Buffer buf, uint16_t hint
) const NOEXCEPT {
unsigned char buf2[2*HASH_BYTES];
memset(buf2,0,sizeof(buf2));
memcpy(buf2,buf,(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size());
memcpy(buf2,buf.data(),(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size());
decaf_bool_t ret;
if (buf.size() > HASH_BYTES) {
ret = decaf_255_invert_elligator_uniform(buf2, p, hint);
@@ -423,7 +433,7 @@ public:
}
if (ret) {
/* TODO: make this constant time?? */
memcpy(buf,buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES);
memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES);
}
decaf_bzero(buf2,sizeof(buf2));
return !!ret;
@@ -435,7 +445,7 @@ public:
SecureBuffer out(STEG_BYTES);
bool done;
do {
rng.read(out.slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1));
rng.read(Buffer(out).slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1));
done = invert_elligator(out, out[HASH_BYTES-1]);
} while (!done);
return out;
@@ -553,7 +563,7 @@ inline SecureBuffer IsoEd25519::Scalar::direct_scalarmul (
decaf_bool_t short_circuit
) const throw(CryptoException) {
SecureBuffer out(IsoEd25519::Point::SER_BYTES);
if (!decaf_255_direct_scalarmul(out, in.data(), s, allow_identity, short_circuit))
if (!decaf_255_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit))
throw CryptoException();
return out;
}


+ 23
- 18
src/public_include/decaf/decaf_448.hxx View File

@@ -130,17 +130,17 @@ public:
static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
Scalar &sc, const FixedBlock<SER_BYTES> buffer
) NOEXCEPT {
return decaf_448_scalar_decode(sc.s,buffer);
return decaf_448_scalar_decode(sc.s,buffer.data());
}
/** @brief Encode to fixed-length string */
inline operator SecureBuffer() const NOEXCEPT {
SecureBuffer buf(SER_BYTES); decaf_448_scalar_encode(buf,s); return buf;
/** @brief Encode to fixed-length buffer */
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT{
decaf_448_scalar_encode(buffer.data(), s);
}
/** @brief Encode to fixed-length buffer */
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT{
decaf_448_scalar_encode(buffer, s);
inline SecureBuffer encode() const throw(std::bad_alloc) {
SecureBuffer buffer(SER_BYTES); encode(buffer); return buffer;
}
/** Add. */
@@ -192,7 +192,7 @@ public:
decaf_bool_t short_circuit=DECAF_TRUE
) const throw(CryptoException) {
SecureBuffer out(/*FIXME Point::*/SER_BYTES);
if (!decaf_448_direct_scalarmul(out, in.data(), s, allow_identity, short_circuit))
if (!decaf_448_direct_scalarmul(out.data(), in.data(), s, allow_identity, short_circuit))
throw CryptoException();
return out;
}
@@ -296,15 +296,15 @@ public:
if (s.size() < HASH_BYTES) {
SecureBuffer b(HASH_BYTES);
memcpy(b.data(), s.data(), s.size());
decaf_448_point_from_hash_nonuniform(p,b);
decaf_448_point_from_hash_nonuniform(p,b.data());
} else if (s.size() == HASH_BYTES) {
decaf_448_point_from_hash_nonuniform(p,s);
decaf_448_point_from_hash_nonuniform(p,s.data());
} else if (s.size() < 2*HASH_BYTES) {
SecureBuffer b(2*HASH_BYTES);
memcpy(b.data(), s.data(), s.size());
decaf_448_point_from_hash_uniform(p,b);
decaf_448_point_from_hash_uniform(p,b.data());
} else {
decaf_448_point_from_hash_uniform(p,s);
decaf_448_point_from_hash_uniform(p,s.data());
}
}
@@ -313,7 +313,7 @@ public:
*/
inline operator SecureBuffer() const NOEXCEPT {
SecureBuffer buffer(SER_BYTES);
decaf_448_point_encode(buffer, p);
decaf_448_point_encode(buffer.data(), p);
return buffer;
}
@@ -321,7 +321,12 @@ public:
* @brief Encode to a C buffer. The identity encodes to all zeros.
*/
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT{
decaf_448_point_encode(buffer, p);
decaf_448_point_encode(buffer.data(), p);
}

/** @brief Encode to fixed-length buffer */
inline SecureBuffer encode() const throw(std::bad_alloc) {
SecureBuffer buffer(SER_BYTES); encode(buffer); return buffer;
}
/** @brief Point add. */
@@ -402,7 +407,7 @@ public:
/** @brief Return a point equal to *this, whose internal data has a modified representation. */
inline Point debugging_pscale(const FixedBlock<SER_BYTES> factor) const NOEXCEPT {
Point q;
decaf_448_point_debugging_pscale(q.p,p,factor);
decaf_448_point_debugging_pscale(q.p,p,factor.data());
return q;
}
@@ -417,11 +422,11 @@ public:
* or leave buf unmodified and return false.
*/
inline bool invert_elligator (
Buffer &buf, uint16_t hint
Buffer buf, uint16_t hint
) const NOEXCEPT {
unsigned char buf2[2*HASH_BYTES];
memset(buf2,0,sizeof(buf2));
memcpy(buf2,buf,(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size());
memcpy(buf2,buf.data(),(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size());
decaf_bool_t ret;
if (buf.size() > HASH_BYTES) {
ret = decaf_448_invert_elligator_uniform(buf2, p, hint);
@@ -433,7 +438,7 @@ public:
}
if (ret) {
/* TODO: make this constant time?? */
memcpy(buf,buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES);
memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES);
}
decaf_bzero(buf2,sizeof(buf2));
return !!ret;
@@ -444,7 +449,7 @@ public:
SecureBuffer out(STEG_BYTES);
bool done;
do {
rng.read(out.slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1));
rng.read(Buffer(out).slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1));
done = invert_elligator(out, out[HASH_BYTES-1]);
} while (!done);
return out;


+ 114
- 137
src/public_include/decaf/secure_buffer.hxx View File

@@ -14,6 +14,7 @@
#include <string>
#include <sys/types.h>
#include <stdio.h>
#include <vector>

/** @cond internal */
#if __cplusplus >= 201103L
@@ -27,11 +28,67 @@

namespace decaf {

/**
* Securely zeroize contents of memory.
*/
static inline void really_bzero(void *data, size_t size) { decaf_bzero(data,size); }

/** @brief An allocator which zeros its memory on free */
template<typename T, size_t alignment = 0> class SanitizingAllocator {
/** @cond internal */
/* Based on http://www.codeproject.com/Articles/4795/C-Standard-Allocator-An-Introduction-and-Implement */
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;

template<typename U> struct rebind { typedef SanitizingAllocator<U> other; };
inline SanitizingAllocator() NOEXCEPT {}
inline ~SanitizingAllocator() NOEXCEPT {}
inline SanitizingAllocator(const SanitizingAllocator &) NOEXCEPT {}
template<typename U, size_t a> inline SanitizingAllocator(const SanitizingAllocator<U, a> &) NOEXCEPT {}

inline T* address(T& r) const NOEXCEPT { return &r; }
inline const T* address(const T& r) const NOEXCEPT { return &r; }

inline T* allocate (
size_type cnt,
typename std::allocator<void>::const_pointer = 0
) throw(std::bad_alloc) {
void *v;
int ret = 0;
if (alignment) ret = posix_memalign(&v, alignment, cnt * sizeof(T));
else v = malloc(cnt * sizeof(T));
if (ret || v==NULL) throw(std::bad_alloc());
return reinterpret_cast<T*>(v);
}

inline void deallocate(T* p, size_t size) NOEXCEPT {
if (p==NULL) return;
really_bzero(reinterpret_cast<void*>(p), size);
free(reinterpret_cast<void*>(p));
}

inline size_t max_size() const NOEXCEPT { return std::numeric_limits<size_t>::max() / sizeof(T); }

inline void construct(T* p, const T& t) { new(p) T(t); }
inline void destroy(T* p) { p->~T(); }

inline bool operator==(SanitizingAllocator const&) const NOEXCEPT { return true; }
inline bool operator!=(SanitizingAllocator const&) const NOEXCEPT { return false; }
/** @endcond */
};

typedef std::vector<unsigned char, SanitizingAllocator<unsigned char, 0> > SecureBuffer;

/**@cond internal*/
/** Forward-declare sponge RNG object */
class Buffer;
class TmpBuffer;
class SecureBuffer;
/**@endcond*/
/** @brief An exception for when crypto (ie point decode) has failed. */
@@ -67,19 +124,12 @@ protected:
public:
/** @brief Read into a Buffer */
virtual void read(Buffer &buffer) NOEXCEPT = 0;
/** @brief Read into a value-passed (eg temporary) TmpBuffer. */
inline void read(TmpBuffer buffer) NOEXCEPT;
virtual void read(Buffer buffer) NOEXCEPT = 0;

/** @brief Read into a SecureBuffer. */
inline SecureBuffer read(size_t length) throw(std::bad_alloc);
};

/**
* Securely zeroize contents of memory.
*/
static inline void really_bzero(void *data, size_t size) { decaf_bzero(data,size); }

/** A reference to a block of data, which (when accessed through this base class) is const. */
class Block {
@@ -105,16 +155,23 @@ public:
((unsigned char *)(s.data()))
#endif
), size_(s.size()) {}
/** Block from std::vector */
template<class alloc> inline Block(const std::vector<unsigned char,alloc> &s)
: data_(((unsigned char *)&(s)[0])), size_(s.size()) {}

/** Get const data */
inline const unsigned char *data() const NOEXCEPT { return data_; }
/** Subscript */
inline const unsigned char &operator[](size_t off) const throw(std::out_of_range) {
if (off >= size()) throw(std::out_of_range("decaf::Block"));
return data_[off];
}

/** Get the size */
inline size_t size() const NOEXCEPT { return size_; }

/** Autocast to const unsigned char * */
inline operator const unsigned char*() const NOEXCEPT { return data_; }

/** Convert to C++ string */
inline std::string get_string() const {
return std::string((const char *)data_,size_);
@@ -122,48 +179,48 @@ public:

/** Slice the buffer*/
inline Block slice(size_t off, size_t length) const throw(LengthException) {
if (off > size() || length > size() - off)
throw LengthException();
if (off > size() || length > size() - off) throw LengthException();
return Block(data()+off, length);
}
/** @cond internal */
inline decaf_bool_t operator>=(const Block &b) const NOEXCEPT DELETE;
inline decaf_bool_t operator<=(const Block &b) const NOEXCEPT DELETE;
inline decaf_bool_t operator> (const Block &b) const NOEXCEPT DELETE;
inline decaf_bool_t operator< (const Block &b) const NOEXCEPT DELETE;
/** @endcond */
/* Content-wise comparison; constant-time if they are the same length. */
inline decaf_bool_t operator!=(const Block &b) const NOEXCEPT {
if (b.size() != size()) return true;
return ~decaf_memeq(b,*this,size());
}
/* Content-wise comparison; constant-time if they are the same length. */
inline decaf_bool_t operator==(const Block &b) const NOEXCEPT {
return ~(*this != b);
inline decaf_bool_t contents_equal(const Block &b) const NOEXCEPT {
if (b.size() != size()) return false;
return decaf_memeq(b.data(),data(),size());
}

/** Virtual destructor for SecureBlock. TODO: probably means vtable? Make bool? */
inline virtual ~Block() {};
/** Debugging print in hex */
inline void debug_print(const char *name = NULL) {
inline void debug_print_hex(const char *name = NULL) {
if (name) printf("%s = ", name);
for (size_t s = 0; s < size(); s++) printf("%02x", data_[s]);
printf("\n");
}
private:
/** @cond internal */
inline decaf_bool_t operator>=(const Block &b) const NOEXCEPT DELETE;
inline decaf_bool_t operator<=(const Block &b) const NOEXCEPT DELETE;
inline decaf_bool_t operator> (const Block &b) const NOEXCEPT DELETE;
inline decaf_bool_t operator< (const Block &b) const NOEXCEPT DELETE;
/** @endcond */
};

/** A fixed-size block */
template<size_t Size> class FixedBlock : public Block {
public:
/** Check a block's length. */
inline FixedBlock(const Block &b) throw(LengthException) : Block(b,Size) {
inline FixedBlock(const Block &b) throw(LengthException) : Block(b.data(),Size) {
if (Size != b.size()) throw LengthException();
}
/** Block from std::vector */
template<class alloc> inline FixedBlock(const std::vector<unsigned char,alloc> &s) : Block(s) {
if (Size != s.size()) throw LengthException();
}
/** Explicitly pass a C buffer. */
inline explicit FixedBlock(const uint8_t data[Size]) NOEXCEPT : Block(data,Size) {}
};
@@ -176,26 +233,29 @@ public:

/** Unowned init */
inline Buffer(unsigned char *data, size_t size) NOEXCEPT : Block(data,size) {}
/** Get unconst data */
inline unsigned char *data() NOEXCEPT { return data_; }
/** Block from std::vector */
template<class alloc> inline Buffer(std::vector<unsigned char,alloc> &s) : Block(s) {}

/** Get const data */
inline const unsigned char *data() const NOEXCEPT { return data_; }

/** Autocast to const unsigned char * */
inline operator const unsigned char*() const NOEXCEPT { return data_; }

/** Autocast to unsigned char */
inline operator unsigned char*() NOEXCEPT { return data_; }
/** Cast to unsigned char */
inline unsigned char* data() NOEXCEPT { return data_; }

/** Slice the buffer*/
inline TmpBuffer slice(size_t off, size_t length) throw(LengthException);
inline Buffer slice(size_t off, size_t length) throw(LengthException);
/** Subscript */
inline unsigned char &operator[](size_t off) throw(std::out_of_range) {
if (off >= size()) throw(std::out_of_range("decaf::Buffer"));
return data_[off];
}
/** Copy from another block */
inline void assign(const Block b) throw(LengthException) {
if (b.size() != size()) throw LengthException();
memmove(*this,b,size());
memmove(data(),b.data(),size());
}
/** Securely set the buffer to 0. */
@@ -207,7 +267,12 @@ public:
template<size_t Size> class FixedBuffer : public Buffer {
public:
/** Check a block's length. */
inline FixedBuffer(Buffer &b) throw(LengthException) : Buffer(b,Size) {
inline FixedBuffer(Buffer b) throw(LengthException) : Buffer(b) {
if (Size != b.size()) throw LengthException();
}
/** Check a block's length. */
inline FixedBuffer(SecureBuffer &b) throw(LengthException) : Buffer(b) {
if (Size != b.size()) throw LengthException();
}
@@ -220,13 +285,6 @@ public:
}
};

/** A temporary reference to a writeable buffer, for converting C to C++. */
class TmpBuffer : public Buffer {
public:
/** Unowned init */
inline TmpBuffer(unsigned char *data, size_t size) NOEXCEPT : Buffer(data,size) {}
};

/** A fixed-size stack-allocated buffer (for NOEXCEPT semantics) */
template<size_t Size> class FixedArrayBuffer : public FixedBuffer<Size> {
private:
@@ -245,18 +303,18 @@ public:
/** Copy constructor */
inline explicit FixedArrayBuffer(const FixedBlock<Size> &b) NOEXCEPT : FixedBuffer<Size>(storage) {
memcpy(storage,b,Size);
memcpy(storage,b.data(),Size);
}
/** Copy constructor */
inline explicit FixedArrayBuffer(const Block &b) throw(LengthException) : FixedBuffer<Size>(storage) {
if (b.size() != Size) throw LengthException();
memcpy(storage,b,Size);
memcpy(storage,b.data(),Size);
}
/** Copy constructor */
inline explicit FixedArrayBuffer(const FixedArrayBuffer<Size> &b) NOEXCEPT : FixedBuffer<Size>(storage) {
memcpy(storage,b,Size);
memcpy(storage,b.data(),Size);
}
/** Destroy the buffer */
@@ -264,90 +322,9 @@ public:
};

/** @cond internal */
inline void Rng::read(TmpBuffer buffer) NOEXCEPT { read((Buffer &)buffer); }
/** @endcond */

/** A self-erasing block of data */
class SecureBuffer : public Buffer {
public:
/** Null secure block */
inline SecureBuffer() NOEXCEPT : Buffer() {}

/** Construct empty from size */
inline SecureBuffer(size_t size) throw(std::bad_alloc) {
data_ = new unsigned char[size_ = size];
memset(data_,0,size);
}

/** Construct from data */
inline SecureBuffer(const unsigned char *data, size_t size) throw(std::bad_alloc) {
data_ = new unsigned char[size_ = size];
memcpy(data_, data, size);
}
/** Construct from random */
inline SecureBuffer(Rng &r, size_t size) NOEXCEPT {
data_ = new unsigned char[size_ = size];
r.read(*this);
}

/** Copy constructor */
inline SecureBuffer(const Block &copy) throw(std::bad_alloc) : Buffer() { *this = copy; }

/** Copy-assign constructor */
inline SecureBuffer& operator=(const Block &copy) throw(std::bad_alloc) {
if (&copy == this) return *this;
clear();
data_ = new unsigned char[size_ = copy.size()];
memcpy(data_,copy.data(),size_);
return *this;
}

/** Copy-assign constructor */
inline SecureBuffer& operator=(const SecureBuffer &copy) throw(std::bad_alloc) {
if (&copy == this) return *this;
clear();
data_ = new unsigned char[size_ = copy.size()];
memcpy(data_,copy.data(),size_);
return *this;
}

/** Destructor zeroizes data */
~SecureBuffer() NOEXCEPT { clear(); }

/** Clear data */
inline void clear() NOEXCEPT {
if (data_ == NULL) return;
zeroize();
delete[] data_;
data_ = NULL;
size_ = 0;
}

#if __cplusplus >= 201103L
/** Move constructor */
inline SecureBuffer(SecureBuffer &&move) { *this = move; }

/** Move non-constructor */
inline SecureBuffer(Block &&move) { *this = (Block &)move; }

/** Move-assign constructor. TODO: check that this actually gets used.*/
inline SecureBuffer& operator=(SecureBuffer &&move) {
clear();
data_ = move.data_; move.data_ = NULL;
size_ = move.size_; move.size_ = 0;
return *this;
}

/** C++11-only explicit cast */
inline explicit operator std::string() const { return get_string(); }
#endif
};

/** @cond internal */
TmpBuffer Buffer::slice(size_t off, size_t length) throw(LengthException) {
Buffer Buffer::slice(size_t off, size_t length) throw(LengthException) {
if (off > size() || length > size() - off) throw LengthException();
return TmpBuffer(data()+off, length);
return Buffer(data()+off, length);
}

inline SecureBuffer Rng::read(size_t length) throw(std::bad_alloc) {


+ 19
- 51
src/public_include/decaf/shake.hxx View File

@@ -71,7 +71,7 @@ public:
* @brief Output bytes from the sponge.
* @todo make this throw exceptions.
*/
inline void output(TmpBuffer b) { sha3_output(sp,b.data(),b.size()); }
inline void output(Buffer b) { sha3_output(sp,b.data(),b.size()); }
/**
* @brief Output bytes from the sponge.
@@ -82,7 +82,7 @@ public:
/** @brief Output bytes from the sponge. */
inline SecureBuffer output(size_t len) {
SecureBuffer buffer(len);
sha3_output(sp,buffer,len);
sha3_output(sp,buffer.data(),len);
return buffer;
}
@@ -182,7 +182,7 @@ public:
using Rng::read;
/** Read data to a buffer. */
virtual inline void read(Buffer &buffer) NOEXCEPT
virtual inline void read(Buffer buffer) NOEXCEPT
#if __cplusplus >= 201103L
final
#endif
@@ -211,43 +211,37 @@ public:
inline void key (
const Block &data, bool more = false
) throw(ProtocolException) {
if (!strobe_key(sp, data, data.size(), more)) throw ProtocolException();
if (!strobe_key(sp, data.data(), data.size(), more)) throw ProtocolException();
}

inline void nonce(const Block &data, bool more = false
) throw(ProtocolException) {
if (!strobe_nonce(sp, data, data.size(), more)) throw ProtocolException();
if (!strobe_nonce(sp, data.data(), data.size(), more)) throw ProtocolException();
}

inline void send_plaintext(const Block &data, bool more = false
) throw(ProtocolException) {
if (!strobe_plaintext(sp, data, data.size(), true, more))
if (!strobe_plaintext(sp, data.data(), data.size(), true, more))
throw(ProtocolException());
}

inline void recv_plaintext(const Block &data, bool more = false
) throw(ProtocolException) {
if (!strobe_plaintext(sp, data, data.size(), false, more))
if (!strobe_plaintext(sp, data.data(), data.size(), false, more))
throw(ProtocolException());
}

inline void ad(const Block &data, bool more = false
) throw(ProtocolException) {
if (!strobe_ad(sp, data, data.size(), more))
if (!strobe_ad(sp, data.data(), data.size(), more))
throw(ProtocolException());
}
inline void encrypt_no_auth(
Buffer &out, const Block &data, bool more = false
Buffer out, const Block &data, bool more = false
) throw(LengthException,ProtocolException) {
if (out.size() != data.size()) throw LengthException();
if (!strobe_encrypt(sp, out, data, data.size(), more)) throw(ProtocolException());
}
inline void encrypt_no_auth(
TmpBuffer out, const Block &data, bool more = false
) throw(LengthException,ProtocolException) {
encrypt_no_auth((Buffer &)out, data, more);
if (!strobe_encrypt(sp, out.data(), data.data(), data.size(), more)) throw(ProtocolException());
}
inline SecureBuffer encrypt_no_auth(const Block &data, bool more = false
@@ -256,16 +250,10 @@ public:
}
inline void decrypt_no_auth(
Buffer &out, const Block &data, bool more = false
Buffer out, const Block &data, bool more = false
) throw(LengthException,ProtocolException) {
if (out.size() != data.size()) throw LengthException();
if (!strobe_decrypt(sp, out, data, data.size(), more)) throw ProtocolException();
}
inline void decrypt_no_auth(
TmpBuffer out, const Block &data, bool more = false
) throw(LengthException,ProtocolException) {
decrypt_no_auth((Buffer &)out, data, more);
if (!strobe_decrypt(sp, out.data(), data.data(), data.size(), more)) throw ProtocolException();
}
inline SecureBuffer decrypt_no_auth(const Block &data, bool more = false
@@ -273,13 +261,9 @@ public:
SecureBuffer out(data.size()); decrypt_no_auth(out, data, more); return out;
}
inline void produce_auth(Buffer &out) throw(LengthException,ProtocolException) {
inline void produce_auth(Buffer out) throw(LengthException,ProtocolException) {
if (out.size() > STROBE_MAX_AUTH_BYTES) throw LengthException();
if (!strobe_produce_auth(sp, out, out.size())) throw ProtocolException();
}
inline void produce_auth(TmpBuffer out) throw(LengthException,ProtocolException) {
produce_auth((Buffer &)out);
if (!strobe_produce_auth(sp, out.data(), out.size())) throw ProtocolException();
}
inline SecureBuffer produce_auth(
@@ -289,19 +273,13 @@ public:
}
inline void encrypt(
Buffer &out, const Block &data, uint8_t auth = 8
Buffer out, const Block &data, uint8_t auth = 8
) throw(LengthException,ProtocolException) {
if (out.size() < data.size() || out.size() != data.size() + auth) throw LengthException();
encrypt_no_auth(out.slice(0,data.size()), data);
produce_auth(out.slice(data.size(),auth));
}
inline void encrypt (
TmpBuffer out, const Block &data, uint8_t auth = 8
) throw(LengthException,ProtocolException) {
encrypt((Buffer &)out, data, auth);
}
inline SecureBuffer encrypt (
const Block &data, uint8_t auth = 8
) throw(LengthException,ProtocolException,std::bad_alloc ){
@@ -309,19 +287,13 @@ public:
}
inline void decrypt (
Buffer &out, const Block &data, uint8_t bytes = 8
Buffer out, const Block &data, uint8_t bytes = 8
) throw(LengthException, CryptoException, ProtocolException) {
if (out.size() > data.size() || out.size() != data.size() - bytes) throw LengthException();
decrypt_no_auth(out, data.slice(0,out.size()));
verify_auth(data.slice(out.size(),bytes));
}
inline void decrypt (
TmpBuffer out, const Block &data, uint8_t bytes = 8
) throw(LengthException,CryptoException,ProtocolException) {
decrypt((Buffer &)out, data, bytes);
}
inline SecureBuffer decrypt (
const Block &data, uint8_t bytes = 8
) throw(LengthException,CryptoException,ProtocolException,std::bad_alloc) {
@@ -331,15 +303,11 @@ public:
inline void verify_auth(const Block &auth) throw(LengthException,CryptoException) {
if (auth.size() == 0 || auth.size() > STROBE_MAX_AUTH_BYTES) throw LengthException();
if (!strobe_verify_auth(sp, auth, auth.size())) throw CryptoException();
}
inline void prng(Buffer &out, bool more = false) NOEXCEPT {
(void)strobe_prng(sp, out, out.size(), more);
if (!strobe_verify_auth(sp, auth.data(), auth.size())) throw CryptoException();
}
inline void prng(TmpBuffer out, bool more = false) NOEXCEPT {
prng((Buffer &)out, more);
inline void prng(Buffer out, bool more = false) NOEXCEPT {
(void)strobe_prng(sp, out.data(), out.size(), more);
}
inline SecureBuffer prng(size_t bytes, bool more = false) {


+ 8
- 8
test/bench_decaf.cxx View File

@@ -361,25 +361,25 @@ int main(int argc, char **argv) {
SHA3<512> sha5;
Strobe strobe(Strobe::CLIENT);
unsigned char b1024[1024] = {1};
for (Benchmark b("SHAKE128 1kiB", 30); b.iter(); ) { shake1 += TmpBuffer(b1024,1024); }
for (Benchmark b("SHAKE256 1kiB", 30); b.iter(); ) { shake2 += TmpBuffer(b1024,1024); }
for (Benchmark b("SHA3-512 1kiB", 30); b.iter(); ) { sha5 += TmpBuffer(b1024,1024); }
strobe.key(TmpBuffer(b1024,1024));
for (Benchmark b("SHAKE128 1kiB", 30); b.iter(); ) { shake1 += Buffer(b1024,1024); }
for (Benchmark b("SHAKE256 1kiB", 30); b.iter(); ) { shake2 += Buffer(b1024,1024); }
for (Benchmark b("SHA3-512 1kiB", 30); b.iter(); ) { sha5 += Buffer(b1024,1024); }
strobe.key(Buffer(b1024,1024));
strobe.respec(STROBE_128);
for (Benchmark b("STROBE128 1kiB", 10); b.iter(); ) {
strobe.encrypt_no_auth(TmpBuffer(b1024,1024),TmpBuffer(b1024,1024),b.i>1);
strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024),b.i>1);
}
strobe.respec(STROBE_256);
for (Benchmark b("STROBE256 1kiB", 10); b.iter(); ) {
strobe.encrypt_no_auth(TmpBuffer(b1024,1024),TmpBuffer(b1024,1024),b.i>1);
strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024),b.i>1);
}
strobe.respec(STROBE_KEYED_128);
for (Benchmark b("STROBEk128 1kiB", 10); b.iter(); ) {
strobe.encrypt_no_auth(TmpBuffer(b1024,1024),TmpBuffer(b1024,1024),b.i>1);
strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024),b.i>1);
}
strobe.respec(STROBE_KEYED_256);
for (Benchmark b("STROBEk256 1kiB", 10); b.iter(); ) {
strobe.encrypt_no_auth(TmpBuffer(b1024,1024),TmpBuffer(b1024,1024),b.i>1);
strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024),b.i>1);
}
/* TODO: scalarmul for verif, etc */
Benches<IsoEd25519>::micro();


+ 6
- 6
test/test_decaf.cxx View File

@@ -303,8 +303,8 @@ static void test_ec() {
point_check(test,base,q,r,x,y,x*base+y*q,q.non_secret_combo_with_base(y,x),"ds vt mul");
point_check(test,p,q,r,x,0,Precomputed(p)*x,p*x,"precomp mul");
point_check(test,p,q,r,0,0,r,
Point::from_hash(buffer.slice(0,Point::HASH_BYTES))
+ Point::from_hash(buffer.slice(Point::HASH_BYTES,Point::HASH_BYTES)),
Point::from_hash(Buffer(buffer).slice(0,Point::HASH_BYTES))
+ Point::from_hash(Buffer(buffer).slice(Point::HASH_BYTES,Point::HASH_BYTES)),
"unih = hash+add"
);
@@ -320,8 +320,8 @@ static void test_crypto() {
PrivateKey<Group> priv1(rng), priv2(rng);
PublicKey<Group> pub1(priv1), pub2(priv2);
SecureBuffer message(rng, i);
FixedArrayBuffer<PublicKey<Group>::SIG_BYTES> sig(priv1.sign(message));
SecureBuffer message = rng.read(i);
SecureBuffer sig(priv1.sign(message));
pub1.verify(message, sig);
}
}
@@ -341,8 +341,8 @@ static void test_decaf() {
const char *message = "Hello, world!";

for (int i=0; i<NTESTS && test.passing_now; i++) {
rng.read(TmpBuffer(proto1,sizeof(proto1)));
rng.read(TmpBuffer(proto2,sizeof(proto2)));
rng.read(Buffer(proto1,sizeof(proto1)));
rng.read(Buffer(proto2,sizeof(proto2)));
decaf_255_derive_private_key(s1,proto1);
decaf_255_private_to_public(p1,s1);
decaf_255_derive_private_key(s2,proto2);


Loading…
Cancel
Save