Browse Source

tear out STROBE. Probably will re-introduce later

master
Michael Hamburg 7 years ago
parent
commit
bb1eef3712
22 changed files with 231 additions and 3133 deletions
  1. +8
    -0
      HISTORY.txt
  2. +4
    -8
      Makefile
  3. +0
    -13
      README.md
  4. +0
    -231
      src/GENERATED/c/curve25519/crypto.c
  5. +0
    -24
      src/GENERATED/c/decaf/crypto.h
  6. +0
    -178
      src/GENERATED/c/decaf/crypto_255.h
  7. +0
    -216
      src/GENERATED/c/decaf/crypto_255.hxx
  8. +0
    -178
      src/GENERATED/c/decaf/crypto_448.h
  9. +0
    -216
      src/GENERATED/c/decaf/crypto_448.hxx
  10. +0
    -231
      src/GENERATED/c/ed448goldilocks/crypto.c
  11. +0
    -10
      src/include/decaf/crypto.tmpl.h
  12. +0
    -341
      src/include/decaf/strobe.h
  13. +0
    -239
      src/include/decaf/strobe.hxx
  14. +3
    -3
      src/include/keccak_internal.h
  15. +0
    -222
      src/per_curve/crypto.tmpl.c
  16. +0
    -163
      src/per_curve/crypto.tmpl.h
  17. +0
    -199
      src/per_curve/crypto.tmpl.hxx
  18. +4
    -4
      src/shake.c
  19. +164
    -0
      src/spongerng.c
  20. +0
    -412
      src/strobe.c
  21. +0
    -214
      test/bench_decaf.cxx
  22. +48
    -31
      test/test_decaf.cxx

+ 8
- 0
HISTORY.txt View File

@@ -1,3 +1,11 @@
April 22, 2017:
Remove STROBE in preparation for 1.0 release. STROBE has its own
repo now at https://strobe.sourceforge.io. I might re-integrate
it into Decaf once I have produced a version that matches the
STROBE v1 spec, but it's just confusing to keep v0.2 in here.
Change x{25519,448}_generate_key to _derive_public_key.

January 15, 2016:
Lots of changes since the last entry in HISTORY.TXT.


+ 4
- 8
Makefile View File

@@ -1,4 +1,4 @@
# Copyright (c) 2014 Cryptography Research, Inc.
# Copyright (c) 2014-2017 Cryptography Research, Inc.
# Released under the MIT License. See LICENSE.txt for license information.


@@ -77,9 +77,9 @@ GEN_CODE= $(GEN_CODE_1:%.tmpl.hxx=%.hxx)
HEADERS= Makefile $(shell find src test -name "*.h") $(BUILD_OBJ)/timestamp $(GEN_CODE)

# components needed by the lib
LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/strobe.o $(BUILD_OBJ)/sha512.o # and per-field components
LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/sha512.o $(BUILD_OBJ)/spongerng.o # and per-field components

BENCHCOMPONENTS = $(BUILD_OBJ)/bench.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/strobe.o
BENCHCOMPONENTS = $(BUILD_OBJ)/bench.o $(BUILD_OBJ)/shake.o

all: lib $(BUILD_IBIN)/test $(BUILD_IBIN)/bench $(BUILD_BIN)/shakesum

@@ -174,10 +174,9 @@ endef
define define_curve

LIBCOMPONENTS += $$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/$(1)/elligator.o $$(BUILD_OBJ)/$(1)/scalar.o \
$$(BUILD_OBJ)/$(1)/crypto.o $$(BUILD_OBJ)/$(1)/eddsa.o $$(BUILD_OBJ)/$(1)/decaf_tables.o
$$(BUILD_OBJ)/$(1)/eddsa.o $$(BUILD_OBJ)/$(1)/decaf_tables.o
PER_OBJ_DIRS += $$(BUILD_OBJ)/$(1)
GLOBAL_HEADERS_OF_$(1) = $(BUILD_INC)/decaf/point_$(3).h $(BUILD_INC)/decaf/point_$(3).hxx \
$(BUILD_C)/decaf/crypto_$(3).h $(BUILD_C)/decaf/crypto_$(3).hxx \
$(BUILD_INC)/decaf/ed$(3).h $(BUILD_INC)/decaf/ed$(3).hxx
HEADERS_OF_$(1) = $$(HEADERS_OF_$(2)) $$(GLOBAL_HEADERS_OF_$(1))
HEADERS += $$(GLOBAL_HEADERS_OF_$(1))
@@ -199,9 +198,6 @@ $$(BUILD_INC)/decaf/elligator_$(3).%: src/per_curve/elligator.tmpl.% src/generat
$$(BUILD_INC)/decaf/scalar_$(3).%: src/per_curve/scalar.tmpl.% src/generator/* Makefile
python -B src/generator/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$<
$$(BUILD_C)/decaf/crypto_$(3).%: src/per_curve/crypto.tmpl.% src/generator/* Makefile
python -B src/generator/template.py --per=curve --item=$(1) --guard=$$(@:$(BUILD_INC)/%=%) -o $$@ $$<

$$(BUILD_IBIN)/decaf_gen_tables_$(1): $$(BUILD_OBJ)/$(1)/decaf_gen_tables.o \
$$(BUILD_OBJ)/$(1)/decaf.o $$(BUILD_OBJ)/$(1)/scalar.o $$(BUILD_OBJ)/utils.o \


+ 0
- 13
README.md View File

@@ -60,19 +60,6 @@ The Decaf library doesn't implement much symmetric crypto, but it does
contain the hash functions required by the CFRG cryptosystems: SHA512,
SHA-3 and SHAKE.

The library also includes some work on an experimental protocol framework
called STROBE (based on Markku-Juhani Saarinen's BLINKER). This
framework is incomplete and will change in the future! There's also a
significant chance that it's insecure in its current form. Therefore,
all the STROBE interfaces have been marked as TOY for this version.
Please don't use them for anything serious.

The Decaf library contains a random number generator, SpongeRNG, which
uses STROBE internally. This is used in the test suite to generate
random tests. It's probably secure, but since STROBE is not final,
its internals will almost certainly change. I recommend using your own
RNG instead for now. For example, consider libottery.

## Internals

The "decaf" technique is described in https://eprint.iacr.org/2015/673


+ 0
- 231
src/GENERATED/c/curve25519/crypto.c View File

@@ -1,231 +0,0 @@
/**
* @file curve25519/crypto.c
* @author Mike Hamburg
*
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
* @cond internal
* @brief Example Decaf crypto routines
*
* @warning This file was automatically generated in Python.
* Please do not edit it.
*/
#include <decaf/crypto.h>
#include <string.h>

#define API_NAME "decaf_255"
#define API_NS(_id) decaf_255_##_id
#define API_NS_TOY(_id) decaf_255_TOY_##_id
#define SCALAR_BITS DECAF_255_SCALAR_BITS
#define SCALAR_BYTES ((SCALAR_BITS + 7)/8)
#define SER_BYTES DECAF_255_SER_BYTES

/* TODO: canonicalize and freeze the STROBE constants in this file
* (and STROBE itself for that matter)
*/
static const char *DERIVE_MAGIC = API_NAME"::derive_private_key";
static const char *SIGN_MAGIC = API_NAME"::sign";
static const char *SHARED_SECRET_MAGIC = API_NAME"::shared_secret";
static const uint16_t SHARED_SECRET_MAX_BLOCK_SIZE = 1<<12;
static const unsigned int SCALAR_OVERKILL_BYTES = SCALAR_BYTES + 8;

void API_NS_TOY(derive_private_key) (
API_NS_TOY(private_key_t) priv,
const API_NS_TOY(symmetric_key_t) proto
) {
uint8_t encoded_scalar[SCALAR_OVERKILL_BYTES];
API_NS(point_t) pub;
keccak_decaf_TOY_strobe_t strobe;
decaf_TOY_strobe_init(strobe, &STROBE_256, DERIVE_MAGIC, 0);
decaf_TOY_strobe_fixed_key(strobe, proto, sizeof(API_NS_TOY(symmetric_key_t)));
decaf_TOY_strobe_prng(strobe, encoded_scalar, sizeof(encoded_scalar));
decaf_TOY_strobe_destroy(strobe);
memcpy(priv->sym, proto, sizeof(API_NS_TOY(symmetric_key_t)));
API_NS(scalar_decode_long)(priv->secret_scalar, encoded_scalar, sizeof(encoded_scalar));
API_NS(precomputed_scalarmul)(pub, API_NS(precomputed_base), priv->secret_scalar);
API_NS(point_encode)(priv->pub, pub);
decaf_bzero(encoded_scalar, sizeof(encoded_scalar));
}

void API_NS_TOY(destroy_private_key) (
API_NS_TOY(private_key_t) priv
) {
decaf_bzero((void*)priv, sizeof(API_NS_TOY(private_key_t)));
}

void API_NS_TOY(private_to_public) (
API_NS_TOY(public_key_t) pub,
const API_NS_TOY(private_key_t) priv
) {
memcpy(pub, priv->pub, sizeof(API_NS_TOY(public_key_t)));
}

/* Performance vs consttime tuning.
* Specifying true here might give better DOS resistance in certain corner
* cases. Specifying false gives a tighter result in test_ct.
*/
#ifndef DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT
#define DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT DECAF_FALSE
#endif

decaf_error_t API_NS_TOY(shared_secret) (
uint8_t *shared,
size_t shared_bytes,
const API_NS_TOY(private_key_t) my_privkey,
const API_NS_TOY(public_key_t) your_pubkey,
int me_first
) {
keccak_decaf_TOY_strobe_t strobe;
decaf_TOY_strobe_init(strobe, &STROBE_256, SHARED_SECRET_MAGIC, 0);
uint8_t ss_ser[SER_BYTES];
if (me_first) {
decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t)));
decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t)));
} else {
decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t)));
decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t)));
}
decaf_error_t ret = API_NS(direct_scalarmul)(
ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE,
DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT
);
decaf_TOY_strobe_transact(strobe,NULL,ss_ser,sizeof(ss_ser),STROBE_CW_DH_KEY);
while (shared_bytes) {
uint16_t cando = (shared_bytes > SHARED_SECRET_MAX_BLOCK_SIZE)
? SHARED_SECRET_MAX_BLOCK_SIZE : shared_bytes;
decaf_TOY_strobe_prng(strobe,shared,cando);
shared_bytes -= cando;
shared += cando;
}

decaf_TOY_strobe_destroy(strobe);
decaf_bzero(ss_ser, sizeof(ss_ser));
return ret;
}

void API_NS_TOY(sign_strobe) (
keccak_decaf_TOY_strobe_t strobe,
API_NS_TOY(signature_t) sig,
const API_NS_TOY(private_key_t) priv
) {
uint8_t overkill[SCALAR_OVERKILL_BYTES];
API_NS(point_t) point;
API_NS(scalar_t) nonce, challenge;
/* Stir pubkey */
decaf_TOY_strobe_transact(strobe,NULL,priv->pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK);
/* Derive nonce */
keccak_decaf_TOY_strobe_t strobe2;
memcpy(strobe2,strobe,sizeof(strobe2));
decaf_TOY_strobe_fixed_key(strobe2,priv->sym,sizeof(API_NS_TOY(symmetric_key_t)));
decaf_TOY_strobe_prng(strobe2,overkill,sizeof(overkill));
decaf_TOY_strobe_destroy(strobe2);
API_NS(scalar_decode_long)(nonce, overkill, sizeof(overkill));
API_NS(precomputed_scalarmul)(point, API_NS(precomputed_base), nonce);
API_NS(point_encode)(sig, point);

/* Derive challenge */
decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH);
decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL);
API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill));
/* Respond */
API_NS(scalar_mul)(challenge, challenge, priv->secret_scalar);
API_NS(scalar_sub)(nonce, nonce, challenge);
/* Save results */
API_NS(scalar_encode)(overkill, nonce);
decaf_TOY_strobe_transact(strobe,&sig[SER_BYTES],overkill,SCALAR_BYTES,STROBE_CW_SIG_RESP);
/* Clean up */
API_NS(scalar_destroy)(nonce);
API_NS(scalar_destroy)(challenge);
decaf_bzero(overkill,sizeof(overkill));
}

decaf_error_t API_NS_TOY(verify_strobe) (
keccak_decaf_TOY_strobe_t strobe,
const API_NS_TOY(signature_t) sig,
const API_NS_TOY(public_key_t) pub
) {
decaf_bool_t ret;
uint8_t overkill[SCALAR_OVERKILL_BYTES];
API_NS(point_t) point, pubpoint;
API_NS(scalar_t) challenge, response;
/* Stir pubkey */
decaf_TOY_strobe_transact(strobe,NULL,pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK);
/* Derive nonce */
decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH);
ret = decaf_successful( API_NS(point_decode)(point, sig, DECAF_TRUE) );
/* Derive challenge */
decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL);
API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill));
/* Decode response */
decaf_TOY_strobe_transact(strobe,overkill,&sig[SER_BYTES],SCALAR_BYTES,STROBE_CW_SIG_RESP);
ret &= decaf_successful( API_NS(scalar_decode)(response, overkill) );
ret &= decaf_successful( API_NS(point_decode)(pubpoint, pub, DECAF_FALSE) );

API_NS(base_double_scalarmul_non_secret) (
pubpoint, response, pubpoint, challenge
);

ret &= API_NS(point_eq)(pubpoint, point);
/* Nothing here is secret, so don't do these things:
decaf_bzero(overkill,sizeof(overkill));
API_NS(point_destroy)(point);
API_NS(point_destroy)(pubpoint);
API_NS(scalar_destroy)(challenge);
API_NS(scalar_destroy)(response);
*/
return decaf_succeed_if(ret);
}

void
API_NS_TOY(sign) (
API_NS_TOY(signature_t) sig,
const API_NS_TOY(private_key_t) priv,
const unsigned char *message,
size_t message_len
) {
keccak_decaf_TOY_strobe_t ctx;
decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0);
decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT);
API_NS_TOY(sign_strobe)(ctx, sig, priv);
decaf_TOY_strobe_destroy(ctx);
}

decaf_error_t
API_NS_TOY(verify) (
const API_NS_TOY(signature_t) sig,
const API_NS_TOY(public_key_t) pub,
const unsigned char *message,
size_t message_len
) {
keccak_decaf_TOY_strobe_t ctx;
decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0);
decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT);
decaf_error_t ret = API_NS_TOY(verify_strobe)(ctx, sig, pub);
decaf_TOY_strobe_destroy(ctx);
return ret;
}

+ 0
- 24
src/GENERATED/c/decaf/crypto.h View File

@@ -1,24 +0,0 @@
/**
* @file decaf/crypto.h
* @author Mike Hamburg
*
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
* Example Decaf crypto routines, metaheader.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
*
* @warning This file was automatically generated in Python.
* Please do not edit it.
*/

#ifndef __DECAF_CRYPTO_H__
#define __DECAF_CRYPTO_H__ 1

#include <decaf/crypto_255.h>
#include <decaf/crypto_448.h>

#endif /* __DECAF_CRYPTO_H__ */

+ 0
- 178
src/GENERATED/c/decaf/crypto_255.h View File

@@ -1,178 +0,0 @@
/**
* @file src/GENERATED/c/decaf/crypto_255.h
* @author Mike Hamburg
*
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
* Example Decaf crypto routines.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
* @warning Experimental! The names, parameter orders etc are likely to change.
*
* @warning This file was automatically generated in Python.
* Please do not edit it.
*/

#ifndef __SRC_GENERATED_C_DECAF_CRYPTO_255_H__
#define __SRC_GENERATED_C_DECAF_CRYPTO_255_H__ 1

