From b849d2cd91de8d3e51e66a5c5eef043d72f37827 Mon Sep 17 00:00:00 2001 From: Mike Hamburg Date: Sat, 18 Jul 2015 14:09:54 -0700 Subject: [PATCH] working on securebuffer problems, might just switch things to vector --- src/public_include/decaf/decaf_255.hxx | 11 ++-- src/public_include/decaf/decaf_448.hxx | 8 +-- src/public_include/decaf/secure_buffer.hxx | 40 ++++++++++-- src/public_include/decaf/shake.hxx | 11 ++++ test/test_decaf.cxx | 72 ++++++++++++++-------- 5 files changed, 101 insertions(+), 41 deletions(-) diff --git a/src/public_include/decaf/decaf_255.hxx b/src/public_include/decaf/decaf_255.hxx index 7350e7a..5932870 100644 --- a/src/public_include/decaf/decaf_255.hxx +++ b/src/public_include/decaf/decaf_255.hxx @@ -88,7 +88,7 @@ public: /** @brief Construct from RNG */ inline explicit Scalar(Rng &rng) NOEXCEPT { - StackBuffer sb(rng); + FixedArrayBuffer sb(rng); *this = sb; } @@ -230,10 +230,10 @@ public: /** @brief Construct from RNG */ inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT { if (uniform) { - StackBuffer<2*HASH_BYTES> b(rng); + FixedArrayBuffer<2*HASH_BYTES> b(rng); set_to_hash(b); } else { - StackBuffer b(rng); + FixedArrayBuffer b(rng); set_to_hash(b); } } @@ -399,7 +399,7 @@ public: /** @brief Return a point equal to *this, whose internal data has a randomized representation. */ inline Point debugging_pscale(Rng &r) const NOEXCEPT { - StackBuffer sb(r); return debugging_pscale(sb); + FixedArrayBuffer sb(r); return debugging_pscale(sb); } /** @@ -430,7 +430,8 @@ public: } /** @brief Steganographically encode this */ - inline SecureBuffer steg_encode(Rng &rng) const throw(std::bad_alloc) { + inline SecureBuffer steg_encode(Rng &rng, size_t size=STEG_BYTES) const throw(std::bad_alloc, LengthException) { + if (size <= HASH_BYTES + 4 || size > 2*HASH_BYTES) throw LengthException(); SecureBuffer out(STEG_BYTES); bool done; do { diff --git a/src/public_include/decaf/decaf_448.hxx b/src/public_include/decaf/decaf_448.hxx index 287236b..95769d4 100644 --- a/src/public_include/decaf/decaf_448.hxx +++ b/src/public_include/decaf/decaf_448.hxx @@ -88,7 +88,7 @@ public: /** @brief Construct from RNG */ inline explicit Scalar(Rng &rng) NOEXCEPT { - StackBuffer sb(rng); + FixedArrayBuffer sb(rng); *this = sb; } @@ -233,10 +233,10 @@ public: /** @brief Construct from RNG */ inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT { if (uniform) { - StackBuffer<2*HASH_BYTES> b(rng); + FixedArrayBuffer<2*HASH_BYTES> b(rng); set_to_hash(b); } else { - StackBuffer b(rng); + FixedArrayBuffer b(rng); set_to_hash(b); } } @@ -408,7 +408,7 @@ public: /** @brief Return a point equal to *this, whose internal data has a randomized representation. */ inline Point debugging_pscale(Rng &r) const NOEXCEPT { - StackBuffer sb(r); + FixedArrayBuffer sb(r); return debugging_pscale(sb); } diff --git a/src/public_include/decaf/secure_buffer.hxx b/src/public_include/decaf/secure_buffer.hxx index 2ce19a2..98bc9fc 100644 --- a/src/public_include/decaf/secure_buffer.hxx +++ b/src/public_include/decaf/secure_buffer.hxx @@ -13,6 +13,7 @@ #include #include +#include /** @cond internal */ #if __cplusplus >= 201103L @@ -146,6 +147,13 @@ public: /** 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) { + if (name) printf("%s = ", name); + for (size_t s = 0; s < size(); s++) printf("%02x", data_[s]); + printf("\n"); + } }; /** A fixed-size block */ @@ -184,6 +192,12 @@ public: /** Slice the buffer*/ inline TmpBuffer slice(size_t off, size_t length) throw(LengthException); + /** Copy from another block */ + inline void assign(const Block b) throw(LengthException) { + if (b.size() != size()) throw LengthException(); + memmove(*this,b,size()); + } + /** Securely set the buffer to 0. */ inline void zeroize() NOEXCEPT { really_bzero(data(),size()); } }; @@ -214,23 +228,39 @@ public: }; /** A fixed-size stack-allocated buffer (for NOEXCEPT semantics) */ -template class StackBuffer : public FixedBuffer { +template class FixedArrayBuffer : public FixedBuffer { private: uint8_t storage[Size]; public: using Buffer::zeroize; /** New buffer initialized to zero. */ - inline explicit StackBuffer() NOEXCEPT : FixedBuffer(storage) { memset(storage,0,Size); } + inline explicit FixedArrayBuffer() NOEXCEPT : FixedBuffer(storage) { memset(storage,0,Size); } /** New uninitialized buffer. */ - inline explicit StackBuffer(const NOINIT &) NOEXCEPT : FixedBuffer(storage) { } + inline explicit FixedArrayBuffer(const NOINIT &) NOEXCEPT : FixedBuffer(storage) { } /** New random buffer */ - inline explicit StackBuffer(Rng &r) NOEXCEPT : FixedBuffer(storage) { r.read(*this); } + inline explicit FixedArrayBuffer(Rng &r) NOEXCEPT : FixedBuffer(storage) { r.read(*this); } + + /** Copy constructor */ + inline explicit FixedArrayBuffer(const FixedBlock &b) NOEXCEPT : FixedBuffer(storage) { + memcpy(storage,b,Size); + } + + /** Copy constructor */ + inline explicit FixedArrayBuffer(const Block &b) throw(LengthException) : FixedBuffer(storage) { + if (b.size() != Size) throw LengthException(); + memcpy(storage,b,Size); + } + + /** Copy constructor */ + inline explicit FixedArrayBuffer(const FixedArrayBuffer &b) NOEXCEPT : FixedBuffer(storage) { + memcpy(storage,b,Size); + } /** Destroy the buffer */ - ~StackBuffer() NOEXCEPT { zeroize(); } + ~FixedArrayBuffer() NOEXCEPT { zeroize(); } }; /** @cond internal */ diff --git a/src/public_include/decaf/shake.hxx b/src/public_include/decaf/shake.hxx index 42c153d..d278721 100644 --- a/src/public_include/decaf/shake.hxx +++ b/src/public_include/decaf/shake.hxx @@ -108,6 +108,12 @@ public: /** Reset the hash to the empty string */ inline void reset() NOEXCEPT { sponge_init(sp, get_params()); } + + + /** Hash bytes with this SHA3 instance. TODO: output length? */ + static inline SecureBuffer hash(const Block &b) throw(std::bad_alloc) { + SHA3 s; s += b; return s.output(); + } }; /** Variable-output-length SHAKE */ @@ -122,6 +128,11 @@ public: /** Reset the hash to the empty string */ inline void reset() NOEXCEPT { sponge_init(sp, get_params()); } + + /** Hash bytes with this SHAKE instance */ + static inline SecureBuffer hash(const Block &b, size_t outlen) throw(std::bad_alloc) { + SHAKE s; s += b; return s.output(outlen); + } }; /** @cond internal */ diff --git a/test/test_decaf.cxx b/test/test_decaf.cxx index 2a9103a..a282c3a 100644 --- a/test/test_decaf.cxx +++ b/test/test_decaf.cxx @@ -12,8 +12,10 @@ #include #include #include +#include #include +using namespace decaf; static bool passing = true; static const long NTESTS = 10000; @@ -49,7 +51,7 @@ typedef typename Group::Precomputed Precomputed; static void print(const char *name, const Scalar &x) { unsigned char buffer[Scalar::SER_BYTES]; - x.encode(decaf::FixedBuffer(buffer)); + x.encode(FixedBuffer(buffer)); printf(" %s = 0x", name); for (int i=sizeof(buffer)-1; i>=0; i--) { printf("%02x", buffer[i]); @@ -57,7 +59,7 @@ static void print(const char *name, const Scalar &x) { printf("\n"); } -static void hexprint(const char *name, const decaf::SecureBuffer &buffer) { +static void hexprint(const char *name, const SecureBuffer &buffer) { printf(" %s = 0x", name); for (int i=buffer.size()-1; i>=0; i--) { printf("%02x", buffer[i]); @@ -66,7 +68,7 @@ static void hexprint(const char *name, const decaf::SecureBuffer &buffer) { } static void print(const char *name, const Point &x) { - decaf::StackBuffer buffer; + FixedArrayBuffer buffer; x.encode(buffer); printf(" %s = 0x", name); for (int i=Point::SER_BYTES-1; i>=0; i--) { @@ -126,7 +128,7 @@ static bool point_check( } static void test_arithmetic() { - decaf::SpongeRng rng(decaf::Block("test_arithmetic")); + SpongeRng rng(Block("test_arithmetic")); Test test("Arithmetic"); Scalar x(0),y(0),z(0); @@ -161,18 +163,18 @@ static void test_arithmetic() { } static void test_elligator() { - decaf::SpongeRng rng(decaf::Block("test_elligator")); + SpongeRng rng(Block("test_elligator")); Test test("Elligator"); const int NHINTS = Group::REMOVED_COFACTOR * 2; - decaf::SecureBuffer *alts[NHINTS]; + SecureBuffer *alts[NHINTS]; bool successes[NHINTS]; - decaf::SecureBuffer *alts2[NHINTS]; + SecureBuffer *alts2[NHINTS]; bool successes2[NHINTS]; for (int i=0; i= Point::HASH_BYTES) b1[Point::HASH_BYTES-1] &= 0x7F; // FIXME MAGIC @@ -184,8 +186,8 @@ static void test_elligator() { bool good = false; for (int j=0; j Point::HASH_BYTES) memcpy(&(*alts[j])[Point::HASH_BYTES], &b1[Point::HASH_BYTES], len-Point::HASH_BYTES); @@ -263,7 +265,7 @@ static void test_elligator() { } static void test_ec() { - decaf::SpongeRng rng(decaf::Block("test_ec")); + SpongeRng rng(Block("test_ec")); Test test("EC"); @@ -278,13 +280,13 @@ static void test_ec() { Point p(rng); Point q(rng); - decaf::SecureBuffer buffer(2*Point::HASH_BYTES); + 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"); + point_check(test,p,q,r,0,0,p,Point((SecureBuffer)p),"round-trip"); Point pp = p.debugging_torque().debugging_pscale(rng); - if (decaf::SecureBuffer(pp) != decaf::SecureBuffer(p)) { + if (SecureBuffer(pp) != SecureBuffer(p)) { test.fail(); printf("Fail torque seq test\n"); } @@ -306,16 +308,30 @@ static void test_ec() { "unih = hash+add" ); - point_check(test,p,q,r,x,0,Point(x.direct_scalarmul(decaf::SecureBuffer(p))),x*p,"direct mul"); + point_check(test,p,q,r,x,0,Point(x.direct_scalarmul(SecureBuffer(p))),x*p,"direct mul"); } } -}; // template +static void test_crypto() { + Test test("Sample crypto"); + SpongeRng rng(Block("test_decaf_crypto")); + + for (int i=0; i priv1(rng), priv2(rng); + PublicKey pub1(priv1), pub2(priv2); + + SecureBuffer message(rng, i); + FixedArrayBuffer::SIG_BYTES> sig(priv1.sign(message)); + pub1.verify(message, sig); + } +} + +}; // template // FIXME cross-field static void test_decaf() { Test test("Sample crypto"); - decaf::SpongeRng rng(decaf::Block("test_decaf")); + SpongeRng rng(Block("test_decaf")); decaf_255_symmetric_key_t proto1,proto2; decaf_255_private_key_t s1,s2; @@ -325,8 +341,8 @@ static void test_decaf() { const char *message = "Hello, world!"; for (int i=0; i::test_arithmetic(); - Tests::test_elligator(); - Tests::test_ec(); + printf("Testing %s:\n",IsoEd25519::name()); + Tests::test_arithmetic(); + Tests::test_elligator(); + Tests::test_ec(); + Tests::test_crypto(); test_decaf(); printf("\n"); - printf("Testing %s:\n", decaf::Ed448Goldilocks::name()); - Tests::test_arithmetic(); - Tests::test_elligator(); - Tests::test_ec(); + printf("Testing %s:\n", Ed448Goldilocks::name()); + Tests::test_arithmetic(); + Tests::test_elligator(); + Tests::test_ec(); + Tests::test_crypto(); if (passing) printf("Passed all tests.\n");