@@ -61,6 +61,14 @@ void API_NS(private_to_public) ( | |||||
memcpy(pub, priv->pub, sizeof(API_NS(public_key_t))); | memcpy(pub, priv->pub, sizeof(API_NS(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 | decaf_error_t | ||||
API_NS(shared_secret) ( | API_NS(shared_secret) ( | ||||
uint8_t *shared, | uint8_t *shared, | ||||
@@ -82,7 +90,8 @@ API_NS(shared_secret) ( | |||||
strobe_ad(strobe,my_privkey->pub,sizeof(API_NS(public_key_t))); | strobe_ad(strobe,my_privkey->pub,sizeof(API_NS(public_key_t))); | ||||
} | } | ||||
decaf_error_t ret = API_NS(direct_scalarmul)( | decaf_error_t ret = API_NS(direct_scalarmul)( | ||||
ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE, DECAF_TRUE | |||||
ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE, | |||||
DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
); | ); | ||||
strobe_transact(strobe,NULL,ss_ser,sizeof(ss_ser),STROBE_CW_DH_KEY); | strobe_transact(strobe,NULL,ss_ser,sizeof(ss_ser),STROBE_CW_DH_KEY); | ||||
@@ -161,6 +161,16 @@ public: | |||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
/** Derive a shared secret */ | |||||
inline decaf_error_t __attribute__((warn_unused_result)) | |||||
sharedSecretNoexcept( | |||||
Buffer ret, | |||||
const PublicKey<%(cxx_ns)s> &pub, | |||||
bool me_first | |||||
) const NOEXCEPT { | |||||
return %(c_ns)s_shared_secret(ret.data(),ret.size(),wrapped,pub.wrapped,me_first); | |||||
} | |||||
/** Sign a message. */ | /** Sign a message. */ | ||||
inline SecureBuffer sign(const Block &message) const { | inline SecureBuffer sign(const Block &message) const { | ||||
@@ -88,7 +88,7 @@ public: | |||||
/** Construct from RNG */ | /** Construct from RNG */ | ||||
inline explicit Scalar(Rng &rng) NOEXCEPT { | inline explicit Scalar(Rng &rng) NOEXCEPT { | ||||
FixedArrayBuffer<SER_BYTES> sb(rng); | |||||
FixedArrayBuffer<SER_BYTES + 16> sb(rng); | |||||
*this = sb; | *this = sb; | ||||
} | } | ||||
@@ -445,9 +445,8 @@ public: | |||||
if (buf.size() < HASH_BYTES) { | if (buf.size() < HASH_BYTES) { | ||||
ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); | ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); | ||||
} | } | ||||
if (ret) { | |||||
/* TODO: make this constant time?? */ | |||||
memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); | |||||
for (size_t i=0; i<buf.size() && i<HASH_BYTES; i++) { | |||||
buf[i] = (buf[i] & ~ret) | (buf2[i] &ret); | |||||
} | } | ||||
decaf_bzero(buf2,sizeof(buf2)); | decaf_bzero(buf2,sizeof(buf2)); | ||||
return decaf_succeed_if(ret); | return decaf_succeed_if(ret); | ||||
@@ -55,11 +55,13 @@ static void test_arithmetic() { | |||||
static void test_elligator() { | static void test_elligator() { | ||||
SpongeRng rng(Block("test_elligator")); | SpongeRng rng(Block("test_elligator")); | ||||
rng.stir(undef_block); | rng.stir(undef_block); | ||||
FixedArrayBuffer<Group::Point::HASH_BYTES> inv; | |||||
for (int i=0; i<NTESTS; i++) { | for (int i=0; i<NTESTS; i++) { | ||||
Point x(rng); | |||||
(void)x; | |||||
/* TODO: uniform, nonuniform... */ | |||||
Point x(rng), y(rng,false); | |||||
ignore((x+y).invert_elligator(inv,i)); | |||||
} | } | ||||
} | } | ||||
@@ -82,7 +84,7 @@ static void test_ec() { | |||||
(void)(p.times_two()); | (void)(p.times_two()); | ||||
(void)(p==q); | (void)(p==q); | ||||
(void)(p.debugging_torque()); | (void)(p.debugging_torque()); | ||||
//(void)(p.non_secret_combo_with_base(y,z)); // Should fail | |||||
/* (void)(p.non_secret_combo_with_base(y,z)); */ /* Should fail */ | |||||
(void)(Precomputed(p)*y); | (void)(Precomputed(p)*y); | ||||
p.dual_scalarmul(q,r,y,z); | p.dual_scalarmul(q,r,y,z); | ||||
Group::Point::double_scalarmul(p,y,q,z); | Group::Point::double_scalarmul(p,y,q,z); | ||||
@@ -90,17 +92,32 @@ static void test_ec() { | |||||
} | } | ||||
} | } | ||||
/* Specify the same value as you did when compiling decaf_crypto.c */ | |||||
#ifndef DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
#define DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT DECAF_FALSE | |||||
#endif | |||||
static void test_crypto() { | static void test_crypto() { | ||||
SpongeRng rng(Block("test_crypto")); | SpongeRng rng(Block("test_crypto")); | ||||
rng.stir(undef_block); | rng.stir(undef_block); | ||||
#if DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
SpongeRng defrng(Block("test_crypto_defined")); | |||||
#endif | |||||
FixedArrayBuffer<Group::Point::SER_BYTES> shared; | |||||
for (int i=0; i<NTESTS; i++) { | for (int i=0; i<NTESTS; i++) { | ||||
PrivateKey<Group> sk1(rng); | PrivateKey<Group> sk1(rng); | ||||
PrivateKey<Group> sk2(rng); | |||||
SecureBuffer sig = sk1.sign(undef_block); | SecureBuffer sig = sk1.sign(undef_block); | ||||
//sk.pub().verify(undef_block,sig); would fail. FUTURE: ct version of this? | |||||
/* TODO: shared_secret nothrow? have to test shared_secret... */ | |||||
#if DECAF_CRYPTO_SHARED_SECRET_SHORT_CIRUIT | |||||
PrivateKey<Group> sk2(defrng); | |||||
(void)sk1.sharedSecretNoexcept(shared,sk2.pub(),i&1); | |||||
#else | |||||
PrivateKey<Group> sk3(rng); | |||||
(void)sk1.sharedSecretNoexcept(shared,sk3.pub(),i&1); | |||||
#endif | |||||
} | } | ||||
} | } | ||||