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.
 
 
 
 
 

209 lines
6.0 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 "shake.hxx"
  13. #include <stdio.h>
  14. static bool passing = true;
  15. static const long NTESTS = 10000;
  16. class Test {
  17. public:
  18. bool passing_now;
  19. Test(const char *test) {
  20. passing_now = true;
  21. printf("%s...", test);
  22. if (strlen(test) < 27) printf("%*s",int(27-strlen(test)),"");
  23. fflush(stdout);
  24. }
  25. ~Test() {
  26. if (std::uncaught_exception()) {
  27. fail();
  28. printf(" due to uncaught exception.\n");
  29. }
  30. if (passing_now) printf("[PASS]\n");
  31. }
  32. void fail() {
  33. if (!passing_now) return;
  34. passing_now = passing = false;
  35. printf("[FAIL]\n");
  36. }
  37. };
  38. template<decaf::GroupId GROUP> struct Tests {
  39. typedef typename decaf::EcGroup<GROUP>::Scalar Scalar;
  40. typedef typename decaf::EcGroup<GROUP>::Point Point;
  41. typedef typename decaf::EcGroup<GROUP>::Precomputed Precomputed;
  42. static void print(const char *name, const Scalar &x) {
  43. unsigned char buffer[Scalar::SER_BYTES];
  44. x.encode(buffer);
  45. printf(" %s = 0x", name);
  46. for (int i=sizeof(buffer)-1; i>=0; i--) {
  47. printf("%02x", buffer[i]);
  48. }
  49. printf("\n");
  50. }
  51. static void print(const char *name, const Point &x) {
  52. unsigned char buffer[Point::SER_BYTES];
  53. x.encode(buffer);
  54. printf(" %s = 0x", name);
  55. for (int i=sizeof(buffer)-1; i>=0; i--) {
  56. printf("%02x", buffer[i]);
  57. }
  58. printf("\n");
  59. }
  60. static bool arith_check(
  61. Test &test,
  62. const Scalar &x,
  63. const Scalar &y,
  64. const Scalar &z,
  65. const Scalar &r,
  66. const Scalar &l,
  67. const char *name
  68. ) {
  69. if (l == r) return true;
  70. test.fail();
  71. printf(" %s", name);
  72. print("x", x);
  73. print("y", y);
  74. print("z", z);
  75. print("lhs", r);
  76. print("rhs", l);
  77. return false;
  78. }
  79. static bool point_check(
  80. Test &test,
  81. const Point &p,
  82. const Point &q,
  83. const Point &R,
  84. const Scalar &x,
  85. const Scalar &y,
  86. const Point &l,
  87. const Point &r,
  88. const char *name
  89. ) {
  90. bool good = l==r;
  91. if (!p.validate()) { good = false; printf(" p invalid\n"); }
  92. if (!q.validate()) { good = false; printf(" q invalid\n"); }
  93. if (!r.validate()) { good = false; printf(" r invalid\n"); }
  94. if (!l.validate()) { good = false; printf(" l invalid\n"); }
  95. if (good) return true;
  96. test.fail();
  97. printf(" %s", name);
  98. print("x", x);
  99. print("y", y);
  100. print("p", p);
  101. print("q", q);
  102. print("r", R);
  103. print("lhs", r);
  104. print("rhs", l);
  105. return false;
  106. }
  107. static void test_arithmetic() {
  108. decaf::SpongeRng rng(decaf::Block("test_arithmetic"));
  109. Test test("Arithmetic");
  110. Scalar x(0),y(0),z(0);
  111. arith_check(test,x,y,z,INT_MAX,(decaf_word_t)INT_MAX,"cast from max");
  112. arith_check(test,x,y,z,INT_MIN,-Scalar(1+(decaf_word_t)INT_MAX),"cast from min");
  113. for (int i=0; i<NTESTS*10 && test.passing_now; i++) {
  114. /* TODO: pathological cases */
  115. size_t sob = DECAF_448_SCALAR_BYTES + 8 - (i%16);
  116. Scalar x(rng.read(sob));
  117. Scalar y(rng.read(sob));
  118. Scalar z(rng.read(sob));
  119. arith_check(test,x,y,z,x+y,y+x,"commute add");
  120. arith_check(test,x,y,z,x,x+0,"ident add");
  121. arith_check(test,x,y,z,x,x-0,"ident sub");
  122. arith_check(test,x,y,z,x+(y+z),(x+y)+z,"assoc add");
  123. arith_check(test,x,y,z,x*(y+z),x*y + x*z,"distributive mul/add");
  124. arith_check(test,x,y,z,x*(y-z),x*y - x*z,"distributive mul/add");
  125. arith_check(test,x,y,z,x*(y*z),(x*y)*z,"assoc mul");
  126. arith_check(test,x,y,z,x*y,y*x,"commute mul");
  127. arith_check(test,x,y,z,x,x*1,"ident mul");
  128. arith_check(test,x,y,z,0,x*0,"mul by 0");
  129. arith_check(test,x,y,z,-x,x*-1,"mul by -1");
  130. arith_check(test,x,y,z,x+x,x*2,"mul by 2");
  131. if (i%20) continue;
  132. if (y!=0) arith_check(test,x,y,z,x*y/y,x,"invert");
  133. arith_check(test,x,y,z,x/0,0,"invert0");
  134. }
  135. }
  136. static void test_ec() {
  137. decaf::SpongeRng rng(decaf::Block("test_ec"));
  138. Test test("EC");
  139. Point id = Point::identity(), base = Point::base();
  140. point_check(test,id,id,id,0,0,Point::from_hash(""),id,"fh0");
  141. point_check(test,id,id,id,0,0,Point::from_hash("\x01"),id,"fh1");
  142. for (int i=0; i<NTESTS && test.passing_now; i++) {
  143. /* TODO: pathological cases */
  144. Scalar x(rng);
  145. Scalar y(rng);
  146. Point p(rng);
  147. Point q(rng);
  148. decaf::SecureBuffer buffer(2*Point::HASH_BYTES);
  149. rng.read(buffer);
  150. Point r = Point::from_hash(buffer);
  151. point_check(test,p,q,r,0,0,p,Point((decaf::SecureBuffer)p),"round-trip");
  152. point_check(test,p,q,r,0,0,p+q,q+p,"commute add");
  153. point_check(test,p,q,r,0,0,p+(q+r),(p+q)+r,"assoc add");
  154. point_check(test,p,q,r,0,0,p.times_two(),p+p,"dbl add");
  155. if (i%10) continue;
  156. point_check(test,p,q,r,x,0,x*(p+q),x*p+x*q,"distr mul");
  157. point_check(test,p,q,r,x,y,(x*y)*p,x*(y*p),"assoc mul");
  158. point_check(test,p,q,r,x,y,x*p+y*q,Point::double_scalarmul(x,p,y,q),"ds mul");
  159. point_check(test,base,q,r,x,y,x*base+y*q,q.non_secret_combo_with_base(y,x),"ds vt mul");
  160. point_check(test,p,q,r,x,0,Precomputed(p)*x,p*x,"precomp mul");
  161. point_check(test,p,q,r,0,0,r,
  162. Point::from_hash(buffer.slice(0,Point::HASH_BYTES))
  163. + Point::from_hash(buffer.slice(Point::HASH_BYTES,Point::HASH_BYTES)),
  164. "unih = hash+add"
  165. );
  166. point_check(test,p,q,r,x,0,Point(x.direct_scalarmul(decaf::SecureBuffer(p))),x*p,"direct mul");
  167. }
  168. }
  169. }; // template<decaf::GroupId GROUP>
  170. int main(int argc, char **argv) {
  171. (void) argc; (void) argv;
  172. Tests<448>::test_arithmetic();
  173. Tests<448>::test_ec();
  174. if (passing) printf("Passed all tests.\n");
  175. return passing ? 0 : 1;
  176. }