@@ -81,11 +81,9 @@ void sha3_output ( | |||||
* for the purpose of C++ default operators. | * for the purpose of C++ default operators. | ||||
* | * | ||||
* Returns n/8 for SHA3-n and 2n/8 for SHAKE-n. | * Returns n/8 for SHA3-n and 2n/8 for SHAKE-n. | ||||
* | |||||
* @param [inout] sponge The context. | |||||
*/ | */ | ||||
size_t sponge_default_output_bytes ( | size_t sponge_default_output_bytes ( | ||||
const keccak_sponge_t sponge | |||||
const keccak_sponge_t sponge /**< [inout] The context. */ | |||||
) API_VIS; | ) API_VIS; | ||||
/** | /** | ||||
@@ -32,33 +32,19 @@ | |||||
namespace decaf { | 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 | * Hash function derived from Keccak | ||||
* @todo throw exceptions when hash is misused. | * @todo throw exceptions when hash is misused. | ||||
*/ | */ | ||||
class KeccakHash : public KeccakSponge { | |||||
class KeccakHash { | |||||
protected: | protected: | ||||
/** @cond internal */ | |||||
/** The C-wrapper sponge state */ | |||||
keccak_sponge_t sp; | |||||
/** Initialize from parameters */ | /** 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: | public: | ||||
/** Add more data to running hash */ | /** Add more data to running hash */ | ||||
@@ -95,6 +81,9 @@ public: | |||||
inline SecureBuffer output() { | inline SecureBuffer output() { | ||||
return output(default_output_size()); | return output(default_output_size()); | ||||
} | } | ||||
/** Destructor zeroizes state */ | |||||
inline ~KeccakHash() NOEXCEPT { sponge_destroy(sp); } | |||||
}; | }; | ||||
/** Fixed-output-length SHA3 */ | /** Fixed-output-length SHA3 */ | ||||
@@ -160,7 +149,11 @@ public: | |||||
}; | }; | ||||
/** Sponge-based random-number generator */ | /** Sponge-based random-number generator */ | ||||
class SpongeRng : public Rng, private KeccakSponge { | |||||
class SpongeRng : public Rng { | |||||
private: | |||||
/** C wrapped object */ | |||||
keccak_prng_t sp; | |||||
public: | public: | ||||
/** Exception thrown when The RNG fails (to seed itself) */ | /** Exception thrown when The RNG fails (to seed itself) */ | ||||
class RngException : public std::exception { | class RngException : public std::exception { | ||||
@@ -175,21 +168,22 @@ public: | |||||
}; | }; | ||||
/** Initialize, deterministically by default, from block */ | /** 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); | spongerng_init_from_buffer(sp,in.data(),in.size(),deterministic); | ||||
} | } | ||||
/** Initialize, non-deterministically by default, from C/C++ filename */ | /** Initialize, non-deterministically by default, from C/C++ filename */ | ||||
inline SpongeRng( const std::string &in = "/dev/urandom", size_t len = 32, bool deterministic = false ) | 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); | decaf_error_t ret = spongerng_init_from_file(sp,in.c_str(),len,deterministic); | ||||
if (!decaf_successful(ret)) { | if (!decaf_successful(ret)) { | ||||
throw RngException(errno, "Couldn't load from file"); | throw RngException(errno, "Couldn't load from file"); | ||||
} | } | ||||
} | } | ||||
/** Securely destroy by overwriting state. */ | |||||
inline ~SpongeRng() NOEXCEPT { spongerng_destroy(sp); } | |||||
using Rng::read; | using Rng::read; | ||||
/** Read data to a buffer. */ | /** Read data to a buffer. */ | ||||
@@ -206,7 +200,11 @@ private: | |||||
/**@endcond*/ | /**@endcond*/ | ||||
/** STROBE protocol framework object */ | /** STROBE protocol framework object */ | ||||
class Strobe : private KeccakSponge { | |||||
class Strobe { | |||||
private: | |||||
/** The wrapped object */ | |||||
keccak_strobe_t sp; | |||||
public: | public: | ||||
/** Number of bytes in a default authentication size. */ | /** Number of bytes in a default authentication size. */ | ||||
static const uint16_t DEFAULT_AUTH_SIZE = 16; | static const uint16_t DEFAULT_AUTH_SIZE = 16; | ||||
@@ -219,10 +217,13 @@ public: | |||||
const char *description, /**< Description of this protocol. */ | const char *description, /**< Description of this protocol. */ | ||||
client_or_server whoami, /**< Am I client or server? */ | client_or_server whoami, /**< Am I client or server? */ | ||||
const kparams_s ¶ms = STROBE_256 /**< Strength parameters */ | const kparams_s ¶ms = STROBE_256 /**< Strength parameters */ | ||||
) NOEXCEPT : KeccakSponge(NOINIT()) { | |||||
) NOEXCEPT { | |||||
strobe_init(sp, ¶ms, description, whoami == CLIENT); | strobe_init(sp, ¶ms, description, whoami == CLIENT); | ||||
keyed = false; | keyed = false; | ||||
} | } | ||||
/** Securely destroy by overwriting state. */ | |||||
inline ~Strobe() NOEXCEPT { strobe_destroy(sp); } | |||||
/** Stir in fixed key, from a C++ block. */ | /** Stir in fixed key, from a C++ block. */ | ||||
inline void fixed_key ( | inline void fixed_key ( | ||||
@@ -18,8 +18,10 @@ | |||||
extern "C" { | extern "C" { | ||||
#endif | #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 */ | /** Keccak CSPRNG structure as one-element array */ | ||||
typedef keccak_prng_s keccak_prng_t[1]; | typedef keccak_prng_s keccak_prng_t[1]; | ||||
@@ -80,7 +82,7 @@ spongerng_destroy ( | |||||
/* Implementations of inline functions */ | /* Implementations of inline functions */ | ||||
/***************************************/ | /***************************************/ | ||||
void spongerng_destroy (keccak_prng_t doomed) { | void spongerng_destroy (keccak_prng_t doomed) { | ||||
sponge_destroy(doomed); | |||||
sponge_destroy(doomed->sponge); | |||||
} | } | ||||
/** @endcond */ /* internal */ | /** @endcond */ /* internal */ | ||||
@@ -17,8 +17,10 @@ | |||||
extern "C" { | extern "C" { | ||||
#endif | #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 */ | /** Keccak STROBE structure as one-element array */ | ||||
typedef keccak_strobe_s keccak_strobe_t[1]; | typedef keccak_strobe_s keccak_strobe_t[1]; | ||||
@@ -198,7 +200,9 @@ typedef enum { | |||||
#define STROBE_FLAG_NONDIR (STROBE_FLAG_IMPLICIT) | #define STROBE_FLAG_NONDIR (STROBE_FLAG_IMPLICIT) | ||||
/** Automatic flags implied by the mode */ | /** 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) \ | #define STROBE_AUTO_FLAGS(_mode) \ | ||||
( (((_mode)&1) ? STROBE_FLAG_RUN_F : 0) \ | ( (((_mode)&1) ? STROBE_FLAG_RUN_F : 0) \ | ||||
| (( ((_mode) & ~2) == STROBE_MODE_ABSORB \ | | (( ((_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) { | void strobe_destroy (keccak_strobe_t doomed) { | ||||
sponge_destroy(doomed); | |||||
sponge_destroy(doomed->sponge); | |||||
} | } | ||||
/** @endcond */ /* internal */ | /** @endcond */ /* internal */ | ||||
@@ -63,7 +63,7 @@ typedef struct kparams_s { | |||||
typedef struct keccak_sponge_s { | typedef struct keccak_sponge_s { | ||||
kdomain_t state; | kdomain_t state; | ||||
kparams_t params; | kparams_t params; | ||||
} keccak_sponge_t[1]; | |||||
} keccak_sponge_s, keccak_sponge_t[1]; | |||||
#define INTERNAL_SPONGE_STRUCT 1 | #define INTERNAL_SPONGE_STRUCT 1 | ||||
#include <decaf/shake.h> | #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 */ | static const char *SPONGERNG_NAME = "strobe::spongerng"; /* TODO: canonicalize name */ | ||||
void spongerng_next ( | void spongerng_next ( | ||||
keccak_sponge_t sponge, | |||||
keccak_prng_t prng, | |||||
uint8_t * __restrict__ out, | uint8_t * __restrict__ out, | ||||
size_t len | size_t len | ||||
) { | ) { | ||||
keccak_sponge_s *sponge = prng->sponge; | |||||
if (sponge->params->client) { | if (sponge->params->client) { | ||||
/* nondet */ | /* nondet */ | ||||
uint8_t cpu_entropy[32]; | uint8_t cpu_entropy[32]; | ||||
get_cpu_entropy(cpu_entropy, sizeof(cpu_entropy)); | 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 ( | void spongerng_stir ( | ||||
keccak_sponge_t sponge, | |||||
keccak_prng_t sponge, | |||||
const uint8_t * __restrict__ in, | const uint8_t * __restrict__ in, | ||||
size_t len | 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 = { | static const struct kparams_s spongerng_params = { | ||||
@@ -323,22 +324,24 @@ static const struct kparams_s spongerng_params = { | |||||
}; | }; | ||||
void spongerng_init_from_buffer ( | void spongerng_init_from_buffer ( | ||||
keccak_sponge_t sponge, | |||||
keccak_prng_t prng, | |||||
const uint8_t * __restrict__ in, | const uint8_t * __restrict__ in, | ||||
size_t len, | size_t len, | ||||
int deterministic | 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 ( | decaf_error_t spongerng_init_from_file ( | ||||
keccak_sponge_t sponge, | |||||
keccak_prng_t prng, | |||||
const char *file, | const char *file, | ||||
size_t len, | size_t len, | ||||
int deterministic | 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; | if (!len) return DECAF_FAILURE; | ||||
int fd = open(file, O_RDONLY); | int fd = open(file, O_RDONLY); | ||||
@@ -352,7 +355,7 @@ decaf_error_t spongerng_init_from_file ( | |||||
close(fd); | close(fd); | ||||
return DECAF_FAILURE; | 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)); | first ? STROBE_CW_PRNG_USER_SEED : (STROBE_CW_PRNG_USER_SEED | STROBE_FLAG_MORE)); | ||||
len -= red; | len -= red; | ||||
first = 0; | first = 0; | ||||
@@ -363,7 +366,7 @@ decaf_error_t spongerng_init_from_file ( | |||||
} | } | ||||
decaf_error_t spongerng_init_from_dev_urandom ( | 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); | 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. */ | /* Strobe is different in that its rate is padded by one byte. */ | ||||
void strobe_init( | void strobe_init( | ||||
keccak_sponge_t sponge, | |||||
keccak_strobe_t strobe, | |||||
const struct kparams_s *params, | const struct kparams_s *params, | ||||
const char *proto, | const char *proto, | ||||
uint8_t am_client | uint8_t am_client | ||||
) { | ) { | ||||
keccak_sponge_s *sponge = strobe->sponge; | |||||
sponge_init(sponge,params); | sponge_init(sponge,params); | ||||
const char *a_string = "STROBE full v0.2"; | const char *a_string = "STROBE full v0.2"; | ||||
@@ -390,7 +394,7 @@ void strobe_init( | |||||
len | 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->state->b[sponge->params->rate+1] = 1; | ||||
sponge->params->client = !!am_client; | sponge->params->client = !!am_client; | ||||
@@ -524,12 +528,13 @@ static const int STROBE_FORGET_BYTES = 32; | |||||
static const uint8_t FLAG_NOPARSE = 1; | static const uint8_t FLAG_NOPARSE = 1; | ||||
void strobe_transact ( | void strobe_transact ( | ||||
keccak_sponge_t sponge, | |||||
keccak_strobe_t strobe, | |||||
unsigned char *out, | unsigned char *out, | ||||
const unsigned char *in, | const unsigned char *in, | ||||
size_t len, | size_t len, | ||||
uint32_t cw_flags | uint32_t cw_flags | ||||
) { | ) { | ||||
keccak_sponge_s *sponge = strobe->sponge; | |||||
if ( (cw_flags & STROBE_FLAG_NONDIR) == 0 | if ( (cw_flags & STROBE_FLAG_NONDIR) == 0 | ||||
/* extraneous nots to change ints to bools :-/ */ | /* extraneous nots to change ints to bools :-/ */ | ||||
&& !(cw_flags & STROBE_FLAG_RECV) != !(sponge->params->client) ) { | && !(cw_flags & STROBE_FLAG_RECV) != !(sponge->params->client) ) { | ||||
@@ -588,12 +593,13 @@ void strobe_transact ( | |||||
} | } | ||||
decaf_error_t strobe_verify_auth ( | decaf_error_t strobe_verify_auth ( | ||||
keccak_sponge_t sponge, | |||||
keccak_strobe_t strobe, | |||||
const unsigned char *in, | const unsigned char *in, | ||||
uint16_t len | uint16_t len | ||||
) { | ) { | ||||
keccak_sponge_s *sponge = strobe->sponge; | |||||
if (len > sponge->params->rate) return DECAF_FAILURE; | 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; | int32_t residue = 0; | ||||
int i; | int i; | ||||
@@ -605,12 +611,13 @@ decaf_error_t strobe_verify_auth ( | |||||
} | } | ||||
void strobe_respec ( | void strobe_respec ( | ||||
keccak_sponge_t sponge, | |||||
keccak_strobe_t strobe, | |||||
const struct kparams_s *params | const struct kparams_s *params | ||||
) { | ) { | ||||
keccak_sponge_s *sponge = strobe->sponge; | |||||
uint8_t in[] = { params->rate, params->startRound }; | 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); | assert(sponge->params->position == 0); | ||||
sponge->params->rate = params->rate; | sponge->params->rate = params->rate; | ||||
sponge->params->startRound = params->startRound; | sponge->params->startRound = params->startRound; | ||||