diff --git a/src/decaf_crypto_255.c b/src/decaf_crypto_255.c index 2647541..815511e 100644 --- a/src/decaf_crypto_255.c +++ b/src/decaf_crypto_255.c @@ -23,7 +23,7 @@ void decaf_255_derive_private_key ( keccak_strobe_t strobe; strobe_init(strobe, &STROBE_256, magic, 0); - strobe_key(strobe, proto, sizeof(decaf_255_symmetric_key_t)); + strobe_fixed_key(strobe, proto, sizeof(decaf_255_symmetric_key_t)); strobe_prng(strobe, encoded_scalar, sizeof(encoded_scalar)); strobe_destroy(strobe); @@ -109,7 +109,7 @@ decaf_255_sign_strobe ( /* Derive nonce */ keccak_strobe_t strobe2; memcpy(strobe2,strobe,sizeof(strobe2)); - strobe_key(strobe2,priv->sym,sizeof(decaf_255_symmetric_key_t)); + strobe_fixed_key(strobe2,priv->sym,sizeof(decaf_255_symmetric_key_t)); strobe_prng(strobe2,overkill,sizeof(overkill)); strobe_destroy(strobe2); diff --git a/src/decaf_crypto_448.c b/src/decaf_crypto_448.c index 111f4a8..5a47995 100644 --- a/src/decaf_crypto_448.c +++ b/src/decaf_crypto_448.c @@ -24,7 +24,7 @@ void decaf_448_derive_private_key ( keccak_strobe_t strobe; strobe_init(strobe, &STROBE_256, magic, 0); - strobe_key(strobe, proto, sizeof(decaf_448_symmetric_key_t)); + strobe_fixed_key(strobe, proto, sizeof(decaf_448_symmetric_key_t)); strobe_prng(strobe, encoded_scalar, sizeof(encoded_scalar)); strobe_destroy(strobe); @@ -110,7 +110,7 @@ decaf_448_sign_strobe ( /* Derive nonce */ keccak_strobe_t strobe2; memcpy(strobe2,strobe,sizeof(strobe2)); - strobe_key(strobe2,priv->sym,sizeof(decaf_448_symmetric_key_t)); + strobe_fixed_key(strobe2,priv->sym,sizeof(decaf_448_symmetric_key_t)); strobe_prng(strobe2,overkill,sizeof(overkill)); strobe_destroy(strobe2); diff --git a/src/public_include/decaf/shake.h b/src/public_include/decaf/shake.h index 32eb7c8..aa1fc4b 100644 --- a/src/public_include/decaf/shake.h +++ b/src/public_include/decaf/shake.h @@ -189,11 +189,6 @@ void spongerng_init_from_buffer ( size_t len, int deterministic ) NONNULL2 API_VIS; - -/* FIXME!! This interface has the opposite retval convention from other functions - * in the library. (0=success). Should they be harmonized? - */ - /** * @brief Initialize a sponge-based CSPRNG from a file. * @@ -203,33 +198,27 @@ void spongerng_init_from_buffer ( * @param [in] deterministic If zero, allow RNG to stir in nondeterministic * data from RDRAND or RDTSC. * - * @retval 0 Success. - * @retval positive An error has occurred, and this was the errno. - * @retval -1 An unknown error has occurred. - * @retval -2 len was 0. + * @retval DECAF_SUCCESS success. + * @retval DECAF_FAILURE failure. + * @note On failure, errno can be used to determine the cause. */ -int spongerng_init_from_file ( +decaf_error_t spongerng_init_from_file ( keccak_prng_t prng, const char *file, size_t len, int deterministic ) NONNULL2 API_VIS WARN_UNUSED; - -/* FIXME!! This interface has the opposite retval convention from other functions - * in the library. (0=success). Should they be harmonized? - */ - /** * @brief Initialize a nondeterministic sponge-based CSPRNG from /dev/urandom. * * @param [out] sponge The sponge object. * - * @retval 0 Success. - * @retval positive An error has occurred, and this was the errno. - * @retval -1 An unknown error has occurred. + * @retval DECAF_SUCCESS success. + * @retval DECAF_FAILURE failure. + * @note On failure, errno can be used to determine the cause. */ -int spongerng_init_from_dev_urandom ( +decaf_error_t spongerng_init_from_dev_urandom ( keccak_prng_t prng ) API_VIS WARN_UNUSED; @@ -312,8 +301,8 @@ STROBE_CONTROL_WORD(STROBE_CW_PRNG, 0x18, STROBE_MODE_SQUEEZE, S STROBE_CONTROL_WORD(STROBE_CW_SESSION_HASH, 0x19, STROBE_MODE_SQUEEZE, 0); /* Reuse for PRNG */ -STROBE_CONTROL_WORD(STROBE_CW_PRNG_INITIAL_SEED, 0x10, STROBE_MODE_ABSORB, STROBE_FLAG_LENGTH_64); -STROBE_CONTROL_WORD(STROBE_CW_PRNG_RESEED, 0x11, STROBE_MODE_ABSORB, STROBE_FLAG_LENGTH_64); +STROBE_CONTROL_WORD(STROBE_CW_PRNG_INITIAL_SEED, 0x10, STROBE_MODE_ABSORB, STROBE_FLAG_NO_LENGTH); +STROBE_CONTROL_WORD(STROBE_CW_PRNG_RESEED, 0x11, STROBE_MODE_ABSORB, STROBE_FLAG_NO_LENGTH); STROBE_CONTROL_WORD(STROBE_CW_PRNG_CPU_SEED, 0x12, STROBE_MODE_ABSORB, 0); STROBE_CONTROL_WORD(STROBE_CW_PRNG_USER_SEED, 0x13, STROBE_MODE_ABSORB, STROBE_FLAG_LENGTH_64); STROBE_CONTROL_WORD(STROBE_CW_PRNG_PRNG, 0x14, STROBE_MODE_SQUEEZE, STROBE_FLAG_LENGTH_64 | STROBE_FLAG_FORGET); @@ -452,18 +441,33 @@ static INLINE UNUSED void strobe_nonce ( } /** - * @brief Set key in strobe context. + * @brief Set fixed key in strobe context. + * @param [inout] The initialized strobe object. + * @param [in] in The key. + * @param [in] len The length of the key. + */ +static INLINE UNUSED void +strobe_fixed_key ( + keccak_strobe_t strobe, + const unsigned char *in, + uint16_t len +) { + strobe_transact( strobe, NULL, in, len, STROBE_CW_FIXED_KEY ); +} + +/** + * @brief Set Diffie-Hellman key in strobe context. * @param [inout] The initialized strobe object. * @param [in] in The key. * @param [in] len The length of the key. */ static INLINE UNUSED void -strobe_key ( +strobe_dh_key ( keccak_strobe_t strobe, const unsigned char *in, uint16_t len ) { - strobe_transact( strobe, NULL, in, len, STROBE_CW_DH_KEY ); /* FIXME: what about other kinds of keys? */ + strobe_transact( strobe, NULL, in, len, STROBE_CW_DH_KEY ); } diff --git a/src/public_include/decaf/shake.hxx b/src/public_include/decaf/shake.hxx index b275103..87694af 100644 --- a/src/public_include/decaf/shake.hxx +++ b/src/public_include/decaf/shake.hxx @@ -15,6 +15,7 @@ #include #include #include +#include /** @cond internal */ #if __cplusplus >= 201103L @@ -167,9 +168,9 @@ public: inline SpongeRng( const std::string &in = "/dev/urandom", size_t len = 32, bool deterministic = false ) throw(RngException) : KeccakSponge((NOINIT())) { - int ret = spongerng_init_from_file(sp,in.c_str(),len,deterministic); - if (ret) { - throw RngException(ret, "Couldn't load from file"); + 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"); } } @@ -205,18 +206,30 @@ public: keyed = false; } - /* TODO: add a key type keyword */ - inline void key ( + inline void fixed_key ( const Block &data ) throw(ProtocolException) { - strobe_key(sp, data.data(), data.size()); + strobe_fixed_key(sp, data.data(), data.size()); keyed = true; } - template inline void key ( + template inline void fixed_key ( const Serializable &data ) throw(ProtocolException) { - key(data.serialize()); + fixed_key(data.serialize()); + } + + inline void dh_key ( + const Block &data + ) throw(ProtocolException) { + strobe_dh_key(sp, data.data(), data.size()); + keyed = true; + } + + template inline void dh_key ( + const Serializable &data + ) throw(ProtocolException) { + dh_key(data.serialize()); } inline void nonce(const Block &data) NOEXCEPT { diff --git a/src/shake.c b/src/shake.c index a5fa91c..f9d1a0f 100644 --- a/src/shake.c +++ b/src/shake.c @@ -21,7 +21,6 @@ #include #include #include -#include #include /* Subset of Mathias Panzenböck's portable endian code, public domain */ @@ -292,9 +291,7 @@ static void get_cpu_entropy(uint8_t *entropy, size_t len) { #endif } -static const uint16_t SPONGERNG_MAX_BLOCK_SIZE = 1<<12; /* TODO: standardize and freeze */ -static const uint16_t SPONGERNG_FILE_BLOCK_SIZE = 1<<12; /* TODO: standardize and freeze */ -static const char *SPONGERNG_NAME = "spongerng"; /* TODO: canonicalize name */ +static const char *SPONGERNG_NAME = "strobe::spongerng"; /* TODO: canonicalize name */ void spongerng_next ( keccak_sponge_t sponge, @@ -308,12 +305,7 @@ void spongerng_next ( strobe_transact(sponge,NULL,cpu_entropy,sizeof(cpu_entropy),STROBE_CW_PRNG_CPU_SEED); } - while (len) { - uint16_t cando = (len > SPONGERNG_MAX_BLOCK_SIZE) ? SPONGERNG_MAX_BLOCK_SIZE : len; - strobe_transact(sponge,out,NULL,cando,STROBE_CW_PRNG); - out += cando; - len -= cando; - } + strobe_transact(sponge,out,NULL,len,STROBE_CW_PRNG); } void spongerng_stir ( @@ -321,12 +313,7 @@ void spongerng_stir ( const uint8_t * __restrict__ in, size_t len ) { - while (len) { - uint16_t cando = (len > SPONGERNG_MAX_BLOCK_SIZE) ? SPONGERNG_MAX_BLOCK_SIZE : len; - strobe_transact(sponge,NULL,in,cando,STROBE_CW_PRNG_USER_SEED); - in += cando; - len -= cando; - } + strobe_transact(sponge,NULL,in,len,STROBE_CW_PRNG_USER_SEED); } static const struct kparams_s spongerng_params = { @@ -343,34 +330,37 @@ void spongerng_init_from_buffer ( spongerng_stir(sponge, in, len); } -int spongerng_init_from_file ( +decaf_error_t spongerng_init_from_file ( keccak_sponge_t sponge, const char *file, size_t len, int deterministic ) { strobe_init(sponge, &spongerng_params, SPONGERNG_NAME, !deterministic); - if (!len) return -2; + if (!len) return DECAF_FAILURE; int fd = open(file, O_RDONLY); - if (fd < 0) return errno ? errno : -1; + if (fd < 0) return DECAF_FAILURE; - uint8_t buffer[SPONGERNG_FILE_BLOCK_SIZE]; + uint8_t buffer[128]; + int first = 1; while (len) { ssize_t red = read(fd, buffer, (len > sizeof(buffer)) ? sizeof(buffer) : len); if (red <= 0) { close(fd); - return errno ? errno : -1; + return DECAF_FAILURE; } - spongerng_stir(sponge,buffer,red); + strobe_transact(sponge,NULL,buffer,red, + first ? STROBE_CW_PRNG_USER_SEED : (STROBE_CW_PRNG_USER_SEED | STROBE_FLAG_MORE)); len -= red; + first = 0; }; close(fd); - return 0; + return DECAF_SUCCESS; } -int spongerng_init_from_dev_urandom ( +decaf_error_t spongerng_init_from_dev_urandom ( keccak_sponge_t sponge ) { return spongerng_init_from_file(sponge, "/dev/urandom", 64, 0); @@ -547,7 +537,7 @@ void strobe_transact ( uint64_t my_len = len, len_cw = (cw_flags & STROBE_FLAG_LENGTH_64) ? 10 : 4; if (cw_flags & STROBE_FLAG_NO_LENGTH) { my_len = 0; - } else { + } else if ((cw_flags & STROBE_FLAG_LENGTH_64)==0) { assert(my_len < 1<<16); } @@ -586,6 +576,7 @@ void strobe_transact ( len -= len_cw; /* HACK */ if (cw_flags & STROBE_FLAG_NO_LENGTH) len = 2*STROBE_FORGET_BYTES; + assert(!(cw_flags & STROBE_FLAG_MORE)); strobe_duplex( sponge, NULL, NULL, len, @@ -615,7 +606,7 @@ void strobe_respec ( keccak_sponge_t sponge, const struct kparams_s *params ) { - uint8_t in[] = { params->rate, params->startRound }; /* TODO: nail down */ + 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 ); assert(sponge->params->position == 0); diff --git a/test/bench_decaf.cxx b/test/bench_decaf.cxx index a64d9f3..23fb625 100644 --- a/test/bench_decaf.cxx +++ b/test/bench_decaf.cxx @@ -171,23 +171,23 @@ static void tdh ( client.recv_plaintext(gye); Point pgxe(gxe); - server.key(pgxe*ye); + server.dh_key(pgxe*ye); SecureBuffer tag1 = server.produce_auth(); //SecureBuffer ct = server.encrypt(gy); - server.key(pgxe*y); + server.dh_key(pgxe*y); SecureBuffer tag2 = server.produce_auth(); Point pgye(gye); - client.key(pgye*xe); + client.dh_key(pgye*xe); client.verify_auth(tag1); - client.key(Point(gy) * xe); + client.dh_key(Point(gy) * xe); client.verify_auth(tag2); // ct = client.encrypt(gx); - client.key(pgye * x); + client.dh_key(pgye * x); tag1 = client.produce_auth(); client.respec(STROBE_KEYED_128); - server.key(Point(gx) * ye); + server.dh_key(Point(gx) * ye); server.verify_auth(tag1); server.respec(STROBE_KEYED_128); } @@ -217,14 +217,14 @@ static void fhmqv ( Scalar schx(server.prng(Scalar::SER_BYTES)); Scalar schy(server.prng(Scalar::SER_BYTES)); Scalar yec = y + ye*schy; - server.key(Point::double_scalarmul(Point(gx),yec,Point(gxe),yec*schx)); + server.dh_key(Point::double_scalarmul(Point(gx),yec,Point(gxe),yec*schx)); SecureBuffer as = server.produce_auth(); client.recv_plaintext(gye); Scalar cchx(client.prng(Scalar::SER_BYTES)); Scalar cchy(client.prng(Scalar::SER_BYTES)); Scalar xec = x + xe*schx; - client.key(Point::double_scalarmul(Point(gy),xec,Point(gye),xec*schy)); + client.dh_key(Point::double_scalarmul(Point(gy),xec,Point(gye),xec*schy)); client.verify_auth(as); SecureBuffer ac = client.produce_auth(); client.respec(STROBE_KEYED_128); @@ -264,19 +264,19 @@ static void spake2ee( server.send_plaintext(gy); client.recv_plaintext(gy); - server.key(h1); - server.key((Point(gx) - hc)*y); + server.dh_key(h1); + server.dh_key((Point(gx) - hc)*y); if(aug) { /* This step isn't actually online but whatever, it's fastish */ SecureBuffer serverAug((Precomputed::base() * gs).serialize()); - server.key(Point(serverAug)*y); + server.dh_key(Point(serverAug)*y); } SecureBuffer tag = server.produce_auth(); - client.key(h1); + client.dh_key(h1); Point pgy(gy); pgy -= hs; - client.key(pgy*x); - if (aug) client.key(pgy * gs); + client.dh_key(pgy*x); + if (aug) client.dh_key(pgy * gs); client.verify_auth(tag); tag = client.produce_auth(); client.respec(STROBE_KEYED_128); @@ -395,7 +395,7 @@ int main(int argc, char **argv) { for (Benchmark b("SHAKE128 1kiB", 30); b.iter(); ) { shake1 += Buffer(b1024,1024); } for (Benchmark b("SHAKE256 1kiB", 30); b.iter(); ) { shake2 += Buffer(b1024,1024); } for (Benchmark b("SHA3-512 1kiB", 30); b.iter(); ) { sha5 += Buffer(b1024,1024); } - strobe.key(Buffer(b1024,1024)); + strobe.dh_key(Buffer(b1024,1024)); strobe.respec(STROBE_128); for (Benchmark b("STROBE128 1kiB", 10); b.iter(); ) { strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024));