/** * @file test_decaf.cxx * @author Mike Hamburg * * @copyright * Copyright (c) 2015 Cryptography Research, Inc. \n * Released under the MIT License. See LICENSE.txt for license information. * * @brief C++ tests, because that's easier. */ #include <decaf.hxx> #include <decaf/spongerng.hxx> #include <decaf/crypto.h> #include <decaf/crypto.hxx> #include <stdio.h> #include <valgrind/memcheck.h> using namespace decaf; static const long NTESTS = 10; const char *undef_str = "Valgrind thinks this string is undefined."; const Block undef_block(undef_str); static inline void ignore(decaf_error_t x) { (void)x; } template<typename Group> struct Tests { typedef typename Group::Scalar Scalar; typedef typename Group::Point Point; typedef typename Group::Precomputed Precomputed; static void test_arithmetic() { SpongeRng rng(Block("test_arithmetic"),SpongeRng::DETERMINISTIC); rng.stir(undef_block); Scalar x(rng),y(rng),z; uint8_t ser[Group::Scalar::SER_BYTES]; for (int i=0; i<NTESTS; i++) { (void)(x+y); (void)(x-y); (void)(x*y); ignore(x.inverse_noexcept(y)); (void)(x==y); (void)(z=y); x.serialize_into(ser); x = y; } } static void test_elligator() { SpongeRng rng(Block("test_elligator"),SpongeRng::DETERMINISTIC); rng.stir(undef_block); FixedArrayBuffer<Group::Point::HASH_BYTES> inv; for (int i=0; i<NTESTS; i++) { Point x(rng), y(rng,false); ignore((x+y).invert_elligator(inv,i)); } } static void test_ec() { SpongeRng rng(Block("test_ec"),SpongeRng::DETERMINISTIC); rng.stir(undef_block); uint8_t ser[Group::Point::SER_BYTES]; for (int i=0; i<NTESTS; i++) { Scalar y(rng),z(rng); Point p(rng),q(rng),r; p.serialize_into(ser); ignore(Group::Point::decode(p,FixedBlock<Group::Point::SER_BYTES>(ser))); (void)(p*y); (void)(p+q); (void)(p-q); (void)(-p); (void)(p.times_two()); (void)(p==q); (void)(p.debugging_torque()); /* (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); } } static void test_cfrg() { SpongeRng rng(Block("test_cfrg"),SpongeRng::DETERMINISTIC); rng.stir(undef_block); for (int i=0; i<NTESTS; i++) { FixedArrayBuffer<Group::DhLadder::PUBLIC_BYTES> pub(rng); FixedArrayBuffer<Group::DhLadder::PRIVATE_BYTES> priv(rng); Group::DhLadder::generate_key(priv); ignore(Group::DhLadder::shared_secret_noexcept(pub,pub,priv)); } } /* 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"),SpongeRng::DETERMINISTIC); 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); SecureBuffer sig = sk1.sign(undef_block); #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 } } static void run() { printf("Testing %s:\n",Group::name()); test_arithmetic(); test_elligator(); test_ec(); test_cfrg(); test_crypto(); printf("\n"); } }; /* template<GroupId GROUP> struct Tests */ int main(int argc, char **argv) { (void) argc; (void) argv; VALGRIND_MAKE_MEM_UNDEFINED(undef_str, strlen(undef_str)); run_for_all_curves<Tests>(); return 0; }