@@ -13,6 +13,7 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include "field.h" | #include "field.h" | ||||
#include "f_field.h" | |||||
#include "decaf.h" | #include "decaf.h" | ||||
#include "decaf_config.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 */ | 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); | gf_serialize(ser,f); | ||||
int b=0, i, comma=0; | int b=0, i, comma=0; | ||||
unsigned long long limb = 0; | unsigned long long limb = 0; | ||||
printf("{FIELD_LITERAL("); | printf("{FIELD_LITERAL("); | ||||
for (i=0; i<GF_SER_BYTES; i++) { | |||||
for (i=0; i<SER_BYTES; i++) { | |||||
limb |= ((uint64_t)ser[i])<<b; | limb |= ((uint64_t)ser[i])<<b; | ||||
b += 8; | 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; | limb &= (1ull<<GF_LIT_LIMB_BITS) -1; | ||||
b -= GF_LIT_LIMB_BITS; | b -= GF_LIT_LIMB_BITS; | ||||
if (comma) printf(","); | if (comma) printf(","); | ||||
@@ -49,8 +49,6 @@ public: | |||||
/** Serialization size. */ | /** Serialization size. */ | ||||
static const size_t SER_BYTES = sizeof(Wrapped); | static const size_t SER_BYTES = sizeof(Wrapped); | ||||
/* TODO: convenience types like signature? */ | |||||
/** Read a private key from a string*/ | /** Read a private key from a string*/ | ||||
inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | ||||
memcpy(wrapped,b.data(),sizeof(wrapped)); | memcpy(wrapped,b.data(),sizeof(wrapped)); | ||||
@@ -70,7 +68,7 @@ public: | |||||
/** Serialization size. */ | /** Serialization size. */ | ||||
inline size_t serSize() const NOEXCEPT { return SER_BYTES; } | inline size_t serSize() const NOEXCEPT { return SER_BYTES; } | ||||
/* TODO: verify_strobe */ | |||||
/* FUTURE: verify_strobe */ | |||||
/** Verify a message */ | /** Verify a message */ | ||||
inline void verify( | inline void verify( | ||||
@@ -32,9 +32,6 @@ | |||||
* a naive autovectorizer will do with constant_time_lookup on Intel). | * a naive autovectorizer will do with constant_time_lookup on Intel). | ||||
* | * | ||||
* Instead, we're putting our trust in the loop unroller and unswitcher. | * 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 */ | /* PERF: vectorize vs unroll */ | ||||
#ifdef __clang__ | #ifdef __clang__ | ||||
#if 100*__clang_major__ + __clang_minor__ > 305 | #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 | ||||
#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) { | 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) { | 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) { | 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. | * Released under the MIT License. See LICENSE.txt for license information. | ||||
* @author Mike Hamburg | * @author Mike Hamburg | ||||
* @brief SHA-3-n and SHAKE-n instances, C++ wrapper. | * @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/shake.h> | ||||
#include <decaf/strobe.h> /* TODO remove */ | |||||
#include <decaf/spongerng.h> /* TODO remove */ | |||||
#include <string> | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <errno.h> | |||||
/** @cond internal */ | /** @cond internal */ | ||||
#if __cplusplus >= 201103L | #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<384>::get_params() { return &SHA3_384_params_s; } | ||||
template<> inline const struct kparams_s *SHA3<512>::get_params() { return &SHA3_512_params_s; } | template<> inline const struct kparams_s *SHA3<512>::get_params() { return &SHA3_512_params_s; } | ||||
/** @endcond */ | /** @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 */ | } /* namespace decaf */ | ||||
#undef NOEXCEPT | #undef NOEXCEPT | ||||
#undef DELETE | #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.hxx> | ||||
#include <decaf/shake.hxx> | #include <decaf/shake.hxx> | ||||
#include <decaf/strobe.hxx> | |||||
#include <decaf/spongerng.hxx> | |||||
#include <decaf/crypto_255.h> | #include <decaf/crypto_255.h> | ||||
#include <decaf/crypto_448.h> | #include <decaf/crypto_448.h> | ||||
#include <decaf/crypto.hxx> | #include <decaf/crypto.hxx> | ||||
@@ -10,7 +10,7 @@ | |||||
*/ | */ | ||||
#include <decaf.hxx> | #include <decaf.hxx> | ||||
#include <decaf/shake.hxx> | |||||
#include <decaf/spongerng.hxx> | |||||
#include <decaf/crypto.h> | #include <decaf/crypto.h> | ||||
#include <decaf/crypto.hxx> | #include <decaf/crypto.hxx> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
@@ -10,7 +10,7 @@ | |||||
*/ | */ | ||||
#include <decaf.hxx> | #include <decaf.hxx> | ||||
#include <decaf/shake.hxx> | |||||
#include <decaf/spongerng.hxx> | |||||
#include <decaf/crypto.h> | #include <decaf/crypto.h> | ||||
#include <decaf/crypto.hxx> | #include <decaf/crypto.hxx> | ||||
#include <stdio.h> | #include <stdio.h> | ||||