#include <decaf/point_255.h>
#include <decaf/strobe.h>

#ifdef __cplusplus
extern "C" {
#endif

/** Number of bytes for a symmetric key (expanded to full key) */
#define DECAF_255_SYMMETRIC_KEY_BYTES 32

/** A symmetric key, the compressed point of a private key. */
typedef unsigned char decaf_255_TOY_symmetric_key_t[DECAF_255_SYMMETRIC_KEY_BYTES];

/** An encoded public key. */
typedef unsigned char decaf_255_TOY_public_key_t[DECAF_255_SER_BYTES];

/** A signature. */
typedef unsigned char decaf_255_TOY_signature_t[DECAF_255_SER_BYTES + DECAF_255_SCALAR_BYTES];

typedef struct {
/** @cond internal */
/** The symmetric key from which everything is expanded */
decaf_255_TOY_symmetric_key_t sym;
/** The scalar x */
decaf_255_scalar_t secret_scalar;
/** x*Base */
decaf_255_TOY_public_key_t pub;
/** @endcond */
} /** Private key structure for pointers. */
decaf_255_TOY_private_key_s,
/** A private key (gmp array[1] style). */
decaf_255_TOY_private_key_t[1];
/**
* Derive a key from its compressed form.
* @param [out] priv The derived private key.
* @param [in] proto The compressed or proto-key, which must be 32 random bytes.
*/
void decaf_255_TOY_derive_private_key (
decaf_255_TOY_private_key_t priv,
const decaf_255_TOY_symmetric_key_t proto
) NONNULL API_VIS;

/**
* Destroy a private key.
*/
void decaf_255_TOY_destroy_private_key (
decaf_255_TOY_private_key_t priv
) NONNULL API_VIS;

/**
* Convert a private key to a public one.
* @param [out] pub The extracted private key.
* @param [in] priv The private key.
*/
void decaf_255_TOY_private_to_public (
decaf_255_TOY_public_key_t pub,
const decaf_255_TOY_private_key_t priv
) NONNULL API_VIS;
/**
* Compute a Diffie-Hellman shared secret.
*
* This is an example routine; real protocols would use something
* protocol-specific.
*
* @param [out] shared A buffer to store the shared secret.
* @param [in] shared_bytes The size of the buffer.
* @param [in] my_privkey My private key.
* @param [in] your_pubkey Your public key.
* @param [in] me_first Direction flag to break symmetry.
*
* @retval DECAF_SUCCESS Key exchange was successful.
* @retval DECAF_FAILURE Key exchange failed.
*/
decaf_error_t
decaf_255_TOY_shared_secret (
uint8_t *shared,
size_t shared_bytes,
const decaf_255_TOY_private_key_t my_privkey,
const decaf_255_TOY_public_key_t your_pubkey,
int me_first
) NONNULL WARN_UNUSED API_VIS;
/**
* Sign a message from a STROBE context.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
* @param [in] strobe A STROBE context with the message.
*/
void
decaf_255_TOY_sign_strobe (
keccak_decaf_TOY_strobe_t strobe,
decaf_255_TOY_signature_t sig,
const decaf_255_TOY_private_key_t priv
) NONNULL API_VIS;

/**
* Sign a message.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
* @param [in] message The message.
* @param [in] message_len The message's length.
*/
void
decaf_255_TOY_sign (
decaf_255_TOY_signature_t sig,
const decaf_255_TOY_private_key_t priv,
const unsigned char *message,
size_t message_len
) NONNULL API_VIS;

/**
* Verify a signed message from its STROBE context.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
* @param [in] strobe A STROBE context with the message.
*
* @return DECAF_SUCCESS The signature verified successfully.
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
decaf_255_TOY_verify_strobe (
keccak_decaf_TOY_strobe_t strobe,
const decaf_255_TOY_signature_t sig,
const decaf_255_TOY_public_key_t pub
) NONNULL API_VIS WARN_UNUSED;

/**
* Verify a signed message.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
* @param [in] message The message.
* @param [in] message_len The message's length.
*
* @return DECAF_SUCCESS The signature verified successfully.
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
decaf_255_TOY_verify (
const decaf_255_TOY_signature_t sig,
const decaf_255_TOY_public_key_t pub,
const unsigned char *message,
size_t message_len
) NONNULL API_VIS WARN_UNUSED;

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

#endif /* __SRC_GENERATED_C_DECAF_CRYPTO_255_H__ */

+ 0
- 216
src/GENERATED/c/decaf/crypto_255.hxx View File

@@ -1,216 +0,0 @@
/**
* @file src/GENERATED/c/decaf/crypto_255.hxx
* @author Mike Hamburg
*
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
*
*
* @warning This file was automatically generated in Python.
* Please do not edit it.
*/

#ifndef __SRC_GENERATED_C_DECAF_CRYPTO_255_HXX__
#define __SRC_GENERATED_C_DECAF_CRYPTO_255_HXX__ 1
/*
* Example Decaf cyrpto routines, C++ wrapper.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
* @warning Experimental! The names, parameter orders etc are likely to change.
*/

#include <decaf/point_255.hxx>
#include <decaf/shake.hxx>
#include <decaf/strobe.hxx>

/** @cond internal */
#if __cplusplus >= 201103L
#define NOEXCEPT noexcept
#else
#define NOEXCEPT throw()
#endif
/** @endcond */

namespace decaf { namespace TOY {

/** A public key for crypto over some Group */
template <typename Group> class PublicKey;

/** A private key for crypto over some Group */
template <typename Group> class PrivateKey;

/** A public key for crypto over Iso-Ed25519 */
template<> class PublicKey<IsoEd25519>
: public Serializable< PublicKey<IsoEd25519> > {
private:
/** @cond internal */
typedef decaf_255_TOY_public_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PrivateKey;
/** @endcond */
public:
/** Underlying group */
typedef IsoEd25519 Group;
/** Signature size. */
static const size_t SIG_BYTES = sizeof(decaf_255_TOY_signature_t);
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
/** Read a private key from a string*/
inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT {
memcpy(wrapped,b.data(),sizeof(wrapped));
}
/** Read a private key from a string*/
inline explicit PublicKey(const PrivateKey<IsoEd25519> &b) NOEXCEPT;
/** Create but don't initialize */
inline explicit PublicKey(const NOINIT&) NOEXCEPT { }
/** Serialize into a buffer. */
inline void serialize_into(unsigned char *x) const NOEXCEPT {
memcpy(x,wrapped,sizeof(wrapped));
}
/** Serialization size. */
inline size_t ser_size() const NOEXCEPT { return SER_BYTES; }
/** Verify a message */
inline void verify(
const Block &message,
const FixedBlock<SIG_BYTES> &sig
) const throw(CryptoException) {
if (DECAF_SUCCESS != decaf_255_TOY_verify(sig.data(),wrapped,message.data(),message.size())) {
throw(CryptoException());
}
}
/** Verify a message */
inline void verify(
Strobe &context,
const FixedBlock<SIG_BYTES> &sig
) const throw(CryptoException) {
if (DECAF_SUCCESS != decaf_255_TOY_verify_strobe(context.wrapped,sig.data(),wrapped)) {
throw(CryptoException());
}
}
};

/** A private key for crypto over Iso-Ed25519 */
template<> class PrivateKey<IsoEd25519>
: public Serializable< PrivateKey<IsoEd25519> > {
private:
/** @cond internal */
typedef decaf_255_TOY_private_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PublicKey;
/** @endcond */
public:
/** Underlying group */
typedef IsoEd25519 Group;
/** Signature size. */
static const size_t SIG_BYTES = sizeof(decaf_255_TOY_signature_t);
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
/** Compressed size. */
static const size_t SYM_BYTES = DECAF_255_SYMMETRIC_KEY_BYTES;
/** Create but don't initialize */
inline explicit PrivateKey(const NOINIT&) NOEXCEPT { }
/** Read a private key from a string*/
inline explicit PrivateKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT {
memcpy(wrapped,b.data(),sizeof(wrapped));
}
/** Read a private key from a string*/
inline explicit PrivateKey(const FixedBlock<SYM_BYTES> &b) NOEXCEPT {
decaf_255_TOY_derive_private_key(wrapped, b.data());
}
/** Create at random */
inline explicit PrivateKey(Rng &r) NOEXCEPT {
FixedArrayBuffer<SYM_BYTES> tmp(r);
decaf_255_TOY_derive_private_key(wrapped, tmp.data());
}
/** Secure destructor */
inline ~PrivateKey() NOEXCEPT {
decaf_255_TOY_destroy_private_key(wrapped);
}
/** Serialization size. */
inline size_t ser_size() const NOEXCEPT { return SER_BYTES; }
/** Serialize into a buffer. */
inline void serialize_into(unsigned char *x) const NOEXCEPT {
memcpy(x,wrapped,sizeof(wrapped));
}
/** Compressed serialize. */
inline SecureBuffer compress() const throw(std::bad_alloc) {
SecureBuffer ret(sizeof(wrapped->sym));
memcpy(ret.data(),wrapped->sym,sizeof(wrapped->sym));
return ret;
}
/** Get the public key */
inline PublicKey<IsoEd25519> pub() const NOEXCEPT {
PublicKey<IsoEd25519> ret(*this); return ret;
}
/** Derive a shared secret */
inline SecureBuffer shared_secret(
const PublicKey<IsoEd25519> &pub,
size_t bytes,
bool me_first
) const throw(CryptoException,std::bad_alloc) {
SecureBuffer ret(bytes);
if (DECAF_SUCCESS != decaf_255_TOY_shared_secret(ret.data(),bytes,wrapped,pub.wrapped,me_first)) {
throw(CryptoException());
}
return ret;
}
/** Derive a shared secret */
inline decaf_error_t __attribute__((warn_unused_result))
shared_secret_noexcept(
Buffer ret,
const PublicKey<IsoEd25519> &pub,
bool me_first
) const NOEXCEPT {
return decaf_255_TOY_shared_secret(ret.data(),ret.size(),wrapped,pub.wrapped,me_first);
}

/** Sign a message. */
inline SecureBuffer sign(const Block &message) const {
SecureBuffer sig(SIG_BYTES);
decaf_255_TOY_sign(sig.data(), wrapped, message.data(), message.size());
return sig;
}

/** Sign a message. */
inline SecureBuffer verify(Strobe &context) const {
SecureBuffer sig(SIG_BYTES);
decaf_255_TOY_sign_strobe(context.wrapped, sig.data(), wrapped);
return sig;
}
};

/** @cond internal */
PublicKey<IsoEd25519>::PublicKey(const PrivateKey<IsoEd25519> &b) NOEXCEPT {
decaf_255_TOY_private_to_public(wrapped,b.wrapped);
}
/** @endcond */

#undef NOEXCEPT
}} /* namespace decaf::TOY */
#endif /* __SRC_GENERATED_C_DECAF_CRYPTO_255_HXX__ */

+ 0
- 178
src/GENERATED/c/decaf/crypto_448.h View File

@@ -1,178 +0,0 @@
/**
* @file src/GENERATED/c/decaf/crypto_448.h
* @author Mike Hamburg
*
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
* Example Decaf crypto routines.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
* @warning Experimental! The names, parameter orders etc are likely to change.
*
* @warning This file was automatically generated in Python.
* Please do not edit it.
*/

#ifndef __SRC_GENERATED_C_DECAF_CRYPTO_448_H__
#define __SRC_GENERATED_C_DECAF_CRYPTO_448_H__ 1

#include <decaf/point_448.h>
#include <decaf/strobe.h>

#ifdef __cplusplus
extern "C" {
#endif

/** Number of bytes for a symmetric key (expanded to full key) */
#define DECAF_448_SYMMETRIC_KEY_BYTES 32

/** A symmetric key, the compressed point of a private key. */
typedef unsigned char decaf_448_TOY_symmetric_key_t[DECAF_448_SYMMETRIC_KEY_BYTES];

/** An encoded public key. */
typedef unsigned char decaf_448_TOY_public_key_t[DECAF_448_SER_BYTES];

/** A signature. */
typedef unsigned char decaf_448_TOY_signature_t[DECAF_448_SER_BYTES + DECAF_448_SCALAR_BYTES];

typedef struct {
/** @cond internal */
/** The symmetric key from which everything is expanded */
decaf_448_TOY_symmetric_key_t sym;
/** The scalar x */
decaf_448_scalar_t secret_scalar;
/** x*Base */
decaf_448_TOY_public_key_t pub;
/** @endcond */
} /** Private key structure for pointers. */
decaf_448_TOY_private_key_s,
/** A private key (gmp array[1] style). */
decaf_448_TOY_private_key_t[1];
/**
* Derive a key from its compressed form.
* @param [out] priv The derived private key.
* @param [in] proto The compressed or proto-key, which must be 32 random bytes.
*/
void decaf_448_TOY_derive_private_key (
decaf_448_TOY_private_key_t priv,
const decaf_448_TOY_symmetric_key_t proto
) NONNULL API_VIS;

/**
* Destroy a private key.
*/
void decaf_448_TOY_destroy_private_key (
decaf_448_TOY_private_key_t priv
) NONNULL API_VIS;

/**
* Convert a private key to a public one.
* @param [out] pub The extracted private key.
* @param [in] priv The private key.
*/
void decaf_448_TOY_private_to_public (
decaf_448_TOY_public_key_t pub,
const decaf_448_TOY_private_key_t priv
) NONNULL API_VIS;
/**
* Compute a Diffie-Hellman shared secret.
*
* This is an example routine; real protocols would use something
* protocol-specific.
*
* @param [out] shared A buffer to store the shared secret.
* @param [in] shared_bytes The size of the buffer.
* @param [in] my_privkey My private key.
* @param [in] your_pubkey Your public key.
* @param [in] me_first Direction flag to break symmetry.
*
* @retval DECAF_SUCCESS Key exchange was successful.
* @retval DECAF_FAILURE Key exchange failed.
*/
decaf_error_t
decaf_448_TOY_shared_secret (
uint8_t *shared,
size_t shared_bytes,
const decaf_448_TOY_private_key_t my_privkey,
const decaf_448_TOY_public_key_t your_pubkey,
int me_first
) NONNULL WARN_UNUSED API_VIS;
/**
* Sign a message from a STROBE context.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
* @param [in] strobe A STROBE context with the message.
*/
void
decaf_448_TOY_sign_strobe (
keccak_decaf_TOY_strobe_t strobe,
decaf_448_TOY_signature_t sig,
const decaf_448_TOY_private_key_t priv
) NONNULL API_VIS;

/**
* Sign a message.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
* @param [in] message The message.
* @param [in] message_len The message's length.
*/
void
decaf_448_TOY_sign (
decaf_448_TOY_signature_t sig,
const decaf_448_TOY_private_key_t priv,
const unsigned char *message,
size_t message_len
) NONNULL API_VIS;

/**
* Verify a signed message from its STROBE context.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
* @param [in] strobe A STROBE context with the message.
*
* @return DECAF_SUCCESS The signature verified successfully.
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
decaf_448_TOY_verify_strobe (
keccak_decaf_TOY_strobe_t strobe,
const decaf_448_TOY_signature_t sig,
const decaf_448_TOY_public_key_t pub
) NONNULL API_VIS WARN_UNUSED;

/**
* Verify a signed message.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
* @param [in] message The message.
* @param [in] message_len The message's length.
*
* @return DECAF_SUCCESS The signature verified successfully.
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
decaf_448_TOY_verify (
const decaf_448_TOY_signature_t sig,
const decaf_448_TOY_public_key_t pub,
const unsigned char *message,
size_t message_len
) NONNULL API_VIS WARN_UNUSED;

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

#endif /* __SRC_GENERATED_C_DECAF_CRYPTO_448_H__ */

+ 0
- 216
src/GENERATED/c/decaf/crypto_448.hxx View File

@@ -1,216 +0,0 @@
/**
* @file src/GENERATED/c/decaf/crypto_448.hxx
* @author Mike Hamburg
*
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
*
*
* @warning This file was automatically generated in Python.
* Please do not edit it.
*/

#ifndef __SRC_GENERATED_C_DECAF_CRYPTO_448_HXX__
#define __SRC_GENERATED_C_DECAF_CRYPTO_448_HXX__ 1
/*
* Example Decaf cyrpto routines, C++ wrapper.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
* @warning Experimental! The names, parameter orders etc are likely to change.
*/

#include <decaf/point_448.hxx>
#include <decaf/shake.hxx>
#include <decaf/strobe.hxx>

/** @cond internal */
#if __cplusplus >= 201103L
#define NOEXCEPT noexcept
#else
#define NOEXCEPT throw()
#endif
/** @endcond */

namespace decaf { namespace TOY {

/** A public key for crypto over some Group */
template <typename Group> class PublicKey;

/** A private key for crypto over some Group */
template <typename Group> class PrivateKey;

/** A public key for crypto over Ed448-Goldilocks */
template<> class PublicKey<Ed448Goldilocks>
: public Serializable< PublicKey<Ed448Goldilocks> > {
private:
/** @cond internal */
typedef decaf_448_TOY_public_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PrivateKey;
/** @endcond */
public:
/** Underlying group */
typedef Ed448Goldilocks Group;
/** Signature size. */
static const size_t SIG_BYTES = sizeof(decaf_448_TOY_signature_t);
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
/** Read a private key from a string*/
inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT {
memcpy(wrapped,b.data(),sizeof(wrapped));
}
/** Read a private key from a string*/
inline explicit PublicKey(const PrivateKey<Ed448Goldilocks> &b) NOEXCEPT;
/** Create but don't initialize */
inline explicit PublicKey(const NOINIT&) NOEXCEPT { }
/** Serialize into a buffer. */
inline void serialize_into(unsigned char *x) const NOEXCEPT {
memcpy(x,wrapped,sizeof(wrapped));
}
/** Serialization size. */
inline size_t ser_size() const NOEXCEPT { return SER_BYTES; }
/** Verify a message */
inline void verify(
const Block &message,
const FixedBlock<SIG_BYTES> &sig
) const throw(CryptoException) {
if (DECAF_SUCCESS != decaf_448_TOY_verify(sig.data(),wrapped,message.data(),message.size())) {
throw(CryptoException());
}
}
/** Verify a message */
inline void verify(
Strobe &context,
const FixedBlock<SIG_BYTES> &sig
) const throw(CryptoException) {
if (DECAF_SUCCESS != decaf_448_TOY_verify_strobe(context.wrapped,sig.data(),wrapped)) {
throw(CryptoException());
}
}
};

/** A private key for crypto over Ed448-Goldilocks */
template<> class PrivateKey<Ed448Goldilocks>
: public Serializable< PrivateKey<Ed448Goldilocks> > {
private:
/** @cond internal */
typedef decaf_448_TOY_private_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PublicKey;
/** @endcond */
public:
/** Underlying group */
typedef Ed448Goldilocks Group;
/** Signature size. */
static const size_t SIG_BYTES = sizeof(decaf_448_TOY_signature_t);
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
/** Compressed size. */
static const size_t SYM_BYTES = DECAF_448_SYMMETRIC_KEY_BYTES;
/** Create but don't initialize */
inline explicit PrivateKey(const NOINIT&) NOEXCEPT { }
/** Read a private key from a string*/
inline explicit PrivateKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT {
memcpy(wrapped,b.data(),sizeof(wrapped));
}
/** Read a private key from a string*/
inline explicit PrivateKey(const FixedBlock<SYM_BYTES> &b) NOEXCEPT {
decaf_448_TOY_derive_private_key(wrapped, b.data());
}
/** Create at random */
inline explicit PrivateKey(Rng &r) NOEXCEPT {
FixedArrayBuffer<SYM_BYTES> tmp(r);
decaf_448_TOY_derive_private_key(wrapped, tmp.data());
}
/** Secure destructor */
inline ~PrivateKey() NOEXCEPT {
decaf_448_TOY_destroy_private_key(wrapped);
}
/** Serialization size. */
inline size_t ser_size() const NOEXCEPT { return SER_BYTES; }
/** Serialize into a buffer. */
inline void serialize_into(unsigned char *x) const NOEXCEPT {
memcpy(x,wrapped,sizeof(wrapped));
}
/** Compressed serialize. */
inline SecureBuffer compress() const throw(std::bad_alloc) {
SecureBuffer ret(sizeof(wrapped->sym));
memcpy(ret.data(),wrapped->sym,sizeof(wrapped->sym));
return ret;
}
/** Get the public key */
inline PublicKey<Ed448Goldilocks> pub() const NOEXCEPT {
PublicKey<Ed448Goldilocks> ret(*this); return ret;
}
/** Derive a shared secret */
inline SecureBuffer shared_secret(
const PublicKey<Ed448Goldilocks> &pub,
size_t bytes,
bool me_first
) const throw(CryptoException,std::bad_alloc) {
SecureBuffer ret(bytes);
if (DECAF_SUCCESS != decaf_448_TOY_shared_secret(ret.data(),bytes,wrapped,pub.wrapped,me_first)) {
throw(CryptoException());
}
return ret;
}
/** Derive a shared secret */
inline decaf_error_t __attribute__((warn_unused_result))
shared_secret_noexcept(
Buffer ret,
const PublicKey<Ed448Goldilocks> &pub,
bool me_first
) const NOEXCEPT {
return decaf_448_TOY_shared_secret(ret.data(),ret.size(),wrapped,pub.wrapped,me_first);
}

/** Sign a message. */
inline SecureBuffer sign(const Block &message) const {
SecureBuffer sig(SIG_BYTES);
decaf_448_TOY_sign(sig.data(), wrapped, message.data(), message.size());
return sig;
}

/** Sign a message. */
inline SecureBuffer verify(Strobe &context) const {
SecureBuffer sig(SIG_BYTES);
decaf_448_TOY_sign_strobe(context.wrapped, sig.data(), wrapped);
return sig;
}
};

/** @cond internal */
PublicKey<Ed448Goldilocks>::PublicKey(const PrivateKey<Ed448Goldilocks> &b) NOEXCEPT {
decaf_448_TOY_private_to_public(wrapped,b.wrapped);
}
/** @endcond */

#undef NOEXCEPT
}} /* namespace decaf::TOY */
#endif /* __SRC_GENERATED_C_DECAF_CRYPTO_448_HXX__ */

+ 0
- 231
src/GENERATED/c/ed448goldilocks/crypto.c View File

@@ -1,231 +0,0 @@
/**
* @file ed448goldilocks/crypto.c
* @author Mike Hamburg
*
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
*
* @cond internal
* @brief Example Decaf crypto routines
*
* @warning This file was automatically generated in Python.
* Please do not edit it.
*/
#include <decaf/crypto.h>
#include <string.h>

#define API_NAME "decaf_448"
#define API_NS(_id) decaf_448_##_id
#define API_NS_TOY(_id) decaf_448_TOY_##_id
#define SCALAR_BITS DECAF_448_SCALAR_BITS
#define SCALAR_BYTES ((SCALAR_BITS + 7)/8)
#define SER_BYTES DECAF_448_SER_BYTES

/* TODO: canonicalize and freeze the STROBE constants in this file
* (and STROBE itself for that matter)
*/
static const char *DERIVE_MAGIC = API_NAME"::derive_private_key";
static const char *SIGN_MAGIC = API_NAME"::sign";
static const char *SHARED_SECRET_MAGIC = API_NAME"::shared_secret";
static const uint16_t SHARED_SECRET_MAX_BLOCK_SIZE = 1<<12;
static const unsigned int SCALAR_OVERKILL_BYTES = SCALAR_BYTES + 8;

void API_NS_TOY(derive_private_key) (
API_NS_TOY(private_key_t) priv,
const API_NS_TOY(symmetric_key_t) proto
) {
uint8_t encoded_scalar[SCALAR_OVERKILL_BYTES];
API_NS(point_t) pub;
keccak_decaf_TOY_strobe_t strobe;
decaf_TOY_strobe_init(strobe, &STROBE_256, DERIVE_MAGIC, 0);
decaf_TOY_strobe_fixed_key(strobe, proto, sizeof(API_NS_TOY(symmetric_key_t)));
decaf_TOY_strobe_prng(strobe, encoded_scalar, sizeof(encoded_scalar));
decaf_TOY_strobe_destroy(strobe);
memcpy(priv->sym, proto, sizeof(API_NS_TOY(symmetric_key_t)));
API_NS(scalar_decode_long)(priv->secret_scalar, encoded_scalar, sizeof(encoded_scalar));
API_NS(precomputed_scalarmul)(pub, API_NS(precomputed_base), priv->secret_scalar);
API_NS(point_encode)(priv->pub, pub);
decaf_bzero(encoded_scalar, sizeof(encoded_scalar));
}

void API_NS_TOY(destroy_private_key) (
API_NS_TOY(private_key_t) priv
) {
decaf_bzero((void*)priv, sizeof(API_NS_TOY(private_key_t)));
}

void API_NS_TOY(private_to_public) (
API_NS_TOY(public_key_t) pub,
const API_NS_TOY(private_key_t) priv
) {
memcpy(pub, priv->pub, sizeof(API_NS_TOY(public_key_t)));
}

/* Performance vs consttime tuning.
* Specifying true here might give better DOS resistance in certain corner
* cases. Specifying false gives a tighter result in test_ct.
*/
#ifndef DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT
#define DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT DECAF_FALSE
#endif

decaf_error_t API_NS_TOY(shared_secret) (
uint8_t *shared,
size_t shared_bytes,
const API_NS_TOY(private_key_t) my_privkey,
const API_NS_TOY(public_key_t) your_pubkey,
int me_first
) {
keccak_decaf_TOY_strobe_t strobe;
decaf_TOY_strobe_init(strobe, &STROBE_256, SHARED_SECRET_MAGIC, 0);
uint8_t ss_ser[SER_BYTES];
if (me_first) {
decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t)));
decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t)));
} else {
decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t)));
decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t)));
}
decaf_error_t ret = API_NS(direct_scalarmul)(
ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE,
DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT
);
decaf_TOY_strobe_transact(strobe,NULL,ss_ser,sizeof(ss_ser),STROBE_CW_DH_KEY);
while (shared_bytes) {
uint16_t cando = (shared_bytes > SHARED_SECRET_MAX_BLOCK_SIZE)
? SHARED_SECRET_MAX_BLOCK_SIZE : shared_bytes;
decaf_TOY_strobe_prng(strobe,shared,cando);
shared_bytes -= cando;
shared += cando;
}

