| @@ -61,6 +61,14 @@ void API_NS(private_to_public) ( | |||
| 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 | |||
| API_NS(shared_secret) ( | |||
| uint8_t *shared, | |||
| @@ -82,7 +90,8 @@ API_NS(shared_secret) ( | |||
| strobe_ad(strobe,my_privkey->pub,sizeof(API_NS(public_key_t))); | |||
| } | |||
| 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); | |||
| @@ -161,6 +161,16 @@ public: | |||
| } | |||
| 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. */ | |||
| inline SecureBuffer sign(const Block &message) const { | |||
| @@ -88,7 +88,7 @@ public: | |||
| /** Construct from RNG */ | |||
| inline explicit Scalar(Rng &rng) NOEXCEPT { | |||
| FixedArrayBuffer<SER_BYTES> sb(rng); | |||
| FixedArrayBuffer<SER_BYTES + 16> sb(rng); | |||
| *this = sb; | |||
| } | |||
| @@ -445,9 +445,8 @@ public: | |||
| if (buf.size() < HASH_BYTES) { | |||
| 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)); | |||
| return decaf_succeed_if(ret); | |||
| @@ -55,11 +55,13 @@ static void test_arithmetic() { | |||
| static void test_elligator() { | |||
| SpongeRng rng(Block("test_elligator")); | |||
| rng.stir(undef_block); | |||
| FixedArrayBuffer<Group::Point::HASH_BYTES> inv; | |||
| 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==q); | |||
| (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); | |||
| p.dual_scalarmul(q,r,y,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() { | |||
| SpongeRng rng(Block("test_crypto")); | |||
| 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++) { | |||
| PrivateKey<Group> sk1(rng); | |||
| PrivateKey<Group> sk2(rng); | |||
| 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 | |||
| } | |||
| } | |||