Browse Source

add serializable class, though i might repent of this because i dont want a vtable

master
Michael Hamburg 9 years ago
parent
commit
b35f966cf4
7 changed files with 132 additions and 97 deletions
  1. +5
    -5
      src/public_include/decaf/crypto.hxx
  2. +22
    -47
      src/public_include/decaf/decaf_255.hxx
  3. +19
    -33
      src/public_include/decaf/decaf_448.hxx
  4. +37
    -0
      src/public_include/decaf/secure_buffer.hxx
  5. +42
    -5
      src/public_include/decaf/shake.hxx
  6. +1
    -1
      test/bench_decaf.cxx
  7. +6
    -6
      test/test_decaf.cxx

+ 5
- 5
src/public_include/decaf/crypto.hxx View File

@@ -51,7 +51,7 @@ public:
}
/** @brief Set the public key to a point */
inline explicit PublicKey(const typename Group::Point &p) NOEXCEPT : ser(SecureBuffer(p)) {}
inline explicit PublicKey(const typename Group::Point &p) NOEXCEPT : ser(p.serialize()) {}
/** @brief Get the private key for a given public key */
inline explicit PublicKey(const PrivateKey<Group> &priv) NOEXCEPT;
@@ -111,7 +111,7 @@ public:
inline PrivateKey(Rng &r) :
sym(r),
scalar(SHAKE<SHAKE_BITS>::hash(sym, SCALAR_HASH_BYTES)),
pub_(SecureBuffer(Group::Precomputed::base() * scalar)) {}
pub_((Group::Precomputed::base() * scalar).serialize()) {}
/** @brief Construct from buffer */
inline PrivateKey(const FixedBlock<SYM_BYTES> &sym_) :
@@ -134,16 +134,16 @@ public:
}
/** @brief Sign from a SHAKE context. TODO: double check random oracle eval of this; destructive version? */
inline SecureBuffer sign_shake(const SHAKE<SHAKE_BITS> &ctx_) NOEXCEPT {
inline SecureBuffer sign_shake(const SHAKE<SHAKE_BITS> &ctx_) throw(std::bad_alloc) {
SHAKE<SHAKE_BITS> ctx(ctx_);
ctx << sym << "decaf_255_sign_shake";
typename Group::Scalar nonce(ctx.output(SCALAR_HASH_BYTES));
SecureBuffer g_nonce(Group::Precomputed::base() * nonce); /* FIXME: make output fixed size, avoid std::bad_alloc */
SecureBuffer g_nonce = (Group::Precomputed::base() * nonce).serialize();
ctx = ctx_;
ctx << pub_.ser << g_nonce;
SecureBuffer challenge(ctx.output(PublicKey<Group>::CHALLENGE_BYTES));
SecureBuffer response((nonce - scalar * typename Group::Scalar(challenge)).encode());
SecureBuffer response((nonce - scalar * typename Group::Scalar(challenge)).serialize());
SecureBuffer ret(PublicKey<Group>::SIG_BYTES);
Buffer(ret).slice(0,Group::Point::SER_BYTES).assign(g_nonce);


+ 22
- 47
src/public_include/decaf/decaf_255.hxx View File

@@ -38,8 +38,10 @@
/** @cond internal */
#if __cplusplus >= 201103L
#define NOEXCEPT noexcept
#define FINAL final
#else
#define NOEXCEPT throw()
#define FINAL
#endif
/** @endcond */

@@ -64,8 +66,9 @@ class Precomputed;
/**
* @brief A scalar modulo the curve order.
* Supports the usual arithmetic operations, all in constant time.
* FIXME: make it clearer which init-from-buffer operations reject scalars that are too big.
*/
class Scalar {
class Scalar : public Serializable {
private:
/** @brief wrapped C type */
typedef decaf_255_scalar_t Wrapped;
@@ -100,6 +103,14 @@ public:
/** @brief Construct from arbitrary-length little-endian byte sequence. */
inline Scalar(const Block &buffer) NOEXCEPT { *this = buffer; }

/** @brief Serializable instance */
virtual inline size_t serSize() const NOEXCEPT FINAL { return SER_BYTES; }
/** @brief Serializable instance */
virtual inline void serializeInto(unsigned char *buffer) const NOEXCEPT FINAL {
decaf_255_scalar_encode(buffer, s);
}
/** @brief Assignment. */
inline Scalar& operator=(const Scalar &x) NOEXCEPT { decaf_255_scalar_copy(s,x.s); return *this; }
@@ -133,21 +144,6 @@ public:
return decaf_255_scalar_decode(sc.s,buffer.data());
}
/** @brief Encode to fixed-length string */
inline operator SecureBuffer() const NOEXCEPT {
SecureBuffer buf(SER_BYTES); encode(buf); return buf;
}
/** @brief Encode to fixed-length buffer */
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT{
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. */
inline Scalar operator+ (const Scalar &q) const NOEXCEPT { Scalar r((NOINIT())); decaf_255_scalar_add(r.s,s,q.s); return r; }
@@ -201,7 +197,7 @@ public:
/**
* @brief Element of prime-order group.
*/
class Point {
class Point : public Serializable {
public:
typedef decaf_255_point_t Wrapped;
@@ -242,17 +238,6 @@ public:
set_to_hash(b);
}
}
/**
* @brief Initialize from C++ fixed-length byte string.
* The all-zero string maps to the identity.
*
* @throw CryptoException the string was the wrong length, or wasn't the encoding of a point,
* or was the identity and allow_identity was DECAF_FALSE.
*/
inline explicit Point(const Block &s, decaf_bool_t allow_identity=DECAF_TRUE) throw(CryptoException) {
if (!decode(*this,s,allow_identity)) throw CryptoException();
}
/**
* @brief Initialize from a fixed-length byte string.
@@ -261,7 +246,7 @@ public:
* @throw CryptoException the string was the wrong length, or wasn't the encoding of a point,
* or was the identity and allow_identity was DECAF_FALSE.
*/
inline explicit Point(const FixedBuffer<SER_BYTES> buffer, decaf_bool_t allow_identity=DECAF_TRUE)
inline explicit Point(const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE)
throw(CryptoException) { if (!decode(*this,buffer,allow_identity)) throw CryptoException(); }
/**
@@ -273,7 +258,7 @@ public:
* or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined.
*/
static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
Point &p, const FixedBlock<SER_BYTES> buffer, decaf_bool_t allow_identity=DECAF_TRUE
Point &p, const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE
) NOEXCEPT {
return decaf_255_point_decode(p.p,buffer.data(),allow_identity);
}
@@ -309,24 +294,13 @@ public:
decaf_255_point_from_hash_uniform(p,s.data());
}
}
/**
* @brief Encode to string. The identity encodes to the all-zero string.
*/
inline operator SecureBuffer() const NOEXCEPT {
SecureBuffer buffer(SER_BYTES); encode(buffer); return buffer;
}
/**
* @brief Encode to a C buffer. The identity encodes to all zeros.
*/
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT {
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 Serializable instance */
virtual inline size_t serSize() const NOEXCEPT FINAL { return SER_BYTES; }
/** @brief Serializable instance */
virtual inline void serializeInto(unsigned char *buffer) const NOEXCEPT FINAL {
decaf_255_point_encode(buffer, p);
}
/** @brief Point add. */
@@ -570,6 +544,7 @@ inline SecureBuffer IsoEd25519::Scalar::direct_scalarmul (
/** endcond */

#undef NOEXCEPT
#undef FINAL
} /* namespace decaf */

#endif /* __DECAF_255_HXX__ */

+ 19
- 33
src/public_include/decaf/decaf_448.hxx View File

@@ -38,8 +38,10 @@
/** @cond internal */
#if __cplusplus >= 201103L
#define NOEXCEPT noexcept
#define FINAL final
#else
#define NOEXCEPT throw()
#define FINAL
#endif
/** @endcond */

@@ -65,7 +67,7 @@ class Precomputed;
* @brief A scalar modulo the curve order.
* Supports the usual arithmetic operations, all in constant time.
*/
class Scalar {
class Scalar : public Serializable {
private:
/** @brief wrapped C type */
typedef decaf_448_scalar_t Wrapped;
@@ -133,14 +135,12 @@ public:
return decaf_448_scalar_decode(sc.s,buffer.data());
}
/** @brief Encode to fixed-length buffer */
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT{
decaf_448_scalar_encode(buffer.data(), s);
}
/** @brief Serializable instance */
virtual inline size_t serSize() const NOEXCEPT FINAL { return SER_BYTES; }
/** @brief Encode to fixed-length buffer */
inline SecureBuffer encode() const throw(std::bad_alloc) {
SecureBuffer buffer(SER_BYTES); encode(buffer); return buffer;
/** @brief Serializable instance */
virtual inline void serializeInto(unsigned char *buffer) const NOEXCEPT FINAL {
decaf_448_scalar_encode(buffer, s);
}
/** Add. */
@@ -201,7 +201,7 @@ public:
/**
* @brief Element of prime-order group.
*/
class Point {
class Point : public Serializable {
public:
/** @brief Size of a serialized element */
static const size_t SER_BYTES = DECAF_448_SER_BYTES;
@@ -240,17 +240,6 @@ public:
set_to_hash(b);
}
}
/**
* @brief Initialize from C++ fixed-length byte string.
* The all-zero string maps to the identity.
*
* @throw CryptoException the string was the wrong length, or wasn't the encoding of a point,
* or was the identity and allow_identity was DECAF_FALSE.
*/
inline explicit Point(const Block &s, decaf_bool_t allow_identity=DECAF_TRUE) throw(CryptoException) {
if (!decode(*this,s,allow_identity)) throw CryptoException();
}
/**
* @brief Initialize from a fixed-length byte string.
@@ -259,7 +248,7 @@ public:
* @throw CryptoException the string was the wrong length, or wasn't the encoding of a point,
* or was the identity and allow_identity was DECAF_FALSE.
*/
inline explicit Point(const FixedBuffer<SER_BYTES> buffer, decaf_bool_t allow_identity=DECAF_TRUE)
inline explicit Point(const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE)
throw(CryptoException) { if (!decode(*this,buffer,allow_identity)) throw CryptoException(); }
/**
@@ -271,7 +260,7 @@ public:
* or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined.
*/
static inline decaf_bool_t __attribute__((warn_unused_result)) decode (
Point &p, const FixedBlock<SER_BYTES> buffer, decaf_bool_t allow_identity=DECAF_TRUE
Point &p, const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE
) NOEXCEPT {
return decaf_448_point_decode(p.p,buffer.data(),allow_identity);
}
@@ -316,17 +305,13 @@ public:
decaf_448_point_encode(buffer.data(), p);
return buffer;
}
/**
* @brief Encode to a C buffer. The identity encodes to all zeros.
*/
inline void encode(FixedBuffer<SER_BYTES> buffer) const NOEXCEPT{
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 Serializable instance */
virtual inline size_t serSize() const NOEXCEPT FINAL { return SER_BYTES; }
/** @brief Serializable instance */
virtual inline void serializeInto(unsigned char *buffer) const NOEXCEPT FINAL {
decaf_448_point_encode(buffer, p);
}
/** @brief Point add. */
@@ -559,6 +544,7 @@ public:
}; /* struct Decaf448 */

#undef NOEXCEPT
#undef FINAL
} /* namespace decaf */

#endif /* __DECAF_448_HXX__ */

+ 37
- 0
src/public_include/decaf/secure_buffer.hxx View File

@@ -87,6 +87,38 @@ public:

typedef std::vector<unsigned char, SanitizingAllocator<unsigned char, 0> > SecureBuffer;

/** Constant-time compare two buffers */
template<class T,class U, class V, class W>
inline bool memeq(const std::vector<T,U> &a, const std::vector<V,W> &b) {
if (a.size() != b.size()) return false;
return decaf_memeq(a.data(),b.data(),a.size());
}

/** Base class of objects which support serialization */
class Serializable {
public:
/** @brief Return the number of bytes needed to serialize this object */
virtual inline size_t serSize() const NOEXCEPT = 0;
/** @brief Serialize this object into a buffer */
virtual inline void serializeInto(unsigned char *buf) const NOEXCEPT = 0;
/** @brief Serialize this object into a SecureBuffer and return it */
inline SecureBuffer serialize() const throw(std::bad_alloc) {
SecureBuffer out(serSize());
serializeInto(out.data());
return out;
}
/** Cast operator */
#if __cplusplus >= 201103L
explicit
#endif
inline operator SecureBuffer() const throw(std::bad_alloc) {
return serialize();
}
};

/**@cond internal*/
class Buffer;
/**@endcond*/
@@ -188,6 +220,11 @@ public:
if (b.size() != size()) return false;
return decaf_memeq(b.data(),data(),size());
}
/* Create new block from this */
inline operator SecureBuffer() const throw(std::bad_alloc) {
return SecureBuffer(data_,data_+size_);
}

/** Virtual destructor for SecureBlock. TODO: probably means vtable? Make bool? */
inline virtual ~Block() {};


+ 42
- 5
src/public_include/decaf/shake.hxx View File

@@ -214,28 +214,43 @@ public:
if (!strobe_key(sp, data.data(), data.size(), more)) throw ProtocolException();
}