decaf_TOY_strobe_destroy(strobe);
decaf_bzero(ss_ser, sizeof(ss_ser));
return ret;
}

void API_NS_TOY(sign_strobe) (
keccak_decaf_TOY_strobe_t strobe,
API_NS_TOY(signature_t) sig,
const API_NS_TOY(private_key_t) priv
) {
uint8_t overkill[SCALAR_OVERKILL_BYTES];
API_NS(point_t) point;
API_NS(scalar_t) nonce, challenge;
/* Stir pubkey */
decaf_TOY_strobe_transact(strobe,NULL,priv->pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK);
/* Derive nonce */
keccak_decaf_TOY_strobe_t strobe2;
memcpy(strobe2,strobe,sizeof(strobe2));
decaf_TOY_strobe_fixed_key(strobe2,priv->sym,sizeof(API_NS_TOY(symmetric_key_t)));
decaf_TOY_strobe_prng(strobe2,overkill,sizeof(overkill));
decaf_TOY_strobe_destroy(strobe2);
API_NS(scalar_decode_long)(nonce, overkill, sizeof(overkill));
API_NS(precomputed_scalarmul)(point, API_NS(precomputed_base), nonce);
API_NS(point_encode)(sig, point);

/* Derive challenge */
decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH);
decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL);
API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill));
/* Respond */
API_NS(scalar_mul)(challenge, challenge, priv->secret_scalar);
API_NS(scalar_sub)(nonce, nonce, challenge);
/* Save results */
API_NS(scalar_encode)(overkill, nonce);
decaf_TOY_strobe_transact(strobe,&sig[SER_BYTES],overkill,SCALAR_BYTES,STROBE_CW_SIG_RESP);
/* Clean up */
API_NS(scalar_destroy)(nonce);
API_NS(scalar_destroy)(challenge);
decaf_bzero(overkill,sizeof(overkill));
}

decaf_error_t API_NS_TOY(verify_strobe) (
keccak_decaf_TOY_strobe_t strobe,
const API_NS_TOY(signature_t) sig,
const API_NS_TOY(public_key_t) pub
) {
decaf_bool_t ret;
uint8_t overkill[SCALAR_OVERKILL_BYTES];
API_NS(point_t) point, pubpoint;
API_NS(scalar_t) challenge, response;
/* Stir pubkey */
decaf_TOY_strobe_transact(strobe,NULL,pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK);
/* Derive nonce */
decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH);
ret = decaf_successful( API_NS(point_decode)(point, sig, DECAF_TRUE) );
/* Derive challenge */
decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL);
API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill));
/* Decode response */
decaf_TOY_strobe_transact(strobe,overkill,&sig[SER_BYTES],SCALAR_BYTES,STROBE_CW_SIG_RESP);
ret &= decaf_successful( API_NS(scalar_decode)(response, overkill) );
ret &= decaf_successful( API_NS(point_decode)(pubpoint, pub, DECAF_FALSE) );

API_NS(base_double_scalarmul_non_secret) (
pubpoint, response, pubpoint, challenge
);

ret &= API_NS(point_eq)(pubpoint, point);
/* Nothing here is secret, so don't do these things:
decaf_bzero(overkill,sizeof(overkill));
API_NS(point_destroy)(point);
API_NS(point_destroy)(pubpoint);
API_NS(scalar_destroy)(challenge);
API_NS(scalar_destroy)(response);
*/
return decaf_succeed_if(ret);
}

void
API_NS_TOY(sign) (
API_NS_TOY(signature_t) sig,
const API_NS_TOY(private_key_t) priv,
const unsigned char *message,
size_t message_len
) {
keccak_decaf_TOY_strobe_t ctx;
decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0);
decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT);
API_NS_TOY(sign_strobe)(ctx, sig, priv);
decaf_TOY_strobe_destroy(ctx);
}

decaf_error_t
API_NS_TOY(verify) (
const API_NS_TOY(signature_t) sig,
const API_NS_TOY(public_key_t) pub,
const unsigned char *message,
size_t message_len
) {
keccak_decaf_TOY_strobe_t ctx;
decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0);
decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT);
decaf_error_t ret = API_NS_TOY(verify_strobe)(ctx, sig, pub);
decaf_TOY_strobe_destroy(ctx);
return ret;
}

+ 0
- 10
src/include/decaf/crypto.tmpl.h View File

@@ -1,10 +0,0 @@
/**
* Example Decaf crypto routines, metaheader.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
*/

$("\n".join([
"#include <decaf/crypto_%s.h>" % g for g in sorted([c["bits"] for _,c in curve.iteritems()])
]))

+ 0
- 341
src/include/decaf/strobe.h View File

