@@ -81,11 +81,9 @@ void sha3_output ( | |||
* for the purpose of C++ default operators. | |||
* | |||
* Returns n/8 for SHA3-n and 2n/8 for SHAKE-n. | |||
* | |||
* @param [inout] sponge The context. | |||
*/ | |||
size_t sponge_default_output_bytes ( | |||
const keccak_sponge_t sponge | |||
const keccak_sponge_t sponge /**< [inout] The context. */ | |||
) API_VIS; | |||
/** | |||
@@ -32,33 +32,19 @@ | |||
namespace decaf { | |||
/** A Keccak sponge internal class */ | |||
class KeccakSponge { | |||
protected: | |||
/** @cond internal */ | |||
/** The C-wrapper sponge state */ | |||
keccak_sponge_t sp; | |||
/** Initialize from parameters */ | |||
inline KeccakSponge(const struct kparams_s *params) NOEXCEPT { sponge_init(sp, params); } | |||
/** No initialization */ | |||
inline KeccakSponge(const NOINIT &) NOEXCEPT { } | |||
/** @endcond */ | |||
public: | |||
/** Destructor zeroizes state */ | |||
inline ~KeccakSponge() NOEXCEPT { sponge_destroy(sp); } | |||
}; | |||
/** | |||
* Hash function derived from Keccak | |||
* @todo throw exceptions when hash is misused. | |||
*/ | |||
class KeccakHash : public KeccakSponge { | |||
class KeccakHash { | |||
protected: | |||
/** @cond internal */ | |||
/** The C-wrapper sponge state */ | |||
keccak_sponge_t sp; | |||
/** Initialize from parameters */ | |||
inline KeccakHash(const kparams_s *params) NOEXCEPT : KeccakSponge(params) {} | |||
inline KeccakHash(const kparams_s *params) NOEXCEPT { sponge_init(sp, params); } | |||
/** @endcond */ | |||
public: | |||
/** Add more data to running hash */ | |||
@@ -95,6 +81,9 @@ public: | |||
inline SecureBuffer output() { | |||
return output(default_output_size()); | |||
} | |||
/** Destructor zeroizes state */ | |||
inline ~KeccakHash() NOEXCEPT { sponge_destroy(sp); } | |||
}; | |||
/** Fixed-output-length SHA3 */ | |||
@@ -160,7 +149,11 @@ public: | |||
}; | |||
/** Sponge-based random-number generator */ | |||
class SpongeRng : public Rng, private KeccakSponge { | |||
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 { | |||
@@ -175,21 +168,22 @@ public: | |||
}; | |||
/** Initialize, deterministically by default, from block */ | |||
inline SpongeRng( const Block &in, bool deterministic = true ) | |||
: KeccakSponge((NOINIT())) { | |||
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) | |||
: KeccakSponge((NOINIT())) { | |||
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"); | |||
} | |||
} | |||
/** Securely destroy by overwriting state. */ | |||
inline ~SpongeRng() NOEXCEPT { spongerng_destroy(sp); } | |||
using Rng::read; | |||
/** Read data to a buffer. */ | |||
@@ -206,7 +200,11 @@ private: | |||
/**@endcond*/ | |||
/** STROBE protocol framework object */ | |||
class Strobe : private KeccakSponge { | |||
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; | |||
@@ -219,10 +217,13 @@ public: | |||
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 : KeccakSponge(NOINIT()) { | |||
) 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 ( | |||
@@ -18,8 +18,10 @@ | |||
extern "C" { | |||
#endif | |||
/** Keccak CSPRNG structure as struct. FUTURE: distinguish. */ | |||
typedef struct keccak_sponge_s keccak_prng_s; | |||
/** Keccak CSPRNG structure as struct. */ | |||
typedef struct { | |||
keccak_sponge_t sponge; /**< Internal sponge object. */ | |||
} keccak_prng_s; | |||
/** Keccak CSPRNG structure as one-element array */ | |||
typedef keccak_prng_s keccak_prng_t[1]; | |||
@@ -80,7 +82,7 @@ spongerng_destroy ( | |||
/* Implementations of inline functions */ | |||
/***************************************/ | |||
void spongerng_destroy (keccak_prng_t doomed) { | |||
sponge_destroy(doomed); | |||
sponge_destroy(doomed->sponge); | |||
} | |||
/** @endcond */ /* internal */ | |||
@@ -17,8 +17,10 @@ | |||
extern "C" { | |||
#endif | |||
/** Keccak STROBE structure as struct. FUTURE: distinguish. */ | |||
typedef struct keccak_sponge_s keccak_strobe_s; | |||
/** Keccak STROBE structure as struct. */ | |||
typedef struct { | |||
keccak_sponge_t sponge; /**< Internal sponge object. */ | |||
} keccak_strobe_s; | |||
/** Keccak STROBE structure as one-element array */ | |||
typedef keccak_strobe_s keccak_strobe_t[1]; | |||
@@ -198,7 +200,9 @@ typedef enum { | |||
#define STROBE_FLAG_NONDIR (STROBE_FLAG_IMPLICIT) | |||
/** Automatic flags implied by the mode */ | |||
/* HACK: SQUEEZE_R is treated as directional because its' MAC */ | |||
/* NB: SQUEEZE_R is treated as directional because its' MAC. | |||
* can of course override by orring in IMPLICIT|NONDIR | |||
*/ | |||
#define STROBE_AUTO_FLAGS(_mode) \ | |||
( (((_mode)&1) ? STROBE_FLAG_RUN_F : 0) \ | |||
| (( ((_mode) & ~2) == STROBE_MODE_ABSORB \ | |||
@@ -325,7 +329,7 @@ void strobe_prng(keccak_strobe_t strobe, unsigned char *out, uint16_t len) { | |||
} | |||
void strobe_destroy (keccak_strobe_t doomed) { | |||
sponge_destroy(doomed); | |||
sponge_destroy(doomed->sponge); | |||
} | |||
/** @endcond */ /* internal */ | |||
@@ -63,7 +63,7 @@ typedef struct kparams_s { | |||
typedef struct keccak_sponge_s { | |||
kdomain_t state; | |||
kparams_t params; | |||
} keccak_sponge_t[1]; | |||
} keccak_sponge_s, keccak_sponge_t[1]; | |||
#define INTERNAL_SPONGE_STRUCT 1 | |||
#include <decaf/shake.h> | |||
@@ -296,26 +296,27 @@ static void get_cpu_entropy(uint8_t *entropy, size_t len) { | |||
static const char *SPONGERNG_NAME = "strobe::spongerng"; /* TODO: canonicalize name */ | |||
void spongerng_next ( | |||
keccak_sponge_t sponge, | |||
keccak_prng_t prng, | |||
uint8_t * __restrict__ out, | |||
size_t len | |||
) { | |||
keccak_sponge_s *sponge = prng->sponge; | |||
if (sponge->params->client) { | |||
/* nondet */ | |||
uint8_t cpu_entropy[32]; | |||
get_cpu_entropy(cpu_entropy, sizeof(cpu_entropy)); | |||
strobe_transact(sponge,NULL,cpu_entropy,sizeof(cpu_entropy),STROBE_CW_PRNG_CPU_SEED); | |||
strobe_transact((keccak_strobe_s*)sponge,NULL,cpu_entropy,sizeof(cpu_entropy),STROBE_CW_PRNG_CPU_SEED); | |||
} | |||
strobe_transact(sponge,out,NULL,len,STROBE_CW_PRNG); | |||
strobe_transact((keccak_strobe_s*)sponge,out,NULL,len,STROBE_CW_PRNG); | |||
} | |||
void spongerng_stir ( | |||
keccak_sponge_t sponge, | |||
keccak_prng_t sponge, | |||
const uint8_t * __restrict__ in, | |||
size_t len | |||
) { | |||
strobe_transact(sponge,NULL,in,len,STROBE_CW_PRNG_USER_SEED); | |||
strobe_transact((keccak_strobe_s*)sponge,NULL,in,len,STROBE_CW_PRNG_USER_SEED); | |||
} | |||
static const struct kparams_s spongerng_params = { | |||
@@ -323,22 +324,24 @@ static const struct kparams_s spongerng_params = { | |||
}; | |||
void spongerng_init_from_buffer ( | |||
keccak_sponge_t sponge, | |||
keccak_prng_t prng, | |||
const uint8_t * __restrict__ in, | |||
size_t len, | |||
int deterministic | |||
) { | |||
strobe_init(sponge, &spongerng_params, SPONGERNG_NAME, !deterministic); | |||
spongerng_stir(sponge, in, len); | |||
keccak_sponge_s *sponge = prng->sponge; | |||
strobe_init((keccak_strobe_s*)sponge, &spongerng_params, SPONGERNG_NAME, !deterministic); | |||
spongerng_stir(prng, in, len); | |||
} | |||
decaf_error_t spongerng_init_from_file ( | |||
keccak_sponge_t sponge, | |||
keccak_prng_t prng, | |||
const char *file, | |||
size_t len, | |||
int deterministic | |||
) { | |||
strobe_init(sponge, &spongerng_params, SPONGERNG_NAME, !deterministic); | |||
keccak_sponge_s *sponge = prng->sponge; | |||
strobe_init((keccak_strobe_s*)sponge, &spongerng_params, SPONGERNG_NAME, !deterministic); | |||
if (!len) return DECAF_FAILURE; | |||
int fd = open(file, O_RDONLY); | |||
@@ -352,7 +355,7 @@ decaf_error_t spongerng_init_from_file ( | |||
close(fd); | |||
return DECAF_FAILURE; | |||
} | |||
strobe_transact(sponge,NULL,buffer,red, | |||
strobe_transact((keccak_strobe_s*)sponge,NULL,buffer,red, | |||
first ? STROBE_CW_PRNG_USER_SEED : (STROBE_CW_PRNG_USER_SEED | STROBE_FLAG_MORE)); | |||
len -= red; | |||
first = 0; | |||
@@ -363,7 +366,7 @@ decaf_error_t spongerng_init_from_file ( | |||
} | |||
decaf_error_t spongerng_init_from_dev_urandom ( | |||
keccak_sponge_t sponge | |||
keccak_prng_t sponge | |||
) { | |||
return spongerng_init_from_file(sponge, "/dev/urandom", 64, 0); | |||
} | |||
@@ -375,11 +378,12 @@ const struct kparams_s STROBE_KEYED_128 = { 0, 0, 200-128/4, 12, 0, 0, 0, 0 }; | |||
/* Strobe is different in that its rate is padded by one byte. */ | |||
void strobe_init( | |||
keccak_sponge_t sponge, | |||
keccak_strobe_t strobe, | |||
const struct kparams_s *params, | |||
const char *proto, | |||
uint8_t am_client | |||
) { | |||
keccak_sponge_s *sponge = strobe->sponge; | |||
sponge_init(sponge,params); | |||
const char *a_string = "STROBE full v0.2"; | |||
@@ -390,7 +394,7 @@ void strobe_init( | |||
len | |||
); | |||
strobe_transact(sponge, NULL, (const unsigned char *)proto, strlen(proto), STROBE_CW_INIT); | |||
strobe_transact(strobe, NULL, (const unsigned char *)proto, strlen(proto), STROBE_CW_INIT); | |||
sponge->state->b[sponge->params->rate+1] = 1; | |||
sponge->params->client = !!am_client; | |||
@@ -524,12 +528,13 @@ static const int STROBE_FORGET_BYTES = 32; | |||
static const uint8_t FLAG_NOPARSE = 1; | |||
void strobe_transact ( | |||
keccak_sponge_t sponge, | |||
keccak_strobe_t strobe, | |||
unsigned char *out, | |||
const unsigned char *in, | |||
size_t len, | |||
uint32_t cw_flags | |||
) { | |||
keccak_sponge_s *sponge = strobe->sponge; | |||
if ( (cw_flags & STROBE_FLAG_NONDIR) == 0 | |||
/* extraneous nots to change ints to bools :-/ */ | |||
&& !(cw_flags & STROBE_FLAG_RECV) != !(sponge->params->client) ) { | |||
@@ -588,12 +593,13 @@ void strobe_transact ( | |||
} | |||
decaf_error_t strobe_verify_auth ( | |||
keccak_sponge_t sponge, | |||
keccak_strobe_t strobe, | |||
const unsigned char *in, | |||
uint16_t len | |||
) { | |||
keccak_sponge_s *sponge = strobe->sponge; | |||
if (len > sponge->params->rate) return DECAF_FAILURE; | |||
strobe_transact(sponge, NULL, in, len, strobe_cw_recv(STROBE_CW_MAC)); | |||
strobe_transact(strobe, NULL, in, len, strobe_cw_recv(STROBE_CW_MAC)); | |||
int32_t residue = 0; | |||
int i; | |||
@@ -605,12 +611,13 @@ decaf_error_t strobe_verify_auth ( | |||
} | |||
void strobe_respec ( | |||
keccak_sponge_t sponge, | |||
keccak_strobe_t strobe, | |||
const struct kparams_s *params | |||
) { | |||
keccak_sponge_s *sponge = strobe->sponge; | |||
uint8_t in[] = { params->rate, params->startRound }; | |||
strobe_transact( sponge, NULL, in, sizeof(in), STROBE_CW_RESPEC_INFO ); | |||
strobe_transact( sponge, NULL, NULL, 0, STROBE_CW_RESPEC ); | |||
strobe_transact( strobe, NULL, in, sizeof(in), STROBE_CW_RESPEC_INFO ); | |||
strobe_transact( strobe, NULL, NULL, 0, STROBE_CW_RESPEC ); | |||
assert(sponge->params->position == 0); | |||
sponge->params->rate = params->rate; | |||
sponge->params->startRound = params->startRound; | |||