From 4de70b837cb51ed5c2b2cab6265921ffa3e0f73d Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Sun, 24 Jan 2016 19:16:05 -0800 Subject: [PATCH] separate out strobe and spongerng from shake. strobe is experimental. spongerng is experimental internally but the interface should be pretty good (except for any camelCase vs snake_case issues). shake should be stable --- src/decaf_gen_tables.c | 8 +- src/gen_headers/crypto_hxx.py | 4 +- src/include/constant_time.h | 3 - src/include/word.h | 2 +- src/p25519/arch_32/f_impl.c | 2 +- src/p25519/arch_ref64/f_impl.c | 2 +- src/p448/arch_32/f_impl.c | 2 +- src/public_include/decaf/shake.hxx | 269 +------------------------ src/public_include/decaf/spongerng.hxx | 98 +++++++++ src/public_include/decaf/strobe.hxx | 240 ++++++++++++++++++++++ test/bench_decaf.cxx | 2 + test/test_ct.cxx | 2 +- test/test_decaf.cxx | 2 +- 13 files changed, 354 insertions(+), 282 deletions(-) create mode 100644 src/public_include/decaf/spongerng.hxx create mode 100644 src/public_include/decaf/strobe.hxx diff --git a/src/decaf_gen_tables.c b/src/decaf_gen_tables.c index 641d8e8..0d65727 100644 --- a/src/decaf_gen_tables.c +++ b/src/decaf_gen_tables.c @@ -13,6 +13,7 @@ #include #include "field.h" +#include "f_field.h" #include "decaf.h" #include "decaf_config.h" @@ -59,16 +60,15 @@ static void scalar_print(const char *name, const API_NS(scalar_t) sc) { /* UNIFY } static void field_print(const gf f) { /* UNIFY */ - const int GF_SER_BYTES = (GF_BITS + 7) / 8; - unsigned char ser[GF_SER_BYTES]; + unsigned char ser[SER_BYTES]; gf_serialize(ser,f); int b=0, i, comma=0; unsigned long long limb = 0; printf("{FIELD_LITERAL("); - for (i=0; i= GF_LIT_LIMB_BITS || i == GF_SER_BYTES-1) { + if (b >= GF_LIT_LIMB_BITS || i == SER_BYTES-1) { limb &= (1ull< &b) NOEXCEPT { memcpy(wrapped,b.data(),sizeof(wrapped)); @@ -70,7 +68,7 @@ public: /** Serialization size. */ inline size_t serSize() const NOEXCEPT { return SER_BYTES; } - /* TODO: verify_strobe */ + /* FUTURE: verify_strobe */ /** Verify a message */ inline void verify( diff --git a/src/include/constant_time.h b/src/include/constant_time.h index 2cc0ee4..8755e7f 100644 --- a/src/include/constant_time.h +++ b/src/include/constant_time.h @@ -32,9 +32,6 @@ * a naive autovectorizer will do with constant_time_lookup on Intel). * * Instead, we're putting our trust in the loop unroller and unswitcher. - * - * TODO: verify correctness and performance on each platform, to make sure - * that there are no regressions. */ diff --git a/src/include/word.h b/src/include/word.h index ced2202..189d14f 100644 --- a/src/include/word.h +++ b/src/include/word.h @@ -251,7 +251,7 @@ malloc_vector(size_t size) { /* PERF: vectorize vs unroll */ #ifdef __clang__ #if 100*__clang_major__ + __clang_minor__ > 305 -#define UNROLL _Pragma("clang loop unroll(full)") // PERF TODO: vectorize? +#define UNROLL _Pragma("clang loop unroll(full)") #endif #endif diff --git a/src/p25519/arch_32/f_impl.c b/src/p25519/arch_32/f_impl.c index e4dd1df..7c9ab84 100644 --- a/src/p25519/arch_32/f_impl.c +++ b/src/p25519/arch_32/f_impl.c @@ -87,7 +87,7 @@ void gf_mulw (gf_s *__restrict__ cs, const gf as, uint64_t b) { } void gf_sqr (gf_s *__restrict__ cs, const gf as) { - gf_mul(cs,as,as); // PERF + gf_mul(cs,as,as); /* Performs better with dedicated square */ } diff --git a/src/p25519/arch_ref64/f_impl.c b/src/p25519/arch_ref64/f_impl.c index 87a0753..e8cd206 100644 --- a/src/p25519/arch_ref64/f_impl.c +++ b/src/p25519/arch_ref64/f_impl.c @@ -57,5 +57,5 @@ void gf_mulw (gf_s *__restrict__ cs, const gf as, uint64_t b) { } void gf_sqr (gf_s *__restrict__ cs, const gf as) { - gf_mul(cs,as,as); // PERF + gf_mul(cs,as,as); /* Performs better with dedicated square */ } diff --git a/src/p448/arch_32/f_impl.c b/src/p448/arch_32/f_impl.c index 43d3562..f70b236 100644 --- a/src/p448/arch_32/f_impl.c +++ b/src/p448/arch_32/f_impl.c @@ -100,6 +100,6 @@ void gf_mulw (gf_s *__restrict__ cs, const gf as, uint64_t b) { } void gf_sqr (gf_s *__restrict__ cs, const gf as) { - gf_mul(cs,as,as); /* PERF */ + gf_mul(cs,as,as); /* Performs better with a dedicated square */ } diff --git a/src/public_include/decaf/shake.hxx b/src/public_include/decaf/shake.hxx index 6fe2d6e..970a76b 100644 --- a/src/public_include/decaf/shake.hxx +++ b/src/public_include/decaf/shake.hxx @@ -6,19 +6,14 @@ * Released under the MIT License. See LICENSE.txt for license information. * @author Mike Hamburg * @brief SHA-3-n and SHAKE-n instances, C++ wrapper. - * @warning EXPERIMENTAL! The names, parameter orders etc are likely to change. */ -#ifndef __SHAKE_HXX__ -#define __SHAKE_HXX__ +#ifndef __DECAF_SHAKE_HXX__ +#define __DECAF_SHAKE_HXX__ #include -#include /* TODO remove */ -#include /* TODO remove */ -#include #include -#include /** @cond internal */ #if __cplusplus >= 201103L @@ -140,268 +135,10 @@ template<> inline const struct kparams_s *SHA3<256>::get_params() { return &SHA3 template<> inline const struct kparams_s *SHA3<384>::get_params() { return &SHA3_384_params_s; } template<> inline const struct kparams_s *SHA3<512>::get_params() { return &SHA3_512_params_s; } /** @endcond */ - -/** @brief An exception for misused protocol, eg encrypt with no key. */ -class ProtocolException : public std::exception { -public: - /** @return "ProtocolException" */ - virtual const char * what() const NOEXCEPT { return "ProtocolException"; } -}; - -/** Sponge-based random-number generator */ -class SpongeRng : public Rng { -private: - /** C wrapped object */ - keccak_prng_t sp; - -public: - /** Exception thrown when The RNG fails (to seed itself) */ - class RngException : public std::exception { - private: - /** @cond internal */ - const char *const what_; - /** @endcond */ - public: - const int err_code; /**< errno that caused the reseed to fail. */ - const char *what() const NOEXCEPT { return what_; } /**< Description of exception. */ - RngException(int err_code, const char *what_) NOEXCEPT : what_(what_), err_code(err_code) {} /**< Construct */ - }; - - /** Initialize, deterministically by default, from block */ - inline SpongeRng( const Block &in, bool deterministic = true ) { - spongerng_init_from_buffer(sp,in.data(),in.size(),deterministic); - } - - /** Initialize, non-deterministically by default, from C/C++ filename */ - inline SpongeRng( const std::string &in = "/dev/urandom", size_t len = 32, bool deterministic = false ) - throw(RngException) { - decaf_error_t ret = spongerng_init_from_file(sp,in.c_str(),len,deterministic); - if (!decaf_successful(ret)) { - throw RngException(errno, "Couldn't load from file"); - } - } - - /** Stir in new data */ - inline void stir( const Block &data ) NOEXCEPT { - spongerng_stir(sp,data.data(),data.size()); - } - - /** Securely destroy by overwriting state. */ - inline ~SpongeRng() NOEXCEPT { spongerng_destroy(sp); } - - using Rng::read; - - /** Read data to a buffer. */ - virtual inline void read(Buffer buffer) NOEXCEPT -#if __cplusplus >= 201103L - final -#endif - { spongerng_next(sp,buffer.data(),buffer.size()); } - -private: - SpongeRng(const SpongeRng &) DELETE; - SpongeRng &operator=(const SpongeRng &) DELETE; -}; -/**@endcond*/ - -/** STROBE protocol framework object */ -class Strobe { -private: - /** The wrapped object */ - keccak_strobe_t sp; - -public: - /** Number of bytes in a default authentication size. */ - static const uint16_t DEFAULT_AUTH_SIZE = 16; - - /** Am I a server or a client? */ - enum client_or_server { SERVER, CLIENT }; - - /** Create protocol object. */ - inline Strobe ( - const char *description, /**< Description of this protocol. */ - client_or_server whoami, /**< Am I client or server? */ - const kparams_s ¶ms = STROBE_256 /**< Strength parameters */ - ) NOEXCEPT { - strobe_init(sp, ¶ms, description, whoami == CLIENT); - keyed = false; - } - - /** Securely destroy by overwriting state. */ - inline ~Strobe() NOEXCEPT { strobe_destroy(sp); } - - /** Stir in fixed key, from a C++ block. */ - inline void fixed_key ( - const Block &data /**< The key. */ - ) throw(ProtocolException) { - strobe_fixed_key(sp, data.data(), data.size()); - keyed = true; - } - - /** Stir in fixed key, from a serializeable object. */ - template inline void fixed_key ( - const Serializable &data /**< The key. */ - ) throw(ProtocolException) { - fixed_key(data.serialize()); - } - - /** Stir in DH key, from a C++ block. */ - inline void dh_key ( - const Block &data /**< The key. */ - ) throw(ProtocolException) { - strobe_dh_key(sp, data.data(), data.size()); - keyed = true; - } - - /** Stir in DH key, from a serializeable object. */ - template inline void dh_key ( - const Serializable &data /**< The key. */ - ) throw(ProtocolException) { - dh_key(data.serialize()); - } - - /** Stir in an explicit nonce. */ - inline void nonce(const Block &data) NOEXCEPT { - strobe_nonce(sp, data.data(), data.size()); - } - - /** Stir in data we sent as plaintext. NB This doesn't actually send anything. */ - inline void send_plaintext(const Block &data) NOEXCEPT { - strobe_plaintext(sp, data.data(), data.size(), true); - } - - /** Stir in serializeable data we sent as plaintext. NB This doesn't actually send anything. */ - template inline void send_plaintext(const Serializable &data) NOEXCEPT { - send_plaintext(data.serialize()); - } - - /** Stir in data we received as plaintext. NB This doesn't actually receive anything. */ - inline void recv_plaintext(const Block &data) NOEXCEPT { - strobe_plaintext(sp, data.data(), data.size(), false); - } - - /** Stir in associated data. */ - inline void ad(const Block &data) { - strobe_ad(sp, data.data(), data.size()); - } - - /** Stir in associated serializable data. */ - template inline void ad(const Serializable &data) NOEXCEPT { - ad(data.serialize()); - } - - /** Encrypt into a buffer, without appending authentication data */ - inline void encrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) { - if (!keyed) throw ProtocolException(); - if (out.size() != data.size()) throw LengthException(); - strobe_encrypt(sp, out.data(), data.data(), data.size()); - } - - /** Encrypt, without appending authentication data */ - inline SecureBuffer encrypt_no_auth(const Block &data) throw(ProtocolException) { - SecureBuffer out(data.size()); encrypt_no_auth(out, data); return out; - } - - /** Encrypt a serializable object, without appending authentication data */ - template inline SecureBuffer encrypt_no_auth(const Serializable &data) throw(ProtocolException) { - return encrypt_no_auth(data.serialize()); - } - - /** Decrypt into a buffer, without checking authentication data. */ - inline void decrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) { - if (!keyed) throw ProtocolException(); - if (out.size() != data.size()) throw LengthException(); - strobe_decrypt(sp, out.data(), data.data(), data.size()); - } - - /** Decrypt, without checking authentication data. */ - inline SecureBuffer decrypt_no_auth(const Block &data) throw(ProtocolException) { - SecureBuffer out(data.size()); decrypt_no_auth(out, data); return out; - } - - /** Produce an authenticator into a buffer. */ - inline void produce_auth(Buffer out, bool even_though_unkeyed = false) throw(LengthException,ProtocolException) { - if (!keyed && !even_though_unkeyed) throw ProtocolException(); - if (out.size() > STROBE_MAX_AUTH_BYTES) throw LengthException(); - strobe_produce_auth(sp, out.data(), out.size()); - } - - /** Produce an authenticator. */ - inline SecureBuffer produce_auth(uint8_t bytes = DEFAULT_AUTH_SIZE) throw(ProtocolException) { - SecureBuffer out(bytes); produce_auth(out); return out; - } - - /** Encrypt into a buffer and append authentication data */ - inline void encrypt( - Buffer out, const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE - ) throw(LengthException,ProtocolException) { - if (out.size() < data.size() || out.size() != data.size() + auth) throw LengthException(); - encrypt_no_auth(out.slice(0,data.size()), data); - produce_auth(out.slice(data.size(),auth)); - } - - /** Encrypt and append authentication data */ - inline SecureBuffer encrypt ( - const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE - ) throw(LengthException,ProtocolException,std::bad_alloc ){ - SecureBuffer out(data.size() + auth); encrypt(out, data, auth); return out; - } - - /** Encrypt a serializable object and append authentication data */ - template inline SecureBuffer encrypt ( - const Serializable &data, uint8_t auth = DEFAULT_AUTH_SIZE - ) throw(LengthException,ProtocolException,std::bad_alloc ){ - return encrypt(data.serialize(), auth); - } - - /** Decrypt into a buffer and check authentication data */ - inline void decrypt ( - Buffer out, const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE - ) throw(LengthException, CryptoException, ProtocolException) { - if (out.size() > data.size() || out.size() != data.size() - bytes) throw LengthException(); - decrypt_no_auth(out, data.slice(0,out.size())); - verify_auth(data.slice(out.size(),bytes)); - } - - /** Decrypt and check authentication data */ - inline SecureBuffer decrypt ( - const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE - ) throw(LengthException,CryptoException,ProtocolException,std::bad_alloc) { - if (data.size() < bytes) throw LengthException(); - SecureBuffer out(data.size() - bytes); decrypt(out, data, bytes); return out; - } - - /** Check authentication data */ - inline void verify_auth(const Block &auth) throw(LengthException,CryptoException) { - if (auth.size() == 0 || auth.size() > STROBE_MAX_AUTH_BYTES) throw LengthException(); - if (strobe_verify_auth(sp, auth.data(), auth.size()) != DECAF_SUCCESS) throw CryptoException(); - } - - /** Fill pseudorandom data into a buffer */ - inline void prng(Buffer out) NOEXCEPT { - (void)strobe_prng(sp, out.data(), out.size()); - } - - /** Return pseudorandom data */ - inline SecureBuffer prng(size_t bytes) { - SecureBuffer out(bytes); prng(out); return out; - } - - /** Change specs, perhaps to a faster spec that takes advantage of being keyed. - * @warning Experimental. - */ - inline void respec(const kparams_s ¶ms) throw(ProtocolException) { - if (!keyed) throw(ProtocolException()); - strobe_respec(sp, ¶ms); - } - -private: - bool keyed; -}; } /* namespace decaf */ #undef NOEXCEPT #undef DELETE -#endif /* __SHAKE_HXX__ */ +#endif /* __DECAF_SHAKE_HXX__ */ diff --git a/src/public_include/decaf/spongerng.hxx b/src/public_include/decaf/spongerng.hxx new file mode 100644 index 0000000..e310fec --- /dev/null +++ b/src/public_include/decaf/spongerng.hxx @@ -0,0 +1,98 @@ + + +/** + * @file decaf/strobe.hxx + * @copyright + * Based on CC0 code by David Leon Gil, 2015 \n + * Copyright (c) 2015 Cryptography Research, Inc. \n + * Released under the MIT License. See LICENSE.txt for license information. + * @author Mike Hamburg + * @brief Sponge RNG instances, C++ wrapper. + * @warning The guts of this are subject to change. Please don't implement + * anything that depends on the deterministic RNG being stable across versions + * of this library. + */ + +#ifndef __DECAF_SPONGERNG_HXX__ +#define __DECAF_SPONGERNG_HXX__ + +#include + +#include +#include +#include + +/** @cond internal */ +#if __cplusplus >= 201103L +#define NOEXCEPT noexcept +#define DELETE = delete +#else +#define NOEXCEPT throw() +#define DELETE +#endif +/** @endcond */ + +namespace decaf { + +/** Sponge-based random-number generator */ +class SpongeRng : public Rng { +private: + /** C wrapped object */ + keccak_prng_t sp; + +public: + /** Exception thrown when The RNG fails (to seed itself) */ + class RngException : public std::exception { + private: + /** @cond internal */ + const char *const what_; + /** @endcond */ + public: + const int err_code; /**< errno that caused the reseed to fail. */ + const char *what() const NOEXCEPT { return what_; } /**< Description of exception. */ + RngException(int err_code, const char *what_) NOEXCEPT : what_(what_), err_code(err_code) {} /**< Construct */ + }; + + /** Initialize, deterministically by default, from block */ + inline SpongeRng( const Block &in, bool deterministic = true ) { + spongerng_init_from_buffer(sp,in.data(),in.size(),deterministic); + } + + /** Initialize, non-deterministically by default, from C/C++ filename */ + inline SpongeRng( const std::string &in = "/dev/urandom", size_t len = 32, bool deterministic = false ) + throw(RngException) { + decaf_error_t ret = spongerng_init_from_file(sp,in.c_str(),len,deterministic); + if (!decaf_successful(ret)) { + throw RngException(errno, "Couldn't load from file"); + } + } + + /** Stir in new data */ + inline void stir( const Block &data ) NOEXCEPT { + spongerng_stir(sp,data.data(),data.size()); + } + + /** Securely destroy by overwriting state. */ + inline ~SpongeRng() NOEXCEPT { spongerng_destroy(sp); } + + using Rng::read; + + /** Read data to a buffer. */ + virtual inline void read(Buffer buffer) NOEXCEPT +#if __cplusplus >= 201103L + final +#endif + { spongerng_next(sp,buffer.data(),buffer.size()); } + +private: + SpongeRng(const SpongeRng &) DELETE; + SpongeRng &operator=(const SpongeRng &) DELETE; +}; +/**@endcond*/ + +} /* namespace decaf */ + +#undef NOEXCEPT +#undef DELETE + +#endif /* __DECAF_SPONGERNG_HXX__ */ diff --git a/src/public_include/decaf/strobe.hxx b/src/public_include/decaf/strobe.hxx new file mode 100644 index 0000000..4a41b38 --- /dev/null +++ b/src/public_include/decaf/strobe.hxx @@ -0,0 +1,240 @@ +/** + * @file decaf/strobe.hxx + * @copyright + * Based on CC0 code by David Leon Gil, 2015 \n + * Copyright (c) 2015 Cryptography Research, Inc. \n + * Released under the MIT License. See LICENSE.txt for license information. + * @author Mike Hamburg + * @brief STROBE instances, C++ wrapper. + * @warning This protocol framework is entirely experimental, and shouldn't be + * relied on for anything serious yet. + */ + +#ifndef __DECAF_STROBE_HXX__ +#define __DECAF_STROBE_HXX__ + +#include + +#include + + +/** @cond internal */ +#if __cplusplus >= 201103L +#define NOEXCEPT noexcept +#define DELETE = delete +#else +#define NOEXCEPT throw() +#define DELETE +#endif +/** @endcond */ + +namespace decaf { + +/** @brief An exception for misused protocol, eg encrypt with no key. */ +class ProtocolException : public std::exception { +public: + /** @return "ProtocolException" */ + virtual const char * what() const NOEXCEPT { return "ProtocolException"; } +}; + +/** STROBE protocol framework object */ +class Strobe { +private: + /** The wrapped object */ + keccak_strobe_t sp; + +public: + /** Number of bytes in a default authentication size. */ + static const uint16_t DEFAULT_AUTH_SIZE = 16; + + /** Am I a server or a client? */ + enum client_or_server { SERVER, CLIENT }; + + /** Create protocol object. */ + inline Strobe ( + const char *description, /**< Description of this protocol. */ + client_or_server whoami, /**< Am I client or server? */ + const kparams_s ¶ms = STROBE_256 /**< Strength parameters */ + ) NOEXCEPT { + strobe_init(sp, ¶ms, description, whoami == CLIENT); + keyed = false; + } + + /** Securely destroy by overwriting state. */ + inline ~Strobe() NOEXCEPT { strobe_destroy(sp); } + + /** Stir in fixed key, from a C++ block. */ + inline void fixed_key ( + const Block &data /**< The key. */ + ) throw(ProtocolException) { + strobe_fixed_key(sp, data.data(), data.size()); + keyed = true; + } + + /** Stir in fixed key, from a serializeable object. */ + template inline void fixed_key ( + const Serializable &data /**< The key. */ + ) throw(ProtocolException) { + fixed_key(data.serialize()); + } + + /** Stir in DH key, from a C++ block. */ + inline void dh_key ( + const Block &data /**< The key. */ + ) throw(ProtocolException) { + strobe_dh_key(sp, data.data(), data.size()); + keyed = true; + } + + /** Stir in DH key, from a serializeable object. */ + template inline void dh_key ( + const Serializable &data /**< The key. */ + ) throw(ProtocolException) { + dh_key(data.serialize()); + } + + /** Stir in an explicit nonce. */ + inline void nonce(const Block &data) NOEXCEPT { + strobe_nonce(sp, data.data(), data.size()); + } + + /** Stir in data we sent as plaintext. NB This doesn't actually send anything. */ + inline void send_plaintext(const Block &data) NOEXCEPT { + strobe_plaintext(sp, data.data(), data.size(), true); + } + + /** Stir in serializeable data we sent as plaintext. NB This doesn't actually send anything. */ + template inline void send_plaintext(const Serializable &data) NOEXCEPT { + send_plaintext(data.serialize()); + } + + /** Stir in data we received as plaintext. NB This doesn't actually receive anything. */ + inline void recv_plaintext(const Block &data) NOEXCEPT { + strobe_plaintext(sp, data.data(), data.size(), false); + } + + /** Stir in associated data. */ + inline void ad(const Block &data) { + strobe_ad(sp, data.data(), data.size()); + } + + /** Stir in associated serializable data. */ + template inline void ad(const Serializable &data) NOEXCEPT { + ad(data.serialize()); + } + + /** Encrypt into a buffer, without appending authentication data */ + inline void encrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) { + if (!keyed) throw ProtocolException(); + if (out.size() != data.size()) throw LengthException(); + strobe_encrypt(sp, out.data(), data.data(), data.size()); + } + + /** Encrypt, without appending authentication data */ + inline SecureBuffer encrypt_no_auth(const Block &data) throw(ProtocolException) { + SecureBuffer out(data.size()); encrypt_no_auth(out, data); return out; + } + + /** Encrypt a serializable object, without appending authentication data */ + template inline SecureBuffer encrypt_no_auth(const Serializable &data) throw(ProtocolException) { + return encrypt_no_auth(data.serialize()); + } + + /** Decrypt into a buffer, without checking authentication data. */ + inline void decrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) { + if (!keyed) throw ProtocolException(); + if (out.size() != data.size()) throw LengthException(); + strobe_decrypt(sp, out.data(), data.data(), data.size()); + } + + /** Decrypt, without checking authentication data. */ + inline SecureBuffer decrypt_no_auth(const Block &data) throw(ProtocolException) { + SecureBuffer out(data.size()); decrypt_no_auth(out, data); return out; + } + + /** Produce an authenticator into a buffer. */ + inline void produce_auth(Buffer out, bool even_though_unkeyed = false) throw(LengthException,ProtocolException) { + if (!keyed && !even_though_unkeyed) throw ProtocolException(); + if (out.size() > STROBE_MAX_AUTH_BYTES) throw LengthException(); + strobe_produce_auth(sp, out.data(), out.size()); + } + + /** Produce an authenticator. */ + inline SecureBuffer produce_auth(uint8_t bytes = DEFAULT_AUTH_SIZE) throw(ProtocolException) { + SecureBuffer out(bytes); produce_auth(out); return out; + } + + /** Encrypt into a buffer and append authentication data */ + inline void encrypt( + Buffer out, const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE + ) throw(LengthException,ProtocolException) { + if (out.size() < data.size() || out.size() != data.size() + auth) throw LengthException(); + encrypt_no_auth(out.slice(0,data.size()), data); + produce_auth(out.slice(data.size(),auth)); + } + + /** Encrypt and append authentication data */ + inline SecureBuffer encrypt ( + const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE + ) throw(LengthException,ProtocolException,std::bad_alloc ){ + SecureBuffer out(data.size() + auth); encrypt(out, data, auth); return out; + } + + /** Encrypt a serializable object and append authentication data */ + template inline SecureBuffer encrypt ( + const Serializable &data, uint8_t auth = DEFAULT_AUTH_SIZE + ) throw(LengthException,ProtocolException,std::bad_alloc ){ + return encrypt(data.serialize(), auth); + } + + /** Decrypt into a buffer and check authentication data */ + inline void decrypt ( + Buffer out, const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE + ) throw(LengthException, CryptoException, ProtocolException) { + if (out.size() > data.size() || out.size() != data.size() - bytes) throw LengthException(); + decrypt_no_auth(out, data.slice(0,out.size())); + verify_auth(data.slice(out.size(),bytes)); + } + + /** Decrypt and check authentication data */ + inline SecureBuffer decrypt ( + const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE + ) throw(LengthException,CryptoException,ProtocolException,std::bad_alloc) { + if (data.size() < bytes) throw LengthException(); + SecureBuffer out(data.size() - bytes); decrypt(out, data, bytes); return out; + } + + /** Check authentication data */ + inline void verify_auth(const Block &auth) throw(LengthException,CryptoException) { + if (auth.size() == 0 || auth.size() > STROBE_MAX_AUTH_BYTES) throw LengthException(); + if (strobe_verify_auth(sp, auth.data(), auth.size()) != DECAF_SUCCESS) throw CryptoException(); + } + + /** Fill pseudorandom data into a buffer */ + inline void prng(Buffer out) NOEXCEPT { + (void)strobe_prng(sp, out.data(), out.size()); + } + + /** Return pseudorandom data */ + inline SecureBuffer prng(size_t bytes) { + SecureBuffer out(bytes); prng(out); return out; + } + + /** Change specs, perhaps to a faster spec that takes advantage of being keyed. + * @warning Experimental. + */ + inline void respec(const kparams_s ¶ms) throw(ProtocolException) { + if (!keyed) throw(ProtocolException()); + strobe_respec(sp, ¶ms); + } + +private: + bool keyed; +}; + +} /* namespace decaf */ + +#undef NOEXCEPT +#undef DELETE + +#endif /* __DECAF_STROBE_HXX__ */ diff --git a/test/bench_decaf.cxx b/test/bench_decaf.cxx index 1150e28..c1dfc59 100644 --- a/test/bench_decaf.cxx +++ b/test/bench_decaf.cxx @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include #include diff --git a/test/test_ct.cxx b/test/test_ct.cxx index 7fbaf73..4058267 100644 --- a/test/test_ct.cxx +++ b/test/test_ct.cxx @@ -10,7 +10,7 @@ */ #include -#include +#include #include #include #include diff --git a/test/test_decaf.cxx b/test/test_decaf.cxx index 9ecc8a1..81e53cf 100644 --- a/test/test_decaf.cxx +++ b/test/test_decaf.cxx @@ -10,7 +10,7 @@ */ #include -#include +#include #include #include #include