diff --git a/src/public_include/decaf/crypto.hxx b/src/public_include/decaf/crypto.hxx index b26cab6..00b332c 100644 --- a/src/public_include/decaf/crypto.hxx +++ b/src/public_include/decaf/crypto.hxx @@ -57,7 +57,7 @@ public: inline explicit PublicKey(const PrivateKey &priv) NOEXCEPT; /** @brief Read a private key from a string*/ - inline explicit PublicKey(const FixedBlock b) NOEXCEPT : ser(b) {} + inline explicit PublicKey(const FixedBlock &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 &ctx_, const FixedBlock &sig) throw(CryptoException) { SHAKE ctx(ctx_); ctx << ser << sig.slice(0,Group::Point::SER_BYTES); - FixedBuffer 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::CHALLENGE_BYTES> challenge(ctx.output(PublicKey::CHALLENGE_BYTES)); - challenge.debug_print("ch sign"); - SecureBuffer response(nonce - scalar * challenge); + SecureBuffer challenge(ctx.output(PublicKey::CHALLENGE_BYTES)); + SecureBuffer response((nonce - scalar * typename Group::Scalar(challenge)).encode()); SecureBuffer ret(PublicKey::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; } diff --git a/src/public_include/decaf/decaf_255.hxx b/src/public_include/decaf/decaf_255.hxx index 5932870..a91805b 100644 --- a/src/public_include/decaf/decaf_255.hxx +++ b/src/public_include/decaf/decaf_255.hxx @@ -130,7 +130,7 @@ public: static inline decaf_bool_t __attribute__((warn_unused_result)) decode ( Scalar &sc, const FixedBlock 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 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 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 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; } diff --git a/src/public_include/decaf/decaf_448.hxx b/src/public_include/decaf/decaf_448.hxx index 95769d4..47aa969 100644 --- a/src/public_include/decaf/decaf_448.hxx +++ b/src/public_include/decaf/decaf_448.hxx @@ -130,17 +130,17 @@ public: static inline decaf_bool_t __attribute__((warn_unused_result)) decode ( Scalar &sc, const FixedBlock 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 buffer) const NOEXCEPT{ + decaf_448_scalar_encode(buffer.data(), s); } /** @brief Encode to fixed-length buffer */ - inline void encode(FixedBuffer 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 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 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; diff --git a/src/public_include/decaf/secure_buffer.hxx b/src/public_include/decaf/secure_buffer.hxx index 98bc9fc..58c6477 100644 --- a/src/public_include/decaf/secure_buffer.hxx +++ b/src/public_include/decaf/secure_buffer.hxx @@ -14,6 +14,7 @@ #include #include #include +#include /** @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 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 struct rebind { typedef SanitizingAllocator other; }; + inline SanitizingAllocator() NOEXCEPT {} + inline ~SanitizingAllocator() NOEXCEPT {} + inline SanitizingAllocator(const SanitizingAllocator &) NOEXCEPT {} + template inline SanitizingAllocator(const SanitizingAllocator &) 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::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(v); + } + + inline void deallocate(T* p, size_t size) NOEXCEPT { + if (p==NULL) return; + really_bzero(reinterpret_cast(p), size); + free(reinterpret_cast(p)); + } + + inline size_t max_size() const NOEXCEPT { return std::numeric_limits::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 > 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 inline Block(const std::vector &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 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 inline FixedBlock(const std::vector &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 inline Buffer(std::vector &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 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 class FixedArrayBuffer : public FixedBuffer { private: @@ -245,18 +303,18 @@ public: /** Copy constructor */ inline explicit FixedArrayBuffer(const FixedBlock &b) NOEXCEPT : FixedBuffer(storage) { - memcpy(storage,b,Size); + memcpy(storage,b.data(),Size); } /** Copy constructor */ inline explicit FixedArrayBuffer(const Block &b) throw(LengthException) : FixedBuffer(storage) { if (b.size() != Size) throw LengthException(); - memcpy(storage,b,Size); + memcpy(storage,b.data(),Size); } /** Copy constructor */ inline explicit FixedArrayBuffer(const FixedArrayBuffer &b) NOEXCEPT : FixedBuffer(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 ©) throw(std::bad_alloc) : Buffer() { *this = copy; } - - /** Copy-assign constructor */ - inline SecureBuffer& operator=(const Block ©) throw(std::bad_alloc) { - if (© == 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 ©) throw(std::bad_alloc) { - if (© == 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) { diff --git a/src/public_include/decaf/shake.hxx b/src/public_include/decaf/shake.hxx index d278721..913e3d7 100644 --- a/src/public_include/decaf/shake.hxx +++ b/src/public_include/decaf/shake.hxx @@ -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) { diff --git a/test/bench_decaf.cxx b/test/bench_decaf.cxx index 9b35e8e..c0e635b 100644 --- a/test/bench_decaf.cxx +++ b/test/bench_decaf.cxx @@ -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::micro(); diff --git a/test/test_decaf.cxx b/test/test_decaf.cxx index a282c3a..ac12b8d 100644 --- a/test/test_decaf.cxx +++ b/test/test_decaf.cxx @@ -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 priv1(rng), priv2(rng); PublicKey pub1(priv1), pub2(priv2); - SecureBuffer message(rng, i); - FixedArrayBuffer::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