@@ -1,341 +0,0 @@
/**
* @file decaf/strobe.h
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @brief STROBE experimental protocol framework.
* @warning EXPERIMENTAL! The names, parameter orders etc are likely to change.
*/

#ifndef __DECAF_STROBE_H__
#define __DECAF_STROBE_H__

#include <decaf/shake.h>

#ifdef __cplusplus
extern "C" {
#endif
/** Keccak STROBE structure as struct. */
typedef struct {
decaf_keccak_sponge_t sponge; /**< Internal sponge object. */
} keccak_decaf_TOY_strobe_s;
/** Keccak STROBE structure as one-element array */
typedef keccak_decaf_TOY_strobe_s keccak_decaf_TOY_strobe_t[1];

/** STROBE parameters, 128-bit estimated security for hashing and encryption */
extern const struct decaf_kparams_s STROBE_128 API_VIS;

/** STROBE parameters, 256-bit estimated security for hashing and encryption */
extern const struct decaf_kparams_s STROBE_256 API_VIS;

/** STROBE parameters, 128-bit estimated security for encryption only (not hashing) */
extern const struct decaf_kparams_s STROBE_KEYED_128 API_VIS;

/** STROBE parameters, 256-bit estimated security for encryption only (not hashing) */
extern const struct decaf_kparams_s STROBE_KEYED_256 API_VIS;


/** Initialize Strobe protocol context. */
void decaf_TOY_strobe_init (
keccak_decaf_TOY_strobe_t strobe, /**< [out] The uninitialized strobe object. */
const struct decaf_kparams_s *params, /**< [in] Parameter set descriptor. */
const char *proto, /**< [in] Unique identifier for the protocol. TODO: define namespaces for this */
uint8_t am_client /**< [in] Nonzero if this party. */
) NONNULL API_VIS;

/** Run a transaction against a STROBE state. */
void decaf_TOY_strobe_transact (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized STROBE object. */
unsigned char *out, /**< [out] The output. */
const unsigned char *in, /**< [in] The input. */
size_t len, /**< [in] The length of the input/output. */
uint32_t cw_flags /**< [in] The control word with flags. */
) __attribute__((nonnull(1))) API_VIS;

/** Record a message sent in plaintext */
static INLINE UNUSED NONNULL void decaf_TOY_strobe_plaintext (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The STROBE object */
const unsigned char *in, /**< [in] The message. */
uint16_t len, /**< [in] The length of the message. */
uint8_t iSent /**< [in] If nonzero, I sent the message. */
);

/** Report authenticated data in strobe context. */
static INLINE UNUSED NONNULL void
decaf_TOY_strobe_ad (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The strobe object. */
const unsigned char *in, /**< [in] The plaintext. */
size_t len /**< [in] The length of the ad. */
);

/** Set nonce in strobe context. */
static INLINE UNUSED NONNULL void
decaf_TOY_strobe_nonce (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized strobe object. */
const unsigned char *in, /**< [in] The nonce. */
uint16_t len /**< [in] The length of the nonce. */
);

/** Set fixed key in strobe context. */
static INLINE UNUSED NONNULL void
decaf_TOY_strobe_fixed_key (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized strobe object. */
const unsigned char *in, /**< [in] The key. */
uint16_t len /**< [in] The length of the key. */
);

/** Set Diffie-Hellman key in strobe context. */
static INLINE UNUSED NONNULL void
decaf_TOY_strobe_dh_key (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized strobe object. */
const unsigned char *in, /**< [in] The key. */
uint16_t len /**< [in] The length of the key. */
);

/** The maximum number of bytes that decaf_TOY_strobe_produce_auth can spit out. */
#define STROBE_MAX_AUTH_BYTES 32
/** Produce an authenticator. */
static INLINE UNUSED NONNULL void
decaf_TOY_strobe_produce_auth (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The Strobe protocol context. */
unsigned char *out, /**< [out] The authenticator. */
uint16_t len /**< [in] The length, at most STROBE_MAX_AUTH_BYTES. */
);

/**
* @brief Verify an authenticator.
* @retval DECAF_SUCCESS The operation applied successfully.
* @retval DECAF_FAILURE The operation failed because of a
* bad validator (or because you aren't keyed)
*/
decaf_error_t decaf_TOY_strobe_verify_auth (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The Strobe protocol context */
const unsigned char *in, /**< [in] The authenticator */
uint16_t len /**< [in] The length, at most STROBE_MAX_AUTH_BYTES. */
) WARN_UNUSED NONNULL API_VIS;

/**
* @brief Encrypt bytes from in to out.
* @warning Doesn't produce an auth tag.
*/
static INLINE UNUSED NONNULL void
decaf_TOY_strobe_encrypt (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] strobe The Strobe protocol context. */
unsigned char *out, /**< [out] The ciphertext. */
const unsigned char *in, /**< [in] The plaintext. */
uint16_t len /**< [in] The length of plaintext and ciphertext. */
);

/**
* Decrypt bytes from in to out.
* @warning Doesn't check an auth tag.
*/
static INLINE UNUSED NONNULL void
decaf_TOY_strobe_decrypt (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The Strobe protocol context. */
unsigned char *out, /**< [out] The plaintext. */
const unsigned char *in, /**< [in] The ciphertext. */
uint16_t len /**< [in] The length of plaintext and ciphertext. */
);

/**
* @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.
*/
static inline void NONNULL decaf_TOY_strobe_prng (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The Strobe protocol context */
unsigned char *out, /**< [out] The output random data. */
uint16_t len /**< The length. */
);

/** Respecify Strobe protocol object's crypto. */
void decaf_TOY_strobe_respec (
keccak_decaf_TOY_strobe_t strobe, /**< [inout] The initialized strobe context. */
const struct decaf_kparams_s *params /**< [in] Strobe parameter descriptor. */
) NONNULL API_VIS;

/** Securely destroy a STROBE object by overwriting it. */
static INLINE UNUSED NONNULL void
decaf_TOY_strobe_destroy (
keccak_decaf_TOY_strobe_t doomed /**< [in] The object to destroy. */
);

/** @cond internal */

/************************************************************************/
/* Declarations of various constants and operating modes, for extension */
/************************************************************************/

/** STROBE modes of operation */
typedef enum {
STROBE_MODE_ABSORB = 0,
STROBE_MODE_DUPLEX = 1,
STROBE_MODE_ABSORB_R = 2,
STROBE_MODE_DUPLEX_R = 3,
/* FIXME: no bits allocated in .py version */
STROBE_MODE_PLAINTEXT = 4,
STROBE_MODE_SQUEEZE = 5,
STROBE_MODE_FORGET = 6,
STROBE_MODE_SQUEEZE_R = 7
} decaf_TOY_strobe_mode_t;

#define STROBE_FLAG_CLIENT_SENT (1<<8) /**< Set if the client this message. */
#define STROBE_FLAG_IMPLICIT (1<<9) /**< Set if nobody set this message. */
#define STROBE_FLAG_FORGET (1<<12) /**< After this operation, destroy bytes to prevent rollback. */
/* TODO: maybe just make STROBE heavy non-invertible? */
#define STROBE_FLAG_NO_LENGTH (1<<15) /**< This operation has an unknown length (for streaming). */

/* After 1<<16, flags don't go to the sponge anymore, they just affect the handling */
#define STROBE_FLAG_RECV (1<<16) /**< I received this packet, so reverse directions. */
#define STROBE_FLAG_RUN_F (1<<17) /**< Must run F between control word and data. */
#define STROBE_FLAG_MORE (1<<18) /**< Set for all operations in an unknown-length streaming operation after the first */
#define STROBE_FLAG_LENGTH_64 (1<<19) /**< Length is a 64-bit word instead of a 16-bit one. */
#define STROBE_FLAG_NONDIR (STROBE_FLAG_IMPLICIT)

/** Automatic flags implied by the mode */
/* 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 \
|| (_mode) == STROBE_MODE_SQUEEZE \
|| (_mode) == STROBE_MODE_FORGET \
) ? STROBE_FLAG_IMPLICIT|STROBE_FLAG_NONDIR : 0) \
)

/**@ Define a control word for STROBE protocols. */
#define STROBE_CONTROL_WORD(_name,_id,_mode,_flags) \
static const uint32_t _name = _id | (_mode<<10) | (_mode<<29) | _flags | STROBE_AUTO_FLAGS(_mode)

STROBE_CONTROL_WORD(STROBE_CW_INIT, 0x00, STROBE_MODE_ABSORB, 0); /**< Initialization with protocol name */
/* Ciphers */
STROBE_CONTROL_WORD(STROBE_CW_FIXED_KEY, 0x10, STROBE_MODE_ABSORB, 0); /**< Fixed symmetric/preshared key */
STROBE_CONTROL_WORD(STROBE_CW_STATIC_PUB, 0x11, STROBE_MODE_PLAINTEXT, 0); /**< Static public key of other party */
STROBE_CONTROL_WORD(STROBE_CW_DH_EPH, 0x12, STROBE_MODE_PLAINTEXT, 0); /**< DH ephemeral key on the wire */
STROBE_CONTROL_WORD(STROBE_CW_DH_KEY, 0x13, STROBE_MODE_ABSORB, 0); /**< DH shared secret key */
STROBE_CONTROL_WORD(STROBE_CW_PRNG, 0x18, STROBE_MODE_SQUEEZE, STROBE_FLAG_FORGET); /**< Generate random bits (for PRNG) */
STROBE_CONTROL_WORD(STROBE_CW_SESSION_HASH, 0x19, STROBE_MODE_SQUEEZE, 0); /**< Generate session hash */

/* Reuse for PRNG */
STROBE_CONTROL_WORD(STROBE_CW_PRNG_INITIAL_SEED, 0x10, STROBE_MODE_ABSORB, STROBE_FLAG_NO_LENGTH); /**< Initial seeding for PRNG */
STROBE_CONTROL_WORD(STROBE_CW_PRNG_RESEED, 0x11, STROBE_MODE_ABSORB, STROBE_FLAG_NO_LENGTH); /**< Later seeding for PRNG */
STROBE_CONTROL_WORD(STROBE_CW_PRNG_CPU_SEED, 0x12, STROBE_MODE_ABSORB, 0); /**< Seed from CPU-builin RNG */
STROBE_CONTROL_WORD(STROBE_CW_PRNG_USER_SEED, 0x13, STROBE_MODE_ABSORB, STROBE_FLAG_LENGTH_64); /**< Seed from user */
STROBE_CONTROL_WORD(STROBE_CW_PRNG_PRNG, 0x14, STROBE_MODE_SQUEEZE, STROBE_FLAG_LENGTH_64 | STROBE_FLAG_FORGET); /**< Call to generate bits */

/* Signatures */
STROBE_CONTROL_WORD(STROBE_CW_SIG_SCHEME, 0x20, STROBE_MODE_ABSORB, 0); /**< Name of the signature scheme we're using. */
STROBE_CONTROL_WORD(STROBE_CW_SIG_PK, 0x21, STROBE_MODE_ABSORB, 0); /**< Public (verification key) */
STROBE_CONTROL_WORD(STROBE_CW_SIG_EPH, 0x22, STROBE_MODE_PLAINTEXT, 0); /**< Schnorr ephemeral. */
STROBE_CONTROL_WORD(STROBE_CW_SIG_CHAL, 0x23, STROBE_MODE_SQUEEZE, 0); /**< Schnorr challenge. */
STROBE_CONTROL_WORD(STROBE_CW_SIG_RESP, 0x24, STROBE_MODE_DUPLEX, 0); /**< Schnoll response. */

/* Payloads and encrypted data */

STROBE_CONTROL_WORD(STROBE_CW_PAYLOAD_PLAINTEXT, 0x30, STROBE_MODE_PLAINTEXT, 0);
STROBE_CONTROL_WORD(STROBE_CW_PAYLOAD_CIPHERTEXT, 0x31, STROBE_MODE_DUPLEX, 0);
STROBE_CONTROL_WORD(STROBE_CW_MAC, 0x32, STROBE_MODE_SQUEEZE_R, STROBE_FLAG_FORGET);
STROBE_CONTROL_WORD(STROBE_CW_AD_EXPLICIT, 0x34, STROBE_MODE_PLAINTEXT, 0);
STROBE_CONTROL_WORD(STROBE_CW_AD_IMPLICIT, 0x35, STROBE_MODE_ABSORB, 0);
STROBE_CONTROL_WORD(STROBE_CW_NONCE_EXPLICIT, 0x36, STROBE_MODE_PLAINTEXT, 0);
STROBE_CONTROL_WORD(STROBE_CW_NONCE_IMPLICIT, 0x37, STROBE_MODE_ABSORB, 0);

STROBE_CONTROL_WORD(STROBE_CW_STREAMING_PLAINTEXT,0x30, STROBE_MODE_PLAINTEXT, STROBE_FLAG_NO_LENGTH); /* TODO: orly? */

/* Change spec, control flow, etc */
STROBE_CONTROL_WORD(STROBE_CW_COMPRESS, 0x40, STROBE_MODE_ABSORB_R, 0);
/* FIXME: adjust this respec logic */
STROBE_CONTROL_WORD(STROBE_CW_RESPEC_INFO, 0x41, STROBE_MODE_ABSORB, STROBE_FLAG_RUN_F | STROBE_FLAG_FORGET);
STROBE_CONTROL_WORD(STROBE_CW_RESPEC, 0x42, STROBE_MODE_ABSORB_R, STROBE_FLAG_RUN_F);
STROBE_CONTROL_WORD(STROBE_CW_FORK, 0x43, STROBE_MODE_ABSORB_R, STROBE_FLAG_RUN_F | STROBE_FLAG_FORGET);
/* FIXME: instance can be rolled back to recover other INSTANCEs */
STROBE_CONTROL_WORD(STROBE_CW_INSTANCE, 0x44, STROBE_MODE_ABSORB_R, STROBE_FLAG_FORGET);
STROBE_CONTROL_WORD(STROBE_CW_ACKNOWLEDGE, 0x45, STROBE_MODE_PLAINTEXT, 0);

/** Reverse a keyword because it's being received instead of sent */
static INLINE UNUSED WARN_UNUSED uint32_t
decaf_TOY_strobe_cw_recv(uint32_t cw) {
uint32_t recv_toggle = (cw & STROBE_FLAG_NONDIR) ? 0 : STROBE_FLAG_RECV;
if (cw & STROBE_FLAG_IMPLICIT) {
return cw ^ recv_toggle;
} else {
uint32_t modes_2[8] = {
/* Note: most of these really shouldn't happen... */
STROBE_MODE_ABSORB,
STROBE_MODE_DUPLEX_R,
STROBE_MODE_ABSORB_R,
STROBE_MODE_DUPLEX,
STROBE_MODE_PLAINTEXT,
STROBE_MODE_SQUEEZE,
STROBE_MODE_FORGET,
STROBE_MODE_ABSORB
};

return ((cw & ((1<<29)-1)) | (modes_2[cw>>29]<<29)) ^ recv_toggle;
}
}

/***************************************/
/* Implementations of inline functions */
/***************************************/

void decaf_TOY_strobe_plaintext(keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, uint16_t len, uint8_t iSent) {
decaf_TOY_strobe_transact(
strobe, NULL, in, len,
iSent ? STROBE_CW_PAYLOAD_PLAINTEXT
: decaf_TOY_strobe_cw_recv(STROBE_CW_PAYLOAD_PLAINTEXT)
);
}

void decaf_TOY_strobe_ad(keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, size_t len) {
decaf_TOY_strobe_transact( strobe, NULL, in, len, STROBE_CW_AD_EXPLICIT );
}

void decaf_TOY_strobe_nonce (keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, uint16_t len) {
decaf_TOY_strobe_transact( strobe, NULL, in, len, STROBE_CW_NONCE_EXPLICIT );
}

