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.
 
 
 
 
 

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