Browse Source

working on securebuffer problems, might just switch things to vector

master
Mike Hamburg 9 years ago
parent
commit
b849d2cd91
5 changed files with 101 additions and 41 deletions
  1. +6
    -5
      src/public_include/decaf/decaf_255.hxx
  2. +4
    -4
      src/public_include/decaf/decaf_448.hxx
  3. +35
    -5
      src/public_include/decaf/secure_buffer.hxx
  4. +11
    -0
      src/public_include/decaf/shake.hxx
  5. +45
    -27
      test/test_decaf.cxx

+ 6
- 5
src/public_include/decaf/decaf_255.hxx View File

@@ -88,7 +88,7 @@ public:
/** @brief Construct from RNG */ /** @brief Construct from RNG */
inline explicit Scalar(Rng &rng) NOEXCEPT { inline explicit Scalar(Rng &rng) NOEXCEPT {
StackBuffer<SER_BYTES> sb(rng);
FixedArrayBuffer<SER_BYTES> sb(rng);
*this = sb; *this = sb;
} }
@@ -230,10 +230,10 @@ public:
/** @brief Construct from RNG */ /** @brief Construct from RNG */
inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT { inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT {
if (uniform) { if (uniform) {
StackBuffer<2*HASH_BYTES> b(rng);
FixedArrayBuffer<2*HASH_BYTES> b(rng);
set_to_hash(b); set_to_hash(b);
} else { } else {
StackBuffer<HASH_BYTES> b(rng);
FixedArrayBuffer<HASH_BYTES> b(rng);
set_to_hash(b); set_to_hash(b);
} }
} }
@@ -399,7 +399,7 @@ public:
/** @brief Return a point equal to *this, whose internal data has a randomized representation. */ /** @brief Return a point equal to *this, whose internal data has a randomized representation. */
inline Point debugging_pscale(Rng &r) const NOEXCEPT { inline Point debugging_pscale(Rng &r) const NOEXCEPT {
StackBuffer<SER_BYTES> sb(r); return debugging_pscale(sb);
FixedArrayBuffer<SER_BYTES> sb(r); return debugging_pscale(sb);
} }
/** /**
@@ -430,7 +430,8 @@ public:
} }
/** @brief Steganographically encode this */ /** @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); SecureBuffer out(STEG_BYTES);
bool done; bool done;
do { do {


+ 4
- 4
src/public_include/decaf/decaf_448.hxx View File

@@ -88,7 +88,7 @@ public:
/** @brief Construct from RNG */ /** @brief Construct from RNG */
inline explicit Scalar(Rng &rng) NOEXCEPT { inline explicit Scalar(Rng &rng) NOEXCEPT {
StackBuffer<SER_BYTES> sb(rng);
FixedArrayBuffer<SER_BYTES> sb(rng);
*this = sb; *this = sb;
} }
@@ -233,10 +233,10 @@ public:
/** @brief Construct from RNG */ /** @brief Construct from RNG */
inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT { inline explicit Point(Rng &rng, bool uniform = true) NOEXCEPT {
if (uniform) { if (uniform) {
StackBuffer<2*HASH_BYTES> b(rng);
FixedArrayBuffer<2*HASH_BYTES> b(rng);
set_to_hash(b); set_to_hash(b);
} else { } else {
StackBuffer<HASH_BYTES> b(rng);
FixedArrayBuffer<HASH_BYTES> b(rng);
set_to_hash(b); set_to_hash(b);
} }
} }
@@ -408,7 +408,7 @@ public:
/** @brief Return a point equal to *this, whose internal data has a randomized representation. */ /** @brief Return a point equal to *this, whose internal data has a randomized representation. */
inline Point debugging_pscale(Rng &r) const NOEXCEPT { inline Point debugging_pscale(Rng &r) const NOEXCEPT {
StackBuffer<SER_BYTES> sb(r);
FixedArrayBuffer<SER_BYTES> sb(r);
return debugging_pscale(sb); return debugging_pscale(sb);
} }


+ 35
- 5
src/public_include/decaf/secure_buffer.hxx View File

@@ -13,6 +13,7 @@


