You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

657 lines
22 KiB

  1. /**
  2. * @file test_decaf.cxx
  3. * @author Mike Hamburg
  4. *
  5. * @copyright
  6. * Copyright (c) 2015 Cryptography Research, Inc. \n
  7. * Released under the MIT License. See LICENSE.txt for license information.
  8. *
  9. * @brief C++ tests, because that's easier.
  10. */
  11. #include <decaf.hxx>
  12. #include <decaf/spongerng.hxx>
  13. #include <decaf/eddsa.hxx>
  14. #include <stdio.h>
  15. using namespace decaf;
  16. static bool passing = true;
  17. static const long NTESTS = 10000;
  18. class Test {
  19. public:
  20. bool passing_now;
  21. Test(const char *test) {
  22. passing_now = true;
  23. printf("%s...", test);
  24. if (strlen(test) < 27) printf("%*s",int(27-strlen(test)),"");
  25. fflush(stdout);
  26. }
  27. ~Test() {
  28. if (std::uncaught_exception()) {
  29. fail();
  30. printf(" due to uncaught exception.\n");
  31. }
  32. if (passing_now) printf("[PASS]\n");
  33. }
  34. void fail() {
  35. if (!passing_now) return;
  36. passing_now = passing = false;
  37. printf("[FAIL]\n");
  38. }
  39. };
  40. static uint64_t leint(const SecureBuffer &xx) {
  41. uint64_t out = 0;
  42. for (unsigned int i=0; i<xx.size() && i<sizeof(out); i++) {
  43. out |= uint64_t(xx[i]) << (8*i);
  44. }
  45. return out;
  46. }
  47. template<typename Group> struct Tests {
  48. typedef typename Group::Scalar Scalar;
  49. typedef typename Group::Point Point;
  50. typedef typename Group::DhLadder DhLadder;
  51. typedef typename Group::Precomputed Precomputed;
  52. static void print(const char *name, const Scalar &x) {
  53. unsigned char buffer[Scalar::SER_BYTES];
  54. x.serialize_into(buffer);
  55. printf(" %s = 0x", name);
  56. for (int i=sizeof(buffer)-1; i>=0; i--) {
  57. printf("%02x", buffer[i]);
  58. }
  59. printf("\n");
  60. }
  61. static void hexprint(const char *name, const SecureBuffer &buffer) {
  62. printf(" %s = 0x", name);
  63. for (int i=buffer.size()-1; i>=0; i--) {
  64. printf("%02x", buffer[i]);
  65. }
  66. printf("\n");
  67. }
  68. static void print(const char *name, const Point &x) {
  69. unsigned char buffer[Point::SER_BYTES];
  70. x.serialize_into(buffer);
  71. printf(" %s = 0x", name);
  72. for (int i=Point::SER_BYTES-1; i>=0; i--) {
  73. printf("%02x", buffer[i]);
  74. }
  75. printf("\n");
  76. }
  77. static bool arith_check(
  78. Test &test,
  79. const Scalar &x,
  80. const Scalar &y,
  81. const Scalar &z,
  82. const Scalar &l,
  83. const Scalar &r,
  84. const char *name
  85. ) {
  86. if (l == r) return true;
  87. test.fail();
  88. printf(" %s", name);
  89. print("x", x);
  90. print("y", y);
  91. print("z", z);
  92. print("lhs", l);
  93. print("rhs", r);
  94. return false;
  95. }
  96. static bool point_check(
  97. Test &test,
  98. const Point &p,
  99. const Point &q,
  100. const Point &R,
  101. const Scalar &x,
  102. const Scalar &y,
  103. const Point &l,
  104. const Point &r,
  105. const char *name
  106. ) {
  107. bool good = l==r;
  108. if (!p.validate()) { good = false; printf(" p invalid\n"); }
  109. if (!q.validate()) { good = false; printf(" q invalid\n"); }
  110. if (!r.validate()) { good = false; printf(" r invalid\n"); }
  111. if (!l.validate()) { good = false; printf(" l invalid\n"); }
  112. if (good) return true;
  113. test.fail();
  114. printf(" %s", name);
  115. print("x", x);
  116. print("y", y);
  117. print("p", p);
  118. print("q", q);
  119. print("r", R);
  120. print("lhs", r);
  121. print("rhs", l);
  122. return false;
  123. }
  124. static void test_arithmetic() {
  125. SpongeRng rng(Block("test_arithmetic"),SpongeRng::DETERMINISTIC);
  126. Test test("Arithmetic");
  127. Scalar x(0),y(0),z(0);
  128. arith_check(test,x,y,z,INT_MAX,(decaf_word_t)INT_MAX,"cast from max");
  129. arith_check(test,x,y,z,INT_MIN,-Scalar(1+(decaf_word_t)INT_MAX),"cast from min");
  130. for (int i=0; i<NTESTS*10 && test.passing_now; i++) {
  131. size_t sob = i % (2*Group::Scalar::SER_BYTES);
  132. SecureBuffer xx = rng.read(sob), yy = rng.read(sob), zz = rng.read(sob);
  133. Scalar x(xx);
  134. Scalar y(yy);
  135. Scalar z(zz);
  136. arith_check(test,x,y,z,x+y,y+x,"commute add");
  137. arith_check(test,x,y,z,x,x+0,"ident add");
  138. arith_check(test,x,y,z,x,x-0,"ident sub");
  139. arith_check(test,x,y,z,x+-x,0,"inverse add");
  140. arith_check(test,x,y,z,x-x,0,"inverse sub");
  141. arith_check(test,x,y,z,x-(x+1),-1,"inverse add2");
  142. arith_check(test,x,y,z,x+(y+z),(x+y)+z,"assoc add");
  143. arith_check(test,x,y,z,x*(y+z),x*y + x*z,"distributive mul/add");
  144. arith_check(test,x,y,z,x*(y-z),x*y - x*z,"distributive mul/add");
  145. arith_check(test,x,y,z,x*(y*z),(x*y)*z,"assoc mul");
  146. arith_check(test,x,y,z,x*y,y*x,"commute mul");
  147. arith_check(test,x,y,z,x,x*1,"ident mul");
  148. arith_check(test,x,y,z,0,x*0,"mul by 0");
  149. arith_check(test,x,y,z,-x,x*-1,"mul by -1");
  150. arith_check(test,x,y,z,x+x,x*2,"mul by 2");
  151. arith_check(test,x,y,z,-(x*y),(-x)*y,"neg prop mul");
  152. arith_check(test,x,y,z,x*y,(-x)*(-y),"double neg prop mul");
  153. arith_check(test,x,y,z,-(x+y),(-x)+(-y),"neg prop add");
  154. arith_check(test,x,y,z,x-y,(x)+(-y),"add neg sub");
  155. arith_check(test,x,y,z,(-x)-y,-(x+y),"neg add");
  156. if (sob <= 4) {
  157. uint64_t xi = leint(xx), yi = leint(yy);
  158. arith_check(test,x,y,z,x,xi,"parse consistency");
  159. arith_check(test,x,y,z,x+y,xi+yi,"add consistency");
  160. arith_check(test,x,y,z,x*y,xi*yi,"mul consistency");
  161. }
  162. if (i%20) continue;
  163. if (y!=0) arith_check(test,x,y,z,x*y/y,x,"invert");
  164. try {
  165. y = x/0;
  166. test.fail();
  167. printf(" Inverted zero!");
  168. print("x", x);
  169. print("y", y);
  170. } catch(CryptoException) {}
  171. }
  172. }
  173. static const Block sqrt_minus_one;
  174. static const Block minus_sqrt_minus_one;
  175. static const Block elli_patho; /* sqrt(1/(u(1-d))) */
  176. static void test_elligator() {
  177. SpongeRng rng(Block("test_elligator"),SpongeRng::DETERMINISTIC);
  178. Test test("Elligator");
  179. const int NHINTS = 1<<Point::INVERT_ELLIGATOR_WHICH_BITS;
  180. SecureBuffer *alts[NHINTS];
  181. bool successes[NHINTS];
  182. SecureBuffer *alts2[NHINTS];
  183. bool successes2[NHINTS];
  184. for (unsigned int i=0; i<NTESTS/10 && (i<10 || test.passing_now); i++) {
  185. size_t len = (i % (2*Point::HASH_BYTES + 3));
  186. SecureBuffer b1(len);
  187. if (i!=Point::HASH_BYTES) rng.read(b1); /* special test case */
  188. /* Pathological cases */
  189. if (i==1) b1[0] = 1;
  190. if (i==2 && sqrt_minus_one.size()) b1 = sqrt_minus_one;
  191. if (i==3 && minus_sqrt_minus_one.size()) b1 = minus_sqrt_minus_one;
  192. if (i==4 && elli_patho.size()) b1 = elli_patho;
  193. len = b1.size();
  194. Point s = Point::from_hash(b1), ss=s;
  195. for (unsigned int j=0; j<(i&3); j++) ss = ss.debugging_torque();
  196. ss = ss.debugging_pscale(rng);
  197. bool good = false;
  198. for (int j=0; j<NHINTS; j++) {
  199. alts[j] = new SecureBuffer(len);
  200. alts2[j] = new SecureBuffer(len);
  201. if (len > Point::HASH_BYTES)
  202. memcpy(&(*alts[j])[Point::HASH_BYTES], &b1[Point::HASH_BYTES], len-Point::HASH_BYTES);
  203. if (len > Point::HASH_BYTES)
  204. memcpy(&(*alts2[j])[Point::HASH_BYTES], &b1[Point::HASH_BYTES], len-Point::HASH_BYTES);
  205. successes[j] = decaf_successful( s.invert_elligator(*alts[j], j));
  206. successes2[j] = decaf_successful(ss.invert_elligator(*alts2[j],j));
  207. if (successes[j] != successes2[j]
  208. || (successes[j] && successes2[j] && *alts[j] != *alts2[j])
  209. ) {
  210. test.fail();
  211. printf(" Unscalable Elligator inversion: i=%d, hint=%d, s=%d,%d\n",i,j,
  212. -int(successes[j]),-int(successes2[j]));
  213. hexprint("x",b1);
  214. hexprint("X",*alts[j]);
  215. hexprint("X",*alts2[j]);
  216. }
  217. if (successes[j]) {
  218. good = good || (b1 == *alts[j]);
  219. for (int k=0; k<j; k++) {
  220. if (successes[k] && *alts[j] == *alts[k]) {
  221. test.fail();
  222. printf(" Duplicate Elligator inversion: i=%d, hints=%d, %d\n",i,j,k);
  223. hexprint("x",b1);
  224. hexprint("X",*alts[j]);
  225. }
  226. }
  227. if (s != Point::from_hash(*alts[j])) {
  228. test.fail();
  229. printf(" Fail Elligator inversion round-trip: i=%d, hint=%d %s\n",i,j,
  230. (s==-Point::from_hash(*alts[j])) ? "[output was -input]": "");
  231. hexprint("x",b1);
  232. hexprint("X",*alts[j]);
  233. }
  234. }
  235. }
  236. if (!good) {
  237. test.fail();
  238. printf(" %s Elligator inversion: i=%d\n",good ? "Passed" : "Failed", i);
  239. hexprint("B", b1);
  240. for (int j=0; j<NHINTS; j++) {
  241. printf(" %d: %s%s", j, successes[j] ? "succ" : "fail\n", (successes[j] && *alts[j] == b1) ? " [x]" : "");
  242. if (successes[j]) {
  243. hexprint("b", *alts[j]);
  244. }
  245. }
  246. printf("\n");
  247. }
  248. for (int j=0; j<NHINTS; j++) {
  249. delete alts[j];
  250. alts[j] = NULL;
  251. delete alts2[j];
  252. alts2[j] = NULL;
  253. }
  254. Point t(rng);
  255. point_check(test,t,t,t,0,0,t,Point::from_hash(t.steg_encode(rng)),"steg round-trip");
  256. }
  257. }
  258. static void test_ec() {
  259. SpongeRng rng(Block("test_ec"),SpongeRng::DETERMINISTIC);
  260. Test test("EC");
  261. Point id = Point::identity(), base = Point::base();
  262. point_check(test,id,id,id,0,0,Point::from_hash(""),id,"fh0");
  263. unsigned char enc[Point::SER_BYTES] = {0};
  264. if (Group::FIELD_MODULUS_TYPE == 3) {
  265. /* When p == 3 mod 4, the QNR is -1, so u*1^2 = -1 also produces the
  266. * identity.
  267. */
  268. point_check(test,id,id,id,0,0,Point::from_hash("\x01"),id,"fh1");
  269. }
  270. point_check(test,id,id,id,0,0,Point(FixedBlock<sizeof(enc)>(enc)),id,"decode [0]");
  271. try {
  272. enc[0] = 1;
  273. Point f((FixedBlock<sizeof(enc)>(enc)));
  274. test.fail();
  275. printf(" Allowed deserialize of [1]: %d", f==id);
  276. } catch (CryptoException) {
  277. /* ok */
  278. }
  279. if (sqrt_minus_one.size()) {
  280. try {
  281. Point f(sqrt_minus_one);
  282. test.fail();
  283. printf(" Allowed deserialize of [i]: %d", f==id);
  284. } catch (CryptoException) {
  285. /* ok */
  286. }
  287. }
  288. if (minus_sqrt_minus_one.size()) {
  289. try {
  290. Point f(minus_sqrt_minus_one);
  291. test.fail();
  292. printf(" Allowed deserialize of [-i]: %d", f==id);
  293. } catch (CryptoException) {
  294. /* ok */
  295. }
  296. }
  297. for (int i=0; i<NTESTS && test.passing_now; i++) {
  298. Scalar x(rng);
  299. Scalar y(rng);
  300. Point p(rng);
  301. Point q(rng);
  302. Point d1, d2;
  303. SecureBuffer buffer(2*Point::HASH_BYTES);
  304. rng.read(buffer);
  305. Point r = Point::from_hash(buffer);
  306. try {
  307. point_check(test,p,q,r,0,0,p,Point(p.serialize()),"round-trip");
  308. } catch (CryptoException) {
  309. test.fail();
  310. printf(" Round-trip raised CryptoException!\n");
  311. }
  312. Point pp = p.debugging_torque().debugging_pscale(rng);
  313. if (!memeq(pp.serialize(),p.serialize())) {
  314. test.fail();
  315. printf(" Fail torque seq test\n");
  316. }
  317. if (!memeq((p-pp).serialize(),id.serialize())) {
  318. test.fail();
  319. printf(" Fail torque id test\n");
  320. }
  321. if (!memeq((p-p).serialize(),id.serialize())) {
  322. test.fail();
  323. printf(" Fail id test\n");
  324. }
  325. point_check(test,p,q,r,0,0,p,pp,"torque eq");
  326. point_check(test,p,q,r,0,0,p+q,q+p,"commute add");
  327. point_check(test,p,q,r,0,0,(p-q)+q,p,"correct sub");
  328. point_check(test,p,q,r,0,0,p+(q+r),(p+q)+r,"assoc add");
  329. point_check(test,p,q,r,0,0,p.times_two(),p+p,"dbl add");
  330. if (i%10) continue;
  331. point_check(test,p,q,r,0,0,p.times_two(),p*Scalar(2),"add times two");
  332. point_check(test,p,q,r,x,0,x*(p+q),x*p+x*q,"distr mul");
  333. point_check(test,p,q,r,x,y,(x*y)*p,x*(y*p),"assoc mul");
  334. point_check(test,p,q,r,x,y,x*p+y*q,Point::double_scalarmul(x,p,y,q),"double mul");
  335. p.dual_scalarmul(d1,d2,x,y);
  336. point_check(test,p,q,r,x,y,x*p,d1,"dual mul 1");
  337. point_check(test,p,q,r,x,y,y*p,d2,"dual mul 2");
  338. point_check(test,base,q,r,x,y,x*base+y*q,q.non_secret_combo_with_base(y,x),"ds vt mul");
  339. point_check(test,p,q,r,x,0,Precomputed(p)*x,p*x,"precomp mul");
  340. point_check(test,p,q,r,0,0,r,
  341. Point::from_hash(Buffer(buffer).slice(0,Point::HASH_BYTES))
  342. + Point::from_hash(Buffer(buffer).slice(Point::HASH_BYTES,Point::HASH_BYTES)),
  343. "unih = hash+add"
  344. );
  345. try {
  346. point_check(test,p,q,r,x,0,Point(x.direct_scalarmul(p.serialize())),x*p,"direct mul");
  347. } catch (CryptoException) {
  348. printf(" Direct mul raised CryptoException!\n");
  349. test.fail();
  350. }
  351. q=p;
  352. for (int j=1; j<Group::REMOVED_COFACTOR; j<<=1) q = q.times_two();
  353. decaf_error_t error = r.decode_like_eddsa_and_ignore_cofactor_noexcept(
  354. p.mul_by_cofactor_and_encode_like_eddsa()
  355. );
  356. if (error != DECAF_SUCCESS) {
  357. test.fail();
  358. printf(" Decode like EdDSA failed.");
  359. }
  360. point_check(test,-q,q,r,i,0,q,r,"Encode like EdDSA round-trip");
  361. }
  362. }
  363. static const uint8_t rfc7748_1[DhLadder::PUBLIC_BYTES];
  364. static const uint8_t rfc7748_1000[DhLadder::PUBLIC_BYTES];
  365. static const uint8_t rfc7748_1000000[DhLadder::PUBLIC_BYTES];
  366. static void test_cfrg_crypto() {
  367. Test test("CFRG crypto");
  368. SpongeRng rng(Block("test_cfrg_crypto"),SpongeRng::DETERMINISTIC);
  369. for (int i=0; i<NTESTS && test.passing_now; i++) {
  370. FixedArrayBuffer<DhLadder::PUBLIC_BYTES> base(rng);
  371. FixedArrayBuffer<DhLadder::PRIVATE_BYTES> s1(rng), s2(rng);
  372. SecureBuffer p1 = DhLadder::shared_secret(base,s1);
  373. SecureBuffer p2 = DhLadder::shared_secret(base,s2);
  374. SecureBuffer ss1 = DhLadder::shared_secret(p2,s1);
  375. SecureBuffer ss2 = DhLadder::shared_secret(p1,s2);
  376. if (!memeq(ss1,ss2)) {
  377. test.fail();
  378. printf(" Shared secrets disagree on iteration %d.\n",i);
  379. }
  380. if (!memeq(
  381. DhLadder::shared_secret(DhLadder::base_point(),s1),
  382. DhLadder::derive_public_key(s1)
  383. )) {
  384. test.fail();
  385. printf(" Public keys disagree on iteration %d.\n",i);
  386. }
  387. }
  388. }
  389. static const bool eddsa_prehashed[];
  390. static const Block eddsa_sk[], eddsa_pk[], eddsa_message[], eddsa_context[], eddsa_sig[];
  391. static void test_cfrg_vectors() {
  392. Test test("CFRG test vectors");
  393. SecureBuffer k = DhLadder::base_point();
  394. SecureBuffer u = DhLadder::base_point();
  395. int the_ntests = (NTESTS < 1000000) ? 1000 : 1000000;
  396. /* EdDSA */
  397. for (unsigned int t=0; eddsa_sk[t].size(); t++) {
  398. typename EdDSA<Group>::PrivateKey priv(eddsa_sk[t]);
  399. SecureBuffer eddsa_pk2 = priv.pub().serialize();
  400. if (!memeq(SecureBuffer(eddsa_pk[t]), eddsa_pk2)) {
  401. test.fail();
  402. printf(" EdDSA PK vectors disagree.");
  403. printf("\n Correct: ");
  404. for (unsigned i=0; i<eddsa_pk[t].size(); i++) printf("%02x", eddsa_pk[t][i]);
  405. printf("\n Incorrect: ");
  406. for (unsigned i=0; i<eddsa_pk2.size(); i++) printf("%02x", eddsa_pk2[i]);
  407. printf("\n");
  408. }
  409. SecureBuffer sig;
  410. if (eddsa_prehashed[t]) {
  411. typename EdDSA<Group>::PrivateKeyPh priv2(eddsa_sk[t]);
  412. sig = priv2.sign_with_prehash(eddsa_message[t],eddsa_context[t]);
  413. } else {
  414. sig = priv.sign(eddsa_message[t],eddsa_context[t]);
  415. }
  416. if (!memeq(SecureBuffer(eddsa_sig[t]),sig)) {
  417. test.fail();
  418. printf(" EdDSA sig vectors disagree.");
  419. printf("\n Correct: ");
  420. for (unsigned i=0; i<eddsa_sig[t].size(); i++) printf("%02x", eddsa_sig[t][i]);
  421. printf("\n Incorrect: ");
  422. for (unsigned i=0; i<sig.size(); i++) printf("%02x", sig[i]);
  423. printf("\n");
  424. }
  425. }
  426. /* X25519/X448 */
  427. for (int i=0; i<the_ntests && test.passing_now; i++) {
  428. SecureBuffer n = DhLadder::shared_secret(u,k);
  429. u = k; k = n;
  430. if (i==1-1) {
  431. if (!memeq(k,SecureBuffer(FixedBlock<DhLadder::PUBLIC_BYTES>(rfc7748_1)))) {
  432. test.fail();
  433. printf(" Test vectors disagree at 1.");
  434. }
  435. } else if (i==1000-1) {
  436. if (!memeq(k,SecureBuffer(FixedBlock<DhLadder::PUBLIC_BYTES>(rfc7748_1000)))) {
  437. test.fail();
  438. printf(" Test vectors disagree at 1000.");
  439. }
  440. } else if (i==1000000-1) {
  441. if (!memeq(k,SecureBuffer(FixedBlock<DhLadder::PUBLIC_BYTES>(rfc7748_1000000)))) {
  442. test.fail();
  443. printf(" Test vectors disagree at 1000000.");
  444. }
  445. }
  446. }
  447. }
  448. static void test_eddsa() {
  449. Test test("EdDSA");
  450. SpongeRng rng(Block("test_eddsa"),SpongeRng::DETERMINISTIC);
  451. for (int i=0; i<NTESTS && test.passing_now; i++) {
  452. typename EdDSA<Group>::PrivateKey priv(rng);
  453. typename EdDSA<Group>::PublicKey pub(priv);
  454. SecureBuffer message(i);
  455. rng.read(message);
  456. SecureBuffer context(i%256);
  457. rng.read(context);
  458. SecureBuffer sig = priv.sign(message,context);
  459. try {
  460. pub.verify(sig,message,context);
  461. } catch(CryptoException) {
  462. test.fail();
  463. printf(" Signature validation failed on sig %d\n", i);
  464. }
  465. }
  466. }
  467. /* Thanks Johan Pascal */
  468. static void test_convert_eddsa_to_x() {
  469. Test test("ECDH using EdDSA keys");
  470. SpongeRng rng(Block("test_x_on_eddsa_key"),SpongeRng::DETERMINISTIC);
  471. for (int i=0; i<NTESTS && test.passing_now; i++) {
  472. /* generate 2 pairs of EdDSA keys */
  473. typename EdDSA<Group>::PrivateKey alice_priv(rng);
  474. typename EdDSA<Group>::PublicKey alice_pub(alice_priv);
  475. typename EdDSA<Group>::PrivateKey bob_priv(rng);
  476. typename EdDSA<Group>::PublicKey bob_pub(bob_priv);
  477. /* convert them to ECDH format
  478. * check public key value by computing it from direct conversion and regeneration from converted private)
  479. */
  480. SecureBuffer alice_priv_x = alice_priv.convert_to_x();
  481. SecureBuffer alice_pub_x_conversion = alice_pub.convert_to_x();
  482. SecureBuffer alice_pub_x_generated = DhLadder::derive_public_key(alice_priv_x);
  483. if (!memeq(alice_pub_x_conversion, alice_pub_x_generated)) {
  484. test.fail();
  485. printf(" Ed2X Public key convertion and regeneration from converted private key differs.\n");
  486. }
  487. SecureBuffer bob_priv_x = bob_priv.convert_to_x();
  488. SecureBuffer bob_pub_x_conversion = bob_pub.convert_to_x();
  489. SecureBuffer bob_pub_x_generated = DhLadder::derive_public_key(bob_priv_x);
  490. if (!memeq(bob_pub_x_conversion, bob_pub_x_generated)) {
  491. test.fail();
  492. printf(" Ed2X Public key convertion and regeneration from converted private key differs.\n");
  493. }
  494. /* compute shared secrets and check they match */
  495. SecureBuffer alice_shared = DhLadder::shared_secret(bob_pub_x_conversion, alice_priv_x);
  496. SecureBuffer bob_shared = DhLadder::shared_secret(alice_pub_x_conversion, bob_priv_x);
  497. if (!memeq(alice_shared, bob_shared)) {
  498. test.fail();
  499. printf(" ECDH shared secret mismatch.\n");
  500. }
  501. }
  502. }
  503. static void run() {
  504. printf("Testing %s:\n",Group::name());
  505. test_arithmetic();
  506. test_elligator();
  507. test_ec();
  508. test_eddsa();
  509. test_convert_eddsa_to_x();
  510. test_cfrg_crypto();
  511. test_cfrg_vectors();
  512. printf("\n");
  513. }
  514. }; /* template<GroupId GROUP> struct Tests */
  515. static void test_rng() {
  516. Test test("RNG");
  517. SpongeRng rng_d1(Block("test_rng"),SpongeRng::DETERMINISTIC);
  518. SpongeRng rng_d2(Block("test_rng"),SpongeRng::DETERMINISTIC);
  519. SpongeRng rng_d3(Block("best_rng"),SpongeRng::DETERMINISTIC);
  520. SpongeRng rng_n1;
  521. SpongeRng rng_n2;
  522. SecureBuffer s1,s2,s3;
  523. for (int i=0; i<5; i++) {
  524. s1 = rng_d1.read(16<<i);
  525. s2 = rng_d2.read(16<<i);
  526. s3 = rng_d3.read(16<<i);
  527. if (s1 != s2) {
  528. test.fail();
  529. printf(" Deterministic RNG didn't match!\n");
  530. }
  531. if (s1 == s3) {
  532. test.fail();
  533. printf(" Deterministic matched with different data!\n");
  534. }
  535. rng_d1.stir("hello");
  536. rng_d2.stir("hello");
  537. rng_d3.stir("hello");
  538. s1 = rng_n1.read(16<<i);
  539. s2 = rng_n2.read(16<<i);
  540. if (s1 == s2) {
  541. test.fail();
  542. printf(" Nondeterministic RNG matched!\n");
  543. }
  544. }
  545. rng_d1.stir("hello");
  546. rng_d2.stir("jello");
  547. s1 = rng_d1.read(16);
  548. s2 = rng_d2.read(16);
  549. if (s1 == s2) {
  550. test.fail();
  551. printf(" Deterministic matched with different data!\n");
  552. }
  553. }
  554. #include "vectors.inc.cxx"
  555. int main(int argc, char **argv) {
  556. (void) argc; (void) argv;
  557. test_rng();
  558. printf("\n");
  559. run_for_all_curves<Tests>();
  560. if (passing) printf("Passed all tests.\n");
  561. return passing ? 0 : 1;
  562. }