Browse Source

begin work on strobe

master
Mike Hamburg 9 years ago
parent
commit
a6b94cb600
8 changed files with 322 additions and 19 deletions
  1. +2
    -0
      include/decaf.h
  2. +1
    -7
      include/decaf.hxx
  3. +86
    -0
      include/shake.h
  4. +11
    -7
      include/shake.hxx
  5. +0
    -2
      src/decaf.c
  6. +0
    -2
      src/decaf_fast.c
  7. +213
    -0
      src/shake.c
  8. +9
    -1
      test/bench_decaf.cxx

+ 2
- 0
include/decaf.h View File

@@ -47,9 +47,11 @@
&& !defined(DECAF_FORCE_32_BIT)
#define DECAF_WORD_BITS 64
typedef uint64_t decaf_word_t, decaf_bool_t;
typedef __uint128_t decaf_dword_t;
#else
#define DECAF_WORD_BITS 32
typedef uint32_t decaf_word_t, decaf_bool_t;
typedef uint64_t decaf_dword_t;
#endif

#define DECAF_448_LIMBS (512/DECAF_WORD_BITS)


+ 1
- 7
include/decaf.hxx View File

@@ -281,13 +281,7 @@ public:
inline Scalar(const Scalar &x) NOEXCEPT { *this = x; }
/** @brief Construct from arbitrary-length little-endian byte sequence. */
inline Scalar(const unsigned char *buffer, size_t n) NOEXCEPT { decode(buffer,n); }
/** @brief Construct from arbitrary-length little-endian byte sequence. */
inline Scalar(const Block &buffer) NOEXCEPT { decode(buffer.data(),buffer.size()); }

/** @brief Decode from long buffer. */
inline void decode(const unsigned char *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,buffer,n); }
inline Scalar(const Block &buffer) NOEXCEPT { *this = buffer; }
/** @brief Assignment. */
inline Scalar& operator=(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); return *this; }


+ 86
- 0
include/shake.h View File

@@ -15,6 +15,8 @@
#include <stdint.h>
#include <sys/types.h>

#include "decaf.h" /* TODO: orly? */

/* TODO: unify with other headers (maybe all into one??); add nonnull attributes */
/** @cond internal */
#define API_VIS __attribute__((visibility("default")))
@@ -30,8 +32,14 @@
/** @endcond */
} keccak_sponge_t[1];
struct kparams_s;
typedef struct { uint64_t opaque; } strobe_params_t[1];
#endif

typedef struct strobe_s {
keccak_sponge_t sponge;
strobe_params_t params;
} strobe_s, strobe_t[1];

#ifdef __cplusplus
extern "C" {
#endif
@@ -243,6 +251,84 @@ void spongerng_stir (
size_t len
) API_VIS;

/**
* @brief Initialize Strobe protocol context.
* @param [out] The initialized strobe object.
* @param [in] Strobe parameter descriptor
* @param [in] am_client Nonzero if this party
* is the client.
*/
void strobe_init(
strobe_t strobe,
const struct kparams_s *params,
uint8_t am_client
);
/**
* @brief Produce an authenticator.
* @param [inout] strobe The Strobe protocol context
* @param [out] out The authenticator
* @param len The length, which must be no more than
* @todo 32?
*/
void strobe_produce_auth (
strobe_t strobe,
unsigned char *out,
size_t len
);

/**
* @brief Produce a session-bound pseudorandom value.
*
* @warning This "prng" value is NOT suitable for
* refreshing forward secrecy! It's to replace things
* like TCP session hash.
*
* @todo Figure out how to treat this wrt anti-rollback.
*
* @param [inout] strobe The Strobe protocol context
* @param [out] out The authenticator
* @param len The length.
*/
void strobe_prng (
strobe_t strobe,
unsigned char *out,
size_t len
);

/**
* @brief Verify an authenticator.
* @param [inout] strobe The Strobe protocol context
* @param [in] in The authenticator
* @param len The length, which must be no more than
* @todo 32?
*/
decaf_bool_t strobe_verify_auth (
strobe_t strobe,
const unsigned char *in,
size_t len
);

/**
* @brief Respecify Strobe protocol object's crypto.
* @param [inout] The initialized strobe context.
* @param [in] Strobe parameter descriptor
* @param [in] am_client Nonzero if this party
* is the client.
*/
void strobe_respec (
strobe_t strobe,
const struct kparams_s *params
);

/**
* @brief Destroy a Strobe context.
* @param [out] strobe The object to destroy.
*/
void strobe_destroy (
strobe_t strobe
);

#ifdef __cplusplus
} /* extern "C" */
#endif