#include <string> #include <string>
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h>


/** @cond internal */ /** @cond internal */
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
@@ -146,6 +147,13 @@ public:


/** Virtual destructor for SecureBlock. TODO: probably means vtable? Make bool? */ /** Virtual destructor for SecureBlock. TODO: probably means vtable? Make bool? */
inline virtual ~Block() {}; 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 */ /** A fixed-size block */
@@ -184,6 +192,12 @@ public:
/** Slice the buffer*/ /** Slice the buffer*/
inline TmpBuffer slice(size_t off, size_t length) throw(LengthException); 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. */ /** Securely set the buffer to 0. */
inline void zeroize() NOEXCEPT { really_bzero(data(),size()); } inline void zeroize() NOEXCEPT { really_bzero(data(),size()); }
}; };
@@ -214,23 +228,39 @@ public:
}; };


/** A fixed-size stack-allocated buffer (for NOEXCEPT semantics) */ /** A fixed-size stack-allocated buffer (for NOEXCEPT semantics) */
template<size_t Size> class StackBuffer : public FixedBuffer<Size> {
template<size_t Size> class FixedArrayBuffer : public FixedBuffer<Size> {
private: private:
uint8_t storage[Size]; uint8_t storage[Size];
public: public:
using Buffer::zeroize; using Buffer::zeroize;
/** New buffer initialized to zero. */ /** New buffer initialized to zero. */
inline explicit StackBuffer() NOEXCEPT : FixedBuffer<Size>(storage) { memset(storage,0,Size); }
inline explicit FixedArrayBuffer() NOEXCEPT : FixedBuffer<Size>(storage) { memset(storage,0,Size); }


/** New uninitialized buffer. */ /** New uninitialized buffer. */
inline explicit StackBuffer(const NOINIT &) NOEXCEPT : FixedBuffer<Size>(storage) { }
inline explicit FixedArrayBuffer(const NOINIT &) NOEXCEPT : FixedBuffer<Size>(storage) { }
/** New random buffer */ /** New random buffer */
inline explicit StackBuffer(Rng &r) NOEXCEPT : FixedBuffer<Size>(storage) { r.read(*this); }
inline explicit FixedArrayBuffer(Rng &r) NOEXCEPT : FixedBuffer<Size>(storage) { r.read(*this); }
/** Copy constructor */
inline explicit FixedArrayBuffer(const FixedBlock<Size> &b) NOEXCEPT : FixedBuffer<Size>(storage) {
memcpy(storage,b,Size);
}
/** Copy constructor */
inline explicit FixedArrayBuffer(const Block &b) throw(LengthException) : FixedBuffer<Size>(storage) {
if (b.size() != Size) throw LengthException();
memcpy(storage,b,Size);
}
/** Copy constructor */
inline explicit FixedArrayBuffer(const FixedArrayBuffer<Size> &b) NOEXCEPT : FixedBuffer<Size>(storage) {
memcpy(storage,b,Size);
}
/** Destroy the buffer */ /** Destroy the buffer */
~StackBuffer() NOEXCEPT { zeroize(); }
~FixedArrayBuffer() NOEXCEPT { zeroize(); }
}; };


/** @cond internal */ /** @cond internal */


+ 11
- 0
src/public_include/decaf/shake.hxx View File

@@ -108,6 +108,12 @@ public:


/** Reset the hash to the empty string */ /** Reset the hash to the empty string */
inline void reset() NOEXCEPT { sponge_init(sp, get_params()); } 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 */ /** Variable-output-length SHAKE */
@@ -122,6 +128,11 @@ public:


/** Reset the hash to the empty string */ /** Reset the hash to the empty string */
inline void reset() NOEXCEPT { sponge_init(sp, get_params()); } 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 */ /** @cond internal */


+ 45
- 27
test/test_decaf.cxx View File

@@ -12,8 +12,10 @@
#include <decaf.hxx> #include <decaf.hxx>
#include <decaf/shake.hxx> #include <decaf/shake.hxx>
#include <decaf/crypto.h> #include <decaf/crypto.h>
#include <decaf/crypto.hxx>
#include <stdio.h> #include <stdio.h>


