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.
 
 
 
 
 

393 lines
9.4 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. int inv
  187. ) {
  188. decaf_448_scalar_t xx,yy,tt;
  189. mpz_t t;
  190. mask_t succ = MASK_SUCCESS;
  191. succ = mpz_to_scalar(xx,x);
  192. succ &= mpz_to_scalar(yy,y);
  193. mpz_init(t);
  194. decaf_448_scalar_add(tt,xx,yy);
  195. mpz_add(t,x,y);
  196. succ &= scalar_assert_eq_gmp("scalar add",xx,yy,tt,x,y,t);
  197. decaf_448_scalar_sub(tt,xx,yy);
  198. mpz_sub(t,x,y);
  199. succ &= scalar_assert_eq_gmp("scalar sub",xx,yy,tt,x,y,t);
  200. decaf_448_scalar_mul(tt,xx,yy);
  201. mpz_mul(t,x,y);
  202. succ &= scalar_assert_eq_gmp("scalar mul",xx,yy,tt,x,y,t);
  203. if (inv) {
  204. decaf_bool_t ret = decaf_448_scalar_invert(tt,xx);
  205. if (!mpz_cmp_ui(x,0)) {
  206. mpz_set_ui(t,0);
  207. succ &= (ret == 0) ? MASK_SUCCESS : MASK_FAILURE;
  208. } else {
  209. mpz_invert(t,x,mp_scalar_field);
  210. succ &= (ret == MASK_SUCCESS) ? MASK_SUCCESS : MASK_FAILURE;
  211. }
  212. succ &= scalar_assert_eq_gmp("scalar inv",xx,yy,tt,x,y,t);
  213. }
  214. mpz_clear(t);
  215. return succ;
  216. }
  217. static mask_t test_mul_sqr (
  218. const mpz_t x,
  219. const mpz_t y,
  220. word_t word
  221. ) {
  222. ANALYZE_THIS_ROUTINE_CAREFULLY;
  223. field_a_t xx,yy,tt,zz;
  224. mpz_t t, z;
  225. mask_t succ = MASK_SUCCESS;
  226. succ = mpz_to_field(xx,x);
  227. succ &= mpz_to_field(yy,y);
  228. mpz_init(t);
  229. mpz_init(z);
  230. field_mul(tt,xx,yy);
  231. mpz_mul(t,x,y);
  232. succ &= field_assert_eq_gmp("mul",xx,yy,tt,t,0,1.1);
  233. field_mulw(tt,xx,word);
  234. mpz_mul_ui(t,x,word);
  235. succ &= field_assert_eq_gmp("mulw",xx,yy,tt,t,0,1.1);
  236. field_sqr(tt,xx);
  237. mpz_mul(t,x,x);
  238. succ &= field_assert_eq_gmp("sqrx",xx,yy,tt,t,0,1.1);
  239. field_sqr(tt,yy);
  240. mpz_mul(t,y,y);
  241. succ &= field_assert_eq_gmp("sqy",xx,yy,tt,t,0,1.1);
  242. field_add_nr(zz,xx,xx);
  243. mpz_add(z,x,x);
  244. mpz_mul(t,z,z);
  245. field_mul(tt,zz,zz);
  246. succ &= field_assert_eq_gmp("msr4",xx,yy,tt,t,0,1.1);
  247. field_sqr(tt,zz);
  248. succ &= field_assert_eq_gmp("sqr4",xx,yy,tt,t,0,1.1);
  249. if (!succ) {
  250. field_print(" x", xx);
  251. field_print(" y", yy);
  252. }
  253. mpz_clear(t);
  254. mpz_clear(z);
  255. return succ;
  256. }
  257. static mask_t test_isr (
  258. const mpz_t x
  259. ) {
  260. field_a_t xx,yy,ss,tt;
  261. mask_t succ = 0;
  262. succ = mpz_to_field(xx,x);
  263. field_isr(ss,xx);
  264. field_sqr(tt,ss);
  265. field_mul(yy,xx,tt);
  266. field_addw(tt,1);
  267. succ |= field_is_zero(tt);
  268. field_subw(tt,2);
  269. field_bias(tt,1);
  270. succ |= field_is_zero(tt);
  271. field_addw(tt,1);
  272. if (~succ) {
  273. youfail();
  274. printf("ISR failure.\n");
  275. field_print(" x", xx);
  276. field_print(" s", ss);
  277. field_print(" t", tt);
  278. }
  279. return succ;
  280. }
  281. void dbg_gmp_printf(const mpz_t x);
  282. void dbg_gmp_printf(const mpz_t x) {
  283. gmp_printf("DEBUG: 0x%Zx\n", x);
  284. }
  285. int test_arithmetic (void) {
  286. int j, ntests = 100000;
  287. gmp_randstate_t state;
  288. gmp_randinit_mt(state);
  289. mpz_init(mp_field);
  290. mpz_import(mp_field, FIELD_BYTES, -1, 1, -1, 0, FIELD_MODULUS);
  291. mpz_import(mp_scalar_field, DECAF_448_SCALAR_LIMBS, -1, sizeof(decaf_word_t), -1, 0, decaf_448_scalar_p);
  292. mpz_t x,y;
  293. mpz_init(x);
  294. mpz_init(y);
  295. mask_t succ = MASK_SUCCESS;
  296. int radix_bits = sizeof(word_t) * FIELD_BITS / sizeof(field_a_t);
  297. for (j=0; j<ntests; j++) {
  298. if (j<256) {
  299. mpz_set_ui(x,0);
  300. mpz_set_ui(y,0);
  301. mpz_setbit(x,(j%16)*28);
  302. mpz_setbit(y,(j/16)*28);
  303. } else if (j&1) {
  304. mpz_rrandomb(x, state, FIELD_BITS);
  305. mpz_rrandomb(y, state, FIELD_BITS);
  306. } else {
  307. mpz_urandomb(x, state, FIELD_BITS);
  308. mpz_urandomb(y, state, FIELD_BITS);
  309. }
  310. word_t word = gmp_urandomm_ui (state, 1ull<<radix_bits);
  311. succ &= test_add_sub_RAW(x,y,word);
  312. succ &= test_mul_sqr(x,y,word);
  313. succ &= test_scalar(x,y,(j%20==0));
  314. if (j < 1000)
  315. succ &= test_isr(x);
  316. // TODO: test neg, cond_neg_RAW, set_ui, wrd, srd, inv, ...?
  317. }
  318. mpz_clear(x);
  319. mpz_clear(y);
  320. mpz_clear(mp_field);
  321. gmp_randclear(state);
  322. return succ ? 0 : 1;
  323. }