/** * @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 "shake.hxx" #include "decaf_crypto.h" #include 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.encode(buffer); printf(" %s = 0x", name); for (int i=sizeof(buffer)-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.encode(buffer); printf(" %s = 0x", name); for (int i=sizeof(buffer)-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 &r, const Scalar &l, const char *name ) { if (l == r) return true; test.fail(); printf(" %s", name); print("x", x); print("y", y); print("z", z); print("lhs", r); print("rhs", l); 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", l); print("rhs", r); return false; } static void test_arithmetic() { decaf::SpongeRng rng(decaf::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=8) p.debugging_torque_in_place(); bool succ = p.invert_elligator(b1,i&7); Point q; unsigned char hint = q.set_to_hash(b1); if (succ != ((i&7) != 4) || (q != p) || (succ && (hint != (i&7)))) { test.fail(); printf("Elligator test: t=%d, h=%d->%d, q%sp, %s %02x%02x\n", i/8, i&7, hint, (q==p)?"==":"!=",succ ? "SUCC" : "FAIL", b1[0], b1[1]); } } for (int i=0; i Point::HASH_BYTES) memcpy(&b2[Point::HASH_BYTES], &b1[Point::HASH_BYTES], len-Point::HASH_BYTES); Point s; unsigned char hint = s.set_to_hash(b1); if (i&1) s.debugging_torque_in_place(); bool succ = s.invert_elligator(b2,hint); if (!succ || memcmp(b1,b2,len)) { test.fail(); printf(" Fail elligator inversion i=%d, len=%d (claimed %s, hint=0x%02x)\n", i, (int)len, succ ? "success" : "failure", hint); } // Point t(rng); //point_check(test,t,t,t,0,0,t,Point::from_hash(t.steg_encode(rng)),"steg round-trip"); } } static void test_ec() { decaf::SpongeRng rng(decaf::Block("test_ec")); Test test("EC"); Point id = Point::identity(), base = Point::base(); point_check(test,id,id,id,0,0,Point::from_hash(""),id,"fh0"); //point_check(test,id,id,id,0,0,Point::from_hash("\x01"),id,"fh1"); // FIXME for (int i=0; i static void test_decaf() { Test test("Sample crypto"); decaf::SpongeRng rng(decaf::Block("test_decaf")); decaf_255_symmetric_key_t proto1,proto2; decaf_255_private_key_t s1,s2; decaf_255_public_key_t p1,p2; decaf_255_signature_t sig; unsigned char shared1[1234],shared2[1234]; const char *message = "Hello, world!"; for (int i=0; i::test_arithmetic(); Tests::test_elligator(); Tests::test_ec(); test_decaf(); if (passing) printf("Passed all tests.\n"); return passing ? 0 : 1; }