using namespace decaf;


static bool passing = true; static bool passing = true;
static const long NTESTS = 10000; static const long NTESTS = 10000;
@@ -49,7 +51,7 @@ typedef typename Group::Precomputed Precomputed;


static void print(const char *name, const Scalar &x) { static void print(const char *name, const Scalar &x) {
unsigned char buffer[Scalar::SER_BYTES]; unsigned char buffer[Scalar::SER_BYTES];
x.encode(decaf::FixedBuffer<Scalar::SER_BYTES>(buffer));
x.encode(FixedBuffer<Scalar::SER_BYTES>(buffer));
printf(" %s = 0x", name); printf(" %s = 0x", name);
for (int i=sizeof(buffer)-1; i>=0; i--) { for (int i=sizeof(buffer)-1; i>=0; i--) {
printf("%02x", buffer[i]); printf("%02x", buffer[i]);
@@ -57,7 +59,7 @@ static void print(const char *name, const Scalar &x) {
printf("\n"); 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); printf(" %s = 0x", name);
for (int i=buffer.size()-1; i>=0; i--) { for (int i=buffer.size()-1; i>=0; i--) {
printf("%02x", buffer[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) { static void print(const char *name, const Point &x) {
decaf::StackBuffer<Point::SER_BYTES> buffer;
FixedArrayBuffer<Point::SER_BYTES> buffer;
x.encode(buffer); x.encode(buffer);
printf(" %s = 0x", name); printf(" %s = 0x", name);
for (int i=Point::SER_BYTES-1; i>=0; i--) { for (int i=Point::SER_BYTES-1; i>=0; i--) {
@@ -126,7 +128,7 @@ static bool point_check(
} }


static void test_arithmetic() { static void test_arithmetic() {
decaf::SpongeRng rng(decaf::Block("test_arithmetic"));
SpongeRng rng(Block("test_arithmetic"));
Test test("Arithmetic"); Test test("Arithmetic");
Scalar x(0),y(0),z(0); Scalar x(0),y(0),z(0);
@@ -161,18 +163,18 @@ static void test_arithmetic() {
} }


static void test_elligator() { static void test_elligator() {
decaf::SpongeRng rng(decaf::Block("test_elligator"));
SpongeRng rng(Block("test_elligator"));
Test test("Elligator"); Test test("Elligator");
const int NHINTS = Group::REMOVED_COFACTOR * 2; const int NHINTS = Group::REMOVED_COFACTOR * 2;
decaf::SecureBuffer *alts[NHINTS];
SecureBuffer *alts[NHINTS];
bool successes[NHINTS]; bool successes[NHINTS];
decaf::SecureBuffer *alts2[NHINTS];
SecureBuffer *alts2[NHINTS];
bool successes2[NHINTS]; bool successes2[NHINTS];


for (int i=0; i<NTESTS/10 && (test.passing_now || i < 100); i++) { for (int i=0; i<NTESTS/10 && (test.passing_now || i < 100); i++) {
size_t len = (i % (2*Point::HASH_BYTES + 3)); size_t len = (i % (2*Point::HASH_BYTES + 3));
decaf::SecureBuffer b1(len);
SecureBuffer b1(len);
if (i!=Point::HASH_BYTES) rng.read(b1); /* special test case */ if (i!=Point::HASH_BYTES) rng.read(b1); /* special test case */
if (i==1) b1[0] = 1; /* special case test */ if (i==1) b1[0] = 1; /* special case test */
if (len >= Point::HASH_BYTES) b1[Point::HASH_BYTES-1] &= 0x7F; // FIXME MAGIC if (len >= Point::HASH_BYTES) b1[Point::HASH_BYTES-1] &= 0x7F; // FIXME MAGIC
@@ -184,8 +186,8 @@ static void test_elligator() {
bool good = false; bool good = false;
for (int j=0; j<NHINTS; j++) { for (int j=0; j<NHINTS; j++) {
alts[j] = new decaf::SecureBuffer(len);
alts2[j] = new decaf::SecureBuffer(len);
alts[j] = new SecureBuffer(len);
alts2[j] = new SecureBuffer(len);


if (len > Point::HASH_BYTES) if (len > Point::HASH_BYTES)
memcpy(&(*alts[j])[Point::HASH_BYTES], &b1[Point::HASH_BYTES], len-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() { static void test_ec() {
decaf::SpongeRng rng(decaf::Block("test_ec"));
SpongeRng rng(Block("test_ec"));
Test test("EC"); Test test("EC");


@@ -278,13 +280,13 @@ static void test_ec() {
Point p(rng); Point p(rng);
Point q(rng); Point q(rng);
decaf::SecureBuffer buffer(2*Point::HASH_BYTES);
SecureBuffer buffer(2*Point::HASH_BYTES);
rng.read(buffer); rng.read(buffer);
Point r = Point::from_hash(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); Point pp = p.debugging_torque().debugging_pscale(rng);
if (decaf::SecureBuffer(pp) != decaf::SecureBuffer(p)) {
if (SecureBuffer(pp) != SecureBuffer(p)) {
test.fail(); test.fail();
printf("Fail torque seq test\n"); printf("Fail torque seq test\n");
} }
@@ -306,16 +308,30 @@ static void test_ec() {
"unih = hash+add" "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<decaf::GroupId GROUP>
static void test_crypto() {
Test test("Sample crypto");
SpongeRng rng(Block("test_decaf_crypto"));

for (int i=0; i<NTESTS && test.passing_now; i++) {
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));
pub1.verify(message, sig);
}
}

}; // template<GroupId GROUP>


// FIXME cross-field // FIXME cross-field
static void test_decaf() { static void test_decaf() {
Test test("Sample crypto"); 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_symmetric_key_t proto1,proto2;
decaf_255_private_key_t s1,s2; decaf_255_private_key_t s1,s2;
@@ -325,8 +341,8 @@ static void test_decaf() {
const char *message = "Hello, world!"; const char *message = "Hello, world!";


for (int i=0; i<NTESTS && test.passing_now; i++) { for (int i=0; i<NTESTS && test.passing_now; i++) {
rng.read(decaf::TmpBuffer(proto1,sizeof(proto1)));
rng.read(decaf::TmpBuffer(proto2,sizeof(proto2)));
rng.read(TmpBuffer(proto1,sizeof(proto1)));
rng.read(TmpBuffer(proto2,sizeof(proto2)));
decaf_255_derive_private_key(s1,proto1); decaf_255_derive_private_key(s1,proto1);
decaf_255_private_to_public(p1,s1); decaf_255_private_to_public(p1,s1);
decaf_255_derive_private_key(s2,proto2); decaf_255_derive_private_key(s2,proto2);
@@ -350,17 +366,19 @@ static void test_decaf() {
int main(int argc, char **argv) { int main(int argc, char **argv) {
(void) argc; (void) argv; (void) argc; (void) argv;
printf("Testing %s:\n", decaf::IsoEd25519::name());
Tests<decaf::IsoEd25519>::test_arithmetic();
Tests<decaf::IsoEd25519>::test_elligator();
Tests<decaf::IsoEd25519>::test_ec();
printf("Testing %s:\n",IsoEd25519::name());
Tests<IsoEd25519>::test_arithmetic();
Tests<IsoEd25519>::test_elligator();
Tests<IsoEd25519>::test_ec();
Tests<IsoEd25519>::test_crypto();
test_decaf(); test_decaf();
printf("\n"); printf("\n");
printf("Testing %s:\n", decaf::Ed448Goldilocks::name());
Tests<decaf::Ed448Goldilocks>::test_arithmetic();
Tests<decaf::Ed448Goldilocks>::test_elligator();
Tests<decaf::Ed448Goldilocks>::test_ec();
printf("Testing %s:\n", Ed448Goldilocks::name());
Tests<Ed448Goldilocks>::test_arithmetic();
Tests<Ed448Goldilocks>::test_elligator();
Tests<Ed448Goldilocks>::test_ec();
Tests<Ed448Goldilocks>::test_crypto();
if (passing) printf("Passed all tests.\n"); if (passing) printf("Passed all tests.\n");


Loading…
Cancel
Save