void decaf_TOY_strobe_fixed_key (keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, uint16_t len) {
decaf_TOY_strobe_transact( strobe, NULL, in, len, STROBE_CW_FIXED_KEY );
}

void decaf_TOY_strobe_dh_key (keccak_decaf_TOY_strobe_t strobe, const unsigned char *in, uint16_t len) {
decaf_TOY_strobe_transact( strobe, NULL, in, len, STROBE_CW_DH_KEY );
}

void decaf_TOY_strobe_produce_auth (keccak_decaf_TOY_strobe_t strobe, unsigned char *out, uint16_t len) {
decaf_TOY_strobe_transact( strobe, out, NULL, len, STROBE_CW_MAC );
}

void decaf_TOY_strobe_encrypt (keccak_decaf_TOY_strobe_t strobe, unsigned char *out, const unsigned char *in, uint16_t len) {
decaf_TOY_strobe_transact(strobe, out, in, len, STROBE_CW_PAYLOAD_CIPHERTEXT);
}

void decaf_TOY_strobe_decrypt(keccak_decaf_TOY_strobe_t strobe, unsigned char *out, const unsigned char *in, uint16_t len) {
decaf_TOY_strobe_transact(strobe, out, in, len, decaf_TOY_strobe_cw_recv(STROBE_CW_PAYLOAD_CIPHERTEXT));
}

void decaf_TOY_strobe_prng(keccak_decaf_TOY_strobe_t strobe, unsigned char *out, uint16_t len) {
decaf_TOY_strobe_transact( strobe, out, NULL, len, STROBE_CW_PRNG );
}

void decaf_TOY_strobe_destroy (keccak_decaf_TOY_strobe_t doomed) {
decaf_sponge_destroy(doomed->sponge);
}

/** @endcond */ /* internal */

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

#endif /* __DECAF_STROBE_H__ */

+ 0
- 239
src/include/decaf/strobe.hxx View File

@@ -1,239 +0,0 @@
/**
* @file decaf/strobe.hxx
* @copyright
* Based on CC0 code by David Leon Gil, 2015 \n
* Copyright (c) 2015 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @brief STROBE instances, C++ wrapper.
* @warning This protocol framework is entirely experimental, and shouldn't be
* relied on for anything serious yet.
*/

#ifndef __DECAF_STROBE_HXX__
#define __DECAF_STROBE_HXX__

#include <decaf/strobe.h>

#include <sys/types.h>


/** @cond internal */
#if __cplusplus >= 201103L
#define NOEXCEPT noexcept
#define DELETE = delete
#else
#define NOEXCEPT throw()
#define DELETE
#endif
/** @endcond */

namespace decaf {

/** @brief An exception for misused protocol, eg encrypt with no key. */
class ProtocolException : public std::exception {
public:
/** @return "ProtocolException" */
virtual const char * what() const NOEXCEPT { return "ProtocolException"; }
};

/** STROBE protocol framework object */
class Strobe {
public:
/** The wrapped object */
keccak_decaf_TOY_strobe_t wrapped;
/** Number of bytes in a default authentication size. */
static const uint16_t DEFAULT_AUTH_SIZE = 16;
/** Am I a server or a client? */
enum client_or_server { SERVER, CLIENT };
/** Create protocol object. */
inline Strobe (
const char *description, /**< Description of this protocol. */
client_or_server whoami, /**< Am I client or server? */
const decaf_kparams_s &params = STROBE_256 /**< Strength parameters */
) NOEXCEPT {
decaf_TOY_strobe_init(wrapped, &params, description, whoami == CLIENT);
keyed = false;
}
/** Securely destroy by overwriting state. */
inline ~Strobe() NOEXCEPT { decaf_TOY_strobe_destroy(wrapped); }

/** Stir in fixed key, from a C++ block. */
inline void fixed_key (
const Block &data /**< The key. */
) throw(ProtocolException) {
decaf_TOY_strobe_fixed_key(wrapped, data.data(), data.size());
keyed = true;
}

/** Stir in fixed key, from a serializeable object. */
template<class T> inline void fixed_key (
const Serializable<T> &data /**< The key. */
) throw(ProtocolException) {
fixed_key(data.serialize());
}

/** Stir in DH key, from a C++ block. */
inline void dh_key (
const Block &data /**< The key. */
) throw(ProtocolException) {
decaf_TOY_strobe_dh_key(wrapped, data.data(), data.size());
keyed = true;
}

/** Stir in DH key, from a serializeable object. */
template<class T> inline void dh_key (
const Serializable<T> &data /**< The key. */
) throw(ProtocolException) {
dh_key(data.serialize());
}

/** Stir in an explicit nonce. */
inline void nonce(const Block &data) NOEXCEPT {
decaf_TOY_strobe_nonce(wrapped, data.data(), data.size());
}

/** Stir in data we sent as plaintext. NB This doesn't actually send anything. */
inline void send_plaintext(const Block &data) NOEXCEPT {
decaf_TOY_strobe_plaintext(wrapped, data.data(), data.size(), true);
}

/** Stir in serializeable data we sent as plaintext. NB This doesn't actually send anything. */
template<class T> inline void send_plaintext(const Serializable<T> &data) NOEXCEPT {
send_plaintext(data.serialize());
}

/** Stir in data we received as plaintext. NB This doesn't actually receive anything. */
inline void recv_plaintext(const Block &data) NOEXCEPT {
decaf_TOY_strobe_plaintext(wrapped, data.data(), data.size(), false);
}

/** Stir in associated data. */
inline void ad(const Block &data) {
decaf_TOY_strobe_ad(wrapped, data.data(), data.size());
}

/** Stir in associated serializable data. */
template<class T> inline void ad(const Serializable<T> &data) NOEXCEPT {
ad(data.serialize());
}
/** Encrypt into a buffer, without appending authentication data */
inline void encrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) {
if (!keyed) throw ProtocolException();
if (out.size() != data.size()) throw LengthException();
decaf_TOY_strobe_encrypt(wrapped, out.data(), data.data(), data.size());
}
/** Encrypt, without appending authentication data */
inline SecureBuffer encrypt_no_auth(const Block &data) throw(ProtocolException) {
SecureBuffer out(data.size()); encrypt_no_auth(out, data); return out;
}
/** Encrypt a serializable object, without appending authentication data */
template<class T> inline SecureBuffer encrypt_no_auth(const Serializable<T> &data) throw(ProtocolException) {
return encrypt_no_auth(data.serialize());
}
/** Decrypt into a buffer, without checking authentication data. */
inline void decrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) {
if (!keyed) throw ProtocolException();
if (out.size() != data.size()) throw LengthException();
decaf_TOY_strobe_decrypt(wrapped, out.data(), data.data(), data.size());
}
/** Decrypt, without checking authentication data. */
inline SecureBuffer decrypt_no_auth(const Block &data) throw(ProtocolException) {
SecureBuffer out(data.size()); decrypt_no_auth(out, data); return out;
}
/** Produce an authenticator into a buffer. */
inline void produce_auth(Buffer out, bool even_though_unkeyed = false) throw(LengthException,ProtocolException) {
if (!keyed && !even_though_unkeyed) throw ProtocolException();
if (out.size() > STROBE_MAX_AUTH_BYTES) throw LengthException();
decaf_TOY_strobe_produce_auth(wrapped, out.data(), out.size());
}
/** Produce an authenticator. */
inline SecureBuffer produce_auth(uint8_t bytes = DEFAULT_AUTH_SIZE) throw(ProtocolException) {
SecureBuffer out(bytes); produce_auth(out); return out;
}
/** Encrypt into a buffer and append authentication data */
inline void encrypt(
Buffer out, const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE
) throw(LengthException,ProtocolException) {
if (out.size() < data.size() || out.size() != data.size() + auth) throw LengthException();
encrypt_no_auth(out.slice(0,data.size()), data);
produce_auth(out.slice(data.size(),auth));
}
/** Encrypt and append authentication data */
inline SecureBuffer encrypt (
const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE
) throw(LengthException,ProtocolException,std::bad_alloc ){
SecureBuffer out(data.size() + auth); encrypt(out, data, auth); return out;
}
/** Encrypt a serializable object and append authentication data */
template<class T> inline SecureBuffer encrypt (
const Serializable<T> &data, uint8_t auth = DEFAULT_AUTH_SIZE
) throw(LengthException,ProtocolException,std::bad_alloc ){
return encrypt(data.serialize(), auth);
}
/** Decrypt into a buffer and check authentication data */
inline void decrypt (
Buffer out, const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE
) throw(LengthException, CryptoException, ProtocolException) {
if (out.size() > data.size() || out.size() != data.size() - bytes) throw LengthException();
decrypt_no_auth(out, data.slice(0,out.size()));
verify_auth(data.slice(out.size(),bytes));
}
/** Decrypt and check authentication data */
inline SecureBuffer decrypt (
const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE
) throw(LengthException,CryptoException,ProtocolException,std::bad_alloc) {
if (data.size() < bytes) throw LengthException();
SecureBuffer out(data.size() - bytes); decrypt(out, data, bytes); return out;
}
/** Check authentication data */
inline void verify_auth(const Block &auth) throw(LengthException,CryptoException) {
if (auth.size() == 0 || auth.size() > STROBE_MAX_AUTH_BYTES) throw LengthException();
if (decaf_TOY_strobe_verify_auth(wrapped, auth.data(), auth.size()) != DECAF_SUCCESS) throw CryptoException();
}
/** Fill pseudorandom data into a buffer */
inline void prng(Buffer out) NOEXCEPT {
(void)decaf_TOY_strobe_prng(wrapped, out.data(), out.size());
}
/** Return pseudorandom data */
inline SecureBuffer prng(size_t bytes) {
SecureBuffer out(bytes); prng(out); return out;
}
/** Change specs, perhaps to a faster spec that takes advantage of being keyed.
* @warning Experimental.
*/
inline void respec(const decaf_kparams_s &params) throw(ProtocolException) {
if (!keyed) throw(ProtocolException());
decaf_TOY_strobe_respec(wrapped, &params);
}
private:
bool keyed;
};
} /* namespace decaf */

#undef NOEXCEPT
#undef DELETE

#endif /* __DECAF_STROBE_HXX__ */

+ 3
- 3
src/include/keccak_internal.h View File

@@ -5,7 +5,7 @@
* Copyright (c) 2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @brief Keccak internal interfaces, used by STROBE.
* @brief Keccak internal interfaces. Will be used by STROBE once reintegrated.
*/
#ifndef __DECAF_KECCAK_INTERNAL_H__
#define __DECAF_KECCAK_INTERNAL_H__ 1
@@ -18,8 +18,8 @@ typedef union {
} kdomain_t[1];

typedef struct decaf_kparams_s {
uint8_t position, flags, rate, start_round, pad, rate_pad, max_out, client; /* client = max_outRemaining for decaf_sha3 */
} decaf_kparams_t[1];
uint8_t position, flags, rate, start_round, pad, rate_pad, max_out, remaining;
} decaf_kparams_s, decaf_kparams_t[1];

typedef struct decaf_keccak_sponge_s {
kdomain_t state;


+ 0
- 222
src/per_curve/crypto.tmpl.c View File

@@ -1,222 +0,0 @@
/**
* @cond internal
* @brief Example Decaf crypto routines
*/

#include <decaf/crypto.h>
#include <string.h>

#define API_NAME "$(c_ns)"
#define API_NS(_id) $(c_ns)_##_id
#define API_NS_TOY(_id) $(c_ns)_TOY_##_id
#define SCALAR_BITS $(C_NS)_SCALAR_BITS
#define SCALAR_BYTES ((SCALAR_BITS + 7)/8)
#define SER_BYTES $(C_NS)_SER_BYTES

/* TODO: canonicalize and freeze the STROBE constants in this file
* (and STROBE itself for that matter)
*/
static const char *DERIVE_MAGIC = API_NAME"::derive_private_key";
static const char *SIGN_MAGIC = API_NAME"::sign";
static const char *SHARED_SECRET_MAGIC = API_NAME"::shared_secret";
static const uint16_t SHARED_SECRET_MAX_BLOCK_SIZE = 1<<12;
static const unsigned int SCALAR_OVERKILL_BYTES = SCALAR_BYTES + 8;

void API_NS_TOY(derive_private_key) (
API_NS_TOY(private_key_t) priv,
const API_NS_TOY(symmetric_key_t) proto
) {
uint8_t encoded_scalar[SCALAR_OVERKILL_BYTES];
API_NS(point_t) pub;
keccak_decaf_TOY_strobe_t strobe;
decaf_TOY_strobe_init(strobe, &STROBE_256, DERIVE_MAGIC, 0);
decaf_TOY_strobe_fixed_key(strobe, proto, sizeof(API_NS_TOY(symmetric_key_t)));
decaf_TOY_strobe_prng(strobe, encoded_scalar, sizeof(encoded_scalar));
decaf_TOY_strobe_destroy(strobe);
memcpy(priv->sym, proto, sizeof(API_NS_TOY(symmetric_key_t)));
API_NS(scalar_decode_long)(priv->secret_scalar, encoded_scalar, sizeof(encoded_scalar));
API_NS(precomputed_scalarmul)(pub, API_NS(precomputed_base), priv->secret_scalar);
API_NS(point_encode)(priv->pub, pub);
decaf_bzero(encoded_scalar, sizeof(encoded_scalar));
}

void API_NS_TOY(destroy_private_key) (
API_NS_TOY(private_key_t) priv
) {
decaf_bzero((void*)priv, sizeof(API_NS_TOY(private_key_t)));
}

void API_NS_TOY(private_to_public) (
API_NS_TOY(public_key_t) pub,
const API_NS_TOY(private_key_t) priv
) {
memcpy(pub, priv->pub, sizeof(API_NS_TOY(public_key_t)));
}

/* Performance vs consttime tuning.
* Specifying true here might give better DOS resistance in certain corner
* cases. Specifying false gives a tighter result in test_ct.
*/
#ifndef DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT
#define DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT DECAF_FALSE
#endif

decaf_error_t API_NS_TOY(shared_secret) (
uint8_t *shared,
size_t shared_bytes,
const API_NS_TOY(private_key_t) my_privkey,
const API_NS_TOY(public_key_t) your_pubkey,
int me_first
) {
keccak_decaf_TOY_strobe_t strobe;
decaf_TOY_strobe_init(strobe, &STROBE_256, SHARED_SECRET_MAGIC, 0);
uint8_t ss_ser[SER_BYTES];
if (me_first) {
decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t)));
decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t)));
} else {
decaf_TOY_strobe_ad(strobe,your_pubkey,sizeof(API_NS_TOY(public_key_t)));
decaf_TOY_strobe_ad(strobe,my_privkey->pub,sizeof(API_NS_TOY(public_key_t)));
}
decaf_error_t ret = API_NS(direct_scalarmul)(
ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE,
DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT
);
decaf_TOY_strobe_transact(strobe,NULL,ss_ser,sizeof(ss_ser),STROBE_CW_DH_KEY);
while (shared_bytes) {
uint16_t cando = (shared_bytes > SHARED_SECRET_MAX_BLOCK_SIZE)
? SHARED_SECRET_MAX_BLOCK_SIZE : shared_bytes;
decaf_TOY_strobe_prng(strobe,shared,cando);
shared_bytes -= cando;
shared += cando;
}

decaf_TOY_strobe_destroy(strobe);
decaf_bzero(ss_ser, sizeof(ss_ser));
return ret;
}

