Browse Source

get rid of std::string

master
Mike Hamburg 9 years ago
parent
commit
3fe31a7e9a
3 changed files with 84 additions and 98 deletions
  1. +65
    -57
      include/decaf.hxx
  2. +11
    -33
      include/shake.hxx
  3. +8
    -8
      test/test_decaf.cxx

+ 65
- 57
include/decaf.hxx View File

@@ -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<GroupId group = Ed448Goldilocks> struct decaf;
*/
template<> struct decaf<Ed448Goldilocks> {

/** @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;
}
/**


+ 11
- 33
include/shake.hxx View File

@@ -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*/


+ 8
- 8
test/test_decaf.cxx View File

@@ -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<NTESTS && test.passing_now; i++) {
/* TODO: pathological cases */
@@ -167,7 +166,8 @@ static void test_ec() {
Point p(rng);
Point q(rng);
rng.read(buffer, 2*DECAF_448_SER_BYTES);
decaf::SecureBuffer buffer(2*Point::HASH_BYTES);
rng.read(buffer);
Point r = Point::from_hash(buffer);
point_check(test,p,q,r,0,0,p,Point((decaf::SecureBuffer)p),"round-trip");
@@ -181,8 +181,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_nonuniform(buffer)
+Point::from_hash_nonuniform(&buffer[DECAF_448_SCALAR_BYTES]),
Point::from_hash(buffer.slice(0,Point::HASH_BYTES))
+ Point::from_hash(buffer.slice(Point::HASH_BYTES,Point::HASH_BYTES)),
"unih = hash+add"
);


Loading…
Cancel
Save