/** * @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 #include #include #include #include using namespace decaf; static bool passing = true; static const long NTESTS = 10000; class Test { public: bool passing_now; Test(const char *test) { passing_now = true; printf("%s...", test); if (strlen(test) < 27) printf("%*s",int(27-strlen(test)),""); fflush(stdout); } ~Test() { if (std::uncaught_exception()) { fail(); printf(" due to uncaught exception.\n"); } if (passing_now) printf("[PASS]\n"); } void fail() { if (!passing_now) return; passing_now = passing = false; printf("[FAIL]\n"); } }; template struct Tests { typedef typename Group::Scalar Scalar; typedef typename Group::Point Point; typedef typename Group::Precomputed Precomputed; static void print(const char *name, const Scalar &x) { unsigned char buffer[Scalar::SER_BYTES]; x.serialize_into(buffer); printf(" %s = 0x", name); for (int i=sizeof(buffer)-1; i>=0; i--) { printf("%02x", buffer[i]); } printf("\n"); } static void hexprint(const char *name, const SecureBuffer &buffer) { printf(" %s = 0x", name); for (int i=buffer.size()-1; i>=0; i--) { printf("%02x", buffer[i]); } printf("\n"); } static void print(const char *name, const Point &x) { unsigned char buffer[Point::SER_BYTES]; x.serialize_into(buffer); printf(" %s = 0x", name); for (int i=Point::SER_BYTES-1; i>=0; i--) { printf("%02x", buffer[i]); } printf("\n"); } static bool arith_check( Test &test, const Scalar &x, const Scalar &y, const Scalar &z, const Scalar &l, const Scalar &r, const char *name ) { if (l == r) return true; test.fail(); printf(" %s", name); print("x", x); print("y", y); print("z", z); print("lhs", l); print("rhs", r); return false; } static bool point_check( Test &test, const Point &p, const Point &q, const Point &R, const Scalar &x, const Scalar &y, const Point &l, const Point &r, const char *name ) { bool good = l==r; if (!p.validate()) { good = false; printf(" p invalid\n"); } if (!q.validate()) { good = false; printf(" q invalid\n"); } if (!r.validate()) { good = false; printf(" r invalid\n"); } if (!l.validate()) { good = false; printf(" l invalid\n"); } if (good) return true; test.fail(); printf(" %s", name); print("x", x); print("y", y); print("p", p); print("q", q); print("r", R); print("lhs", r); print("rhs", l); return false; } static void test_arithmetic() { SpongeRng rng(Block("test_arithmetic")); Test test("Arithmetic"); Scalar x(0),y(0),z(0); arith_check(test,x,y,z,INT_MAX,(decaf_word_t)INT_MAX,"cast from max"); arith_check(test,x,y,z,INT_MIN,-Scalar(1+(decaf_word_t)INT_MAX),"cast from min"); for (int i=0; i= Point::HASH_BYTES) b1[Point::HASH_BYTES-1] &= 0x7F; // FIXME MAGIC Point s = Point::from_hash(b1), ss=s; for (int j=0; j<(i&3); j++) ss = ss.debugging_torque(); ss = ss.debugging_pscale(rng); bool good = false; for (int j=0; j Point::HASH_BYTES) memcpy(&(*alts[j])[Point::HASH_BYTES], &b1[Point::HASH_BYTES], len-Point::HASH_BYTES); if (len > Point::HASH_BYTES) memcpy(&(*alts2[j])[Point::HASH_BYTES], &b1[Point::HASH_BYTES], len-Point::HASH_BYTES); successes[j] = decaf_successful( s.invert_elligator(*alts[j], j)); successes2[j] = decaf_successful(ss.invert_elligator(*alts2[j],j)); if (successes[j] != successes2[j] || (successes[j] && successes2[j] && *alts[j] != *alts2[j]) ) { test.fail(); printf(" Unscalable Elligator inversion: i=%d, hint=%d, s=%d,%d\n",i,j, -int(successes[j]),-int(successes2[j])); hexprint("x",b1); hexprint("X",*alts[j]); hexprint("X",*alts2[j]); } if (successes[j]) { good = good || (b1 == *alts[j]); for (int k=0; k priv1(rng), priv2(rng); PublicKey pub1(priv1), pub2(priv2); SecureBuffer message = rng.read(i); SecureBuffer sig(priv1.sign(message)); pub1.verify(message, sig); SecureBuffer s1(priv1.sharedSecret(pub2,32,true)); SecureBuffer s2(priv2.sharedSecret(pub1,32,false)); if (memcmp(s1.data(),s2.data(),s1.size())) { test.fail(); printf(" Shared secrets disagree."); } } } }; /* template */ int main(int argc, char **argv) { (void) argc; (void) argv; printf("Testing %s:\n",IsoEd25519::name()); Tests::test_arithmetic(); Tests::test_elligator(); Tests::test_ec(); Tests::test_crypto(); printf("\n"); printf("Testing %s:\n", Ed448Goldilocks::name()); Tests::test_arithmetic(); Tests::test_elligator(); Tests::test_ec(); Tests::test_crypto(); if (passing) printf("Passed all tests.\n"); return passing ? 0 : 1; }