void API_NS_TOY(sign_strobe) (
keccak_decaf_TOY_strobe_t strobe,
API_NS_TOY(signature_t) sig,
const API_NS_TOY(private_key_t) priv
) {
uint8_t overkill[SCALAR_OVERKILL_BYTES];
API_NS(point_t) point;
API_NS(scalar_t) nonce, challenge;
/* Stir pubkey */
decaf_TOY_strobe_transact(strobe,NULL,priv->pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK);
/* Derive nonce */
keccak_decaf_TOY_strobe_t strobe2;
memcpy(strobe2,strobe,sizeof(strobe2));
decaf_TOY_strobe_fixed_key(strobe2,priv->sym,sizeof(API_NS_TOY(symmetric_key_t)));
decaf_TOY_strobe_prng(strobe2,overkill,sizeof(overkill));
decaf_TOY_strobe_destroy(strobe2);
API_NS(scalar_decode_long)(nonce, overkill, sizeof(overkill));
API_NS(precomputed_scalarmul)(point, API_NS(precomputed_base), nonce);
API_NS(point_encode)(sig, point);

/* Derive challenge */
decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH);
decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL);
API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill));
/* Respond */
API_NS(scalar_mul)(challenge, challenge, priv->secret_scalar);
API_NS(scalar_sub)(nonce, nonce, challenge);
/* Save results */
API_NS(scalar_encode)(overkill, nonce);
decaf_TOY_strobe_transact(strobe,&sig[SER_BYTES],overkill,SCALAR_BYTES,STROBE_CW_SIG_RESP);
/* Clean up */
API_NS(scalar_destroy)(nonce);
API_NS(scalar_destroy)(challenge);
decaf_bzero(overkill,sizeof(overkill));
}

decaf_error_t API_NS_TOY(verify_strobe) (
keccak_decaf_TOY_strobe_t strobe,
const API_NS_TOY(signature_t) sig,
const API_NS_TOY(public_key_t) pub
) {
decaf_bool_t ret;
uint8_t overkill[SCALAR_OVERKILL_BYTES];
API_NS(point_t) point, pubpoint;
API_NS(scalar_t) challenge, response;
/* Stir pubkey */
decaf_TOY_strobe_transact(strobe,NULL,pub,sizeof(API_NS_TOY(public_key_t)),STROBE_CW_SIG_PK);
/* Derive nonce */
decaf_TOY_strobe_transact(strobe,NULL,sig,SER_BYTES,STROBE_CW_SIG_EPH);
ret = decaf_successful( API_NS(point_decode)(point, sig, DECAF_TRUE) );
/* Derive challenge */
decaf_TOY_strobe_transact(strobe,overkill,NULL,sizeof(overkill),STROBE_CW_SIG_CHAL);
API_NS(scalar_decode_long)(challenge, overkill, sizeof(overkill));
/* Decode response */
decaf_TOY_strobe_transact(strobe,overkill,&sig[SER_BYTES],SCALAR_BYTES,STROBE_CW_SIG_RESP);
ret &= decaf_successful( API_NS(scalar_decode)(response, overkill) );
ret &= decaf_successful( API_NS(point_decode)(pubpoint, pub, DECAF_FALSE) );

API_NS(base_double_scalarmul_non_secret) (
pubpoint, response, pubpoint, challenge
);

ret &= API_NS(point_eq)(pubpoint, point);
/* Nothing here is secret, so don't do these things:
decaf_bzero(overkill,sizeof(overkill));
API_NS(point_destroy)(point);
API_NS(point_destroy)(pubpoint);
API_NS(scalar_destroy)(challenge);
API_NS(scalar_destroy)(response);
*/
return decaf_succeed_if(ret);
}

void
API_NS_TOY(sign) (
API_NS_TOY(signature_t) sig,
const API_NS_TOY(private_key_t) priv,
const unsigned char *message,
size_t message_len
) {
keccak_decaf_TOY_strobe_t ctx;
decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0);
decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT);
API_NS_TOY(sign_strobe)(ctx, sig, priv);
decaf_TOY_strobe_destroy(ctx);
}

decaf_error_t
API_NS_TOY(verify) (
const API_NS_TOY(signature_t) sig,
const API_NS_TOY(public_key_t) pub,
const unsigned char *message,
size_t message_len
) {
keccak_decaf_TOY_strobe_t ctx;
decaf_TOY_strobe_init(ctx,&STROBE_256,SIGN_MAGIC,0);
decaf_TOY_strobe_transact(ctx, NULL, message, message_len, STROBE_CW_STREAMING_PLAINTEXT);
decaf_error_t ret = API_NS_TOY(verify_strobe)(ctx, sig, pub);
decaf_TOY_strobe_destroy(ctx);
return ret;
}

+ 0
- 163
src/per_curve/crypto.tmpl.h View File

@@ -1,163 +0,0 @@
/**
* Example Decaf crypto routines.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
* @warning Experimental! The names, parameter orders etc are likely to change.
*/

#include <decaf/point_$(gf_bits).h>
#include <decaf/strobe.h>

