| @@ -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; | ||||