| @@ -13,6 +13,7 @@ | |||
| #include <stdlib.h> | |||
| #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_SER_BYTES; i++) { | |||
| for (i=0; i<SER_BYTES; i++) { | |||
| limb |= ((uint64_t)ser[i])<<b; | |||
| b += 8; | |||
| if (b >= GF_LIT_LIMB_BITS || i == GF_SER_BYTES-1) { | |||
| if (b >= GF_LIT_LIMB_BITS || i == SER_BYTES-1) { | |||
| limb &= (1ull<<GF_LIT_LIMB_BITS) -1; | |||
| b -= GF_LIT_LIMB_BITS; | |||
| if (comma) printf(","); | |||
| @@ -49,8 +49,6 @@ public: | |||
| /** Serialization size. */ | |||
| static const size_t SER_BYTES = sizeof(Wrapped); | |||
| /* TODO: convenience types like signature? */ | |||
| /** Read a private key from a string*/ | |||
| inline explicit PublicKey(const FixedBlock<SER_BYTES> &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( | |||
| @@ -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. | |||
| */ | |||
| @@ -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 | |||
| @@ -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 */ | |||
| } | |||
| @@ -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 */ | |||
| } | |||
| @@ -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 */ | |||
| } | |||
| @@ -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 <decaf/shake.h> | |||
| #include <decaf/strobe.h> /* TODO remove */ | |||
| #include <decaf/spongerng.h> /* TODO remove */ | |||
| #include <string> | |||
| #include <sys/types.h> | |||
| #include <errno.h> | |||
| /** @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<class T> inline void fixed_key ( | |||
| const Serializable<T> &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<class T> inline void dh_key ( | |||
| const Serializable<T> &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<class T> inline void send_plaintext(const Serializable<T> &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<class T> inline void ad(const Serializable<T> &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<class T> inline SecureBuffer encrypt_no_auth(const Serializable<T> &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<class T> inline SecureBuffer encrypt ( | |||
| const Serializable<T> &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__ */ | |||
| @@ -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 <decaf/spongerng.h> | |||
| #include <string> | |||
| #include <sys/types.h> | |||
| #include <errno.h> | |||
| /** @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__ */ | |||
| @@ -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 <decaf/strobe.h> | |||
| #include <sys/types.h> | |||
| /** @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<class T> inline void fixed_key ( | |||
| const Serializable<T> &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<class T> inline void dh_key ( | |||
| const Serializable<T> &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<class T> inline void send_plaintext(const Serializable<T> &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<class T> inline void ad(const Serializable<T> &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<class T> inline SecureBuffer encrypt_no_auth(const Serializable<T> &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<class T> inline SecureBuffer encrypt ( | |||
| const Serializable<T> &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__ */ | |||
| @@ -11,6 +11,8 @@ | |||
| #include <decaf.hxx> | |||
| #include <decaf/shake.hxx> | |||
| #include <decaf/strobe.hxx> | |||
| #include <decaf/spongerng.hxx> | |||
| #include <decaf/crypto_255.h> | |||
| #include <decaf/crypto_448.h> | |||
| #include <decaf/crypto.hxx> | |||
| @@ -10,7 +10,7 @@ | |||
| */ | |||
| #include <decaf.hxx> | |||
| #include <decaf/shake.hxx> | |||
| #include <decaf/spongerng.hxx> | |||
| #include <decaf/crypto.h> | |||
| #include <decaf/crypto.hxx> | |||
| #include <stdio.h> | |||
| @@ -10,7 +10,7 @@ | |||
| */ | |||
| #include <decaf.hxx> | |||
| #include <decaf/shake.hxx> | |||
| #include <decaf/spongerng.hxx> | |||
| #include <decaf/crypto.h> | |||
| #include <decaf/crypto.hxx> | |||
| #include <stdio.h> | |||