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.
 
 
 
 
 

369 lines
8.7 KiB

  1. #include "field.h"
  2. #include "test.h"
  3. #include "decaf.h"
  4. #include <gmp.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7. mpz_t mp_field;
  8. mpz_t mp_scalar_field;
  9. static void decaf_448_scalar_print (
  10. const char *descr,
  11. const decaf_448_scalar_t scalar
  12. ) {
  13. int j;
  14. printf("%s = 0x", descr);
  15. for (j=DECAF_448_SCALAR_LIMBS-1; j>=0; j--) {
  16. printf(PRIxWORDfull, scalar->limb[j]);
  17. }
  18. printf("\n");
  19. }
  20. static mask_t mpz_to_field (
  21. field_a_t out,
  22. const mpz_t in
  23. ) {
  24. uint8_t ser[FIELD_BYTES];
  25. mpz_t modded;
  26. memset(ser,0,sizeof(ser));
  27. mpz_init(modded);
  28. mpz_mod(modded, in, mp_field);
  29. mpz_export(ser, NULL, -1, 1, -1, 0, modded);
  30. mask_t succ = field_deserialize(out, ser);
  31. return succ;
  32. }
  33. static mask_t mpz_to_scalar (
  34. decaf_448_scalar_t out,
  35. const mpz_t in
  36. ) {
  37. uint8_t ser[DECAF_448_SCALAR_BYTES];
  38. mpz_t modded;
  39. memset(ser,0,sizeof(ser));
  40. mpz_init(modded);
  41. mpz_mod(modded, in, mp_scalar_field);
  42. mpz_export(ser, NULL, -1, 1, -1, 0, modded);
  43. mask_t succ = decaf_448_scalar_decode(out, ser);
  44. return succ;
  45. }
  46. static mask_t scalar_assert_eq_gmp(
  47. const char *descr,
  48. const decaf_448_scalar_t a,
  49. const decaf_448_scalar_t b,
  50. const decaf_448_scalar_t x,
  51. const mpz_t ma,
  52. const mpz_t mb,
  53. const mpz_t y
  54. ) {
  55. uint8_t xser[FIELD_BYTES], yser[FIELD_BYTES];
  56. mpz_t modded;
  57. memset(yser,0,sizeof(yser));
  58. decaf_448_scalar_encode(xser, x);
  59. mpz_init(modded);
  60. mpz_mod(modded, y, mp_scalar_field);
  61. mpz_export(yser, NULL, -1, 1, -1, 0, modded);
  62. if (memcmp(xser,yser,FIELD_BYTES)) {
  63. youfail();
  64. printf(" Failed arithmetic test %s\n", descr);
  65. decaf_448_scalar_print(" a", a);
  66. decaf_448_scalar_print(" b", b);
  67. decaf_448_scalar_print(" decaf_448", x);
  68. // printf(" gmpa = 0x");
  69. int j;
  70. // mpz_export(yser, NULL, -1, 1, -1, 0, ma);
  71. // for (j=FIELD_BYTES-1; j>=0; j--) {
  72. // printf("%02x", yser[j]);
  73. // }
  74. // printf("\n");
  75. // printf(" gmpb = 0x");
  76. //
  77. //
  78. // mpz_export(yser, NULL, -1, 1, -1, 0, mb);
  79. // for (j=FIELD_BYTES-1; j>=0; j--) {
  80. // printf("%02x", yser[j]);
  81. // }
  82. // printf("\n");
  83. (void)ma; (void)mb;
  84. printf(" gmpy = 0x");
  85. mpz_export(yser, NULL, -1, 1, -1, 0, modded);
  86. for (j=FIELD_BYTES-1; j>=0; j--) {
  87. printf("%02x", yser[j]);
  88. }
  89. printf("\n");
  90. return MASK_FAILURE;
  91. }
  92. mpz_clear(modded);
  93. return MASK_SUCCESS;
  94. }
  95. static inline int BRANCH_ON_CONSTANT(int x) {
  96. __asm__ ("" : "+r"(x));
  97. return x;
  98. }
  99. static mask_t field_assert_eq_gmp(
  100. const char *descr,
  101. const field_a_t a,
  102. const field_a_t b,
  103. const field_a_t x,
  104. const mpz_t y,
  105. float lowBound,
  106. float highBound
  107. ) {
  108. uint8_t xser[FIELD_BYTES], yser[FIELD_BYTES];
  109. mpz_t modded;
  110. memset(yser,0,sizeof(yser));
  111. field_serialize(xser, x);
  112. mpz_init(modded);
  113. mpz_mod(modded, y, mp_field);
  114. mpz_export(yser, NULL, -1, 1, -1, 0, modded);
  115. unsigned int i;
  116. for (i=0; i<sizeof(*x)/sizeof(x->limb[0]); i++) {
  117. int radix_bits = 1 + (sizeof(x->limb[0]) * FIELD_BITS - 1) / sizeof(*x);
  118. word_t yardstick;
  119. if (BRANCH_ON_CONSTANT(FIELD_BITS == 521) && BRANCH_ON_CONSTANT(sizeof(*x)==12*8)) {
  120. radix_bits = 58;
  121. }
  122. yardstick = (1ull<<radix_bits) - 1;
  123. if (x->limb[i] < yardstick * lowBound || x->limb[i] > yardstick * highBound) {
  124. youfail();
  125. printf(" Limb %d -> " PRIxWORDfull " is out of bounds (%0.2f, %0.2f) for test %s (yardstick = " PRIxWORDfull ")\n",
  126. i, x->limb[i], lowBound, highBound, descr, yardstick);
  127. break;
  128. }
  129. }
  130. if (memcmp(xser,yser,FIELD_BYTES)) {
  131. youfail();
  132. printf(" Failed arithmetic test %s\n", descr);
  133. field_print(" a", a);
  134. field_print(" b", b);
  135. field_print(" goldi", x);
  136. printf(" gmp = 0x");
  137. int j;
  138. for (j=FIELD_BYTES-1; j>=0; j--) {
  139. printf("%02x", yser[j]);
  140. }
  141. printf("\n");
  142. return MASK_FAILURE;
  143. }
  144. mpz_clear(modded);
  145. return MASK_SUCCESS;
  146. }
  147. static mask_t test_add_sub_RAW (
  148. const mpz_t x,
  149. const mpz_t y,
  150. word_t word
  151. ) {
  152. field_a_t xx,yy,tt;
  153. mpz_t t;
  154. mask_t succ = MASK_SUCCESS;
  155. succ = mpz_to_field(xx,x);
  156. succ &= mpz_to_field(yy,y);
  157. mpz_init(t);
  158. field_add_RAW(tt,xx,yy);
  159. mpz_add(t,x,y);
  160. succ &= field_assert_eq_gmp("add",xx,yy,tt,t,0,2.1);
  161. field_sub_RAW(tt,xx,yy);
  162. field_bias(tt,2);
  163. mpz_sub(t,x,y);
  164. succ &= field_assert_eq_gmp("sub",xx,yy,tt,t,0,3.1);
  165. field_copy(tt,xx);
  166. field_addw(tt,word);
  167. mpz_add_ui(t,x,word);
  168. succ &= field_assert_eq_gmp("addw",xx,yy,tt,t,0,2.1);
  169. field_copy(tt,xx);
  170. field_subw(tt,word);
  171. field_bias(tt,1);
  172. mpz_sub_ui(t,x,word);
  173. succ &= field_assert_eq_gmp("subw",xx,yy,tt,t,0,2.1);
  174. /*
  175. if (!succ) {
  176. field_print(" x", &xx);
  177. field_print(" y", &yy);
  178. }
  179. */
  180. mpz_clear(t);
  181. return succ;
  182. }
  183. static mask_t test_scalar (
  184. const mpz_t x,
  185. const mpz_t y
  186. ) {
  187. decaf_448_scalar_t xx,yy,tt;
  188. mpz_t t;
  189. mask_t succ = MASK_SUCCESS;
  190. succ = mpz_to_scalar(xx,x);
  191. succ &= mpz_to_scalar(yy,y);
  192. mpz_init(t);
  193. decaf_448_scalar_add(tt,xx,yy);
  194. mpz_add(t,x,y);
  195. succ &= scalar_assert_eq_gmp("scalar add",xx,yy,tt,x,y,t);
  196. decaf_448_scalar_sub(tt,xx,yy);
  197. mpz_sub(t,x,y);
  198. succ &= scalar_assert_eq_gmp("scalar sub",xx,yy,tt,x,y,t);
  199. decaf_448_scalar_mul(tt,xx,yy);
  200. mpz_mul(t,x,y);
  201. succ &= scalar_assert_eq_gmp("scalar mul",xx,yy,tt,x,y,t);
  202. mpz_clear(t);
  203. return succ;
  204. }
  205. static mask_t test_mul_sqr (
  206. const mpz_t x,
  207. const mpz_t y,
  208. word_t word
  209. ) {
  210. field_a_t xx,yy,tt;
  211. mpz_t t;
  212. mask_t succ = MASK_SUCCESS;
  213. succ = mpz_to_field(xx,x);
  214. succ &= mpz_to_field(yy,y);
  215. mpz_init(t);
  216. field_mul(tt,xx,yy);
  217. mpz_mul(t,x,y);
  218. succ &= field_assert_eq_gmp("mul",xx,yy,tt,t,0,1.1);
  219. field_mulw(tt,xx,word);
  220. mpz_mul_ui(t,x,word);
  221. succ &= field_assert_eq_gmp("mulw",xx,yy,tt,t,0,1.1);
  222. field_sqr(tt,xx);
  223. mpz_mul(t,x,x);
  224. succ &= field_assert_eq_gmp("sqrx",xx,yy,tt,t,0,1.1);
  225. field_sqr(tt,yy);
  226. mpz_mul(t,y,y);
  227. succ &= field_assert_eq_gmp("sqy",xx,yy,tt,t,0,1.1);
  228. if (!succ) {
  229. field_print(" x", xx);
  230. field_print(" y", yy);
  231. }
  232. mpz_clear(t);
  233. return succ;
  234. }
  235. static mask_t test_isr (
  236. const mpz_t x
  237. ) {
  238. field_a_t xx,yy,ss,tt;
  239. mask_t succ = 0;
  240. succ = mpz_to_field(xx,x);
  241. field_isr(ss,xx);
  242. field_sqr(tt,ss);
  243. field_mul(yy,xx,tt);
  244. field_addw(tt,1);
  245. succ |= field_is_zero(tt);
  246. field_subw(tt,2);
  247. field_bias(tt,1);
  248. succ |= field_is_zero(tt);
  249. field_addw(tt,1);
  250. if (~succ) {
  251. youfail();
  252. printf("ISR failure.\n");
  253. field_print(" x", xx);
  254. field_print(" s", ss);
  255. field_print(" t", tt);
  256. }
  257. return succ;
  258. }
  259. void dbg_gmp_printf(const mpz_t x);
  260. void dbg_gmp_printf(const mpz_t x) {
  261. gmp_printf("DEBUG: 0x%Zx\n", x);
  262. }
  263. int test_arithmetic (void) {
  264. int j, ntests = 100000;
  265. gmp_randstate_t state;
  266. gmp_randinit_mt(state);
  267. mpz_init(mp_field);
  268. mpz_import(mp_field, FIELD_BYTES, -1, 1, -1, 0, FIELD_MODULUS);
  269. mpz_import(mp_scalar_field, DECAF_448_SCALAR_LIMBS, -1, sizeof(decaf_word_t), -1, 0, decaf_448_scalar_p);
  270. mpz_t x,y;
  271. mpz_init(x);
  272. mpz_init(y);
  273. mask_t succ = MASK_SUCCESS;
  274. int radix_bits = sizeof(word_t) * FIELD_BITS / sizeof(field_a_t);
  275. for (j=0; j<ntests; j++) {
  276. if (j<256) {
  277. mpz_set_ui(x,0);
  278. mpz_set_ui(y,0);
  279. mpz_setbit(x,(j%16)*28);
  280. mpz_setbit(y,(j/16)*28);
  281. } else if (j&1) {
  282. mpz_rrandomb(x, state, FIELD_BITS);
  283. mpz_rrandomb(y, state, FIELD_BITS);
  284. } else {
  285. mpz_urandomb(x, state, FIELD_BITS);
  286. mpz_urandomb(y, state, FIELD_BITS);
  287. }
  288. word_t word = gmp_urandomm_ui (state, 1ull<<radix_bits);
  289. succ &= test_add_sub_RAW(x,y,word);
  290. succ &= test_mul_sqr(x,y,word);
  291. succ &= test_scalar(x,y);
  292. if (j < 1000)
  293. succ &= test_isr(x);
  294. // TODO: test neg, cond_neg_RAW, set_ui, wrd, srd, inv, ...?
  295. }
  296. mpz_clear(x);
  297. mpz_clear(y);
  298. mpz_clear(mp_field);
  299. gmp_randclear(state);
  300. return succ ? 0 : 1;
  301. }