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.
 
 
 
 
 

764 lines
20 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. montgomery_step (
  231. montgomery_a_t a
  232. ) {
  233. ANALYZE_THIS_ROUTINE_CAREFULLY;
  234. field_a_t L0, L1;
  235. field_add_nr ( L0, a->zd, a->xd );
  236. field_sub ( L1, a->xd, a->zd );
  237. field_sub ( a->zd, a->xa, a->za );
  238. field_mul ( a->xd, L0, a->zd );
  239. field_add_nr ( a->zd, a->za, a->xa );
  240. field_mul ( a->za, L1, a->zd );
  241. field_add_nr ( a->xa, a->za, a->xd );
  242. field_sqr ( a->zd, a->xa );
  243. field_mul ( a->xa, a->z0, a->zd );
  244. field_sub ( a->zd, a->xd, a->za );
  245. field_sqr ( a->za, a->zd );
  246. field_sqr ( a->xd, L0 );
  247. field_sqr ( L0, L1 );
  248. field_mulw_scc ( a->zd, a->xd, 1-EDWARDS_D ); /* FIXME PERF MULW */
  249. field_sub ( L1, a->xd, L0 );
  250. field_mul ( a->xd, L0, a->zd );
  251. field_sub_nr ( L0, a->zd, L1 );
  252. field_bias ( L0, 4 - 2*is32 /*is32 ? 2 : 4*/ );
  253. IF32( field_weak_reduce( L0 ) );
  254. field_mul ( a->zd, L0, L1 );
  255. }
  256. void
  257. deserialize_montgomery (
  258. montgomery_a_t a,
  259. const field_a_t sbz
  260. ) {
  261. field_sqr ( a->z0, sbz );
  262. field_set_ui( a->xd, 1 );
  263. field_set_ui( a->zd, 0 );
  264. field_set_ui( a->xa, 1 );
  265. field_copy ( a->za, a->z0 );
  266. }
  267. mask_t
  268. serialize_montgomery (
  269. field_a_t b,
  270. const montgomery_a_t a,
  271. const field_a_t sbz
  272. ) {
  273. mask_t L4, L5, L6;
  274. field_a_t L0, L1, L2, L3;
  275. field_mul ( L3, a->z0, a->zd );
  276. field_sub ( L1, L3, a->xd );
  277. field_mul ( L3, a->za, L1 );
  278. field_mul ( L2, a->z0, a->xd );
  279. field_sub ( L1, L2, a->zd );
  280. field_mul ( L0, a->xa, L1 );
  281. field_add ( L2, L0, L3 );
  282. field_sub ( L1, L3, L0 );
  283. field_mul ( L3, L1, L2 );
  284. field_copy ( L2, a->z0 );
  285. field_addw ( L2, 1 );
  286. field_sqr ( L0, L2 );
  287. field_mulw_scc_wr ( L1, L0, EDWARDS_D-1 );
  288. field_add ( L2, a->z0, a->z0 );
  289. field_add ( L0, L2, L2 );
  290. field_add ( L2, L0, L1 );
  291. field_mul ( L0, a->xd, L2 );
  292. L5 = field_is_zero( a->zd );
  293. L6 = - L5;
  294. constant_time_mask ( L1, L0, sizeof(L1), L5 );
  295. field_add ( L2, L1, a->zd );
  296. L4 = ~ L5;
  297. field_mul ( L1, sbz, L3 );
  298. field_addw ( L1, L6 );
  299. field_mul ( L3, L2, L1 );
  300. field_mul ( L1, L3, L2 );
  301. field_mul ( L2, L3, a->xd );
  302. field_mul ( L3, L1, L2 );
  303. field_isr ( L0, L3 );
  304. field_mul ( L2, L1, L0 );
  305. field_sqr ( L1, L0 );
  306. field_mul ( L0, L3, L1 );
  307. constant_time_mask ( b, L2, sizeof(L1), L4 );
  308. field_subw( L0, 1 );
  309. L5 = field_is_zero( L0 );
  310. L4 = field_is_zero( sbz );
  311. return L5 | L4;
  312. }
  313. void
  314. serialize_extensible (
  315. field_a_t b,
  316. const extensible_a_t a
  317. ) {
  318. field_a_t L0, L1, L2;
  319. field_sub ( L0, a->y, a->z );
  320. field_add ( b, a->z, a->y );
  321. field_mul ( L1, a->z, a->x );
  322. field_mul ( L2, L0, L1 );
  323. field_mul ( L1, L2, L0 );
  324. field_mul ( L0, L2, b );
  325. field_mul ( L2, L1, L0 );
  326. field_isr ( L0, L2 );
  327. field_mul ( b, L1, L0 );
  328. field_sqr ( L1, L0 );
  329. field_mul ( L0, L2, L1 );
  330. }
  331. void
  332. untwist_and_double_and_serialize (
  333. field_a_t b,
  334. const tw_extensible_a_t a
  335. ) {
  336. field_a_t L0, L1, L2, L3;
  337. field_mul ( L3, a->y, a->x );
  338. field_add ( b, a->y, a->x );
  339. field_sqr ( L1, b );
  340. field_add ( L2, L3, L3 );
  341. field_sub ( b, L1, L2 );
  342. field_sqr ( L2, a->z );
  343. field_sqr ( L1, L2 );
  344. field_add ( b, b, b );
  345. field_mulw_scc ( L2, b, EDWARDS_D-1 );
  346. field_mulw_scc ( b, L2, EDWARDS_D-1 );
  347. field_mul ( L0, L2, L1 );
  348. field_mul ( L2, b, L0 );
  349. field_isr ( L0, L2 );
  350. field_mul ( L1, b, L0 );
  351. field_sqr ( b, L0 );
  352. field_mul ( L0, L2, b );
  353. field_mul ( b, L1, L3 );
  354. }
  355. void
  356. twist_even (
  357. tw_extensible_a_t b,
  358. const extensible_a_t a
  359. ) {
  360. field_sqr ( b->y, a->z );
  361. field_sqr ( b->z, a->x );
  362. field_sub ( b->u, b->y, b->z );
  363. field_sub ( b->z, a->z, a->x );
  364. field_mul ( b->y, b->z, a->y );
  365. field_sub ( b->z, a->z, a->y );
  366. field_mul ( b->x, b->z, b->y );
  367. field_mul ( b->t, b->x, b->u );
  368. field_mul ( b->y, b->x, b->t );
  369. field_isr ( b->t, b->y );
  370. field_mul ( b->u, b->x, b->t );
  371. field_sqr ( b->x, b->t );
  372. field_mul ( b->t, b->y, b->x );
  373. field_mul ( b->x, a->x, b->u );
  374. field_mul ( b->y, a->y, b->u );
  375. field_addw ( b->y, -field_is_zero( b->z ) );
  376. field_set_ui( b->z, 1 );
  377. field_copy ( b->t, b->x );
  378. field_copy ( b->u, b->y );
  379. }
  380. void
  381. test_only_twist (
  382. tw_extensible_a_t b,
  383. const extensible_a_t a
  384. ) {
  385. field_a_t L0, L1;
  386. field_sqr ( b->u, a->z );
  387. field_sqr ( b->y, a->x );
  388. field_sub ( b->z, b->u, b->y );
  389. field_add ( b->y, b->z, b->z );
  390. field_add ( b->u, b->y, b->y );
  391. field_sub ( b->y, a->z, a->x );
  392. field_mul ( b->x, b->y, a->y );
  393. field_sub ( b->z, a->z, a->y );
  394. field_mul ( b->t, b->z, b->x );
  395. field_mul ( L1, b->t, b->u );
  396. field_mul ( b->x, b->t, L1 );
  397. field_isr ( L0, b->x );
  398. field_mul ( b->u, b->t, L0 );
  399. field_sqr ( L1, L0 );
  400. field_mul ( b->t, b->x, L1 );
  401. field_add ( L1, a->y, a->x );
  402. field_sub ( L0, a->x, a->y );
  403. field_mul ( b->x, b->t, L0 );
  404. field_add ( L0, b->x, L1 );
  405. field_sub ( b->t, L1, b->x );
  406. field_mul ( b->x, L0, b->u );
  407. field_addw ( b->x, -field_is_zero( b->y ) );
  408. field_mul ( b->y, b->t, b->u );
  409. field_addw ( b->y, -field_is_zero( b->z ) );
  410. field_set_ui( b->z, 1+field_is_zero( a->y ) );
  411. field_copy ( b->t, b->x );
  412. field_copy ( b->u, b->y );
  413. }
  414. mask_t
  415. is_even_pt (
  416. const extensible_a_t a
  417. ) {
  418. field_a_t L0, L1, L2;
  419. field_sqr ( L2, a->z );
  420. field_sqr ( L1, a->x );
  421. field_sub ( L0, L2, L1 );
  422. return field_is_square ( L0 );
  423. }
  424. mask_t
  425. is_even_tw (
  426. const tw_extensible_a_t a
  427. ) {
  428. field_a_t L0, L1, L2;
  429. field_sqr ( L2, a->z );
  430. field_sqr ( L1, a->x );
  431. field_add ( L0, L1, L2 );
  432. return field_is_square ( L0 );
  433. }
  434. mask_t
  435. deserialize_affine (
  436. affine_a_t a,
  437. const field_a_t sz
  438. ) {
  439. field_a_t L0, L1, L2, L3;
  440. field_sqr ( L1, sz );
  441. field_copy ( L3, L1 );
  442. field_addw ( L3, 1 );
  443. field_sqr ( L2, L3 );
  444. field_mulw_scc ( a->x, L2, EDWARDS_D-1 ); /* PERF MULW */
  445. field_add ( L3, L1, L1 ); /* FIXME: i adjusted the bias here, was it right? */
  446. field_add ( a->y, L3, L3 );
  447. field_add ( L3, a->y, a->x );
  448. field_copy ( a->y, L1 );
  449. field_neg ( a->x, a->y );
  450. field_addw ( a->x, 1 );
  451. field_mul ( a->y, a->x, L3 );
  452. field_sqr ( L2, a->x );
  453. field_mul ( L0, L2, a->y );
  454. field_mul ( a->y, a->x, L0 );
  455. field_isr ( L3, a->y );
  456. field_mul ( a->y, L2, L3 );
  457. field_sqr ( L2, L3 );
  458. field_mul ( L3, L0, L2 );
  459. field_mul ( L0, a->x, L3 );
  460. field_add ( L2, a->y, a->y );
  461. field_mul ( a->x, sz, L2 );
  462. field_addw ( L1, 1 );
  463. field_mul ( a->y, L1, L3 );
  464. field_subw( L0, 1 );
  465. return field_is_zero( L0 );
  466. }
  467. mask_t
  468. deserialize_and_twist_approx (
  469. tw_extensible_a_t a,
  470. const field_a_t sz
  471. ) {
  472. field_a_t L0, L1;
  473. field_sqr ( a->z, sz );
  474. field_copy ( a->y, a->z );
  475. field_addw ( a->y, 1 );
  476. field_sqr ( L0, a->y );
  477. field_mulw_scc ( a->x, L0, EDWARDS_D-1 );
  478. field_add ( a->y, a->z, a->z );
  479. field_add ( a->u, a->y, a->y );
  480. field_add ( a->y, a->u, a->x );
  481. field_sqr ( a->x, a->z );
  482. field_neg ( a->u, a->x );
  483. field_addw ( a->u, 1 );
  484. field_mul ( a->x, sqrt_d_minus_1, a->u );
  485. field_mul ( L0, a->x, a->y );
  486. field_mul ( a->t, L0, a->y );
  487. field_mul ( a->u, a->x, a->t );
  488. field_mul ( a->t, a->u, L0 );
  489. field_mul ( a->y, a->x, a->t );
  490. field_isr ( L0, a->y );
  491. field_mul ( a->y, a->u, L0 );
  492. field_sqr ( L1, L0 );
  493. field_mul ( a->u, a->t, L1 );
  494. field_mul ( a->t, a->x, a->u );
  495. field_add ( a->x, sz, sz );
  496. field_mul ( L0, a->u, a->x );
  497. field_copy ( a->x, a->z );
  498. field_neg ( L1, a->x );
  499. field_addw ( L1, 1 );
  500. field_mul ( a->x, L1, L0 );
  501. field_mul ( L0, a->u, a->y );
  502. field_addw ( a->z, 1 );
  503. field_mul ( a->y, a->z, L0 );
  504. field_subw( a->t, 1 );
  505. mask_t ret = field_is_zero( a->t );
  506. field_set_ui( a->z, 1 );
  507. field_copy ( a->t, a->x );
  508. field_copy ( a->u, a->y );
  509. return ret;
  510. }
  511. void
  512. set_identity_extensible (
  513. extensible_a_t a
  514. ) {
  515. field_set_ui( a->x, 0 );
  516. field_set_ui( a->y, 1 );
  517. field_set_ui( a->z, 1 );
  518. field_set_ui( a->t, 0 );
  519. field_set_ui( a->u, 0 );
  520. }
  521. void
  522. set_identity_tw_extensible (
  523. tw_extensible_a_t a
  524. ) {
  525. field_set_ui( a->x, 0 );
  526. field_set_ui( a->y, 1 );
  527. field_set_ui( a->z, 1 );
  528. field_set_ui( a->t, 0 );
  529. field_set_ui( a->u, 0 );
  530. }
  531. void
  532. set_identity_affine (
  533. affine_a_t a
  534. ) {
  535. field_set_ui( a->x, 0 );
  536. field_set_ui( a->y, 1 );
  537. }
  538. mask_t
  539. eq_affine (
  540. const affine_a_t a,
  541. const affine_a_t b
  542. ) {
  543. mask_t L1, L2;
  544. field_a_t L0;
  545. field_sub ( L0, a->x, b->x );
  546. L2 = field_is_zero( L0 );
  547. field_sub ( L0, a->y, b->y );
  548. L1 = field_is_zero( L0 );
  549. return L2 & L1;
  550. }
  551. mask_t
  552. eq_extensible (
  553. const extensible_a_t a,
  554. const extensible_a_t b
  555. ) {
  556. mask_t L3, L4;
  557. field_a_t L0, L1, L2;
  558. field_mul ( L2, b->z, a->x );
  559. field_mul ( L1, a->z, b->x );
  560. field_sub ( L0, L2, L1 );
  561. L4 = field_is_zero( L0 );
  562. field_mul ( L2, b->z, a->y );
  563. field_mul ( L1, a->z, b->y );
  564. field_sub ( L0, L2, L1 );
  565. L3 = field_is_zero( L0 );
  566. return L4 & L3;
  567. }
  568. mask_t
  569. eq_tw_extensible (
  570. const tw_extensible_a_t a,
  571. const tw_extensible_a_t b
  572. ) {
  573. mask_t L3, L4;
  574. field_a_t L0, L1, L2;
  575. field_mul ( L2, b->z, a->x );
  576. field_mul ( L1, a->z, b->x );
  577. field_sub ( L0, L2, L1 );
  578. L4 = field_is_zero( L0 );
  579. field_mul ( L2, b->z, a->y );
  580. field_mul ( L1, a->z, b->y );
  581. field_sub ( L0, L2, L1 );
  582. L3 = field_is_zero( L0 );
  583. return L4 & L3;
  584. }
  585. void
  586. elligator_2s_inject (
  587. affine_a_t a,
  588. const field_a_t r
  589. ) {
  590. field_a_t L2, L3, L4, L5, L6, L7, L8;
  591. field_sqr ( a->x, r );
  592. field_sqr ( L3, a->x );
  593. field_copy ( a->y, L3 );
  594. field_neg ( L4, a->y );
  595. field_addw ( L4, 1 );
  596. field_sqr ( L2, L4 );
  597. field_mulw ( L7, L2, (EDWARDS_D-1)*(EDWARDS_D-1) );
  598. field_mulw ( L8, L3, 4*(EDWARDS_D+1)*(EDWARDS_D+1) );
  599. field_add ( a->y, L8, L7 );
  600. field_mulw ( L8, L2, 4*(EDWARDS_D)*(EDWARDS_D-1) );
  601. field_sub ( L7, a->y, L8 );
  602. field_mulw_scc ( L6, a->y, -2-2*EDWARDS_D );
  603. field_mul ( L5, L7, L6 );
  604. /* FIXME Stability problem (API stability, not crash) / possible bug.
  605. * change to: p448_mul ( L5, L7, L4 ); ?
  606. * This isn't a deep change: it's for sign adjustment.
  607. * Need to check which one leads to the correct sign, probably by writig
  608. * the invert routine.
  609. *
  610. * Also, the tool doesn't produce the optimal route to this.
  611. * Let incoming L6 = a, L7 = e, L4 = b.
  612. *
  613. * Could compute be, (be)^2, (be)^3, a b^3 e^3, a b^3 e^4. = 4M+S
  614. * instead of 6M.
  615. */
  616. field_mul ( L8, L5, L4 );
  617. field_mul ( L4, L5, L6 );
  618. field_mul ( L5, L7, L8 );
  619. field_mul ( L8, L5, L4 );
  620. field_mul ( L4, L7, L8 );
  621. field_isr ( L6, L4 );
  622. field_mul ( L4, L5, L6 );
  623. field_sqr ( L5, L6 );
  624. field_mul ( L6, L8, L5 );
  625. field_mul ( L8, L7, L6 );
  626. field_mul ( L7, L8, L6 );
  627. field_copy ( L6, a->x );
  628. field_addw ( a->x, 1 );
  629. field_mul ( L5, a->x, L8 );
  630. field_addw ( L5, 1 );
  631. field_sub ( a->x, L6, L5 );
  632. field_mul ( L5, L4, a->x );
  633. field_mulw_scc_wr ( a->x, L5, -2-2*EDWARDS_D );
  634. field_add ( L4, L3, L3 );
  635. field_add ( L3, L4, L2 );
  636. field_subw( L3, 2 );
  637. field_mul ( L2, L3, L8 );
  638. field_mulw ( L3, L2, 2*(EDWARDS_D+1)*(EDWARDS_D-1) );
  639. field_add ( L2, L3, a->y );
  640. field_mul ( a->y, L7, L2 );
  641. field_addw ( a->y, -field_is_zero( L8 ) );
  642. }
  643. mask_t
  644. validate_affine (
  645. const affine_a_t a
  646. ) {
  647. field_a_t L0, L1, L2, L3;
  648. field_sqr ( L0, a->y );
  649. field_sqr ( L1, a->x );
  650. field_add ( L3, L1, L0 );
  651. field_mulw_scc ( L2, L1, EDWARDS_D );
  652. field_mul ( L1, L0, L2 );
  653. field_addw ( L1, 1 );
  654. field_sub ( L0, L3, L1 );
  655. return field_is_zero( L0 );
  656. }
  657. mask_t
  658. validate_tw_extensible (
  659. const tw_extensible_a_t ext
  660. ) {
  661. mask_t L4, L5;
  662. field_a_t L0, L1, L2, L3;
  663. /*
  664. * Check invariant:
  665. * 0 = -x*y + z*t*u
  666. */
  667. field_mul ( L1, ext->t, ext->u );
  668. field_mul ( L2, ext->z, L1 );
  669. field_mul ( L0, ext->x, ext->y );
  670. field_neg ( L1, L0 );
  671. field_add ( L0, L1, L2 );
  672. L5 = field_is_zero( L0 );
  673. /*
  674. * Check invariant:
  675. * 0 = d*t^2*u^2 + x^2 - y^2 + z^2 - t^2*u^2
  676. */
  677. field_sqr ( L2, ext->y );
  678. field_neg ( L1, L2 );
  679. field_sqr ( L0, ext->x );
  680. field_add ( L2, L0, L1 );
  681. field_sqr ( L3, ext->u );
  682. field_sqr ( L0, ext->t );
  683. field_mul ( L1, L0, L3 );
  684. field_mulw_scc ( L3, L1, EDWARDS_D );
  685. field_add ( L0, L3, L2 );
  686. field_neg ( L3, L1 );
  687. field_add ( L2, L3, L0 );
  688. field_sqr ( L1, ext->z );
  689. field_add ( L0, L1, L2 );
  690. L4 = field_is_zero( L0 );
  691. return L5 & L4 &~ field_is_zero(ext->z);
  692. }
  693. mask_t
  694. validate_extensible (
  695. const extensible_a_t ext
  696. ) {
  697. mask_t L4, L5;
  698. field_a_t L0, L1, L2, L3;
  699. /*
  700. * Check invariant:
  701. * 0 = d*t^2*u^2 - x^2 - y^2 + z^2
  702. */
  703. field_sqr ( L2, ext->y );
  704. field_neg ( L1, L2 );
  705. field_sqr ( L0, ext->z );
  706. field_add ( L2, L0, L1 );
  707. field_sqr ( L3, ext->u );
  708. field_sqr ( L0, ext->t );
  709. field_mul ( L1, L0, L3 );
  710. field_mulw_scc ( L0, L1, EDWARDS_D );
  711. field_add ( L1, L0, L2 );
  712. field_sqr ( L0, ext->x );
  713. field_neg ( L2, L0 );
  714. field_add ( L0, L2, L1 );
  715. L5 = field_is_zero( L0 );
  716. /*
  717. * Check invariant:
  718. * 0 = -x*y + z*t*u
  719. */
  720. field_mul ( L1, ext->t, ext->u );
  721. field_mul ( L2, ext->z, L1 );
  722. field_mul ( L0, ext->x, ext->y );
  723. field_neg ( L1, L0 );
  724. field_add ( L0, L1, L2 );
  725. L4 = field_is_zero( L0 );
  726. return L5 & L4 &~ field_is_zero(ext->z);
  727. }