inline void nonce(const Block &data, bool more = false
inline void key (
const Serializable &data, bool more = false
) throw(ProtocolException) {
key(data.serialize(), more);
}

inline void nonce(const Block &data, bool more = false) 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) {
inline void send_plaintext(const Block &data, bool more = false) throw(ProtocolException) {
if (!strobe_plaintext(sp, data.data(), data.size(), true, more))
throw(ProtocolException());
}

inline void send_plaintext(const Serializable &data, bool more = false) throw(ProtocolException) {
send_plaintext(data.serialize(), more);
}

inline void recv_plaintext(const Block &data, bool more = false
) throw(ProtocolException) {
if (!strobe_plaintext(sp, data.data(), data.size(), false, more))
throw(ProtocolException());
}

inline void ad(const Block &data, bool more = false
) throw(ProtocolException) {
inline void recv_plaintext(const Serializable &data, bool more = false) throw(ProtocolException) {
recv_plaintext(data.serialize(), more);
}

inline void ad(const Block &data, bool more = false) throw(ProtocolException) {
if (!strobe_ad(sp, data.data(), data.size(), more))
throw(ProtocolException());
}

inline void ad(const Serializable &data, bool more = false) throw(ProtocolException) {
ad(data.serialize(), more);
}
inline void encrypt_no_auth(
Buffer out, const Block &data, bool more = false
@@ -249,6 +264,11 @@ public:
SecureBuffer out(data.size()); encrypt_no_auth(out, data, more); return out;
}
inline SecureBuffer encrypt_no_auth(const Serializable &data, bool more = false
) throw(ProtocolException) {
return encrypt_no_auth(data.serialize(), more);
}
inline void decrypt_no_auth(
Buffer out, const Block &data, bool more = false
) throw(LengthException,ProtocolException) {
@@ -261,6 +281,11 @@ public:
SecureBuffer out(data.size()); decrypt_no_auth(out, data, more); return out;
}
inline SecureBuffer decrypt_no_auth(const Serializable &data, bool more = false
) throw(ProtocolException) {
return decrypt_no_auth(data.serialize(),more);
}
inline void produce_auth(Buffer out) throw(LengthException,ProtocolException) {
if (out.size() > STROBE_MAX_AUTH_BYTES) throw LengthException();
if (!strobe_produce_auth(sp, out.data(), out.size())) throw ProtocolException();
@@ -286,6 +311,12 @@ public:
SecureBuffer out(data.size() + auth); encrypt(out, data, auth); return out;
}
inline SecureBuffer encrypt (
const Serializable &data, uint8_t auth = 8
) throw(LengthException,ProtocolException,std::bad_alloc ){
return encrypt(data.serialize(), auth);
}
inline void decrypt (
Buffer out, const Block &data, uint8_t bytes = 8
) throw(LengthException, CryptoException, ProtocolException) {
@@ -294,6 +325,12 @@ public:
verify_auth(data.slice(out.size(),bytes));
}
inline SecureBuffer decrypt (
const Serializable &data, uint8_t auth = 8
) throw(LengthException,ProtocolException,CryptoException, std::bad_alloc ){
return decrypt(data.serialize(), auth);
}
inline SecureBuffer decrypt (
const Block &data, uint8_t bytes = 8
) throw(LengthException,CryptoException,ProtocolException,std::bad_alloc) {


+ 1
- 1
test/bench_decaf.cxx View File

@@ -283,7 +283,7 @@ static void macro() {
printf("Protocol benchmarks:\n");
SpongeRng clientRng(Block("client rng seed"));
SpongeRng serverRng(Block("server rng seed"));
SecureBuffer hashedPassword("hello world");
SecureBuffer hashedPassword(Block("hello world"));
for (Benchmark b("Spake2ee c+s",0.1); b.iter(); ) {
spake2ee(clientRng, serverRng, hashedPassword,false);
}


+ 6
- 6
test/test_decaf.cxx View File

@@ -51,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(FixedBuffer<Scalar::SER_BYTES>(buffer));
x.serializeInto(buffer);
printf(" %s = 0x", name);
for (int i=sizeof(buffer)-1; i>=0; i--) {
printf("%02x", buffer[i]);
@@ -68,8 +68,8 @@ static void hexprint(const char *name, const SecureBuffer &buffer) {
}

static void print(const char *name, const Point &x) {
FixedArrayBuffer<Point::SER_BYTES> buffer;
x.encode(buffer);
unsigned char buffer[Point::SER_BYTES];
x.serializeInto(buffer);
printf(" %s = 0x", name);
for (int i=Point::SER_BYTES-1; i>=0; i--) {
printf("%02x", buffer[i]);
@@ -284,9 +284,9 @@ static void test_ec() {
rng.read(buffer);
Point r = Point::from_hash(buffer);
point_check(test,p,q,r,0,0,p,Point((SecureBuffer)p),"round-trip");
point_check(test,p,q,r,0,0,p,Point(p.serialize()),"round-trip");
Point pp = p.debugging_torque().debugging_pscale(rng);
if (SecureBuffer(pp) != SecureBuffer(p)) {
if (!memeq(pp.serialize(),p.serialize())) {
test.fail();
printf("Fail torque seq test\n");
}
@@ -308,7 +308,7 @@ static void test_ec() {
"unih = hash+add"
);
point_check(test,p,q,r,x,0,Point(x.direct_scalarmul(SecureBuffer(p))),x*p,"direct mul");
point_check(test,p,q,r,x,0,Point(x.direct_scalarmul(p.serialize())),x*p,"direct mul");
}
}



||||||
x
 
000:0
Loading…
Cancel
Save