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.
 
 
 
 
 

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