#ifdef __cplusplus
extern "C" {
#endif

/** Number of bytes for a symmetric key (expanded to full key) */
#define $(C_NS)_SYMMETRIC_KEY_BYTES 32

/** A symmetric key, the compressed point of a private key. */
typedef unsigned char $(c_ns)_TOY_symmetric_key_t[$(C_NS)_SYMMETRIC_KEY_BYTES];

/** An encoded public key. */
typedef unsigned char $(c_ns)_TOY_public_key_t[$(C_NS)_SER_BYTES];

/** A signature. */
typedef unsigned char $(c_ns)_TOY_signature_t[$(C_NS)_SER_BYTES + $(C_NS)_SCALAR_BYTES];

typedef struct {
/** @cond internal */
/** The symmetric key from which everything is expanded */
$(c_ns)_TOY_symmetric_key_t sym;
/** The scalar x */
$(c_ns)_scalar_t secret_scalar;
/** x*Base */
$(c_ns)_TOY_public_key_t pub;
/** @endcond */
} /** Private key structure for pointers. */
$(c_ns)_TOY_private_key_s,
/** A private key (gmp array[1] style). */
$(c_ns)_TOY_private_key_t[1];
/**
* Derive a key from its compressed form.
* @param [out] priv The derived private key.
* @param [in] proto The compressed or proto-key, which must be 32 random bytes.
*/
void $(c_ns)_TOY_derive_private_key (
$(c_ns)_TOY_private_key_t priv,
const $(c_ns)_TOY_symmetric_key_t proto
) NONNULL API_VIS;

/**
* Destroy a private key.
*/
void $(c_ns)_TOY_destroy_private_key (
$(c_ns)_TOY_private_key_t priv
) NONNULL API_VIS;

/**
* Convert a private key to a public one.
* @param [out] pub The extracted private key.
* @param [in] priv The private key.
*/
void $(c_ns)_TOY_private_to_public (
$(c_ns)_TOY_public_key_t pub,
const $(c_ns)_TOY_private_key_t priv
) NONNULL API_VIS;
/**
* Compute a Diffie-Hellman shared secret.
*
* This is an example routine; real protocols would use something
* protocol-specific.
*
* @param [out] shared A buffer to store the shared secret.
* @param [in] shared_bytes The size of the buffer.
* @param [in] my_privkey My private key.
* @param [in] your_pubkey Your public key.
* @param [in] me_first Direction flag to break symmetry.
*
* @retval DECAF_SUCCESS Key exchange was successful.
* @retval DECAF_FAILURE Key exchange failed.
*/
decaf_error_t
$(c_ns)_TOY_shared_secret (
uint8_t *shared,
size_t shared_bytes,
const $(c_ns)_TOY_private_key_t my_privkey,
const $(c_ns)_TOY_public_key_t your_pubkey,
int me_first
) NONNULL WARN_UNUSED API_VIS;
/**
* Sign a message from a STROBE context.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
* @param [in] strobe A STROBE context with the message.
*/
void
$(c_ns)_TOY_sign_strobe (
keccak_decaf_TOY_strobe_t strobe,
$(c_ns)_TOY_signature_t sig,
const $(c_ns)_TOY_private_key_t priv
) NONNULL API_VIS;

/**
* Sign a message.
*
* @param [out] sig The signature.
* @param [in] priv Your private key.
* @param [in] message The message.
* @param [in] message_len The message's length.
*/
void
$(c_ns)_TOY_sign (
$(c_ns)_TOY_signature_t sig,
const $(c_ns)_TOY_private_key_t priv,
const unsigned char *message,
size_t message_len
) NONNULL API_VIS;

/**
* Verify a signed message from its STROBE context.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
* @param [in] strobe A STROBE context with the message.
*
* @return DECAF_SUCCESS The signature verified successfully.
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
$(c_ns)_TOY_verify_strobe (
keccak_decaf_TOY_strobe_t strobe,
const $(c_ns)_TOY_signature_t sig,
const $(c_ns)_TOY_public_key_t pub
) NONNULL API_VIS WARN_UNUSED;

/**
* Verify a signed message.
*
* @param [in] sig The signature.
* @param [in] pub The public key.
* @param [in] message The message.
* @param [in] message_len The message's length.
*
* @return DECAF_SUCCESS The signature verified successfully.
* @return DECAF_FAILURE The signature did not verify successfully.
*/
decaf_error_t
$(c_ns)_TOY_verify (
const $(c_ns)_TOY_signature_t sig,
const $(c_ns)_TOY_public_key_t pub,
const unsigned char *message,
size_t message_len
) NONNULL API_VIS WARN_UNUSED;

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

+ 0
- 199
src/per_curve/crypto.tmpl.hxx View File

@@ -1,199 +0,0 @@
/*
* Example Decaf cyrpto routines, C++ wrapper.
* @warning These are merely examples, though they ought to be secure. But real
* protocols will decide differently on magic numbers, formats, which items to
* hash, etc.
* @warning Experimental! The names, parameter orders etc are likely to change.
*/

#include <decaf/point_$(gf_bits).hxx>
#include <decaf/shake.hxx>
#include <decaf/strobe.hxx>

/** @cond internal */
#if __cplusplus >= 201103L
#define NOEXCEPT noexcept
#else
#define NOEXCEPT throw()
#endif
/** @endcond */

namespace decaf { namespace TOY {

/** A public key for crypto over some Group */
template <typename Group> class PublicKey;

/** A private key for crypto over some Group */
template <typename Group> class PrivateKey;

/** A public key for crypto over $(name) */
template<> class PublicKey<$(cxx_ns)>
: public Serializable< PublicKey<$(cxx_ns)> > {
private:
/** @cond internal */
typedef $(c_ns)_TOY_public_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PrivateKey;
/** @endcond */
public:
/** Underlying group */
typedef $(cxx_ns) Group;
/** Signature size. */
static const size_t SIG_BYTES = sizeof($(c_ns)_TOY_signature_t);
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
/** Read a private key from a string*/
inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT {
memcpy(wrapped,b.data(),sizeof(wrapped));
}
/** Read a private key from a string*/
inline explicit PublicKey(const PrivateKey<$(cxx_ns)> &b) NOEXCEPT;
/** Create but don't initialize */
inline explicit PublicKey(const NOINIT&) NOEXCEPT { }
/** Serialize into a buffer. */
inline void serialize_into(unsigned char *x) const NOEXCEPT {
memcpy(x,wrapped,sizeof(wrapped));
}
/** Serialization size. */
inline size_t ser_size() const NOEXCEPT { return SER_BYTES; }
/** Verify a message */
inline void verify(
const Block &message,
const FixedBlock<SIG_BYTES> &sig
) const throw(CryptoException) {
if (DECAF_SUCCESS != $(c_ns)_TOY_verify(sig.data(),wrapped,message.data(),message.size())) {
throw(CryptoException());
}
}
/** Verify a message */
inline void verify(
Strobe &context,
const FixedBlock<SIG_BYTES> &sig
) const throw(CryptoException) {
if (DECAF_SUCCESS != $(c_ns)_TOY_verify_strobe(context.wrapped,sig.data(),wrapped)) {
throw(CryptoException());
}
}
};

/** A private key for crypto over $(name) */
template<> class PrivateKey<$(cxx_ns)>
: public Serializable< PrivateKey<$(cxx_ns)> > {
private:
/** @cond internal */
typedef $(c_ns)_TOY_private_key_t Wrapped;
Wrapped wrapped;
template<class Group> friend class PublicKey;
/** @endcond */
public:
/** Underlying group */
typedef $(cxx_ns) Group;
/** Signature size. */
static const size_t SIG_BYTES = sizeof($(c_ns)_TOY_signature_t);
/** Serialization size. */
static const size_t SER_BYTES = sizeof(Wrapped);
/** Compressed size. */
static const size_t SYM_BYTES = $(C_NS)_SYMMETRIC_KEY_BYTES;
/** Create but don't initialize */
inline explicit PrivateKey(const NOINIT&) NOEXCEPT { }
/** Read a private key from a string*/
inline explicit PrivateKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT {
memcpy(wrapped,b.data(),sizeof(wrapped));
}
/** Read a private key from a string*/
inline explicit PrivateKey(const FixedBlock<SYM_BYTES> &b) NOEXCEPT {
$(c_ns)_TOY_derive_private_key(wrapped, b.data());
}
/** Create at random */
inline explicit PrivateKey(Rng &r) NOEXCEPT {
FixedArrayBuffer<SYM_BYTES> tmp(r);
$(c_ns)_TOY_derive_private_key(wrapped, tmp.data());
}
/** Secure destructor */
inline ~PrivateKey() NOEXCEPT {
$(c_ns)_TOY_destroy_private_key(wrapped);
}
/** Serialization size. */
inline size_t ser_size() const NOEXCEPT { return SER_BYTES; }
/** Serialize into a buffer. */
inline void serialize_into(unsigned char *x) const NOEXCEPT {
memcpy(x,wrapped,sizeof(wrapped));
}
/** Compressed serialize. */
inline SecureBuffer compress() const throw(std::bad_alloc) {
SecureBuffer ret(sizeof(wrapped->sym));
memcpy(ret.data(),wrapped->sym,sizeof(wrapped->sym));
return ret;
}
/** Get the public key */
inline PublicKey<$(cxx_ns)> pub() const NOEXCEPT {
PublicKey<$(cxx_ns)> ret(*this); return ret;
}
/** Derive a shared secret */
inline SecureBuffer shared_secret(
const PublicKey<$(cxx_ns)> &pub,
size_t bytes,
bool me_first
) const throw(CryptoException,std::bad_alloc) {
SecureBuffer ret(bytes);
if (DECAF_SUCCESS != $(c_ns)_TOY_shared_secret(ret.data(),bytes,wrapped,pub.wrapped,me_first)) {
throw(CryptoException());
}
return ret;
}
/** Derive a shared secret */
inline decaf_error_t __attribute__((warn_unused_result))
shared_secret_noexcept(
Buffer ret,
const PublicKey<$(cxx_ns)> &pub,
bool me_first
) const NOEXCEPT {
return $(c_ns)_TOY_shared_secret(ret.data(),ret.size(),wrapped,pub.wrapped,me_first);
}

/** Sign a message. */
inline SecureBuffer sign(const Block &message) const {
SecureBuffer sig(SIG_BYTES);
$(c_ns)_TOY_sign(sig.data(), wrapped, message.data(), message.size());
return sig;
}

/** Sign a message. */
inline SecureBuffer verify(Strobe &context) const {
SecureBuffer sig(SIG_BYTES);
$(c_ns)_TOY_sign_strobe(context.wrapped, sig.data(), wrapped);
return sig;
}
};

/** @cond internal */
PublicKey<$(cxx_ns)>::PublicKey(const PrivateKey<$(cxx_ns)> &b) NOEXCEPT {
$(c_ns)_TOY_private_to_public(wrapped,b.wrapped);
}
/** @endcond */

#undef NOEXCEPT
}} /* namespace decaf::TOY */

+ 4
- 4
src/shake.c View File

@@ -119,10 +119,10 @@ decaf_error_t decaf_sha3_output (
assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state));
if (decaf_sponge->params->max_out != 0xFF) {
if (decaf_sponge->params->client >= len) {
decaf_sponge->params->client -= len;
if (decaf_sponge->params->remaining >= len) {
decaf_sponge->params->remaining -= len;
} else {
decaf_sponge->params->client = 0;
decaf_sponge->params->remaining = 0;
ret = DECAF_FAILURE;
}
}
@@ -172,7 +172,7 @@ void decaf_sha3_reset (
decaf_keccak_sponge_t decaf_sponge
) {
decaf_sponge_init(decaf_sponge, decaf_sponge->params);
decaf_sponge->params->client = decaf_sponge->params->max_out;
decaf_sponge->params->remaining = decaf_sponge->params->max_out;
}

void decaf_sponge_destroy (decaf_keccak_sponge_t decaf_sponge) { decaf_bzero(decaf_sponge, sizeof(decaf_keccak_sponge_t)); }


+ 164
- 0
src/spongerng.c View File

@@ -0,0 +1,164 @@
/**
* @cond internal
* @file spongerng.c
* @copyright
* Copyright (c) 2015-2017 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @brief Spongerng instances (STROBE removed)
* @warning The SpongeRNG code isn't stable. Future versions are likely to
* have different outputs. Of course, this only matters in deterministic mode.
*/

#define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */
#include <assert.h>
#include <stdint.h>
#include <string.h>

#include "keccak_internal.h"
#include <decaf/spongerng.h>

/* to open and read from /dev/urandom */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */
static void get_cpu_entropy(uint8_t *entropy, size_t len) {
# if (defined(__i386__) || defined(__x86_64__))
static char tested = 0, have_rdrand = 0;
if (!tested) {
uint32_t a,b,c,d;
a=1; __asm__("cpuid" : "+a"(a), "=b"(b), "=c"(c), "=d"(d));
have_rdrand = (c>>30)&1;
tested = 1;
}

if (have_rdrand) {
# if defined(__x86_64__)
uint64_t out, a=0, *eo = (uint64_t *)entropy;
# elif defined(__i386__)
uint32_t out, a=0, *eo = (uint32_t *)entropy;
#endif
len /= sizeof(out);

uint32_t tries;
for (tries = 100+len; tries && len; len--, eo++) {
for (a = 0; tries && !a; tries--) {
__asm__ __volatile__ ("rdrand %0\n\tsetc %%al" : "=r"(out), "+a"(a) :: "cc" );
}
*eo ^= out;
}
} else if (len>=8) {
#ifndef __has_builtin
#define __has_builtin(X) 0
#endif
#if defined(__clang__) && __has_builtin(__builtin_readcyclecounter)
*(uint64_t*) entropy ^= __builtin_readcyclecounter();
#elif defined(__x86_64__)
uint32_t lobits, hibits;
__asm__ __volatile__ ("rdtsc" : "=a"(lobits), "=d"(hibits));
*(uint64_t*) entropy ^= (lobits | ((uint64_t)(hibits) << 32));
#elif defined(__i386__)
uint64_t __value;
__asm__ __volatile__ ("rdtsc" : "=A"(__value));
*(uint64_t*) entropy ^= __value;
#endif
}

#else
(void) entropy;
(void) len;
#endif
}

void decaf_spongerng_next (
decaf_keccak_prng_t prng,
uint8_t * __restrict__ out,
size_t len
) {
if (prng->sponge->params->remaining) {
/* nondet */
uint8_t cpu_entropy[32];
get_cpu_entropy(cpu_entropy, sizeof(cpu_entropy));
decaf_spongerng_stir(prng,cpu_entropy,sizeof(cpu_entropy));
decaf_bzero(cpu_entropy,sizeof(cpu_entropy));
}
uint8_t lenx[8];
size_t len1 = len;
for (unsigned i=0; i<sizeof(lenx); i++) {
lenx[i] = len1;
len1 >>= 8;
}
decaf_sha3_update(prng->sponge,lenx,sizeof(lenx));
decaf_sha3_output(prng->sponge,out,len);
const uint8_t nope;
decaf_spongerng_stir(prng,&nope,0);
}

void decaf_spongerng_stir (
decaf_keccak_prng_t prng,
const uint8_t * __restrict__ in,
size_t len
) {
uint8_t seed[32];
decaf_sha3_output(prng->sponge,seed,sizeof(seed));
uint8_t nondet = prng->sponge->params->remaining;
decaf_sha3_reset(prng->sponge);
decaf_sha3_update(prng->sponge,seed,sizeof(seed));
decaf_sha3_update(prng->sponge,in,len);
prng->sponge->params->remaining = nondet;
decaf_bzero(seed,sizeof(seed));
}

void decaf_spongerng_init_from_buffer (
decaf_keccak_prng_t prng,
const uint8_t * __restrict__ in,
size_t len,
int deterministic
) {
decaf_sponge_init(prng->sponge,&DECAF_SHAKE256_params_s);
prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */
decaf_spongerng_stir(prng, in, len);
}

decaf_error_t decaf_spongerng_init_from_file (
decaf_keccak_prng_t prng,
const char *file,
size_t len,
int deterministic
) {
decaf_sponge_init(prng->sponge,&DECAF_SHAKE256_params_s);
prng->sponge->params->remaining = !deterministic; /* A bit of a hack; this param is ignored for SHAKE */
if (!len) return DECAF_FAILURE;

int fd = open(file, O_RDONLY);
if (fd < 0) return DECAF_FAILURE;
uint8_t buffer[128];
while (len) {
ssize_t red = read(fd, buffer, (len > sizeof(buffer)) ? sizeof(buffer) : len);
if (red <= 0) {
close(fd);
return DECAF_FAILURE;
}
decaf_sha3_update(prng->sponge,buffer,red);
len -= red;
};
close(fd);
const uint8_t nope;
decaf_spongerng_stir(prng,&nope,0);
return DECAF_SUCCESS;
}

decaf_error_t decaf_spongerng_init_from_dev_urandom (
decaf_keccak_prng_t decaf_sponge
) {
return decaf_spongerng_init_from_file(decaf_sponge, "/dev/urandom", 64, 0);
}

+ 0
- 412
src/strobe.c View File

@@ -1,412 +0,0 @@
/**
* @cond internal
* @file strobe.c
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @brief STROBE and spongerng instances.
* @warning All APIs in here are toys. They will change behavior and probably also API.
* Do not use them for anything serious.
*/

#define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */
#include <assert.h>
#include <stdint.h>
#include <string.h>

#include "keccak_internal.h"
#include <decaf/strobe.h>
#include <decaf/spongerng.h>

/* to open and read from /dev/urandom */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

/** Get entropy from a CPU, preferably in the form of RDRAND, but possibly instead from RDTSC. */
static void get_cpu_entropy(uint8_t *entropy, size_t len) {
# if (defined(__i386__) || defined(__x86_64__))
static char tested = 0, have_rdrand = 0;
if (!tested) {
uint32_t a,b,c,d;
a=1; __asm__("cpuid" : "+a"(a), "=b"(b), "=c"(c), "=d"(d));
have_rdrand = (c>>30)&1;
tested = 1;
}

if (have_rdrand) {
# if defined(__x86_64__)
uint64_t out, a=0, *eo = (uint64_t *)entropy;
# elif defined(__i386__)
uint32_t out, a=0, *eo = (uint32_t *)entropy;
#endif
len /= sizeof(out);

uint32_t tries;
for (tries = 100+len; tries && len; len--, eo++) {
for (a = 0; tries && !a; tries--) {
__asm__ __volatile__ ("rdrand %0\n\tsetc %%al" : "=r"(out), "+a"(a) :: "cc" );
}
*eo ^= out;
}
} else if (len>=8) {
#ifndef __has_builtin
#define __has_builtin(X) 0
#endif
#if defined(__clang__) && __has_builtin(__builtin_readcyclecounter)
*(uint64_t*) entropy ^= __builtin_readcyclecounter();
#elif defined(__x86_64__)
uint32_t lobits, hibits;
__asm__ __volatile__ ("rdtsc" : "=a"(lobits), "=d"(hibits));
*(uint64_t*) entropy ^= (lobits | ((uint64_t)(hibits) << 32));
#elif defined(__i386__)
uint64_t __value;
__asm__ __volatile__ ("rdtsc" : "=A"(__value));
*(uint64_t*) entropy ^= __value;
#endif
}

#else
(void) entropy;
(void) len;
#endif
}

static const char *SPONGERNG_NAME = "strobe::decaf_spongerng"; /* TODO: canonicalize name */

void decaf_spongerng_next (
decaf_keccak_prng_t prng,
uint8_t * __restrict__ out,
size_t len
) {
decaf_keccak_sponge_s *decaf_sponge = prng->sponge;
if (decaf_sponge->params->client) {
/* nondet */
uint8_t cpu_entropy[32];
get_cpu_entropy(cpu_entropy, sizeof(cpu_entropy));
decaf_TOY_strobe_transact((keccak_decaf_TOY_strobe_s*)decaf_sponge,NULL,cpu_entropy,sizeof(cpu_entropy),STROBE_CW_PRNG_CPU_SEED);
}
decaf_TOY_strobe_transact((keccak_decaf_TOY_strobe_s*)decaf_sponge,out,NULL,len,STROBE_CW_PRNG);
}

void decaf_spongerng_stir (
decaf_keccak_prng_t decaf_sponge,
const uint8_t * __restrict__ in,
size_t len
) {
decaf_TOY_strobe_transact((keccak_decaf_TOY_strobe_s*)decaf_sponge,NULL,in,len,STROBE_CW_PRNG_USER_SEED);
}

static const struct decaf_kparams_s decaf_spongerng_params = {
0, 0, 200-256/4, 0, 0x06, 0x80, 0xFF, 0
};

void decaf_spongerng_init_from_buffer (
decaf_keccak_prng_t prng,
const uint8_t * __restrict__ in,
size_t len,
int deterministic
) {
decaf_keccak_sponge_s *decaf_sponge = prng->sponge;
decaf_TOY_strobe_init((keccak_decaf_TOY_strobe_s*)decaf_sponge, &decaf_spongerng_params, SPONGERNG_NAME, !deterministic);
decaf_spongerng_stir(prng, in, len);
}

decaf_error_t decaf_spongerng_init_from_file (
decaf_keccak_prng_t prng,
const char *file,
size_t len,
int deterministic
) {
decaf_keccak_sponge_s *decaf_sponge = prng->sponge;
decaf_TOY_strobe_init((keccak_decaf_TOY_strobe_s*)decaf_sponge, &decaf_spongerng_params, SPONGERNG_NAME, !deterministic);
if (!len) return DECAF_FAILURE;

int fd = open(file, O_RDONLY);
if (fd < 0) return DECAF_FAILURE;
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 DECAF_FAILURE;
}
decaf_TOY_strobe_transact((keccak_decaf_TOY_strobe_s*)decaf_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 DECAF_SUCCESS;
}

decaf_error_t decaf_spongerng_init_from_dev_urandom (
decaf_keccak_prng_t decaf_sponge
) {
return decaf_spongerng_init_from_file(decaf_sponge, "/dev/urandom", 64, 0);
}

const struct decaf_kparams_s STROBE_128 = { 0, 0, 200-128/4, 0, 0, 0, 0, 0 };
const struct decaf_kparams_s STROBE_256 = { 0, 0, 200-256/4, 0, 0, 0, 0, 0 };
const struct decaf_kparams_s STROBE_KEYED_256 = { 0, 0, 200-256/4, 12, 0, 0, 0, 0 };
const struct decaf_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 decaf_TOY_strobe_init(
keccak_decaf_TOY_strobe_t strobe,
const struct decaf_kparams_s *params,
const char *proto,
uint8_t am_client
) {
decaf_keccak_sponge_s *decaf_sponge = strobe->sponge;
decaf_sponge_init(decaf_sponge,params);
const char *a_string = "STROBE full v0.2";
unsigned len = strlen(a_string);
memcpy (
&decaf_sponge->state->b[sizeof(decaf_sponge->state)-len],
a_string,
len
);
decaf_TOY_strobe_transact(strobe, NULL, (const unsigned char *)proto, strlen(proto), STROBE_CW_INIT);
decaf_sponge->state->b[decaf_sponge->params->rate+1] = 1;
decaf_sponge->params->client = !!am_client;
}

static const uint8_t EXCEEDED_RATE_PAD = 0x2;
static __inline__ uint8_t CONTROL_WORD_PAD(int cw_size) {
assert(cw_size >= 0 && cw_size <= 31);
return 0xC0 | cw_size;
}

/* PERF vectorize */
static void decaf_TOY_strobe_duplex (
struct decaf_keccak_sponge_s *__restrict__ decaf_sponge,
unsigned char *out,
const unsigned char *in,
size_t len,
mode_t mode
) {
unsigned int j, r = decaf_sponge->params->rate, p = decaf_sponge->params->position;
uint8_t* __restrict__ state = &decaf_sponge->state->b[0];
/* sanity */
assert(r < sizeof(decaf_sponge->state) && r >= p);
switch (mode) {
case STROBE_MODE_PLAINTEXT:
assert(in || len==0);
break;
case STROBE_MODE_ABSORB:
case STROBE_MODE_ABSORB_R:
assert((in||len==0) && !out);
break;
case STROBE_MODE_DUPLEX:
case STROBE_MODE_DUPLEX_R:
assert((in && out) || len==0);
break;
case STROBE_MODE_SQUEEZE:
case STROBE_MODE_SQUEEZE_R:
assert((out || len==0) && !in);
break;
case STROBE_MODE_FORGET:
assert(!in && !out);
break;
default:
assert(0);
}
while(1) {
unsigned int cando = r - p;
unsigned int last = (cando >= len);
if (last) {
cando = len;
}
if (cando) {
switch (mode) {
case STROBE_MODE_PLAINTEXT:
for (j=0; j<cando; j++) state[p+j] ^= in[j];
if (out) {
assert(in != NULL);
memcpy(out, in, cando);
out += cando;
}
in += cando;
break;
case STROBE_MODE_ABSORB:
for (j=0; j<cando; j++) state[p+j] ^= in[j];
in += cando;
break;
case STROBE_MODE_ABSORB_R:
assert(in != NULL);
memcpy(state+p, in, cando);
in += cando;
break;
case STROBE_MODE_SQUEEZE:
assert(out != NULL);
memcpy(out, state+p, cando);
out += cando;
break;
case STROBE_MODE_SQUEEZE_R:
assert(out != NULL);
memcpy(out, state+p, cando);
out += cando;
memset(state+p, 0, cando);
break;
case STROBE_MODE_FORGET:
memset(state+p, 0, cando);
break;
case STROBE_MODE_DUPLEX:
for (j=0; j<cando; j++) {
state[p+j] ^= in[j];
out[j] = state[p+j];
}
in += cando;
out += cando;
break;
case STROBE_MODE_DUPLEX_R:
for (j=0; j<cando; j++) {
unsigned char c = in[j];
out[j] = c ^ state[p+j];
state[p+j] = c;
}
in += cando;
out += cando;
break;

default:
assert(0);
};
}
if (last) {
decaf_sponge->params->position = p+len;
return;
} else {
state[r] ^= EXCEEDED_RATE_PAD;
keccakf(decaf_sponge->state, decaf_sponge->params->start_round);
len -= cando;
p = 0;
}
}
}

static inline mode_t get_mode ( uint32_t cw_flags ) {
return (mode_t)((cw_flags >> 29) & 7);
}

static const int STROBE_FORGET_BYTES = 32;

static const uint8_t FLAG_NOPARSE = 1;

void decaf_TOY_strobe_transact (
keccak_decaf_TOY_strobe_t strobe,
unsigned char *out,
const unsigned char *in,
size_t len,
uint32_t cw_flags
) {
decaf_keccak_sponge_s *decaf_sponge = strobe->sponge;
if ( (cw_flags & STROBE_FLAG_NONDIR) == 0
/* extraneous nots to change ints to bools :-/ */
&& !(cw_flags & STROBE_FLAG_RECV) != !(decaf_sponge->params->client) ) {
cw_flags ^= STROBE_FLAG_CLIENT_SENT;
}
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 if ((cw_flags & STROBE_FLAG_LENGTH_64)==0) {
assert(my_len < 1<<16);
}
if (cw_flags & STROBE_FLAG_MORE) {
assert(cw_flags & STROBE_FLAG_NO_LENGTH); /* FUTURE */
} else {
uint8_t cwb[10] = {
cw_flags,
cw_flags>>8,
my_len,
my_len>>8,
my_len>>16,
my_len>>24,
my_len>>32,
my_len>>40,
my_len>>48,
my_len>>56
};
decaf_TOY_strobe_duplex(decaf_sponge, NULL, cwb, len_cw, STROBE_MODE_ABSORB_R);
if ((cw_flags & STROBE_FLAG_RUN_F) || (decaf_sponge->params->flags & FLAG_NOPARSE)) {
decaf_sponge->state->b[decaf_sponge->params->position] ^= CONTROL_WORD_PAD(len_cw);
dokeccak(decaf_sponge);
}

decaf_sponge->params->flags &= ~FLAG_NOPARSE;
if (cw_flags & STROBE_FLAG_NO_LENGTH) {
decaf_sponge->params->flags |= FLAG_NOPARSE;
}
}
decaf_TOY_strobe_duplex(decaf_sponge, out, in, len, get_mode(cw_flags));
if (cw_flags & STROBE_FLAG_FORGET) {
uint32_t len = decaf_sponge->params->rate - decaf_sponge->params->position;
if (len < STROBE_FORGET_BYTES + len_cw) len += decaf_sponge->params->rate;
len -= len_cw; /* HACK */
if (cw_flags & STROBE_FLAG_NO_LENGTH) len = 2*STROBE_FORGET_BYTES;
assert(!(cw_flags & STROBE_FLAG_MORE));
decaf_TOY_strobe_duplex(
decaf_sponge, NULL, NULL, len,
STROBE_MODE_FORGET
);
}
}

decaf_error_t decaf_TOY_strobe_verify_auth (
keccak_decaf_TOY_strobe_t strobe,
const unsigned char *in,
uint16_t len
) {
decaf_keccak_sponge_s *decaf_sponge = strobe->sponge;
if (len > decaf_sponge->params->rate) return DECAF_FAILURE;
decaf_TOY_strobe_transact(strobe, NULL, in, len, decaf_TOY_strobe_cw_recv(STROBE_CW_MAC));
int32_t residue = 0;
int i;
for (i=0; i<len; i++) {
residue |= decaf_sponge->state->b[i];
}
return decaf_succeed_if((residue-1)>>8);
}

void decaf_TOY_strobe_respec (
keccak_decaf_TOY_strobe_t strobe,
const struct decaf_kparams_s *params
) {
decaf_keccak_sponge_s *decaf_sponge = strobe->sponge;
uint8_t in[] = { params->rate, params->start_round };
decaf_TOY_strobe_transact( strobe, NULL, in, sizeof(in), STROBE_CW_RESPEC_INFO );
decaf_TOY_strobe_transact( strobe, NULL, NULL, 0, STROBE_CW_RESPEC );
assert(decaf_sponge->params->position == 0);
decaf_sponge->params->rate = params->rate;
decaf_sponge->params->start_round = params->start_round;
}

+ 0
- 214
test/bench_decaf.cxx View File

@@ -12,11 +12,7 @@
#include <decaf.hxx>
#include <decaf/shake.hxx>
#include <decaf/sha512.hxx>
#include <decaf/strobe.hxx>
#include <decaf/spongerng.hxx>
#include <decaf/crypto_255.h>
#include <decaf/crypto_448.h>
#include <decaf/crypto.hxx>
#include <decaf/eddsa.hxx>
#include <stdio.h>
#include <sys/time.h>
@@ -26,7 +22,6 @@
#include <algorithm>

using namespace decaf;
using namespace decaf::TOY;


static __inline__ void __attribute__((unused)) ignore_result ( int result ) { (void)result; }
@@ -157,146 +152,6 @@ typedef typename Group::Scalar Scalar;
typedef typename Group::Point Point;
typedef typename Group::Precomputed Precomputed;

static void tdh (
SpongeRng &clientRng,
SpongeRng &serverRng,
Scalar x, const Block &gx,
Scalar y, const Block &gy
) {
/* "TripleDH". A bit of a hack, really: the real TripleDH
* sends gx and gy and certs over the channel, but its goal
* is actually the opposite of STROBE in this case: it doesn't
* hash gx and gy into the session secret (only into the MAC
* and AD) because of IPR concerns.
*/
Strobe client("example::tripleDH",Strobe::CLIENT), server("example::tripleDH",Strobe::SERVER);
Scalar xe(clientRng);
SecureBuffer gxe((Precomputed::base() * xe).serialize());
client.send_plaintext(gxe);
server.recv_plaintext(gxe);
Scalar ye(serverRng);
SecureBuffer gye((Precomputed::base() * ye).serialize());
server.send_plaintext(gye);
client.recv_plaintext(gye);
Point pgxe(gxe);
server.dh_key(pgxe*ye);
SecureBuffer tag1 = server.produce_auth();
//SecureBuffer ct = server.encrypt(gy);
server.dh_key(pgxe*y);
SecureBuffer tag2 = server.produce_auth();
Point pgye(gye);
client.dh_key(pgye*xe);
client.verify_auth(tag1);
client.dh_key(Point(gy) * xe);
client.verify_auth(tag2);
// ct = client.encrypt(gx);
client.dh_key(pgye * x);
tag1 = client.produce_auth();
client.respec(STROBE_KEYED_128);
server.dh_key(Point(gx) * ye);
server.verify_auth(tag1);
server.respec(STROBE_KEYED_128);
}

static void fhmqv (
SpongeRng &clientRng,
SpongeRng &serverRng,
Scalar x, const Block &gx,
Scalar y, const Block &gy
) {
/* Don't use this, it's probably patented */
Strobe client("example::fhmqv",Strobe::CLIENT), server("example::fhmqv",Strobe::SERVER);
Scalar xe(clientRng);
client.send_plaintext(gx);
server.recv_plaintext(gx);
SecureBuffer gxe((Precomputed::base() * xe).serialize());
server.send_plaintext(gxe);
client.recv_plaintext(gxe);

Scalar ye(serverRng);
server.send_plaintext(gy);
client.recv_plaintext(gy);
SecureBuffer gye((Precomputed::base() * ye).serialize());
server.send_plaintext(gye);
Scalar schx(server.prng(Scalar::SER_BYTES));
Scalar schy(server.prng(Scalar::SER_BYTES));
Scalar yec = y + ye*schy;
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.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);
server.verify_auth(ac);
server.respec(STROBE_KEYED_128);
}