+ 11
- 7
include/shake.hxx View File

@@ -75,15 +75,19 @@ public:
* @brief Output bytes from the sponge.
* @todo make this throw exceptions.
*/
inline void output(unsigned char *c, size_t len) {
sha3_output(sp,c,len);
}
inline void output(TmpBuffer b) { sha3_output(sp,b.data(),b.size()); }
/**
* @brief Output bytes from the sponge.
* @todo make this throw exceptions.
*/
inline void output(Buffer &b) { sha3_output(sp,b.data(),b.size()); }
/** @brief Output bytes from the sponge. */
inline SecureBuffer output(size_t len) {
SecureBuffer buffer(len);
SecureBuffer buffer(len);
sha3_output(sp,buffer,len);
return buffer;
return buffer;
}
/** @brief Return the sponge's default output size. */
@@ -98,7 +102,7 @@ public:
};

/** Fixed-output-length SHA3 */
template<int bits> class SHA3 : public KeccakSponge {
template<int bits> class SHA3 : public KeccakHash {
private:
/** Get the parameter template block for this hash */
const struct kparams_s *get_params();
@@ -109,7 +113,7 @@ public:

/** Variable-output-length SHAKE */
template<int bits>
class SHAKE : public KeccakSponge {
class SHAKE : public KeccakHash {
private:
/** Get the parameter template block for this hash */
const struct kparams_s *get_params();


+ 0
- 2
src/decaf.c View File

@@ -17,12 +17,10 @@

#if WBITS == 64
#define LBITS 56
typedef __uint128_t decaf_dword_t;
typedef __int128_t decaf_sdword_t;
#define LIMB(x) (x##ull)
#define SC_LIMB(x) (x##ull)
#elif WBITS == 32
typedef uint64_t decaf_dword_t;
typedef int64_t decaf_sdword_t;
#define LBITS 28
#define LIMB(x) (x##ull)&((1ull<<LBITS)-1), (x##ull)>>LBITS


+ 0
- 2
src/decaf_fast.c View File

@@ -18,12 +18,10 @@

#if WBITS == 64
#define LBITS 56
typedef __uint128_t decaf_dword_t;
typedef __int128_t decaf_sdword_t;
#define LIMB(x) (x##ull)
#define SC_LIMB(x) (x##ull)
#elif WBITS == 32
typedef uint64_t decaf_dword_t;
typedef int64_t decaf_sdword_t;
#define LBITS 28
#define LIMB(x) (x##ull)&((1ull<<LBITS)-1), (x##ull)>>LBITS


+ 213
- 0
src/shake.c View File

@@ -61,6 +61,10 @@ typedef struct kparams_s {
uint8_t position, flags, rate, startRound, pad, ratePad, maxOut, _;
} kparams_t[1];

typedef struct strobe_params_s {
uint8_t client, _[7];
} strobe_params_t[1];

typedef struct keccak_sponge_s {
kdomain_t state;
kparams_t params;
@@ -68,6 +72,7 @@ typedef struct keccak_sponge_s {

#define INTERNAL_SPONGE_STRUCT 1
#include "shake.h"
#include "decaf.h"

#define FLAG_ABSORBING 'A'
#define FLAG_SQUEEZING 'Z'
@@ -446,4 +451,212 @@ int spongerng_init_from_dev_urandom (
return spongerng_init_from_file(sponge, "/dev/urandom", 64, 0);
}

/* Strobe is different in that its rate is padded by one byte. */
void strobe_init(
strobe_t strobe,
const struct kparams_s *params,
uint8_t am_client
) {
sponge_init(strobe->sponge,params);
strobe->params->client = !!am_client;
}

static void strobe_duplex (
keccak_sponge_t sponge,
unsigned char *out,
const unsigned char *in,
size_t len
) {
unsigned j;
while (len) {
assert(sponge->params->rate >= sponge->params->position);
size_t cando = sponge->params->rate - sponge->params->position;
uint8_t* state = &sponge->state->b[sponge->params->position];
if (cando >= len) {
for (j=0; in && j<len; j++) state[j]^=in[j];
if (out) memcpy(out, state, len);
sponge->params->position += len;
return;
} else {
if (in) {
for (j=0; j<cando; j++) state[j]^=in[j];
in += cando;
}
if (out) {
memcpy(out, state, cando);
out += cando;
}
state[cando] ^= 0x1;
dokeccak(sponge);
len -= cando;
}
}
}

static void strobe_unduplex (
keccak_sponge_t sponge,
unsigned char *out,
const unsigned char *in,
size_t len
) {
unsigned j;
while (len) {
assert(sponge->params->rate >= sponge->params->position);
size_t cando = sponge->params->rate - sponge->params->position;
uint8_t* state = &sponge->state->b[sponge->params->position];
if (cando >= len) {
for (j=0; in && j<len; j++) {
unsigned char c = in[j];
out[j] = in[j] ^ state[j];
state[j] = c;
}
sponge->params->position += len;
return;
} else {
for (j=0; in && j<cando; j++) {
unsigned char c = in[j];
out[j] = in[j] ^ state[j];
state[j] = c;
}
state[j] ^= 0x1;
dokeccak(sponge);
len -= cando;
}
}
}

enum { KEY, NONCE, AD, PLAINTEXT, CIPHERTEXT, TAGFORGET, DIVERSIFIER, PRNG, FORK, JOIN, RESPEC };

#define CLIENT_TO_SERVER 0
#define SERVER_TO_CLIENT 1

struct strobe_control {
uint8_t next;
uint8_t bytes;
uint8_t flags;
} __attribute__((packed));

static void strobe_control_word (
strobe_t strobe,
const struct strobe_control *control
) {
assert(strobe->sponge->params->rate < sizeof(strobe->sponge->state));
strobe_duplex(strobe->sponge,NULL,(const unsigned char *)control,sizeof(*control));
strobe->sponge->state->b[strobe->sponge->params->position] ^= 0x1;
strobe->sponge->state->b[strobe->sponge->params->rate] ^= 0x2;
dokeccak(strobe->sponge);
}

void strobe_encrypt (
strobe_t strobe,
unsigned char *out,
const unsigned char *in,
size_t len
) {
struct strobe_control cont = { CIPHERTEXT, 0,
strobe->params->client ? CLIENT_TO_SERVER : SERVER_TO_CLIENT };
strobe_control_word(strobe, &cont);
strobe_duplex(strobe->sponge, out, in, len);
}

void strobe_decrypt (
strobe_t strobe,
unsigned char *out,
const unsigned char *in,
size_t len
) {
struct strobe_control cont = { CIPHERTEXT, 0,
strobe->params->client ? SERVER_TO_CLIENT : CLIENT_TO_SERVER };
strobe_control_word(strobe, &cont);
strobe_duplex(strobe->sponge, out, in, len);
}

void strobe_plaintext (
strobe_t strobe,
const unsigned char *in,
size_t len,
uint8_t iSent
) {
struct strobe_control cont = { CIPHERTEXT, 0,
(strobe->params->client == !!iSent) ? CLIENT_TO_SERVER : SERVER_TO_CLIENT };
strobe_control_word(strobe, &cont);
strobe_duplex(strobe->sponge, NULL, in, len);
}

#define STROBE_FORGET_BYTES 32

void strobe_produce_auth (
strobe_t strobe,
unsigned char *out,
size_t len
) {
assert(len < strobe->sponge->params->rate - STROBE_FORGET_BYTES);
struct strobe_control cont = { TAGFORGET, len,
strobe->params->client ? CLIENT_TO_SERVER : SERVER_TO_CLIENT };
strobe_control_word(strobe, &cont);
strobe_duplex(strobe->sponge, out, NULL, len);
strobe_duplex(strobe->sponge, NULL,
&strobe->sponge->state->b[strobe->sponge->params->position],
STROBE_FORGET_BYTES
);
}

void strobe_prng (
strobe_t strobe,
unsigned char *out,
size_t len
) {
struct strobe_control cont = { PRNG, 0, 0 };
strobe_control_word(strobe, &cont);
strobe_duplex(strobe->sponge, out, NULL, len);
/* Forget. TODO: ORLY? */
cont.next = TAGFORGET;
strobe_control_word(strobe, &cont);
strobe_duplex(strobe->sponge, NULL,
&strobe->sponge->state->b[0],
STROBE_FORGET_BYTES
);
}

/* TODO: remove reliance on decaf? */
decaf_bool_t strobe_verify_auth (
strobe_t strobe,
const unsigned char *in,
size_t len
) {
unsigned char zero[len];
decaf_bool_t chain=0;
assert(len < strobe->sponge->params->rate - STROBE_FORGET_BYTES);
struct strobe_control cont = { TAGFORGET, len,
strobe->params->client ? CLIENT_TO_SERVER : SERVER_TO_CLIENT };
strobe_control_word(strobe, &cont);
strobe_unduplex(strobe->sponge, zero, in, len);
strobe_duplex(strobe->sponge, NULL,
&strobe->sponge->state->b[strobe->sponge->params->position],
STROBE_FORGET_BYTES);
/* Check for 0 */
unsigned i;
for (i=0; i<len; i++) {
chain |= zero[i];
}
return ((decaf_dword_t)chain-1)>>(8*sizeof(decaf_word_t));
}

void strobe_destroy (
strobe_t strobe
) {
decaf_bzero(strobe,sizeof(strobe_t));
}

void strobe_respec (
strobe_t strobe,
const struct kparams_s *params
) {
struct strobe_control cont = { RESPEC, params->rate, params->startRound };
strobe_control_word(strobe, &cont);
strobe->sponge->params[0] = params[0];
}

/* TODO: Keyak instances, etc */

+ 9
- 1
test/bench_decaf.cxx View File

@@ -10,6 +10,7 @@
*/

#include "decaf.hxx"
#include "shake.hxx"
#include "shake.h"
#include "decaf_crypto.h"
#include <stdio.h>
@@ -134,9 +135,16 @@ int main(int argc, char **argv) {
decaf::SecureBuffer ep, ep2(Point::SER_BYTES*2);
printf("Micro-benchmarks:\n");
decaf::SHAKE<128> shake1;
decaf::SHAKE<256> shake2;
decaf::SHA3<512> sha5;
unsigned char b1024[1024] = {1};
for (Benchmark b("SHAKE128 1kiB", 30); b.iter(); ) { shake1 += decaf::TmpBuffer(b1024,1024); }
for (Benchmark b("SHAKE256 1kiB", 30); b.iter(); ) { shake2 += decaf::TmpBuffer(b1024,1024); }
for (Benchmark b("SHA3-512 1kiB", 30); b.iter(); ) { sha5 += decaf::TmpBuffer(b1024,1024); }
for (Benchmark b("Scalar add", 1000); b.iter(); ) { s+=t; }
for (Benchmark b("Scalar times", 100); b.iter(); ) { s*=t; }
for (Benchmark b("Scalar inv", 10); b.iter(); ) { s.inverse(); }
for (Benchmark b("Scalar inv", 1); b.iter(); ) { s.inverse(); }
for (Benchmark b("Point add", 100); b.iter(); ) { p += q; }
for (Benchmark b("Point double", 100); b.iter(); ) { p.double_in_place(); }
for (Benchmark b("Point scalarmul"); b.iter(); ) { p * s; }


Loading…
Cancel
Save