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.
 
 
 
 
 

1047 lines
27 KiB

  1. /**
  2. * @cond internal
  3. * @file ec_point.c
  4. * @copyright
  5. * Copyright (c) 2014 Cryptography Research, Inc. \n
  6. * Released under the MIT License. See LICENSE.txt for license information.
  7. * @author Mike Hamburg
  8. * @warning This file was automatically generated.
  9. * Then it was edited by hand. Good luck, have fun.
  10. */
  11. #include "ec_point.h"
  12. #include "magic.h"
  13. void
  14. add_tw_niels_to_tw_extensible (
  15. tw_extensible_a_t d,
  16. const tw_niels_a_t e
  17. ) {
  18. ANALYZE_THIS_ROUTINE_CAREFULLY;
  19. field_a_t L0, L1;
  20. field_sub ( L1, d->y, d->x );
  21. field_mul ( L0, e->a, L1 );
  22. field_add_nr ( L1, d->x, d->y );
  23. field_mul ( d->y, e->b, L1 );
  24. field_mul ( L1, d->u, d->t );
  25. field_mul ( d->x, e->c, L1 );
  26. field_add_nr ( d->u, L0, d->y );
  27. field_subx_nr ( d->t, d->y, L0 );
  28. field_subx_nr ( d->y, d->z, d->x );
  29. field_add_nr ( L0, d->x, d->z );
  30. field_mul ( d->z, L0, d->y );
  31. field_mul ( d->x, d->y, d->t );
  32. field_mul ( d->y, L0, d->u );
  33. }
  34. void
  35. sub_tw_niels_from_tw_extensible (
  36. tw_extensible_a_t d,
  37. const tw_niels_a_t e
  38. ) {
  39. ANALYZE_THIS_ROUTINE_CAREFULLY;
  40. field_a_t L0, L1;
  41. field_subx_nr ( L1, d->y, d->x );
  42. field_mul ( L0, e->b, L1 );
  43. field_add_nr ( L1, d->x, d->y );
  44. field_mul ( d->y, e->a, L1 );
  45. field_mul ( L1, d->u, d->t );
  46. field_mul ( d->x, e->c, L1 );
  47. field_add_nr ( d->u, L0, d->y );
  48. field_subx_nr ( d->t, d->y, L0 );
  49. field_add_nr ( d->y, d->x, d->z );
  50. field_subx_nr ( L0, d->z, d->x );
  51. field_mul ( d->z, L0, d->y );
  52. field_mul ( d->x, d->y, d->t );
  53. field_mul ( d->y, L0, d->u );
  54. }
  55. void
  56. add_tw_pniels_to_tw_extensible (
  57. tw_extensible_a_t e,
  58. const tw_pniels_a_t a
  59. ) {
  60. field_a_t L0;
  61. field_mul ( L0, e->z, a->z );
  62. field_copy ( e->z, L0 );
  63. add_tw_niels_to_tw_extensible( e, a->n );
  64. }
  65. void
  66. sub_tw_pniels_from_tw_extensible (
  67. tw_extensible_a_t e,
  68. const tw_pniels_a_t a
  69. ) {
  70. field_a_t L0;
  71. field_mul ( L0, e->z, a->z );
  72. field_copy ( e->z, L0 );
  73. sub_tw_niels_from_tw_extensible( e, a->n );
  74. }
  75. void
  76. double_tw_extensible (
  77. tw_extensible_a_t a
  78. ) {
  79. ANALYZE_THIS_ROUTINE_CAREFULLY;
  80. field_a_t L0, L1, L2;
  81. field_sqr ( L2, a->x );
  82. field_sqr ( L0, a->y );
  83. field_add_nr ( a->u, L2, L0 );
  84. field_add_nr ( a->t, a->y, a->x );
  85. field_sqr ( L1, a->t );
  86. field_sub_nr ( a->t, L1, a->u );
  87. field_bias ( a->t, 3 );
  88. IF32( field_weak_reduce( a->t ) );
  89. field_subx_nr ( L1, L0, L2 );
  90. field_sqr ( a->x, a->z );
  91. field_bias ( a->x, 2-is32 /*is32 ? 1 : 2*/ );
  92. field_add_nr ( a->z, a->x, a->x );
  93. field_sub_nr ( L0, a->z, L1 );
  94. IF32( field_weak_reduce( L0 ) );
  95. field_mul ( a->z, L1, L0 );
  96. field_mul ( a->x, L0, a->t );
  97. field_mul ( a->y, L1, a->u );
  98. }
  99. void
  100. double_extensible (
  101. extensible_a_t a
  102. ) {
  103. ANALYZE_THIS_ROUTINE_CAREFULLY;
  104. field_a_t L0, L1, L2;
  105. field_sqr ( L2, a->x );
  106. field_sqr ( L0, a->y );
  107. field_add_nr ( L1, L2, L0 );
  108. field_add_nr ( a->t, a->y, a->x );
  109. field_sqr ( a->u, a->t );
  110. field_sub_nr ( a->t, a->u, L1 );
  111. field_bias ( a->t, 3 );
  112. IF32( field_weak_reduce( a->t ) );
  113. field_subx_nr ( a->u, L0, L2 );
  114. field_sqr ( a->x, a->z );
  115. field_bias ( a->x, 2 );
  116. field_add_nr ( a->z, a->x, a->x );
  117. field_sub_nr ( L0, a->z, L1 );
  118. IF32( field_weak_reduce( L0 ) );
  119. field_mul ( a->z, L1, L0 );
  120. field_mul ( a->x, L0, a->t );
  121. field_mul ( a->y, L1, a->u );
  122. }
  123. void
  124. twist_and_double (
  125. tw_extensible_a_t b,
  126. const extensible_a_t a
  127. ) {
  128. field_a_t L0;
  129. field_sqr ( b->x, a->x );
  130. field_sqr ( b->z, a->y );
  131. field_add ( b->u, b->x, b->z );
  132. field_add ( b->t, a->y, a->x );
  133. field_sqr ( L0, b->t );
  134. field_sub ( b->t, L0, b->u );
  135. field_sub ( L0, b->z, b->x );
  136. field_sqr ( b->x, a->z );
  137. field_add ( b->z, b->x, b->x );
  138. field_sub ( b->y, b->z, b->u );
  139. field_mul ( b->z, L0, b->y );
  140. field_mul ( b->x, b->y, b->t );
  141. field_mul ( b->y, L0, b->u );
  142. }
  143. void
  144. untwist_and_double (
  145. extensible_a_t b,
  146. const tw_extensible_a_t a
  147. ) {
  148. field_a_t L0;
  149. field_sqr ( b->x, a->x );
  150. field_sqr ( b->z, a->y );
  151. field_add ( L0, b->x, b->z );
  152. field_add ( b->t, a->y, a->x );
  153. field_sqr ( b->u, b->t );
  154. field_sub ( b->t, b->u, L0 );
  155. field_sub ( b->u, b->z, b->x );
  156. field_sqr ( b->x, a->z );
  157. field_add ( b->z, b->x, b->x );
  158. field_sub ( b->y, b->z, b->u );
  159. field_mul ( b->z, L0, b->y );
  160. field_mul ( b->x, b->y, b->t );
  161. field_mul ( b->y, L0, b->u );
  162. }
  163. void
  164. convert_tw_affine_to_tw_pniels (
  165. tw_pniels_a_t b,
  166. const tw_affine_a_t a
  167. ) {
  168. field_sub ( b->n->a, a->y, a->x );
  169. field_add ( b->n->b, a->x, a->y );
  170. field_mul ( b->z, a->y, a->x );
  171. field_mulw_scc_wr ( b->n->c, b->z, 2*EDWARDS_D-2 );
  172. field_set_ui( b->z, 2 );
  173. }
  174. void
  175. convert_tw_affine_to_tw_extensible (
  176. tw_extensible_a_t b,
  177. const tw_affine_a_t a
  178. ) {
  179. field_copy ( b->x, a->x );
  180. field_copy ( b->y, a->y );
  181. field_set_ui( b->z, 1 );
  182. field_copy ( b->t, a->x );
  183. field_copy ( b->u, a->y );
  184. }
  185. void
  186. convert_affine_to_extensible (
  187. extensible_a_t b,
  188. const affine_a_t a
  189. ) {
  190. field_copy ( b->x, a->x );
  191. field_copy ( b->y, a->y );
  192. field_set_ui( b->z, 1 );
  193. field_copy ( b->t, a->x );
  194. field_copy ( b->u, a->y );
  195. }
  196. void
  197. convert_tw_extensible_to_tw_pniels (
  198. tw_pniels_a_t b,
  199. const tw_extensible_a_t a
  200. ) {
  201. field_sub ( b->n->a, a->y, a->x );
  202. field_add ( b->n->b, a->x, a->y );
  203. field_mul ( b->z, a->u, a->t );
  204. field_mulw_scc_wr ( b->n->c, b->z, 2*EDWARDS_D-2 );
  205. field_add ( b->z, a->z, a->z );
  206. }
  207. void
  208. convert_tw_pniels_to_tw_extensible (
  209. tw_extensible_a_t e,
  210. const tw_pniels_a_t d
  211. ) {
  212. field_add ( e->u, d->n->b, d->n->a );
  213. field_sub ( e->t, d->n->b, d->n->a );
  214. field_mul ( e->x, d->z, e->t );
  215. field_mul ( e->y, d->z, e->u );
  216. field_sqr ( e->z, d->z );
  217. }
  218. void
  219. convert_tw_niels_to_tw_extensible (
  220. tw_extensible_a_t e,
  221. const tw_niels_a_t d
  222. ) {
  223. field_add ( e->y, d->b, d->a );
  224. field_sub ( e->x, d->b, d->a );
  225. field_set_ui( e->z, 1 );
  226. field_copy ( e->t, e->x );
  227. field_copy ( e->u, e->y );
  228. }
  229. void
  230. decaf_deserialize_montgomery (
  231. montgomery_aux_a_t a,
  232. const field_a_t s
  233. ) {
  234. field_copy ( a->s0, s );
  235. field_sqr ( a->xa, s );
  236. field_set_ui ( a->za, 1 );
  237. field_set_ui ( a->xd, 1 );
  238. field_set_ui ( a->zd, 0 );
  239. }
  240. void
  241. montgomery_aux_step (
  242. struct montgomery_aux_t* a
  243. ) {
  244. ANALYZE_THIS_ROUTINE_CAREFULLY;
  245. field_add_nr ( a->xs, a->xa, a->za );
  246. field_subx_nr ( a->zs, a->xa, a->za );
  247. field_add_nr ( a->xa, a->xd, a->zd );
  248. field_subx_nr ( a->za, a->xd, a->zd );
  249. field_mul ( a->xd, a->xa, a->zs );
  250. field_mul ( a->zd, a->xs, a->za );
  251. field_add_nr ( a->xs, a->xd, a->zd );
  252. field_subx_nr ( a->zd, a->xd, a->zd );
  253. field_mul ( a->zs, a->zd, a->s0 );
  254. field_sqr ( a->zd, a->xa );
  255. field_sqr ( a->xa, a->za );
  256. field_subx_nr ( a->za, a->zd, a->xa );
  257. field_mul ( a->xd, a->xa, a->zd );
  258. field_mulw_scc_wr ( a->zd, a->za, 1-EDWARDS_D );
  259. field_add_nr ( a->xa, a->xa, a->zd );
  260. field_mul ( a->zd, a->xa, a->za );
  261. field_sqr ( a->xa, a->xs );
  262. field_sqr ( a->za, a->zs );
  263. }
  264. void
  265. montgomery_step (
  266. montgomery_a_t a
  267. ) {
  268. ANALYZE_THIS_ROUTINE_CAREFULLY;
  269. field_a_t L0, L1;
  270. field_add_nr ( L0, a->zd, a->xd );
  271. field_subx_nr ( L1, a->xd, a->zd );
  272. field_subx_nr ( a->zd, a->xa, a->za );
  273. field_mul ( a->xd, L0, a->zd );
  274. field_add_nr ( a->zd, a->za, a->xa );
  275. field_mul ( a->za, L1, a->zd );
  276. field_add_nr ( a->xa, a->za, a->xd );
  277. field_sqr ( a->zd, a->xa );
  278. field_mul ( a->xa, a->z0, a->zd );
  279. field_subx_nr ( a->zd, a->xd, a->za );
  280. field_sqr ( a->za, a->zd );
  281. field_sqr ( a->xd, L0 );
  282. field_sqr ( L0, L1 );
  283. field_mulw_scc ( a->zd, a->xd, 1-EDWARDS_D ); /* FIXME PERF MULW */
  284. field_subx_nr ( L1, a->xd, L0 );
  285. field_mul ( a->xd, L0, a->zd );
  286. field_sub_nr ( L0, a->zd, L1 );
  287. field_bias ( L0, 4 - 2*is32 /*is32 ? 2 : 4*/ );
  288. IF32( field_weak_reduce( L0 ) );
  289. field_mul ( a->zd, L0, L1 );
  290. }
  291. void
  292. deserialize_montgomery (
  293. montgomery_a_t a,
  294. const field_a_t sbz
  295. ) {
  296. field_sqr ( a->z0, sbz );
  297. field_set_ui( a->xd, 1 );
  298. field_set_ui( a->zd, 0 );
  299. field_set_ui( a->xa, 1 );
  300. field_copy ( a->za, a->z0 );
  301. }
  302. mask_t
  303. serialize_montgomery (
  304. field_a_t b,
  305. const montgomery_a_t a,
  306. const field_a_t sbz
  307. ) {
  308. mask_t L4, L5, L6;
  309. field_a_t L0, L1, L2, L3;
  310. field_mul ( L3, a->z0, a->zd );
  311. field_sub ( L1, L3, a->xd );
  312. field_mul ( L3, a->za, L1 );
  313. field_mul ( L2, a->z0, a->xd );
  314. field_sub ( L1, L2, a->zd );
  315. field_mul ( L0, a->xa, L1 );
  316. field_add ( L2, L0, L3 );
  317. field_sub ( L1, L3, L0 );
  318. field_mul ( L3, L1, L2 );
  319. field_copy ( L2, a->z0 );
  320. field_addw ( L2, 1 );
  321. field_sqr ( L0, L2 );
  322. field_mulw_scc_wr ( L1, L0, EDWARDS_D-1 );
  323. field_add ( L2, a->z0, a->z0 );
  324. field_add ( L0, L2, L2 );
  325. field_add ( L2, L0, L1 );
  326. field_mul ( L0, a->xd, L2 );
  327. L5 = field_is_zero( a->zd );
  328. L6 = - L5;
  329. constant_time_mask ( L1, L0, sizeof(L1), L5 );
  330. field_add ( L2, L1, a->zd );
  331. L4 = ~ L5;
  332. field_mul ( L1, sbz, L3 );
  333. field_addw ( L1, L6 );
  334. field_mul ( L3, L2, L1 );
  335. field_mul ( L1, L3, L2 );
  336. field_mul ( L2, L3, a->xd );
  337. field_mul ( L3, L1, L2 );
  338. field_isr ( L0, L3 );
  339. field_mul ( L2, L1, L0 );
  340. field_sqr ( L1, L0 );
  341. field_mul ( L0, L3, L1 );
  342. constant_time_mask ( b, L2, sizeof(L1), L4 );
  343. field_subw( L0, 1 );
  344. L5 = field_is_zero( L0 );
  345. L4 = field_is_zero( sbz );
  346. return L5 | L4;
  347. }
  348. void
  349. serialize_extensible (
  350. field_a_t b,
  351. const extensible_a_t a
  352. ) {
  353. field_a_t L0, L1, L2;
  354. field_sub ( L0, a->y, a->z );
  355. field_add ( b, a->z, a->y );
  356. field_mul ( L1, a->z, a->x );
  357. field_mul ( L2, L0, L1 );
  358. field_mul ( L1, L2, L0 );
  359. field_mul ( L0, L2, b );
  360. field_mul ( L2, L1, L0 );
  361. field_isr ( L0, L2 );
  362. field_mul ( b, L1, L0 );
  363. field_sqr ( L1, L0 );
  364. field_mul ( L0, L2, L1 );
  365. }
  366. static void
  367. decaf_abs (
  368. field_a_t a
  369. ) {
  370. field_cond_neg ( a, field_high_bit(a) );
  371. field_strong_reduce ( a );
  372. }
  373. mask_t
  374. decaf_serialize_montgomery (
  375. field_a_t out,
  376. const montgomery_aux_a_t a,
  377. mask_t swapped
  378. ) {
  379. field_a_t xz_d, xz_a, x0, den, L0, L1, L2, L3;
  380. mask_t zcase, output_zero, flip, succ, za_zero;
  381. field_mul(xz_d, a->xd, a->zd);
  382. field_mul(xz_a, a->xa, a->za);
  383. output_zero = field_is_zero(xz_d);
  384. za_zero = field_is_zero(a->za);
  385. field_addw(xz_d, -output_zero); /* make xz_d always nonzero */
  386. zcase = output_zero | field_is_zero(xz_a);
  387. field_sqr(x0, a->s0);
  388. /* Curve test in zcase */
  389. field_copy(L0,x0);
  390. field_addw(L0,1);
  391. field_sqr(L1,L0);
  392. field_mulw_scc_wr(L0,x0,-4*EDWARDS_D);
  393. field_add(L1,L1,L0);
  394. constant_time_select(xz_a,L1,xz_a,sizeof(xz_a),zcase);
  395. /* Compute denominator */
  396. field_mul(L0, x0, xz_d);
  397. field_mulw(L2, L0, 4);
  398. field_mul(L1, L2, xz_a);
  399. field_isr(den, L1);
  400. /* Check squareness */
  401. field_sqr(L2, den);
  402. field_mul(L0, L1, L2);
  403. field_addw(L0, 1);
  404. succ = ~field_high_bit(a->s0) & ~field_is_zero(L0);
  405. /* Compute y/x */
  406. field_mul(L1, x0, a->xd);
  407. field_sub(L1, a->zd, L1);
  408. field_mul(L0, a->za, L1); /* L0 = "opq" */
  409. field_mul(L1, x0, a->zd);
  410. field_sub(L1, L1, a->xd);
  411. field_mul(L2, a->xa, L1); /* L2 = "pqr" */
  412. field_sub(L1, L0, L2);
  413. field_add(L0, L0, L2);
  414. field_mul(L2, L1, den); /* L2 = y0 / x0 */
  415. field_mul(L1, L0, den); /* L1 = yO / xO */
  416. flip = field_high_bit(L1) ^ field_high_bit(L2) ^ za_zero;
  417. constant_time_select(L0, a->zd, a->xd, sizeof(L0), flip); /* L0 = "times" */
  418. /* OK, done with y-coordinates */
  419. /* OK, now correct for swappage */
  420. field_add(den,den,den);
  421. field_mul(L1,den,a->s0);
  422. field_sqr(L2,L1);
  423. field_mul(L3,L2,xz_a);
  424. constant_time_select(den,L3,L1,sizeof(den),swapped | zcase);
  425. /* compute the output */
  426. field_mul(L1,L0,den);
  427. constant_time_select(L2,a->s0,a->zs,sizeof(L2),zcase); /* zs, but s0 in zcase */
  428. field_mul(L0,L1,L2);
  429. constant_time_select(L3,a->zd,a->xd,sizeof(L3),za_zero);
  430. constant_time_select(L2,L3,a->xs,sizeof(L2),zcase); /* xs, but zq or qq in zcase */
  431. field_mul(out,L0,L2);
  432. constant_time_mask(out,out,sizeof(field_a_t),~output_zero);
  433. decaf_abs(out);
  434. return succ;
  435. }
  436. void
  437. decaf_serialize_extensible (
  438. field_a_t b,
  439. const extensible_a_t a
  440. ) {
  441. field_a_t L0, L1, L2, L3;
  442. field_mulw_scc ( L2, a->y, EDWARDS_D );
  443. field_mul ( L3, L2, a->t );
  444. field_mul ( L2, L3, a->u );
  445. field_mul ( L0, a->x, a->z );
  446. field_sub ( L3, L0, L2 );
  447. field_add ( L0, a->y, a->z );
  448. field_sub ( L1, a->z, a->y );
  449. field_mul ( L2, L1, L0 );
  450. field_mulw_scc ( L1, L2, 1-EDWARDS_D );
  451. field_isr ( L0, L1 );
  452. field_mulw_scc ( L1, L0, 1-EDWARDS_D );
  453. field_mul ( L2, L1, L0 );
  454. field_mul ( L0, L2, L3 );
  455. field_add ( L3, L1, L1 );
  456. field_mul ( L2, L3, a->z );
  457. field_cond_neg ( L1, ~field_high_bit(L2) );
  458. field_mul ( L2, L1, a->y );
  459. field_add ( b, L0, L2 );
  460. decaf_abs ( b );
  461. }
  462. void
  463. decaf_serialize_tw_extensible (
  464. field_a_t b,
  465. const tw_extensible_a_t a
  466. ) {
  467. field_a_t L0, L1, L2, L3;
  468. field_mulw_scc ( L2, a->y, 1-EDWARDS_D );
  469. field_mul ( L3, L2, a->t );
  470. field_mul ( L2, L3, a->u );
  471. field_mul ( L0, a->x, a->z );
  472. field_sub ( L3, L2, L0 );
  473. field_add ( L0, a->z, a->y );
  474. field_sub ( L1, a->z, a->y );
  475. field_mul ( L2, L1, L0 );
  476. field_mulw_scc ( L1, L2, -EDWARDS_D );
  477. field_isr ( L0, L1 );
  478. field_mulw_scc ( L1, L0, -EDWARDS_D );
  479. field_mul ( L2, L1, L0 );
  480. field_mul ( L0, L2, L3 );
  481. field_add ( L3, L1, L1 );
  482. field_mul ( L2, L3, a->z );
  483. field_cond_neg ( L1, ~field_high_bit(L2) );
  484. field_mul ( L2, L1, a->y );
  485. field_add ( b, L0, L2 );
  486. decaf_abs ( b );
  487. }
  488. mask_t
  489. decaf_deserialize_affine (
  490. affine_a_t a,
  491. const field_a_t s,
  492. mask_t allow_identity
  493. ) {
  494. field_a_t L0, L1, L2, L3, L4, L5;
  495. mask_t succ, zero;
  496. zero = field_is_zero(s);
  497. succ = allow_identity | ~zero;
  498. succ &= ~field_high_bit(s);
  499. field_sqr ( L0, s );
  500. field_copy ( L1, L0 );
  501. field_addw ( L1, 1 );
  502. field_make_nonzero ( L1 );
  503. field_sqr ( L2, L1 );
  504. field_mulw_scc_wr ( L3, L0, -4*EDWARDS_D );
  505. field_add ( L3, L3, L2 );
  506. field_mul ( L4, L3, L2 );
  507. field_mul ( L2, L4, L0 );
  508. field_isr ( L4, L2 );
  509. field_sqr ( L5, L4 );
  510. field_mul ( L0, L5, L2 );
  511. field_addw( L0, 1 );
  512. succ &= ~field_is_zero( L0 );
  513. field_mul ( L2, L3, L1 );
  514. field_mul ( L3, L2, L4 );
  515. field_cond_neg ( L4, field_high_bit(L3) );
  516. field_mul ( L3, L4, s );
  517. field_sqr ( L4, L3 );
  518. field_mul ( L0, L2, L4 );
  519. field_add ( L0, L0, L0 );
  520. field_mul ( a->x, L0, s );
  521. field_mul ( L2, L1, L3 );
  522. field_neg ( L1, L1 );
  523. field_addw ( L1, 2 );
  524. field_mul ( a->y, L1, L2 );
  525. field_addw ( a->y, -zero );
  526. return succ;
  527. }
  528. mask_t
  529. decaf_deserialize_tw_affine (
  530. tw_affine_a_t a,
  531. const field_a_t s,
  532. mask_t allow_identity
  533. ) {
  534. field_a_t L0, L1, L2, L3, L4, L5;
  535. mask_t succ, zero;
  536. zero = field_is_zero(s);
  537. succ = allow_identity | ~zero;
  538. succ &= ~field_high_bit(s);
  539. field_sqr ( L0, s );
  540. field_neg ( L1, L0 );
  541. field_addw ( L1, 1 );
  542. field_make_nonzero ( L1 );
  543. field_sqr ( L2, L1 );
  544. field_mulw_scc_wr ( L3, L0, 4-4*EDWARDS_D );
  545. field_add ( L3, L3, L2 );
  546. field_mul ( L4, L3, L2 );
  547. field_mul ( L2, L4, L0 );
  548. field_isr ( L4, L2 );
  549. field_sqr ( L5, L4 );
  550. field_mul ( L0, L5, L2 );
  551. field_addw( L0, 1 );
  552. succ &= ~field_is_zero( L0 );
  553. field_mul ( L2, L3, L1 );
  554. field_mul ( L3, L2, L4 );
  555. field_cond_neg ( L4, field_high_bit(L3) );
  556. field_mul ( L3, L4, s );
  557. field_sqr ( L4, L3 );
  558. field_mul ( L0, L2, L4 );
  559. field_add ( L0, L0, L0 );
  560. field_mul ( a->x, L0, s );
  561. field_mul ( L2, L1, L3 );
  562. field_neg ( L1, L1 );
  563. field_addw ( L1, 2 );
  564. field_mul ( a->y, L1, L2 );
  565. field_addw ( a->y, -zero );
  566. return succ;
  567. }
  568. void
  569. untwist_and_double_and_serialize (
  570. field_a_t b,
  571. const tw_extensible_a_t a
  572. ) {
  573. field_a_t L0, L1, L2, L3;
  574. field_mul ( L3, a->y, a->x );
  575. field_add ( b, a->y, a->x );
  576. field_sqr ( L1, b );
  577. field_add ( L2, L3, L3 );
  578. field_sub ( b, L1, L2 );
  579. field_sqr ( L2, a->z );
  580. field_sqr ( L1, L2 );
  581. field_add ( b, b, b );
  582. field_mulw_scc ( L2, b, EDWARDS_D-1 );
  583. field_mulw_scc ( b, L2, EDWARDS_D-1 );
  584. field_mul ( L0, L2, L1 );
  585. field_mul ( L2, b, L0 );
  586. field_isr ( L0, L2 );
  587. field_mul ( L1, b, L0 );
  588. field_sqr ( b, L0 );
  589. field_mul ( L0, L2, b );
  590. field_mul ( b, L1, L3 );
  591. }
  592. void
  593. twist_even (
  594. tw_extensible_a_t b,
  595. const extensible_a_t a
  596. ) {
  597. field_sqr ( b->y, a->z );
  598. field_sqr ( b->z, a->x );
  599. field_sub ( b->u, b->y, b->z );
  600. field_sub ( b->z, a->z, a->x );
  601. field_mul ( b->y, b->z, a->y );
  602. field_sub ( b->z, a->z, a->y );
  603. field_mul ( b->x, b->z, b->y );
  604. field_mul ( b->t, b->x, b->u );
  605. field_mul ( b->y, b->x, b->t );
  606. field_isr ( b->t, b->y );
  607. field_mul ( b->u, b->x, b->t );
  608. field_sqr ( b->x, b->t );
  609. field_mul ( b->t, b->y, b->x );
  610. field_mul ( b->x, a->x, b->u );
  611. field_mul ( b->y, a->y, b->u );
  612. field_addw ( b->y, -field_is_zero( b->z ) );
  613. field_set_ui( b->z, 1 );
  614. field_copy ( b->t, b->x );
  615. field_copy ( b->u, b->y );
  616. }
  617. void
  618. test_only_twist (
  619. tw_extensible_a_t b,
  620. const extensible_a_t a
  621. ) {
  622. field_a_t L0, L1;
  623. field_sqr ( b->u, a->z );
  624. field_sqr ( b->y, a->x );
  625. field_sub ( b->z, b->u, b->y );
  626. field_add ( b->y, b->z, b->z );
  627. field_add ( b->u, b->y, b->y );
  628. field_sub ( b->y, a->z, a->x );
  629. field_mul ( b->x, b->y, a->y );
  630. field_sub ( b->z, a->z, a->y );
  631. field_mul ( b->t, b->z, b->x );
  632. field_mul ( L1, b->t, b->u );
  633. field_mul ( b->x, b->t, L1 );
  634. field_isr ( L0, b->x );
  635. field_mul ( b->u, b->t, L0 );
  636. field_sqr ( L1, L0 );
  637. field_mul ( b->t, b->x, L1 );
  638. field_add ( L1, a->y, a->x );
  639. field_sub ( L0, a->x, a->y );
  640. field_mul ( b->x, b->t, L0 );
  641. field_add ( L0, b->x, L1 );
  642. field_sub ( b->t, L1, b->x );
  643. field_mul ( b->x, L0, b->u );
  644. field_addw ( b->x, -field_is_zero( b->y ) );
  645. field_mul ( b->y, b->t, b->u );
  646. field_addw ( b->y, -field_is_zero( b->z ) );
  647. field_set_ui( b->z, 1+field_is_zero( a->y ) );
  648. field_copy ( b->t, b->x );
  649. field_copy ( b->u, b->y );
  650. }
  651. mask_t
  652. is_even_pt (
  653. const extensible_a_t a
  654. ) {
  655. field_a_t L0, L1, L2;
  656. field_sqr ( L2, a->z );
  657. field_sqr ( L1, a->x );
  658. field_sub ( L0, L2, L1 );
  659. return field_is_square ( L0 );
  660. }
  661. mask_t
  662. is_even_tw (
  663. const tw_extensible_a_t a
  664. ) {
  665. field_a_t L0, L1, L2;
  666. field_sqr ( L2, a->z );
  667. field_sqr ( L1, a->x );
  668. field_add ( L0, L1, L2 );
  669. return field_is_square ( L0 );
  670. }
  671. mask_t
  672. deserialize_affine (
  673. affine_a_t a,
  674. const field_a_t sz
  675. ) {
  676. field_a_t L0, L1, L2, L3;
  677. field_sqr ( L1, sz );
  678. field_copy ( L3, L1 );
  679. field_addw ( L3, 1 );
  680. field_sqr ( L2, L3 );
  681. field_mulw_scc ( a->x, L2, EDWARDS_D-1 ); /* PERF MULW */
  682. field_add ( L3, L1, L1 );
  683. field_add ( a->y, L3, L3 );
  684. field_add ( L3, a->y, a->x );
  685. field_copy ( a->y, L1 );
  686. field_neg ( a->x, a->y );
  687. field_addw ( a->x, 1 );
  688. field_mul ( a->y, a->x, L3 );
  689. field_sqr ( L2, a->x );
  690. field_mul ( L0, L2, a->y );
  691. field_mul ( a->y, a->x, L0 );
  692. field_isr ( L3, a->y );
  693. field_mul ( a->y, L2, L3 );
  694. field_sqr ( L2, L3 );
  695. field_mul ( L3, L0, L2 );
  696. field_mul ( L0, a->x, L3 );
  697. field_add ( L2, a->y, a->y );
  698. field_mul ( a->x, sz, L2 );
  699. field_addw ( L1, 1 );
  700. field_mul ( a->y, L1, L3 );
  701. field_subw( L0, 1 );
  702. return field_is_zero( L0 );
  703. }
  704. mask_t
  705. deserialize_and_twist_approx (
  706. tw_extensible_a_t a,
  707. const field_a_t sz
  708. ) {
  709. field_a_t L0, L1;
  710. field_sqr ( a->z, sz );
  711. field_copy ( a->y, a->z );
  712. field_addw ( a->y, 1 );
  713. field_sqr ( L0, a->y );
  714. field_mulw_scc ( a->x, L0, EDWARDS_D-1 );
  715. field_add ( a->y, a->z, a->z );
  716. field_add ( a->u, a->y, a->y );
  717. field_add ( a->y, a->u, a->x );
  718. field_sqr ( a->x, a->z );
  719. field_neg ( a->u, a->x );
  720. field_addw ( a->u, 1 );
  721. field_mul ( a->x, sqrt_d_minus_1, a->u );
  722. field_mul ( L0, a->x, a->y );
  723. field_mul ( a->t, L0, a->y );
  724. field_mul ( a->u, a->x, a->t );
  725. field_mul ( a->t, a->u, L0 );
  726. field_mul ( a->y, a->x, a->t );
  727. field_isr ( L0, a->y );
  728. field_mul ( a->y, a->u, L0 );
  729. field_sqr ( L1, L0 );
  730. field_mul ( a->u, a->t, L1 );
  731. field_mul ( a->t, a->x, a->u );
  732. field_add ( a->x, sz, sz );
  733. field_mul ( L0, a->u, a->x );
  734. field_copy ( a->x, a->z );
  735. field_neg ( L1, a->x );
  736. field_addw ( L1, 1 );
  737. field_mul ( a->x, L1, L0 );
  738. field_mul ( L0, a->u, a->y );
  739. field_addw ( a->z, 1 );
  740. field_mul ( a->y, a->z, L0 );
  741. field_subw( a->t, 1 );
  742. mask_t ret = field_is_zero( a->t );
  743. field_set_ui( a->z, 1 );
  744. field_copy ( a->t, a->x );
  745. field_copy ( a->u, a->y );
  746. return ret;
  747. }
  748. void
  749. set_identity_extensible (
  750. extensible_a_t a
  751. ) {
  752. field_set_ui( a->x, 0 );
  753. field_set_ui( a->y, 1 );
  754. field_set_ui( a->z, 1 );
  755. field_set_ui( a->t, 0 );
  756. field_set_ui( a->u, 0 );
  757. }
  758. void
  759. set_identity_tw_extensible (
  760. tw_extensible_a_t a
  761. ) {
  762. field_set_ui( a->x, 0 );
  763. field_set_ui( a->y, 1 );
  764. field_set_ui( a->z, 1 );
  765. field_set_ui( a->t, 0 );
  766. field_set_ui( a->u, 0 );
  767. }
  768. void
  769. set_identity_affine (
  770. affine_a_t a
  771. ) {
  772. field_set_ui( a->x, 0 );
  773. field_set_ui( a->y, 1 );
  774. }
  775. mask_t
  776. decaf_eq_extensible (
  777. const struct extensible_t* a,
  778. const struct extensible_t* b
  779. ) {
  780. field_a_t L0, L1, L2;
  781. field_mul ( L2, b->y, a->x );
  782. field_mul ( L1, a->y, b->x );
  783. field_sub ( L0, L2, L1 );
  784. field_bias ( L0, 2 );
  785. return field_is_zero ( L0 );
  786. }
  787. mask_t
  788. decaf_eq_tw_extensible (
  789. const struct tw_extensible_t* a,
  790. const struct tw_extensible_t* b
  791. ) {
  792. field_a_t L0, L1, L2;
  793. field_mul ( L2, b->y, a->x );
  794. field_mul ( L1, a->y, b->x );
  795. field_sub ( L0, L2, L1 );
  796. field_bias ( L0, 2 );
  797. return field_is_zero ( L0 );
  798. }
  799. mask_t
  800. eq_affine (
  801. const affine_a_t a,
  802. const affine_a_t b
  803. ) {
  804. mask_t L1, L2;
  805. field_a_t L0;
  806. field_sub ( L0, a->x, b->x );
  807. L2 = field_is_zero( L0 );
  808. field_sub ( L0, a->y, b->y );
  809. L1 = field_is_zero( L0 );
  810. return L2 & L1;
  811. }
  812. mask_t
  813. eq_extensible (
  814. const extensible_a_t a,
  815. const extensible_a_t b
  816. ) {
  817. mask_t L3, L4;
  818. field_a_t L0, L1, L2;
  819. field_mul ( L2, b->z, a->x );
  820. field_mul ( L1, a->z, b->x );
  821. field_sub ( L0, L2, L1 );
  822. L4 = field_is_zero( L0 );
  823. field_mul ( L2, b->z, a->y );
  824. field_mul ( L1, a->z, b->y );
  825. field_sub ( L0, L2, L1 );
  826. L3 = field_is_zero( L0 );
  827. return L4 & L3;
  828. }
  829. mask_t
  830. eq_tw_extensible (
  831. const tw_extensible_a_t a,
  832. const tw_extensible_a_t b
  833. ) {
  834. mask_t L3, L4;
  835. field_a_t L0, L1, L2;
  836. field_mul ( L2, b->z, a->x );
  837. field_mul ( L1, a->z, b->x );
  838. field_sub ( L0, L2, L1 );
  839. L4 = field_is_zero( L0 );
  840. field_mul ( L2, b->z, a->y );
  841. field_mul ( L1, a->z, b->y );
  842. field_sub ( L0, L2, L1 );
  843. L3 = field_is_zero( L0 );
  844. return L4 & L3;
  845. }
  846. void
  847. elligator_2s_inject (
  848. affine_a_t a,
  849. const field_a_t r
  850. ) {
  851. field_a_t L2, L3, L4, L5, L6, L7, L8;
  852. field_sqr ( a->x, r );
  853. field_sqr ( L3, a->x );
  854. field_copy ( a->y, L3 );
  855. field_neg ( L4, a->y );
  856. field_addw ( L4, 1 );
  857. field_sqr ( L2, L4 );
  858. field_mulw ( L7, L2, (EDWARDS_D-1)*(EDWARDS_D-1) );
  859. field_mulw ( L8, L3, 4*(EDWARDS_D+1)*(EDWARDS_D+1) );
  860. field_add ( a->y, L8, L7 );
  861. field_mulw ( L8, L2, 4*(EDWARDS_D)*(EDWARDS_D-1) );
  862. field_sub ( L7, a->y, L8 );
  863. field_mulw_scc ( L6, a->y, -2-2*EDWARDS_D );
  864. field_mul ( L5, L7, L6 );
  865. /* FIXME Stability problem (API stability, not crash) / possible bug.
  866. * change to: p448_mul ( L5, L7, L4 ); ?
  867. * This isn't a deep change: it's for sign adjustment.
  868. * Need to check which one leads to the correct sign, probably by writig
  869. * the invert routine.
  870. *
  871. * Also, the tool doesn't produce the optimal route to this.
  872. * Let incoming L6 = a, L7 = e, L4 = b.
  873. *
  874. * Could compute be, (be)^2, (be)^3, a b^3 e^3, a b^3 e^4. = 4M+S
  875. * instead of 6M.
  876. */
  877. field_mul ( L8, L5, L4 );
  878. field_mul ( L4, L5, L6 );
  879. field_mul ( L5, L7, L8 );
  880. field_mul ( L8, L5, L4 );
  881. field_mul ( L4, L7, L8 );
  882. field_isr ( L6, L4 );
  883. field_mul ( L4, L5, L6 );
  884. field_sqr ( L5, L6 );
  885. field_mul ( L6, L8, L5 );
  886. field_mul ( L8, L7, L6 );
  887. field_mul ( L7, L8, L6 );
  888. field_copy ( L6, a->x );
  889. field_addw ( a->x, 1 );
  890. field_mul ( L5, a->x, L8 );
  891. field_addw ( L5, 1 );
  892. field_sub ( a->x, L6, L5 );
  893. field_mul ( L5, L4, a->x );
  894. field_mulw_scc_wr ( a->x, L5, -2-2*EDWARDS_D );
  895. field_add ( L4, L3, L3 );
  896. field_add ( L3, L4, L2 );
  897. field_subw( L3, 2 );
  898. field_mul ( L2, L3, L8 );
  899. field_mulw ( L3, L2, 2*(EDWARDS_D+1)*(EDWARDS_D-1) );
  900. field_add ( L2, L3, a->y );
  901. field_mul ( a->y, L7, L2 );
  902. field_addw ( a->y, -field_is_zero( L8 ) );
  903. }
  904. mask_t
  905. validate_affine (
  906. const affine_a_t a
  907. ) {
  908. field_a_t L0, L1, L2, L3;
  909. field_sqr ( L0, a->y );
  910. field_sqr ( L1, a->x );
  911. field_add ( L3, L1, L0 );
  912. field_mulw_scc ( L2, L1, EDWARDS_D );
  913. field_mul ( L1, L0, L2 );
  914. field_addw ( L1, 1 );
  915. field_sub ( L0, L3, L1 );
  916. return field_is_zero( L0 );
  917. }
  918. mask_t
  919. validate_tw_extensible (
  920. const tw_extensible_a_t ext
  921. ) {
  922. mask_t L4, L5;
  923. field_a_t L0, L1, L2, L3;
  924. /*
  925. * Check invariant:
  926. * 0 = -x*y + z*t*u
  927. */
  928. field_mul ( L1, ext->t, ext->u );
  929. field_mul ( L2, ext->z, L1 );
  930. field_mul ( L0, ext->x, ext->y );
  931. field_neg ( L1, L0 );
  932. field_add ( L0, L1, L2 );
  933. L5 = field_is_zero( L0 );
  934. /*
  935. * Check invariant:
  936. * 0 = d*t^2*u^2 + x^2 - y^2 + z^2 - t^2*u^2
  937. */
  938. field_sqr ( L2, ext->y );
  939. field_neg ( L1, L2 );
  940. field_sqr ( L0, ext->x );
  941. field_add ( L2, L0, L1 );
  942. field_sqr ( L3, ext->u );
  943. field_sqr ( L0, ext->t );
  944. field_mul ( L1, L0, L3 );
  945. field_mulw_scc ( L3, L1, EDWARDS_D );
  946. field_add ( L0, L3, L2 );
  947. field_neg ( L3, L1 );
  948. field_add ( L2, L3, L0 );
  949. field_sqr ( L1, ext->z );
  950. field_add ( L0, L1, L2 );
  951. L4 = field_is_zero( L0 );
  952. return L5 & L4 &~ field_is_zero(ext->z);
  953. }
  954. mask_t
  955. validate_extensible (
  956. const extensible_a_t ext
  957. ) {
  958. mask_t L4, L5;
  959. field_a_t L0, L1, L2, L3;
  960. /*
  961. * Check invariant:
  962. * 0 = d*t^2*u^2 - x^2 - y^2 + z^2
  963. */
  964. field_sqr ( L2, ext->y );
  965. field_neg ( L1, L2 );
  966. field_sqr ( L0, ext->z );
  967. field_add ( L2, L0, L1 );
  968. field_sqr ( L3, ext->u );
  969. field_sqr ( L0, ext->t );
  970. field_mul ( L1, L0, L3 );
  971. field_mulw_scc ( L0, L1, EDWARDS_D );
  972. field_add ( L1, L0, L2 );
  973. field_sqr ( L0, ext->x );
  974. field_neg ( L2, L0 );
  975. field_add ( L0, L2, L1 );
  976. L5 = field_is_zero( L0 );
  977. /*
  978. * Check invariant:
  979. * 0 = -x*y + z*t*u
  980. */
  981. field_mul ( L1, ext->t, ext->u );
  982. field_mul ( L2, ext->z, L1 );
  983. field_mul ( L0, ext->x, ext->y );
  984. field_neg ( L1, L0 );
  985. field_add ( L0, L1, L2 );
  986. L4 = field_is_zero( L0 );
  987. return L5 & L4 &~ field_is_zero(ext->z);
  988. }