static void spake2ee(
SpongeRng &clientRng,
SpongeRng &serverRng,
const Block &hashed_password,
bool aug
) {
Strobe client("example::spake2ee",Strobe::CLIENT), server("example::spake2ee",Strobe::SERVER);
Scalar x(clientRng);
SHAKE<256> shake;
shake.update(hashed_password);
SecureBuffer h0 = shake.output(Point::HASH_BYTES);
SecureBuffer h1 = shake.output(Point::HASH_BYTES);
SecureBuffer h2 = shake.output(Scalar::SER_BYTES);
Scalar gs(h2);
Point hc = Point::from_hash(h0);
hc = Point::from_hash(h0); // double-count
Point hs = Point::from_hash(h1);
hs = Point::from_hash(h1); // double-count
SecureBuffer gx((Precomputed::base() * x + hc).serialize());
client.send_plaintext(gx);
server.recv_plaintext(gx);
Scalar y(serverRng);
SecureBuffer gy((Precomputed::base() * y + hs).serialize());
server.send_plaintext(gy);
client.recv_plaintext(gy);
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.dh_key(Point(serverAug)*y);
}
SecureBuffer tag = server.produce_auth();
client.dh_key(h1);
Point pgy(gy); pgy -= hs;
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);
/* A real protocol would continue with fork etc here... */
server.verify_auth(tag);
server.respec(STROBE_KEYED_128);
}

static void cfrg() {
SpongeRng rng(Block("bench_cfrg_crypto"),SpongeRng::DETERMINISTIC);
FixedArrayBuffer<Group::DhLadder::PUBLIC_BYTES> base(rng);
@@ -318,57 +173,6 @@ static void macro() {
printf("\nMacro-benchmarks for %s:\n", Group::name());
printf("CFRG crypto benchmarks:\n");
cfrg();
printf("\nToy crypto benchmarks:\n");
SpongeRng rng(Block("macro rng seed"),SpongeRng::DETERMINISTIC);
PrivateKey<Group> s1((NOINIT())), s2(rng);
PublicKey<Group> p1((NOINIT())), p2(s2);

SecureBuffer message = rng.read(5), sig, ss;

for (Benchmark b("Create private key",1); b.iter(); ) {
s1 = PrivateKey<Group>(rng);
SecureBuffer bb = s1.serialize();
}
for (Benchmark b("Sign",1); b.iter(); ) {
sig = s1.sign(message);
}
p1 = s1.pub();
for (Benchmark b("Verify",1); b.iter(); ) {
rng.read(Buffer(message));
try { p1.verify(message, sig); } catch (CryptoException) {}
}
for (Benchmark b("SharedSecret",1); b.iter(); ) {
ss = s1.shared_secret(p2,32,true);
}
printf("\nToy protocol benchmarks:\n");
SpongeRng clientRng(Block("client rng seed"),SpongeRng::DETERMINISTIC);
SpongeRng serverRng(Block("server rng seed"),SpongeRng::DETERMINISTIC);
SecureBuffer hashedPassword(Block("hello world"));
for (Benchmark b("Spake2ee c+s",0.1); b.iter(); ) {
spake2ee(clientRng, serverRng, hashedPassword,false);
}
for (Benchmark b("Spake2ee c+s aug",0.1); b.iter(); ) {
spake2ee(clientRng, serverRng, hashedPassword,true);
}
Scalar x(clientRng);
SecureBuffer gx((Precomputed::base() * x).serialize());
Scalar y(serverRng);
SecureBuffer gy((Precomputed::base() * y).serialize());
for (Benchmark b("FHMQV c+s",0.1); b.iter(); ) {
fhmqv(clientRng, serverRng,x,gx,y,gy);
}
for (Benchmark b("TripleDH anon c+s",0.1); b.iter(); ) {
tdh(clientRng, serverRng, x,gx,y,gy);
}
}

static void micro() {
@@ -421,29 +225,11 @@ int main(int argc, char **argv) {
SHAKE<256> shake2;
SHA3<512> sha5;
SHA512 sha2;
Strobe strobe("example::bench",Strobe::CLIENT);
unsigned char b1024[1024] = {1};
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); }
for (Benchmark b("SHA512 1kiB", 30); b.iter(); ) { sha2 += 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));
}
strobe.respec(STROBE_256);
for (Benchmark b("STROBE256 1kiB", 10); b.iter(); ) {
strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024));
}
strobe.respec(STROBE_KEYED_128);
for (Benchmark b("STROBEk128 1kiB", 10); b.iter(); ) {
strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024));
}
strobe.respec(STROBE_KEYED_256);
for (Benchmark b("STROBEk256 1kiB", 10); b.iter(); ) {
strobe.encrypt_no_auth(Buffer(b1024,1024),Buffer(b1024,1024));
}
run_for_all_curves<Micro>();
}


+ 48
- 31
test/test_decaf.cxx View File

@@ -11,13 +11,10 @@

#include <decaf.hxx>
#include <decaf/spongerng.hxx>
#include <decaf/crypto.h>
#include <decaf/crypto.hxx>
#include <decaf/eddsa.hxx>
#include <stdio.h>

using namespace decaf;
using namespace decaf::TOY;

static bool passing = true;
static const long NTESTS = 10000;
@@ -410,33 +407,6 @@ static void test_ec() {
}
}

static void test_toy_crypto() {
Test test("Toy crypto");
SpongeRng rng(Block("test_decaf_crypto"),SpongeRng::DETERMINISTIC);

for (int i=0; i<NTESTS && test.passing_now; i++) {
try {
PrivateKey<Group> priv1(rng), priv2(rng);
PublicKey<Group> pub1(priv1), pub2(priv2);
SecureBuffer message = rng.read(i);
SecureBuffer sig(priv1.sign(message));

pub1.verify(message, sig);
SecureBuffer s1(priv1.shared_secret(pub2,32,true));
SecureBuffer s2(priv2.shared_secret(pub1,32,false));
if (!memeq(s1,s2)) {
test.fail();
printf(" Shared secrets disagree on iteration %d.\n",i);
}
} catch (CryptoException) {
test.fail();
printf(" Threw CryptoException.\n");
}
}
}

static const uint8_t rfc7748_1[DhLadder::PUBLIC_BYTES];
static const uint8_t rfc7748_1000[DhLadder::PUBLIC_BYTES];
static const uint8_t rfc7748_1000000[DhLadder::PUBLIC_BYTES];
@@ -572,16 +542,63 @@ static void run() {
test_eddsa();
test_cfrg_crypto();
test_cfrg_vectors();
test_toy_crypto();
printf("\n");
}

}; /* template<GroupId GROUP> struct Tests */

static void test_rng() {
Test test("RNG");
SpongeRng rng_d1(Block("test_rng"),SpongeRng::DETERMINISTIC);
SpongeRng rng_d2(Block("test_rng"),SpongeRng::DETERMINISTIC);
SpongeRng rng_d3(Block("best_rng"),SpongeRng::DETERMINISTIC);
SpongeRng rng_n1;
SpongeRng rng_n2;
SecureBuffer s1,s2,s3;
for (int i=0; i<5; i++) {
s1 = rng_d1.read(16<<i);
s2 = rng_d2.read(16<<i);
s3 = rng_d3.read(16<<i);
if (s1 != s2) {
test.fail();
printf(" Deterministic RNG didn't match!\n");
}
if (s1 == s3) {
test.fail();
printf(" Deterministic matched with different data!\n");
}
rng_d1.stir("hello");
rng_d2.stir("hello");
rng_d3.stir("hello");
s1 = rng_n1.read(16<<i);
s2 = rng_n2.read(16<<i);
if (s1 == s2) {
test.fail();
printf(" Nondeterministic RNG matched!\n");
}
}
rng_d1.stir("hello");
rng_d2.stir("jello");
s1 = rng_d1.read(16);
s2 = rng_d2.read(16);
if (s1 == s2) {
test.fail();
printf(" Deterministic matched with different data!\n");
}
}

#include "vectors.inc.cxx"

int main(int argc, char **argv) {
(void) argc; (void) argv;
test_rng();
printf("\n");
run_for_all_curves<Tests>();
if (passing) printf("Passed all tests.\n");
return passing ? 0 : 1;


Loading…
Cancel
Save