| @@ -17,10 +17,8 @@ | |||||
| /** @cond internal */ | /** @cond internal */ | ||||
| #if __cplusplus >= 201103L | #if __cplusplus >= 201103L | ||||
| #define NOEXCEPT noexcept | #define NOEXCEPT noexcept | ||||
| #define FINAL final | |||||
| #else | #else | ||||
| #define NOEXCEPT throw() | #define NOEXCEPT throw() | ||||
| #define FINAL | |||||
| #endif | #endif | ||||
| /** @endcond */ | /** @endcond */ | ||||
| @@ -31,7 +29,7 @@ namespace decaf { | |||||
| template <typename Group> class PrivateKey; | template <typename Group> class PrivateKey; | ||||
| /** @brief A public key using a particular EC group */ | /** @brief A public key using a particular EC group */ | ||||
| template <typename Group> class PublicKey : public Serializable { | |||||
| template <typename Group> class PublicKey : public Serializable<PublicKey<Group> > { | |||||
| private: | private: | ||||
| /** @cond internal */ | /** @cond internal */ | ||||
| friend class PrivateKey<Group>; | friend class PrivateKey<Group>; | ||||
| @@ -66,17 +64,19 @@ public: | |||||
| } | } | ||||
| /** @brief Verify a sig. TODO: nothrow version? FIXME: doesn't check reduction of scalar! */ | /** @brief Verify a sig. TODO: nothrow version? FIXME: doesn't check reduction of scalar! */ | ||||
| inline void verify_shake(const SHAKE<SHAKE_BITS> &ctx_, const FixedBlock<SIG_BYTES> &sig) throw(CryptoException) { | |||||
| inline bool verify_shake(const SHAKE<SHAKE_BITS> &ctx_, const FixedBlock<SIG_BYTES> &sig) throw(CryptoException) { | |||||
| SHAKE<SHAKE_BITS> ctx(ctx_); | SHAKE<SHAKE_BITS> ctx(ctx_); | ||||
| ctx << ser << sig.slice(0,Group::Point::SER_BYTES); | ctx << ser << sig.slice(0,Group::Point::SER_BYTES); | ||||
| SecureBuffer challenge(ctx.output(CHALLENGE_BYTES)); | |||||
| FixedArrayBuffer<CHALLENGE_BYTES> challenge; | |||||
| ctx.output(challenge); | |||||
| const typename Group::Point combo = point().non_secret_combo_with_base( | const typename Group::Point combo = point().non_secret_combo_with_base( | ||||
| typename Group::Scalar(challenge), | typename Group::Scalar(challenge), | ||||
| sig.slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES) | sig.slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES) | ||||
| ); | ); | ||||
| if (combo != typename Group::Point(sig.slice(0,Group::Point::SER_BYTES))) | |||||
| throw CryptoException(); | |||||
| //if (combo != typename Group::Point(sig.slice(0,Group::Point::SER_BYTES))) | |||||
| // throw CryptoException(); | |||||
| return combo == typename Group::Point(sig.slice(0,Group::Point::SER_BYTES)); | |||||
| } | } | ||||
| /** @brief Sign from a message. */ | /** @brief Sign from a message. */ | ||||
| @@ -87,12 +87,12 @@ public: | |||||
| } | } | ||||
| /** @brief Serialize into a buffer. */ | /** @brief Serialize into a buffer. */ | ||||
| inline void serializeInto(unsigned char *x) const NOEXCEPT FINAL { | |||||
| inline void serializeInto(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,ser.data(),Group::Point::SER_BYTES); | memcpy(x,ser.data(),Group::Point::SER_BYTES); | ||||
| } | } | ||||
| /** @brief Serialize into a buffer. */ | /** @brief Serialize into a buffer. */ | ||||
| inline size_t serSize() const NOEXCEPT FINAL { | |||||
| inline size_t serSize() const NOEXCEPT { | |||||
| return Group::Point::SER_BYTES; | return Group::Point::SER_BYTES; | ||||
| } | } | ||||
| @@ -101,7 +101,7 @@ public: | |||||
| }; | }; | ||||
| /** @brief A private key using a particular EC group */ | /** @brief A private key using a particular EC group */ | ||||
| template <typename Group> class PrivateKey : public Serializable { | |||||
| template <typename Group> class PrivateKey : public Serializable<PrivateKey<Group> > { | |||||
| public: | public: | ||||
| /** Size of associated symmetric key */ | /** Size of associated symmetric key */ | ||||
| static const size_t SYM_BYTES = 32; | static const size_t SYM_BYTES = 32; | ||||
| @@ -140,12 +140,12 @@ public: | |||||
| } | } | ||||
| /** @brief Serialize */ | /** @brief Serialize */ | ||||
| inline size_t serSize() const NOEXCEPT FINAL { | |||||
| inline size_t serSize() const NOEXCEPT { | |||||
| return SYM_BYTES; | return SYM_BYTES; | ||||
| } | } | ||||
| /** @brief Serialize */ | /** @brief Serialize */ | ||||
| inline void serializeInto(unsigned char *target) const NOEXCEPT FINAL { | |||||
| inline void serializeInto(unsigned char *target) const NOEXCEPT { | |||||
| memcpy(target,sym.data(),serSize()); | memcpy(target,sym.data(),serSize()); | ||||
| } | } | ||||
| @@ -38,10 +38,8 @@ | |||||
| /** @cond internal */ | /** @cond internal */ | ||||
| #if __cplusplus >= 201103L | #if __cplusplus >= 201103L | ||||
| #define NOEXCEPT noexcept | #define NOEXCEPT noexcept | ||||
| #define FINAL final | |||||
| #else | #else | ||||
| #define NOEXCEPT throw() | #define NOEXCEPT throw() | ||||
| #define FINAL | |||||
| #endif | #endif | ||||
| /** @endcond */ | /** @endcond */ | ||||
| @@ -68,7 +66,7 @@ class Precomputed; | |||||
| * Supports the usual arithmetic operations, all in constant time. | * Supports the usual arithmetic operations, all in constant time. | ||||
| * FIXME: make it clearer which init-from-buffer operations reject scalars that are too big. | * FIXME: make it clearer which init-from-buffer operations reject scalars that are too big. | ||||
| */ | */ | ||||
| class Scalar : public Serializable { | |||||
| class Scalar : public Serializable<Scalar> { | |||||
| private: | private: | ||||
| /** @brief wrapped C type */ | /** @brief wrapped C type */ | ||||
| typedef decaf_255_scalar_t Wrapped; | typedef decaf_255_scalar_t Wrapped; | ||||
| @@ -105,10 +103,10 @@ public: | |||||
| inline Scalar(const Block &buffer) NOEXCEPT { *this = buffer; } | inline Scalar(const Block &buffer) NOEXCEPT { *this = buffer; } | ||||
| /** @brief Serializable instance */ | /** @brief Serializable instance */ | ||||
| virtual inline size_t serSize() const NOEXCEPT FINAL { return SER_BYTES; } | |||||
| inline size_t serSize() const NOEXCEPT { return SER_BYTES; } | |||||
| /** @brief Serializable instance */ | /** @brief Serializable instance */ | ||||
| virtual inline void serializeInto(unsigned char *buffer) const NOEXCEPT FINAL { | |||||
| inline void serializeInto(unsigned char *buffer) const NOEXCEPT { | |||||
| decaf_255_scalar_encode(buffer, s); | decaf_255_scalar_encode(buffer, s); | ||||
| } | } | ||||
| @@ -197,7 +195,7 @@ public: | |||||
| /** | /** | ||||
| * @brief Element of prime-order group. | * @brief Element of prime-order group. | ||||
| */ | */ | ||||
| class Point : public Serializable { | |||||
| class Point : public Serializable<Point> { | |||||
| public: | public: | ||||
| typedef decaf_255_point_t Wrapped; | typedef decaf_255_point_t Wrapped; | ||||
| @@ -296,10 +294,10 @@ public: | |||||
| } | } | ||||
| /** @brief Serializable instance */ | /** @brief Serializable instance */ | ||||
| virtual inline size_t serSize() const NOEXCEPT FINAL { return SER_BYTES; } | |||||
| inline size_t serSize() const NOEXCEPT { return SER_BYTES; } | |||||
| /** @brief Serializable instance */ | /** @brief Serializable instance */ | ||||
| virtual inline void serializeInto(unsigned char *buffer) const NOEXCEPT FINAL { | |||||
| inline void serializeInto(unsigned char *buffer) const NOEXCEPT { | |||||
| decaf_255_point_encode(buffer, p); | decaf_255_point_encode(buffer, p); | ||||
| } | } | ||||
| @@ -544,7 +542,6 @@ inline SecureBuffer IsoEd25519::Scalar::direct_scalarmul ( | |||||
| /** endcond */ | /** endcond */ | ||||
| #undef NOEXCEPT | #undef NOEXCEPT | ||||
| #undef FINAL | |||||
| } /* namespace decaf */ | } /* namespace decaf */ | ||||
| #endif /* __DECAF_255_HXX__ */ | #endif /* __DECAF_255_HXX__ */ | ||||
| @@ -38,10 +38,8 @@ | |||||
| /** @cond internal */ | /** @cond internal */ | ||||
| #if __cplusplus >= 201103L | #if __cplusplus >= 201103L | ||||
| #define NOEXCEPT noexcept | #define NOEXCEPT noexcept | ||||
| #define FINAL final | |||||
| #else | #else | ||||
| #define NOEXCEPT throw() | #define NOEXCEPT throw() | ||||
| #define FINAL | |||||
| #endif | #endif | ||||
| /** @endcond */ | /** @endcond */ | ||||
| @@ -67,7 +65,7 @@ class Precomputed; | |||||
| * @brief A scalar modulo the curve order. | * @brief A scalar modulo the curve order. | ||||
| * Supports the usual arithmetic operations, all in constant time. | * Supports the usual arithmetic operations, all in constant time. | ||||
| */ | */ | ||||
| class Scalar : public Serializable { | |||||
| class Scalar : public Serializable<Scalar> { | |||||
| private: | private: | ||||
| /** @brief wrapped C type */ | /** @brief wrapped C type */ | ||||
| typedef decaf_448_scalar_t Wrapped; | typedef decaf_448_scalar_t Wrapped; | ||||
| @@ -136,10 +134,10 @@ public: | |||||
| } | } | ||||
| /** @brief Serializable instance */ | /** @brief Serializable instance */ | ||||
| virtual inline size_t serSize() const NOEXCEPT FINAL { return SER_BYTES; } | |||||
| inline size_t serSize() const NOEXCEPT { return SER_BYTES; } | |||||
| /** @brief Serializable instance */ | /** @brief Serializable instance */ | ||||
| virtual inline void serializeInto(unsigned char *buffer) const NOEXCEPT FINAL { | |||||
| inline void serializeInto(unsigned char *buffer) const NOEXCEPT { | |||||
| decaf_448_scalar_encode(buffer, s); | decaf_448_scalar_encode(buffer, s); | ||||
| } | } | ||||
| @@ -201,7 +199,7 @@ public: | |||||
| /** | /** | ||||
| * @brief Element of prime-order group. | * @brief Element of prime-order group. | ||||
| */ | */ | ||||
| class Point : public Serializable { | |||||
| class Point : public Serializable<Point> { | |||||
| public: | public: | ||||
| /** @brief Size of a serialized element */ | /** @brief Size of a serialized element */ | ||||
| static const size_t SER_BYTES = DECAF_448_SER_BYTES; | static const size_t SER_BYTES = DECAF_448_SER_BYTES; | ||||
| @@ -307,10 +305,10 @@ public: | |||||
| } | } | ||||
| /** @brief Serializable instance */ | /** @brief Serializable instance */ | ||||
| virtual inline size_t serSize() const NOEXCEPT FINAL { return SER_BYTES; } | |||||
| inline size_t serSize() const NOEXCEPT { return SER_BYTES; } | |||||
| /** @brief Serializable instance */ | /** @brief Serializable instance */ | ||||
| virtual inline void serializeInto(unsigned char *buffer) const NOEXCEPT FINAL { | |||||
| inline void serializeInto(unsigned char *buffer) const NOEXCEPT { | |||||
| decaf_448_point_encode(buffer, p); | decaf_448_point_encode(buffer, p); | ||||
| } | } | ||||
| @@ -544,7 +542,6 @@ public: | |||||
| }; /* struct Decaf448 */ | }; /* struct Decaf448 */ | ||||
| #undef NOEXCEPT | #undef NOEXCEPT | ||||
| #undef FINAL | |||||
| } /* namespace decaf */ | } /* namespace decaf */ | ||||
| #endif /* __DECAF_448_HXX__ */ | #endif /* __DECAF_448_HXX__ */ | ||||
| @@ -98,13 +98,15 @@ inline bool memeq(const std::vector<T,U> &a, const std::vector<V,W> &b) { | |||||
| } | } | ||||
| /** Base class of objects which support serialization */ | /** Base class of objects which support serialization */ | ||||
| class Serializable { | |||||
| template<class Base> class Serializable { | |||||
| public: | public: | ||||
| /** @brief Return the number of bytes needed to serialize this object */ | /** @brief Return the number of bytes needed to serialize this object */ | ||||
| virtual inline size_t serSize() const NOEXCEPT = 0; | |||||
| inline size_t serSize() const NOEXCEPT { return static_cast<const Base*>(this)->serSize(); } | |||||
| /** @brief Serialize this object into a buffer */ | /** @brief Serialize this object into a buffer */ | ||||
| virtual inline void serializeInto(unsigned char *buf) const NOEXCEPT = 0; | |||||
| inline void serializeInto(unsigned char *buf) const NOEXCEPT { | |||||
| static_cast<const Base*>(this)->serializeInto(buf); | |||||
| } | |||||
| /** @brief Serialize this object into a SecureBuffer and return it */ | /** @brief Serialize this object into a SecureBuffer and return it */ | ||||
| inline SecureBuffer serialize() const throw(std::bad_alloc) { | inline SecureBuffer serialize() const throw(std::bad_alloc) { | ||||
| @@ -73,12 +73,6 @@ public: | |||||
| */ | */ | ||||
| inline void output(Buffer b) { sha3_output(sp,b.data(),b.size()); } | inline void output(Buffer b) { sha3_output(sp,b.data(),b.size()); } | ||||
| /** | |||||
| * @brief Output bytes from the sponge. | |||||
| * @todo make this throw exceptions. | |||||
| */ | |||||
| inline void output(Buffer &b) { sha3_output(sp,b.data(),b.size()); } | |||||
| /** @brief Output bytes from the sponge. */ | /** @brief Output bytes from the sponge. */ | ||||
| inline SecureBuffer output(size_t len) { | inline SecureBuffer output(size_t len) { | ||||
| SecureBuffer buffer(len); | SecureBuffer buffer(len); | ||||
| @@ -214,8 +208,8 @@ public: | |||||
| if (!strobe_key(sp, data.data(), data.size(), more)) throw ProtocolException(); | if (!strobe_key(sp, data.data(), data.size(), more)) throw ProtocolException(); | ||||
| } | } | ||||
| inline void key ( | |||||
| const Serializable &data, bool more = false | |||||
| template<class T> inline void key ( | |||||
| const Serializable<T> &data, bool more = false | |||||
| ) throw(ProtocolException) { | ) throw(ProtocolException) { | ||||
| key(data.serialize(), more); | key(data.serialize(), more); | ||||
| } | } | ||||
| @@ -229,7 +223,7 @@ public: | |||||
| throw(ProtocolException()); | throw(ProtocolException()); | ||||
| } | } | ||||
| inline void send_plaintext(const Serializable &data, bool more = false) throw(ProtocolException) { | |||||
| template<class T> inline void send_plaintext(const Serializable<T> &data, bool more = false) throw(ProtocolException) { | |||||
| send_plaintext(data.serialize(), more); | send_plaintext(data.serialize(), more); | ||||
| } | } | ||||
| @@ -239,7 +233,7 @@ public: | |||||
| throw(ProtocolException()); | throw(ProtocolException()); | ||||
| } | } | ||||
| inline void recv_plaintext(const Serializable &data, bool more = false) throw(ProtocolException) { | |||||
| template<class T> inline void recv_plaintext(const Serializable<T> &data, bool more = false) throw(ProtocolException) { | |||||
| recv_plaintext(data.serialize(), more); | recv_plaintext(data.serialize(), more); | ||||
| } | } | ||||
| @@ -248,7 +242,7 @@ public: | |||||
| throw(ProtocolException()); | throw(ProtocolException()); | ||||
| } | } | ||||
| inline void ad(const Serializable &data, bool more = false) throw(ProtocolException) { | |||||
| template<class T> inline void ad(const Serializable<T> &data, bool more = false) throw(ProtocolException) { | |||||
| ad(data.serialize(), more); | ad(data.serialize(), more); | ||||
| } | } | ||||
| @@ -264,7 +258,7 @@ public: | |||||
| SecureBuffer out(data.size()); encrypt_no_auth(out, data, more); return out; | SecureBuffer out(data.size()); encrypt_no_auth(out, data, more); return out; | ||||
| } | } | ||||
| inline SecureBuffer encrypt_no_auth(const Serializable &data, bool more = false | |||||
| template<class T> inline SecureBuffer encrypt_no_auth(const Serializable<T> &data, bool more = false | |||||
| ) throw(ProtocolException) { | ) throw(ProtocolException) { | ||||
| return encrypt_no_auth(data.serialize(), more); | return encrypt_no_auth(data.serialize(), more); | ||||
| } | } | ||||
| @@ -281,7 +275,7 @@ public: | |||||
| SecureBuffer out(data.size()); decrypt_no_auth(out, data, more); return out; | SecureBuffer out(data.size()); decrypt_no_auth(out, data, more); return out; | ||||
| } | } | ||||
| inline SecureBuffer decrypt_no_auth(const Serializable &data, bool more = false | |||||
| template<class T> inline SecureBuffer decrypt_no_auth(const Serializable<T> &data, bool more = false | |||||
| ) throw(ProtocolException) { | ) throw(ProtocolException) { | ||||
| return decrypt_no_auth(data.serialize(),more); | return decrypt_no_auth(data.serialize(),more); | ||||
| } | } | ||||
| @@ -311,8 +305,8 @@ public: | |||||
| SecureBuffer out(data.size() + auth); encrypt(out, data, auth); return out; | SecureBuffer out(data.size() + auth); encrypt(out, data, auth); return out; | ||||
| } | } | ||||
| inline SecureBuffer encrypt ( | |||||
| const Serializable &data, uint8_t auth = 8 | |||||
| template<class T> inline SecureBuffer encrypt ( | |||||
| const Serializable<T> &data, uint8_t auth = 8 | |||||
| ) throw(LengthException,ProtocolException,std::bad_alloc ){ | ) throw(LengthException,ProtocolException,std::bad_alloc ){ | ||||
| return encrypt(data.serialize(), auth); | return encrypt(data.serialize(), auth); | ||||
| } | } | ||||
| @@ -325,8 +319,8 @@ public: | |||||
| verify_auth(data.slice(out.size(),bytes)); | verify_auth(data.slice(out.size(),bytes)); | ||||
| } | } | ||||
| inline SecureBuffer decrypt ( | |||||
| const Serializable &data, uint8_t auth = 8 | |||||
| template<class T> inline SecureBuffer decrypt ( | |||||
| const Serializable<T> &data, uint8_t auth = 8 | |||||
| ) throw(LengthException,ProtocolException,CryptoException, std::bad_alloc ){ | ) throw(LengthException,ProtocolException,CryptoException, std::bad_alloc ){ | ||||
| return decrypt(data.serialize(), auth); | return decrypt(data.serialize(), auth); | ||||
| } | } | ||||
| @@ -497,8 +497,8 @@ static void strobe_forget ( | |||||
| if (sponge->params->rate < len + sponge->params->position) { | if (sponge->params->rate < len + sponge->params->position) { | ||||
| dokeccak(sponge); | dokeccak(sponge); | ||||
| } | } | ||||
| memset(sponge->state->b, 0, len); | |||||
| sponge->params->position = len; | |||||
| memset(&sponge->state->b[sponge->params->position], 0, len); | |||||
| sponge->params->position += len; | |||||
| } | } | ||||
| } | } | ||||
| @@ -286,7 +286,7 @@ static void macro() { | |||||
| PublicKey<Group> p1((NOINIT())), p2((NOINIT())); | PublicKey<Group> p1((NOINIT())), p2((NOINIT())); | ||||
| PrivateKey<Group> s1((NOINIT())), s2((NOINIT())); | PrivateKey<Group> s1((NOINIT())), s2((NOINIT())); | ||||
| SecureBuffer message = rng.read(12), sig; | |||||
| SecureBuffer message = rng.read(5), sig; | |||||
| for (Benchmark b("Create private key",1); b.iter(); ) { | for (Benchmark b("Create private key",1); b.iter(); ) { | ||||
| s1 = PrivateKey<Group>(rng); | s1 = PrivateKey<Group>(rng); | ||||
| @@ -299,7 +299,7 @@ static void macro() { | |||||
| p1 = s1.pub(); | p1 = s1.pub(); | ||||
| for (Benchmark b("Verify",1); b.iter(); ) { | for (Benchmark b("Verify",1); b.iter(); ) { | ||||
| message = rng.read(12); | |||||
| rng.read(Buffer(message)); | |||||
| try { p1.verify(message, sig); } catch (CryptoException) {} | try { p1.verify(message, sig); } catch (CryptoException) {} | ||||
| } | } | ||||
| @@ -354,6 +354,7 @@ static void micro() { | |||||
| for (Benchmark b("Point double scalarmul"); b.iter(); ) { Point::double_scalarmul(p,s,q,t); } | for (Benchmark b("Point double scalarmul"); b.iter(); ) { Point::double_scalarmul(p,s,q,t); } | ||||
| for (Benchmark b("Point precmp scalarmul"); b.iter(); ) { pBase * s; } | for (Benchmark b("Point precmp scalarmul"); b.iter(); ) { pBase * s; } | ||||
| for (Benchmark b("Point double scalarmul_v"); b.iter(); ) { | for (Benchmark b("Point double scalarmul_v"); b.iter(); ) { | ||||
| s = Scalar(rng); | |||||
| t = Scalar(rng); | t = Scalar(rng); | ||||
| p.non_secret_combo_with_base(s,t); | p.non_secret_combo_with_base(s,t); | ||||
| } | } | ||||
| @@ -362,6 +363,7 @@ static void micro() { | |||||
| }; /* template <typename group> struct Benches */ | }; /* template <typename group> struct Benches */ | ||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||
| bool micro = false; | bool micro = false; | ||||
| if (argc >= 2 && !strcmp(argv[1], "--micro")) | if (argc >= 2 && !strcmp(argv[1], "--micro")) | ||||
| micro = true; | micro = true; | ||||
| @@ -379,9 +381,8 @@ int main(int argc, char **argv) { | |||||
| size_t lmessage = sizeof(umessage); | size_t lmessage = sizeof(umessage); | ||||
| SpongeRng rng(Block("micro-benchmarks")); | |||||
| if (micro) { | if (micro) { | ||||
| SpongeRng rng(Block("micro-benchmarks")); | |||||
| printf("\nMicro-benchmarks:\n"); | printf("\nMicro-benchmarks:\n"); | ||||
| SHAKE<128> shake1; | SHAKE<128> shake1; | ||||
| SHAKE<256> shake2; | SHAKE<256> shake2; | ||||
| @@ -435,8 +436,9 @@ int main(int argc, char **argv) { | |||||
| for (Benchmark b("Verify"); b.iter(); ) { | for (Benchmark b("Verify"); b.iter(); ) { | ||||
| decaf_bool_t ret = decaf_255_verify(sig1,p1,umessage,lmessage); | decaf_bool_t ret = decaf_255_verify(sig1,p1,umessage,lmessage); | ||||
| umessage[0]++; | |||||
| umessage[1]^=umessage[0]; | |||||
| rng.read(Buffer(umessage,lmessage)); | |||||
| // umessage[0]++; | |||||
| // umessage[1]^=umessage[0]; | |||||
| ignore_result(ret); | ignore_result(ret); | ||||
| } | } | ||||