From 3fe31a7e9a51ee988d1698a03b7f3044a9af5836 Mon Sep 17 00:00:00 2001 From: Mike Hamburg Date: Tue, 31 Mar 2015 11:49:01 -0700 Subject: [PATCH] get rid of std::string --- include/decaf.hxx | 122 +++++++++++++++++++++++--------------------- include/shake.hxx | 44 ++++------------ test/test_decaf.cxx | 16 +++--- 3 files changed, 84 insertions(+), 98 deletions(-) diff --git a/include/decaf.hxx b/include/decaf.hxx index e1e2b8b..126fe05 100644 --- a/include/decaf.hxx +++ b/include/decaf.hxx @@ -53,6 +53,20 @@ typedef uint32_t GroupId; static const GroupId Ed448Goldilocks = 448; +/** @brief An exception for when crypto (ie point decode) has failed. */ +class CryptoException : public std::exception { +public: + /** @return "CryptoException" */ + virtual const char * what() const NOEXCEPT { return "CryptoException"; } +}; + +/** @brief An exception for when crypto (ie point decode) has failed. */ +class LengthException : public std::exception { +public: + /** @return "CryptoException" */ + virtual const char * what() const NOEXCEPT { return "LengthException"; } +}; + /** * Securely erase contents of memory. */ @@ -66,7 +80,10 @@ protected: public: /** Empty init */ - inline Block() : data_(NULL), size_(0) {} + inline Block() NOEXCEPT : data_(NULL), size_(0) {} + + /** Init from C string */ + inline Block(const char *data) NOEXCEPT : data_((unsigned char *)data), size_(strlen(data)) {} /** Unowned init */ inline Block(const unsigned char *data, size_t size) NOEXCEPT : data_((unsigned char *)data), size_(size) {} @@ -88,14 +105,23 @@ public: return std::string((const char *)data_,size_); } + /** Slice the buffer*/ + inline Block slice(size_t off, size_t length) const throw(LengthException) { + if (off > size() || length > size() - off) + throw LengthException(); + return Block(data()+off, length); + } + /** Virtual destructor for SecureBlock. TODO: probably means vtable? Make bool? */ inline virtual ~Block() {}; }; +class TmpBuffer; + class Buffer : public Block { public: /** Null init */ - inline Buffer() : Block() {} + inline Buffer() NOEXCEPT : Block() {} /** Unowned init */ inline Buffer(unsigned char *data, size_t size) NOEXCEPT : Block(data,size) {} @@ -111,8 +137,22 @@ public: /** Autocast to unsigned char */ inline operator unsigned char*() NOEXCEPT { return data_; } + + /** Slice the buffer*/ + inline TmpBuffer slice(size_t off, size_t length) throw(LengthException); }; +class TmpBuffer : public Buffer { +public: + /** Unowned init */ + inline TmpBuffer(unsigned char *data, size_t size) NOEXCEPT : Buffer(data,size) {} +}; + +TmpBuffer Buffer::slice(size_t off, size_t length) throw(LengthException) { + if (off > size() || length > size() - off) throw LengthException(); + return TmpBuffer(data()+off, length); +} + /** A self-erasing block of data */ class SecureBuffer : public Buffer { public: @@ -169,7 +209,7 @@ public: inline SecureBuffer(SecureBuffer &&move) { *this = move; } /** Move non-constructor */ - inline SecureBuffer(const Block &&move) { *this = (Block &)move; } + inline SecureBuffer(Block &&move) { *this = (Block &)move; } /** Move-assign constructor */ inline SecureBuffer& operator=(SecureBuffer &&move) { @@ -205,13 +245,6 @@ template struct decaf; */ template<> struct decaf { -/** @brief An exception for when crypto (ie point decode) has failed. */ -class CryptoException : public std::exception { -public: - /** @return "CryptoException" */ - virtual const char * what() const NOEXCEPT { return "CryptoException"; } -}; - /** @cond internal */ class Point; class Precomputed; @@ -442,62 +475,37 @@ public: if (buffer.size() != SER_BYTES) return DECAF_FAILURE; return decaf_448_point_decode(p.p,buffer.data(),allow_identity); } - - /** - * @brief Map to the curve from a C buffer. - * The all-zero buffer maps to the identity, as does the buffer {1,0...} - * @todo remove? - */ - static inline Point from_hash_nonuniform ( const unsigned char buffer[SER_BYTES] ) NOEXCEPT { - Point p((NOINIT())); decaf_448_point_from_hash_nonuniform(p.p,buffer); return p; - } - - /** - * @brief Map to the curve from a C++ string buffer. - * The empty or all-zero string maps to the identity, as does the string "\x01". - * If the buffer is shorter than (TODO) SER_BYTES, it will be zero-padded on the right. - */ - static inline Point from_hash_nonuniform ( const Block &s ) NOEXCEPT { - Point p((NOINIT())); - if (s.size() < SER_BYTES) { - SecureBuffer b(SER_BYTES); - memcpy(b.data(), s.data(), s.size()); - decaf_448_point_from_hash_nonuniform(p.p,b); - } else { - decaf_448_point_from_hash_nonuniform(p.p,s); - } - return p; - } - - - /** - * @brief Map uniformly to the curve from a C buffer. - * The all-zero buffer maps to the identity, as does the buffer {1,0...}. - */ - static inline Point from_hash ( const unsigned char buffer[2*SER_BYTES] ) NOEXCEPT { - Point p((NOINIT())); decaf_448_point_from_hash_uniform(p.p,buffer); return p; - } /** - * @brief Map uniformly to the curve from a C++ buffer. + * @brief Map uniformly to the curve from a hash buffer. * The empty or all-zero string maps to the identity, as does the string "\x01". - * If the buffer is shorter than (TODO) 2*SER_BYTES, well, it won't be as uniform, + * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform, * but the buffer will be zero-padded on the right. */ static inline Point from_hash ( const Block &s ) NOEXCEPT { - if (s.size() <= SER_BYTES) { - return from_hash_nonuniform(s); - } - - Point p((NOINIT())); - if (s.size() < 2*SER_BYTES) { - SecureBuffer b(SER_BYTES); + Point p((NOINIT())); p.set_to_hash(s); return p; + } + + /** + * @brief Map to the curve from a hash buffer. + * The empty or all-zero string maps to the identity, as does the string "\x01". + * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform, + * but the buffer will be zero-padded on the right. + */ + inline void set_to_hash( const Block &s ) NOEXCEPT { + if (s.size() < HASH_BYTES) { + SecureBuffer b(HASH_BYTES); + memcpy(b.data(), s.data(), s.size()); + decaf_448_point_from_hash_nonuniform(p,b); + } else if (s.size() == HASH_BYTES) { + decaf_448_point_from_hash_nonuniform(p,s); + } else if (s.size() < 2*HASH_BYTES) { + SecureBuffer b(2*HASH_BYTES); memcpy(b.data(), s.data(), s.size()); - decaf_448_point_from_hash_nonuniform(p.p,b); + decaf_448_point_from_hash_uniform(p,b); } else { - decaf_448_point_from_hash_nonuniform(p.p,s); + decaf_448_point_from_hash_uniform(p,s); } - return p; } /** diff --git a/include/shake.hxx b/include/shake.hxx index 494f016..6593b52 100644 --- a/include/shake.hxx +++ b/include/shake.hxx @@ -9,8 +9,6 @@ * @warning EXPERIMENTAL! The names, parameter orders etc are likely to change. */ -/** TODO: Crypto++ style secure auto-erasing strings?? */ - #ifndef __SHAKE_HXX__ #define __SHAKE_HXX__ @@ -140,29 +138,15 @@ public: const char *what() const NOEXCEPT { return what_; } RngException(int err_code, const char *what_) NOEXCEPT : what_(what_), err_code(err_code) {} }; - struct FROM_BUFFER {}; - struct FROM_FILE {}; - - /** Initialize, deterministically by default, from C buffer */ - inline SpongeRng( const FROM_BUFFER &, const uint8_t *in, size_t len, bool deterministic = true ) NOEXCEPT - : KeccakSponge((NOINIT())) { - spongerng_init_from_buffer(sp,in,len,deterministic); - } - - /** Initialize, deterministically by default, from C++ string */ - inline SpongeRng( const FROM_BUFFER &, const std::string &in, bool deterministic = true ) - : KeccakSponge((NOINIT())) { - spongerng_init_from_buffer(sp,GET_DATA(in),in.size(),deterministic); - } /** Initialize, deterministically by default, from block */ - inline SpongeRng( const FROM_BUFFER &, const Block &in, bool deterministic = true ) + inline SpongeRng( const Block &in, bool deterministic = true ) : KeccakSponge((NOINIT())) { spongerng_init_from_buffer(sp,in.data(),in.size(),deterministic); } /** Initialize, non-deterministically by default, from C/C++ filename */ - inline SpongeRng( const FROM_FILE &, const std::string &in = "/dev/urandom", size_t len = 32, bool deterministic = false ) + inline SpongeRng( const std::string &in = "/dev/urandom", size_t len = 32, bool deterministic = false ) throw(RngException) : KeccakSponge((NOINIT())) { int ret = spongerng_init_from_file(sp,in.c_str(),len,deterministic); @@ -171,20 +155,18 @@ public: } } - /** Read data to a C buffer. - * @warning TODO Future versions of this function may throw RngException if a - * nondeterministic RNG fails a reseed. - */ - inline void read(uint8_t *buffer, size_t length) { - spongerng_next(sp,buffer,length); - } + /** Read data to a buffer. */ + inline void read(Buffer &buffer) { spongerng_next(sp,buffer.data(),buffer.size()); } + + /** Read data to a buffer. */ + inline void read(TmpBuffer buffer) { read((Buffer &)buffer); } /** Read data to a C++ string * @warning TODO Future versions of this function may throw RngException if a * nondeterministic RNG fails a reseed. */ inline SecureBuffer read(size_t length) throw(std::bad_alloc) { - SecureBuffer out(length); spongerng_next(sp,out,length); return out; + SecureBuffer out(length); read(out); return out; } private: @@ -195,21 +177,17 @@ private: /**@cond internal*/ /* FIXME: multiple sizes */ decaf<448>::Scalar::Scalar(SpongeRng &rng) { - uint8_t buffer[SER_BYTES]; - rng.read(buffer, sizeof(buffer)); - decaf_448_scalar_decode_long(s,buffer,sizeof(buffer)); - really_bzero(buffer, sizeof(buffer)); + *this = rng.read(SER_BYTES); } decaf<448>::Point::Point(SpongeRng &rng, bool uniform) { - uint8_t buffer[2*HASH_BYTES]; - rng.read(buffer, (uniform ? 2 : 1) * HASH_BYTES); + SecureBuffer buffer((uniform ? 2 : 1) * HASH_BYTES); + rng.read(buffer); if (uniform) { decaf_448_point_from_hash_uniform(p,buffer); } else { decaf_448_point_from_hash_nonuniform(p,buffer); } - really_bzero(buffer, sizeof(buffer)); } /**@endcond*/ diff --git a/test/test_decaf.cxx b/test/test_decaf.cxx index 3980d39..0e32a56 100644 --- a/test/test_decaf.cxx +++ b/test/test_decaf.cxx @@ -115,7 +115,7 @@ static bool point_check( } static void test_arithmetic() { - decaf::SpongeRng rng(decaf::SpongeRng::FROM_BUFFER(), "test_arithmetic"); + decaf::SpongeRng rng(decaf::Block("test_arithmetic")); Test test("Arithmetic"); Scalar x(0),y(0),z(0); @@ -151,14 +151,13 @@ static void test_arithmetic() { static void test_ec() { - decaf::SpongeRng rng(decaf::SpongeRng::FROM_BUFFER(), "test_ec"); - unsigned char buffer[2*DECAF_448_SER_BYTES]; + decaf::SpongeRng rng(decaf::Block("test_ec")); Test test("EC"); Point id = Point::identity(), base = Point::base(); - point_check(test,id,id,id,0,0,Point::from_hash(std::string("")),id,"fh0"); - point_check(test,id,id,id,0,0,Point::from_hash(std::string("\x01")),id,"fh1"); + point_check(test,id,id,id,0,0,Point::from_hash(""),id,"fh0"); + point_check(test,id,id,id,0,0,Point::from_hash("\x01"),id,"fh1"); for (int i=0; i