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.
 
 
 
 
 

1011 lines
29 KiB

  1. /* Copyright (c) 2015 Cryptography Research, Inc.
  2. * Released under the MIT License. See LICENSE.txt for license information.
  3. */
  4. /**
  5. * @file decaf.c
  6. * @author Mike Hamburg
  7. * @brief Decaf high-level functions.
  8. */
  9. #define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */
  10. #include "decaf.h"
  11. #include <string.h>
  12. #include <assert.h>
  13. #define WBITS DECAF_WORD_BITS
  14. #if WBITS == 64
  15. #define LBITS 56
  16. typedef __int128_t decaf_sdword_t;
  17. #define LIMB(x) (x##ull)
  18. #define SC_LIMB(x) (x##ull)
  19. #elif WBITS == 32
  20. typedef int64_t decaf_sdword_t;
  21. #define LBITS 28
  22. #define LIMB(x) (x##ull)&((1ull<<LBITS)-1), (x##ull)>>LBITS
  23. #define SC_LIMB(x) (x##ull)&((1ull<<32)-1), (x##ull)>>32
  24. #else
  25. #error "Only supporting 32- and 64-bit platforms right now"
  26. #endif
  27. #define sv static void
  28. #define snv static void __attribute__((noinline))
  29. #define siv static inline void __attribute__((always_inline))
  30. static const gf ZERO = {{{0}}}, ONE = {{{1}}}, TWO = {{{2}}};
  31. #define LMASK ((((decaf_word_t)1)<<LBITS)-1)
  32. #if WBITS == 64
  33. static const gf P = {{{ LMASK, LMASK, LMASK, LMASK, LMASK-1, LMASK, LMASK, LMASK }}};
  34. #else
  35. static const gf P = {{{ LMASK, LMASK, LMASK, LMASK, LMASK, LMASK, LMASK, LMASK,
  36. LMASK-1, LMASK, LMASK, LMASK, LMASK, LMASK, LMASK, LMASK }}};
  37. #endif
  38. static const int EDWARDS_D = -39081;
  39. const decaf_448_scalar_t decaf_448_scalar_p = {{{
  40. SC_LIMB(0x2378c292ab5844f3),
  41. SC_LIMB(0x216cc2728dc58f55),
  42. SC_LIMB(0xc44edb49aed63690),
  43. SC_LIMB(0xffffffff7cca23e9),
  44. SC_LIMB(0xffffffffffffffff),
  45. SC_LIMB(0xffffffffffffffff),
  46. SC_LIMB(0x3fffffffffffffff)
  47. }}}, decaf_448_scalar_one = {{{1}}}, decaf_448_scalar_zero = {{{0}}};
  48. static const decaf_448_scalar_t decaf_448_scalar_r2 = {{{
  49. SC_LIMB(0xe3539257049b9b60),
  50. SC_LIMB(0x7af32c4bc1b195d9),
  51. SC_LIMB(0x0d66de2388ea1859),
  52. SC_LIMB(0xae17cf725ee4d838),
  53. SC_LIMB(0x1a9cc14ba3c47c44),
  54. SC_LIMB(0x2052bcb7e4d070af),
  55. SC_LIMB(0x3402a939f823b729)
  56. }}};
  57. static const decaf_word_t DECAF_MONTGOMERY_FACTOR = (decaf_word_t)(0x3bd440fae918bc5ull);
  58. #define FIELD_LITERAL(a,b,c,d,e,f,g,h) {{LIMB(a),LIMB(b),LIMB(c),LIMB(d),LIMB(e),LIMB(f),LIMB(g),LIMB(h)}}
  59. const decaf_448_point_t decaf_448_point_base = {{
  60. {FIELD_LITERAL(0x00fffffffffffffe,0x00ffffffffffffff,0x00ffffffffffffff,0x00ffffffffffffff,
  61. 0x0000000000000003,0x0000000000000000,0x0000000000000000,0x0000000000000000)},
  62. {FIELD_LITERAL(0x0081e6d37f752992,0x003078ead1c28721,0x00135cfd2394666c,0x0041149c50506061,
  63. 0x0031d30e4f5490b3,0x00902014990dc141,0x0052341b04c1e328,0x0014237853c10a1b)},
  64. {FIELD_LITERAL(0x00fffffffffffffb,0x00ffffffffffffff,0x00ffffffffffffff,0x00ffffffffffffff,
  65. 0x00fffffffffffffe,0x00ffffffffffffff,0x00ffffffffffffff,0x00ffffffffffffff)},
  66. {FIELD_LITERAL(0x008f205b70660415,0x00881c60cfd3824f,0x00377a638d08500d,0x008c66d5d4672615,
  67. 0x00e52fa558e08e13,0x0087770ae1b6983d,0x004388f55a0aa7ff,0x00b4d9a785cf1a91)}
  68. }};
  69. struct decaf_448_precomputed_s { decaf_448_point_t p[1]; };
  70. /* FIXME: restore */
  71. const struct decaf_448_precomputed_s *decaf_448_precomputed_base =
  72. (const struct decaf_448_precomputed_s *)decaf_448_point_base;
  73. const size_t sizeof_decaf_448_precomputed_s = sizeof(struct decaf_448_precomputed_s);
  74. const size_t alignof_decaf_448_precomputed_s = 32;
  75. #ifdef __clang__
  76. #if 100*__clang_major__ + __clang_minor__ > 305
  77. #define VECTORIZE _Pragma("clang loop unroll(disable) vectorize(enable) vectorize_width(8)")
  78. #endif
  79. #endif
  80. #ifndef VECTORIZE
  81. #define VECTORIZE
  82. #endif
  83. #if (defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__)) || defined(DECAF_FORCE_UNROLL)
  84. #if DECAF_448_LIMBS==8
  85. #define FOR_LIMB_U(i,op) { unsigned int i=0; \
  86. op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; \
  87. }
  88. #elif DECAF_448_LIMBS==16
  89. #define FOR_LIMB_U(i,op) { unsigned int i=0; \
  90. op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; \
  91. op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; op;i++; \
  92. }
  93. #else
  94. #define FOR_LIMB_U(i,op) { unsigned int i=0; for (i=0; i<DECAF_448_LIMBS; i++) { op; }}
  95. #endif
  96. #else
  97. #define FOR_LIMB_U(i,op) { unsigned int i=0; for (i=0; i<DECAF_448_LIMBS; i++) { op; }}
  98. #endif
  99. #define FOR_LIMB(i,op) { unsigned int i=0; for (i=0; i<DECAF_448_LIMBS; i++) { op; }}
  100. /* TODO: figure out why this horribly degrades speed if you use it */
  101. #define FOR_LIMB_V(i,op) { unsigned int i=0; VECTORIZE for (i=0; i<DECAF_448_LIMBS; i++) { op; }}
  102. /** Copy x = y */
  103. siv gf_cpy(gf x, const gf y) { FOR_LIMB_U(i, x->limb[i] = y->limb[i]); }
  104. /** Mostly-unoptimized multiply (PERF), but at least it's unrolled. */
  105. snv gf_mul (gf c, const gf a, const gf b) {
  106. gf aa;
  107. gf_cpy(aa,a);
  108. decaf_dword_t accum[DECAF_448_LIMBS] = {0};
  109. FOR_LIMB_U(i, {
  110. FOR_LIMB_U(j,{ accum[(i+j)%DECAF_448_LIMBS] += (decaf_dword_t)b->limb[i] * aa->limb[j]; });
  111. aa->limb[(DECAF_448_LIMBS-1-i)^(DECAF_448_LIMBS/2)] += aa->limb[DECAF_448_LIMBS-1-i];
  112. });
  113. accum[DECAF_448_LIMBS-1] += accum[DECAF_448_LIMBS-2] >> LBITS;
  114. accum[DECAF_448_LIMBS-2] &= LMASK;
  115. accum[DECAF_448_LIMBS/2] += accum[DECAF_448_LIMBS-1] >> LBITS;
  116. FOR_LIMB_U(j,{
  117. accum[j] += accum[(j-1)%DECAF_448_LIMBS] >> LBITS;
  118. accum[(j-1)%DECAF_448_LIMBS] &= LMASK;
  119. });
  120. FOR_LIMB_U(j, c->limb[j] = accum[j] );
  121. }
  122. /** No dedicated square (PERF) */
  123. #define gf_sqr(c,a) gf_mul(c,a,a)
  124. /** Inverse square root using addition chain. */
  125. snv gf_isqrt(gf y, const gf x) {
  126. int i;
  127. #define STEP(s,m,n) gf_mul(s,m,c); gf_cpy(c,s); for (i=0;i<n;i++) gf_sqr(c,c);
  128. gf a, b, c;
  129. gf_sqr ( c, x );
  130. STEP(b,x,1);
  131. STEP(b,x,3);
  132. STEP(a,b,3);
  133. STEP(a,b,9);
  134. STEP(b,a,1);
  135. STEP(a,x,18);
  136. STEP(a,b,37);
  137. STEP(b,a,37);
  138. STEP(b,a,111);
  139. STEP(a,b,1);
  140. STEP(b,x,223);
  141. gf_mul(y,a,c);
  142. }
  143. /** Weak reduce mod p. */
  144. siv gf_reduce(gf x) {
  145. x->limb[DECAF_448_LIMBS/2] += x->limb[DECAF_448_LIMBS-1] >> LBITS;
  146. FOR_LIMB_U(j,{
  147. x->limb[j] += x->limb[(j-1)%DECAF_448_LIMBS] >> LBITS;
  148. x->limb[(j-1)%DECAF_448_LIMBS] &= LMASK;
  149. });
  150. }
  151. /** Add mod p. Conservatively always weak-reduce. (PERF) */
  152. sv gf_add ( gf x, const gf y, const gf z ) {
  153. FOR_LIMB_U(i, x->limb[i] = y->limb[i] + z->limb[i] );
  154. gf_reduce(x);
  155. }
  156. /** Subtract mod p. Conservatively always weak-reduce. (PERF) */
  157. sv gf_sub ( gf x, const gf y, const gf z ) {
  158. FOR_LIMB_U(i, x->limb[i] = y->limb[i] - z->limb[i] + 2*P->limb[i] );
  159. gf_reduce(x);
  160. }
  161. /** Constant time, x = is_z ? z : y */
  162. sv cond_sel(gf x, const gf y, const gf z, decaf_bool_t is_z) {
  163. FOR_LIMB_U(i, x->limb[i] = (y->limb[i] & ~is_z) | (z->limb[i] & is_z) );
  164. }
  165. /** Constant time, if (neg) x=-x; */
  166. siv cond_neg(gf x, decaf_bool_t neg) {
  167. gf y;
  168. gf_sub(y,ZERO,x);
  169. cond_sel(x,x,y,neg);
  170. }
  171. /** Constant time, if (swap) (x,y) = (y,x); */
  172. sv cond_swap(gf x, gf_s *__restrict__ y, decaf_bool_t swap) {
  173. FOR_LIMB_U(i, {
  174. decaf_word_t s = (x->limb[i] ^ y->limb[i]) & swap;
  175. x->limb[i] ^= s;
  176. y->limb[i] ^= s;
  177. });
  178. }
  179. /**
  180. * Mul by signed int. Not constant-time WRT the sign of that int.
  181. * Just uses a full mul (PERF)
  182. */
  183. siv gf_mlw(gf a, const gf b, int w) {
  184. if (w>0) {
  185. gf ww = {{{w}}};
  186. gf_mul(a,b,ww);
  187. } else {
  188. gf ww = {{{-w}}};
  189. gf_mul(a,b,ww);
  190. gf_sub(a,ZERO,a);
  191. }
  192. }
  193. /** Canonicalize */
  194. snv gf_canon ( gf a ) {
  195. gf_reduce(a);
  196. /* subtract p with borrow */
  197. decaf_sdword_t carry = 0;
  198. FOR_LIMB(i, {
  199. carry = carry + a->limb[i] - P->limb[i];
  200. a->limb[i] = carry & LMASK;
  201. carry >>= LBITS;
  202. });
  203. decaf_bool_t addback = carry;
  204. carry = 0;
  205. /* add it back */
  206. FOR_LIMB(i, {
  207. carry = carry + a->limb[i] + (P->limb[i] & addback);
  208. a->limb[i] = carry & LMASK;
  209. carry >>= LBITS;
  210. });
  211. }
  212. /** Compare a==b */
  213. static decaf_word_t __attribute__((noinline)) gf_eq(const gf a, const gf b) {
  214. gf c;
  215. gf_sub(c,a,b);
  216. gf_canon(c);
  217. decaf_word_t ret=0;
  218. FOR_LIMB(i, ret |= c->limb[i] );
  219. /* Hope the compiler is too dumb to optimize this, thus noinline */
  220. return ((decaf_dword_t)ret - 1) >> WBITS;
  221. }
  222. /** Return high bit of x = low bit of 2x mod p */
  223. static decaf_word_t hibit(const gf x) {
  224. gf y;
  225. gf_add(y,x,x);
  226. gf_canon(y);
  227. return -(y->limb[0]&1);
  228. }
  229. /* a = use_c ? c : b */
  230. sv decaf_448_cond_sel (
  231. decaf_448_point_t a,
  232. const decaf_448_point_t b,
  233. const decaf_448_point_t c,
  234. decaf_bool_t use_c
  235. ) {
  236. cond_sel(a->x, b->x, c->x, use_c);
  237. cond_sel(a->y, b->y, c->y, use_c);
  238. cond_sel(a->z, b->z, c->z, use_c);
  239. cond_sel(a->t, b->t, c->t, use_c);
  240. }
  241. /** {extra,accum} - sub +? p
  242. * Must have extra <= 1
  243. */
  244. snv decaf_448_subx(
  245. decaf_448_scalar_t out,
  246. const decaf_word_t accum[DECAF_448_SCALAR_LIMBS],
  247. const decaf_448_scalar_t sub,
  248. const decaf_448_scalar_t p,
  249. decaf_word_t extra
  250. ) {
  251. decaf_sdword_t chain = 0;
  252. unsigned int i;
  253. for (i=0; i<DECAF_448_SCALAR_LIMBS; i++) {
  254. chain = (chain + accum[i]) - sub->limb[i];
  255. out->limb[i] = chain;
  256. chain >>= WBITS;
  257. }
  258. decaf_bool_t borrow = chain+extra; /* = 0 or -1 */
  259. chain = 0;
  260. for (i=0; i<DECAF_448_SCALAR_LIMBS; i++) {
  261. chain = (chain + out->limb[i]) + (p->limb[i] & borrow);
  262. out->limb[i] = chain;
  263. chain >>= WBITS;
  264. }
  265. }
  266. snv decaf_448_montmul (
  267. decaf_448_scalar_t out,
  268. const decaf_448_scalar_t a,
  269. const decaf_448_scalar_t b
  270. ) {
  271. unsigned int i,j;
  272. decaf_word_t accum[DECAF_448_SCALAR_LIMBS+1] = {0};
  273. decaf_word_t hi_carry = 0;
  274. for (i=0; i<DECAF_448_SCALAR_LIMBS; i++) {
  275. decaf_word_t mand = a->limb[i];
  276. const decaf_word_t *mier = b->limb;
  277. decaf_dword_t chain = 0;
  278. for (j=0; j<DECAF_448_SCALAR_LIMBS; j++) {
  279. chain += ((decaf_dword_t)mand)*mier[j] + accum[j];
  280. accum[j] = chain;
  281. chain >>= WBITS;
  282. }
  283. accum[j] = chain;
  284. mand = accum[0] * DECAF_MONTGOMERY_FACTOR;
  285. chain = 0;
  286. mier = decaf_448_scalar_p->limb;
  287. for (j=0; j<DECAF_448_SCALAR_LIMBS; j++) {
  288. chain += (decaf_dword_t)mand*mier[j] + accum[j];
  289. if (j) accum[j-1] = chain;
  290. chain >>= WBITS;
  291. }
  292. chain += accum[j];
  293. chain += hi_carry;
  294. accum[j-1] = chain;
  295. hi_carry = chain >> WBITS;
  296. }
  297. decaf_448_subx(out, accum, decaf_448_scalar_p, decaf_448_scalar_p, hi_carry);
  298. }
  299. void decaf_448_scalar_mul (
  300. decaf_448_scalar_t out,
  301. const decaf_448_scalar_t a,
  302. const decaf_448_scalar_t b
  303. ) {
  304. decaf_448_montmul(out,a,b);
  305. decaf_448_montmul(out,out,decaf_448_scalar_r2);
  306. }
  307. decaf_bool_t decaf_448_scalar_invert (
  308. decaf_448_scalar_t out,
  309. const decaf_448_scalar_t a
  310. ) {
  311. decaf_448_scalar_t b, ma;
  312. int i;
  313. decaf_448_montmul(b,decaf_448_scalar_one,decaf_448_scalar_r2);
  314. decaf_448_montmul(ma,a,decaf_448_scalar_r2);
  315. for (i=DECAF_448_SCALAR_BITS-1; i>=0; i--) {
  316. decaf_448_montmul(b,b,b);
  317. decaf_word_t w = decaf_448_scalar_p->limb[i/WBITS];
  318. if (i<WBITS) {
  319. assert(w >= 2);
  320. w-=2;
  321. }
  322. if (1 & w>>(i%WBITS)) {
  323. decaf_448_montmul(b,b,ma);
  324. }
  325. }
  326. decaf_448_montmul(out,b,decaf_448_scalar_one);
  327. decaf_448_scalar_destroy(b);
  328. decaf_448_scalar_destroy(ma);
  329. return ~decaf_448_scalar_eq(out,decaf_448_scalar_zero);
  330. }
  331. void decaf_448_scalar_sub (
  332. decaf_448_scalar_t out,
  333. const decaf_448_scalar_t a,
  334. const decaf_448_scalar_t b
  335. ) {
  336. decaf_448_subx(out, a->limb, b, decaf_448_scalar_p, 0);
  337. }
  338. void decaf_448_scalar_add (
  339. decaf_448_scalar_t out,
  340. const decaf_448_scalar_t a,
  341. const decaf_448_scalar_t b
  342. ) {
  343. decaf_dword_t chain = 0;
  344. unsigned int i;
  345. for (i=0; i<DECAF_448_SCALAR_LIMBS; i++) {
  346. chain = (chain + a->limb[i]) + b->limb[i];
  347. out->limb[i] = chain;
  348. chain >>= WBITS;
  349. }
  350. decaf_448_subx(out, out->limb, decaf_448_scalar_p, decaf_448_scalar_p, chain);
  351. }
  352. void decaf_448_scalar_set (
  353. decaf_448_scalar_t out,
  354. decaf_word_t w
  355. ) {
  356. memset(out,0,sizeof(decaf_448_scalar_t));
  357. out->limb[0] = w;
  358. }
  359. decaf_bool_t decaf_448_scalar_eq (
  360. const decaf_448_scalar_t a,
  361. const decaf_448_scalar_t b
  362. ) {
  363. int i;
  364. decaf_word_t diff = 0;
  365. for(i=0; i<DECAF_448_SCALAR_LIMBS; i++) {
  366. diff |= a->limb[i] ^ b->limb[i];
  367. }
  368. return (((decaf_dword_t)diff)-1)>>WBITS;
  369. }
  370. /* *** API begins here *** */
  371. /** identity = (0,1) */
  372. const decaf_448_point_t decaf_448_point_identity = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}};
  373. void decaf_448_point_encode( unsigned char ser[DECAF_448_SER_BYTES], const decaf_448_point_t p ) {
  374. /* Can shave off one mul here; not important but makes consistent with paper */
  375. gf a, b, c, d;
  376. gf_mlw ( a, p->y, 1-EDWARDS_D );
  377. gf_mul ( c, a, p->t );
  378. gf_mul ( a, p->x, p->z );
  379. gf_sub ( d, c, a );
  380. gf_add ( a, p->z, p->y );
  381. gf_sub ( b, p->z, p->y );
  382. gf_mul ( c, b, a );
  383. gf_mlw ( b, c, -EDWARDS_D );
  384. gf_isqrt ( a, b );
  385. gf_mlw ( b, a, -EDWARDS_D );
  386. gf_mul ( c, b, a );
  387. gf_mul ( a, c, d );
  388. gf_add ( d, b, b );
  389. gf_mul ( c, d, p->z );
  390. cond_neg ( b, ~hibit(c) );
  391. gf_mul ( c, b, p->y );
  392. gf_add ( a, a, c );
  393. cond_neg ( a, hibit(a) );
  394. gf_canon(a);
  395. int k=0, bits=0;
  396. decaf_dword_t buf=0;
  397. FOR_LIMB(i, {
  398. buf |= (decaf_dword_t)a->limb[i]<<bits;
  399. for (bits += LBITS; (bits>=8 || i==DECAF_448_LIMBS-1) && k<DECAF_448_SER_BYTES; bits-=8, buf>>=8) {
  400. ser[k++]=buf;
  401. }
  402. });
  403. }
  404. /**
  405. * Deserialize a bool, return TRUE if < p.
  406. */
  407. static decaf_bool_t gf_deser(gf s, const unsigned char ser[DECAF_448_SER_BYTES]) {
  408. unsigned int i, k=0, bits=0;
  409. decaf_dword_t buf=0;
  410. for (i=0; i<DECAF_448_SER_BYTES; i++) {
  411. buf |= (decaf_dword_t)ser[i]<<bits;
  412. for (bits += 8; (bits>=LBITS || i==DECAF_448_SER_BYTES-1) && k<DECAF_448_LIMBS; bits-=LBITS, buf>>=LBITS) {
  413. s->limb[k++] = buf & LMASK;
  414. }
  415. }
  416. decaf_sdword_t accum = 0;
  417. FOR_LIMB(i, accum = (accum + s->limb[i] - P->limb[i]) >> WBITS );
  418. return accum;
  419. }
  420. /* Constant-time add or subtract */
  421. snv decaf_448_point_add_sub (
  422. decaf_448_point_t p,
  423. const decaf_448_point_t q,
  424. const decaf_448_point_t r,
  425. decaf_bool_t do_sub
  426. ) {
  427. /* Twisted Edward formulas, complete when 4-torsion isn't involved */
  428. gf a, b, c, d;
  429. gf_sub ( b, q->y, q->x );
  430. gf_sub ( c, r->y, r->x );
  431. gf_add ( d, r->y, r->x );
  432. cond_swap(c,d,do_sub);
  433. gf_mul ( a, c, b );
  434. gf_add ( b, q->y, q->x );
  435. gf_mul ( p->y, d, b );
  436. gf_mul ( b, r->t, q->t );
  437. gf_mlw ( p->x, b, 2-2*EDWARDS_D );
  438. gf_add ( b, a, p->y );
  439. gf_sub ( c, p->y, a );
  440. gf_mul ( a, q->z, r->z );
  441. gf_add ( a, a, a );
  442. gf_add ( p->y, a, p->x );
  443. gf_sub ( a, a, p->x );
  444. cond_swap(a,p->y,do_sub);
  445. gf_mul ( p->z, a, p->y );
  446. gf_mul ( p->x, p->y, c );
  447. gf_mul ( p->y, a, b );
  448. gf_mul ( p->t, b, c );
  449. }
  450. decaf_bool_t decaf_448_point_decode (
  451. decaf_448_point_t p,
  452. const unsigned char ser[DECAF_448_SER_BYTES],
  453. decaf_bool_t allow_identity
  454. ) {
  455. gf s, a, b, c, d, e;
  456. decaf_bool_t succ = gf_deser(s, ser), zero = gf_eq(s, ZERO);
  457. succ &= allow_identity | ~zero;
  458. succ &= ~hibit(s);
  459. gf_sqr ( a, s );
  460. gf_sub ( p->z, ONE, a );
  461. gf_sqr ( b, p->z );
  462. gf_mlw ( c, a, 4-4*EDWARDS_D );
  463. gf_add ( c, c, b );
  464. gf_mul ( b, c, a );
  465. gf_isqrt ( d, b );
  466. gf_sqr ( e, d );
  467. gf_mul ( a, e, b );
  468. gf_add ( a, a, ONE );
  469. succ &= ~gf_eq ( a, ZERO );
  470. gf_mul ( b, c, d );
  471. cond_neg ( d, hibit(b) );
  472. gf_add ( p->x, s, s );
  473. gf_mul ( c, d, s );
  474. gf_sub ( b, TWO, p->z );
  475. gf_mul ( a, b, c );
  476. gf_mul ( p->y,a,p->z );
  477. gf_mul ( p->t,p->x,a );
  478. p->y->limb[0] -= zero;
  479. /* TODO: do something safe if ~succ? */
  480. return succ;
  481. }
  482. void decaf_448_point_sub(decaf_448_point_t a, const decaf_448_point_t b, const decaf_448_point_t c) {
  483. decaf_448_point_add_sub(a,b,c,-1);
  484. }
  485. void decaf_448_point_add(decaf_448_point_t a, const decaf_448_point_t b, const decaf_448_point_t c) {
  486. decaf_448_point_add_sub(a,b,c,0);
  487. }
  488. /* No dedicated point double yet (PERF) */
  489. void decaf_448_point_double(decaf_448_point_t a, const decaf_448_point_t b) {
  490. decaf_448_point_add(a,b,b);
  491. }
  492. void decaf_448_point_negate (
  493. decaf_448_point_t nega,
  494. const decaf_448_point_t a
  495. ) {
  496. gf_sub(nega->x, ZERO, a->x);
  497. gf_cpy(nega->y, a->y);
  498. gf_cpy(nega->z, a->z);
  499. gf_sub(nega->t, ZERO, a->t);
  500. }
  501. decaf_bool_t decaf_448_scalar_decode(
  502. decaf_448_scalar_t s,
  503. const unsigned char ser[DECAF_448_SER_BYTES]
  504. ) {
  505. unsigned int i,j,k=0;
  506. for (i=0; i<DECAF_448_SCALAR_LIMBS; i++) {
  507. decaf_word_t out = 0;
  508. for (j=0; j<sizeof(decaf_word_t); j++,k++) {
  509. out |= ((decaf_word_t)ser[k])<<(8*j);
  510. }
  511. s->limb[i] = out;
  512. }
  513. decaf_sdword_t accum = 0;
  514. for (i=0; i<DECAF_448_SCALAR_LIMBS; i++) {
  515. accum = (accum + s->limb[i] - decaf_448_scalar_p->limb[i]) >> WBITS;
  516. }
  517. decaf_448_scalar_mul(s,s,decaf_448_scalar_one); /* ham-handed reduce */
  518. return accum;
  519. }
  520. void decaf_bzero (
  521. void *s,
  522. size_t size
  523. ) {
  524. #ifdef __STDC_LIB_EXT1__
  525. memset_s(s, size, 0, size);
  526. #else
  527. volatile uint8_t *destroy = (volatile uint8_t *)s;
  528. unsigned i;
  529. for (i=0; i<size; i++) {
  530. destroy[i] = 0;
  531. }
  532. #endif
  533. }
  534. void decaf_448_scalar_destroy (
  535. decaf_448_scalar_t scalar
  536. ) {
  537. decaf_bzero(scalar, sizeof(decaf_448_scalar_t));
  538. }
  539. static inline void ignore_result ( decaf_bool_t boo ) {
  540. (void)boo;
  541. }
  542. void decaf_448_scalar_decode_long(
  543. decaf_448_scalar_t s,
  544. const unsigned char *ser,
  545. size_t ser_len
  546. ) {
  547. if (ser_len == 0) {
  548. decaf_448_scalar_copy(s, decaf_448_scalar_zero);
  549. return;
  550. }
  551. size_t i;
  552. unsigned char tmp[DECAF_448_SER_BYTES] = {0};
  553. decaf_448_scalar_t t1, t2;
  554. i = ser_len - (ser_len%DECAF_448_SER_BYTES);
  555. if (i==ser_len) i -= DECAF_448_SER_BYTES;
  556. memcpy(tmp, ser+i, ser_len - i);
  557. ignore_result( decaf_448_scalar_decode(t1, tmp) );
  558. decaf_bzero(tmp, sizeof(tmp));
  559. while (i) {
  560. i -= DECAF_448_SER_BYTES;
  561. decaf_448_montmul(t1,t1,decaf_448_scalar_r2);
  562. ignore_result( decaf_448_scalar_decode(t2, ser+i) );
  563. decaf_448_scalar_add(t1, t1, t2);
  564. }
  565. decaf_448_scalar_copy(s, t1);
  566. decaf_448_scalar_destroy(t1);
  567. decaf_448_scalar_destroy(t2);
  568. }
  569. void decaf_448_scalar_encode(
  570. unsigned char ser[DECAF_448_SER_BYTES],
  571. const decaf_448_scalar_t s
  572. ) {
  573. unsigned int i,j,k=0;
  574. for (i=0; i<DECAF_448_SCALAR_LIMBS; i++) {
  575. for (j=0; j<sizeof(decaf_word_t); j++,k++) {
  576. ser[k] = s->limb[i] >> (8*j);
  577. }
  578. }
  579. }
  580. void decaf_448_point_scalarmul (
  581. decaf_448_point_t a,
  582. const decaf_448_point_t b,
  583. const decaf_448_scalar_t scalar
  584. ) {
  585. /* w=2 signed window uses about 1.5 adds per bit.
  586. * I figured a few extra lines was worth the 25% speedup.
  587. */
  588. decaf_448_point_t w,b3,tmp;
  589. decaf_448_point_double(w,b);
  590. /* b3 = b*3 */
  591. decaf_448_point_add(b3,w,b);
  592. int i;
  593. for (i=DECAF_448_SCALAR_BITS &~ 1; i>0; i-=2) {
  594. decaf_word_t bits = scalar->limb[i/WBITS]>>(i%WBITS);
  595. decaf_448_cond_sel(tmp,b,b3,((bits^(bits>>1))&1)-1);
  596. decaf_448_point_double(w,w);
  597. decaf_448_point_add_sub(w,w,tmp,((bits>>1)&1)-1);
  598. decaf_448_point_double(w,w);
  599. }
  600. decaf_448_point_add_sub(w,w,b,((scalar->limb[0]>>1)&1)-1);
  601. /* low bit is special because fo signed window */
  602. decaf_448_cond_sel(tmp,b,decaf_448_point_identity,-(scalar->limb[0]&1));
  603. decaf_448_point_sub(a,w,tmp);
  604. }
  605. void decaf_448_point_double_scalarmul (
  606. decaf_448_point_t a,
  607. const decaf_448_point_t b,
  608. const decaf_448_scalar_t scalarb,
  609. const decaf_448_point_t c,
  610. const decaf_448_scalar_t scalarc
  611. ) {
  612. /* w=2 signed window uses about 1.5 adds per bit.
  613. * I figured a few extra lines was worth the 25% speedup.
  614. * NB: if adapting this function to scalarmul by a
  615. * possibly-odd number of unmasked bits, may need to mask.
  616. */
  617. decaf_448_point_t w,b3,c3,tmp;
  618. decaf_448_point_double(w,b);
  619. decaf_448_point_double(tmp,c);
  620. /* b3 = b*3 */
  621. decaf_448_point_add(b3,w,b);
  622. decaf_448_point_add(c3,tmp,c);
  623. decaf_448_point_add(w,w,tmp);
  624. int i;
  625. for (i=DECAF_448_SCALAR_BITS &~ 1; i>0; i-=2) {
  626. decaf_448_point_double(w,w);
  627. decaf_word_t bits = scalarb->limb[i/WBITS]>>(i%WBITS);
  628. decaf_448_cond_sel(tmp,b,b3,((bits^(bits>>1))&1)-1);
  629. decaf_448_point_add_sub(w,w,tmp,((bits>>1)&1)-1);
  630. bits = scalarc->limb[i/WBITS]>>(i%WBITS);
  631. decaf_448_cond_sel(tmp,c,c3,((bits^(bits>>1))&1)-1);
  632. decaf_448_point_add_sub(w,w,tmp,((bits>>1)&1)-1);
  633. decaf_448_point_double(w,w);
  634. }
  635. decaf_448_point_add_sub(w,w,b,((scalarb->limb[0]>>1)&1)-1);
  636. decaf_448_point_add_sub(w,w,c,((scalarc->limb[0]>>1)&1)-1);
  637. /* low bit is special because of signed window */
  638. decaf_448_cond_sel(tmp,b,decaf_448_point_identity,-(scalarb->limb[0]&1));
  639. decaf_448_point_sub(w,w,tmp);
  640. decaf_448_cond_sel(tmp,c,decaf_448_point_identity,-(scalarc->limb[0]&1));
  641. decaf_448_point_sub(a,w,tmp);
  642. }
  643. decaf_bool_t decaf_448_point_eq ( const decaf_448_point_t p, const decaf_448_point_t q ) {
  644. /* equality mod 2-torsion compares x/y */
  645. gf a, b;
  646. gf_mul ( a, p->y, q->x );
  647. gf_mul ( b, q->y, p->x );
  648. return gf_eq(a,b);
  649. }
  650. /** Inverse square root using addition chain. */
  651. static decaf_bool_t gf_isqrt_chk(gf y, const gf x, decaf_bool_t allow_zero) {
  652. gf tmp0, tmp1;
  653. gf_isqrt(y,x);
  654. gf_sqr(tmp0,y);
  655. gf_mul(tmp1,tmp0,x);
  656. return gf_eq(tmp1,ONE) | (allow_zero & gf_eq(tmp1,ZERO));
  657. }
  658. unsigned char decaf_448_point_from_hash_nonuniform (
  659. decaf_448_point_t p,
  660. const unsigned char ser[DECAF_448_SER_BYTES]
  661. ) {
  662. gf r0,r,a,b,c,dee,D,N,rN,e;
  663. decaf_bool_t over = ~gf_deser(r0,ser);
  664. decaf_bool_t sgn_r0 = hibit(r0);
  665. gf_canon(r0);
  666. gf_sqr(a,r0);
  667. gf_sub(r,ZERO,a); /*gf_mlw(r,a,QUADRATIC_NONRESIDUE);*/
  668. gf_mlw(dee,ONE,EDWARDS_D);
  669. gf_mlw(c,r,EDWARDS_D);
  670. /* Compute D := (dr+a-d)(dr-ar-d) with a=1 */
  671. gf_sub(a,c,dee);
  672. gf_add(a,a,ONE);
  673. decaf_bool_t special_identity_case = gf_eq(a,ZERO);
  674. gf_sub(b,c,r);
  675. gf_sub(b,b,dee);
  676. gf_mul(D,a,b);
  677. /* compute N := (r+1)(a-2d) */
  678. gf_add(a,r,ONE);
  679. gf_mlw(N,a,1-2*EDWARDS_D);
  680. /* e = +-1/sqrt(+-ND) */
  681. gf_mul(rN,r,N);
  682. gf_mul(a,rN,D);
  683. decaf_bool_t square = gf_isqrt_chk(e,a,DECAF_FALSE);
  684. decaf_bool_t r_is_zero = gf_eq(r,ZERO);
  685. square |= r_is_zero;
  686. square |= special_identity_case;
  687. /* b <- t/s */
  688. cond_sel(c,r0,r,square); /* r? = sqr ? r : 1 */
  689. /* In two steps to avoid overflow on 32-bit arch */
  690. gf_mlw(a,c,1-2*EDWARDS_D);
  691. gf_mlw(b,a,1-2*EDWARDS_D);
  692. gf_sub(c,r,ONE);
  693. gf_mul(a,b,c); /* = r? * (r-1) * (a-2d)^2 with a=1 */
  694. gf_mul(b,a,e);
  695. cond_neg(b,~square);
  696. cond_sel(c,r0,ONE,square);
  697. gf_mul(a,e,c);
  698. gf_mul(c,a,D); /* 1/s except for sign. FUTURE: simplify using this. */
  699. gf_sub(b,b,c);
  700. /* a <- s = e * N * (sqr ? r : r0)
  701. * e^2 r N D = 1
  702. * 1/s = 1/(e * N * (sqr ? r : r0)) = e * D * (sqr ? 1 : r0)
  703. */
  704. gf_mul(a,N,r0);
  705. cond_sel(rN,a,rN,square);
  706. gf_mul(a,rN,e);
  707. gf_mul(c,a,b);
  708. /* Normalize/negate */
  709. decaf_bool_t neg_s = hibit(a)^~square;
  710. cond_neg(a,neg_s); /* ends up negative if ~square */
  711. decaf_bool_t sgn_t_over_s = hibit(b)^neg_s;
  712. sgn_t_over_s &= ~gf_eq(N,ZERO);
  713. sgn_t_over_s |= gf_eq(D,ZERO);
  714. /* b <- t */
  715. cond_sel(b,c,ONE,gf_eq(c,ZERO)); /* 0,0 -> 1,0 */
  716. /* isogenize */
  717. gf_sqr(c,a); /* s^2 */
  718. gf_add(a,a,a); /* 2s */
  719. gf_add(e,c,ONE);
  720. gf_mul(p->t,a,e); /* 2s(1+s^2) */
  721. gf_mul(p->x,a,b); /* 2st */
  722. gf_sub(a,ONE,c);
  723. gf_mul(p->y,e,a); /* (1+s^2)(1-s^2) */
  724. gf_mul(p->z,a,b); /* (1-s^2)t */
  725. return (~square & 1) | (sgn_t_over_s & 2) | (sgn_r0 & 4) | (over & 8);
  726. }
  727. /* TODO: source these impls instead of copy-pasting them */
  728. decaf_bool_t
  729. decaf_448_invert_elligator_nonuniform (
  730. unsigned char recovered_hash[DECAF_448_SER_BYTES],
  731. const decaf_448_point_t p,
  732. unsigned char hint
  733. ) {
  734. decaf_bool_t sgn_s = -(hint & 1),
  735. sgn_t_over_s = -(hint>>1 & 1),
  736. sgn_r0 = -(hint>>2 & 1);
  737. gf a, b, c, d;
  738. gf_mlw ( a, p->y, 1-EDWARDS_D );
  739. gf_mul ( c, a, p->t );
  740. gf_mul ( a, p->x, p->z );
  741. gf_sub ( d, c, a );
  742. gf_add ( a, p->z, p->y );
  743. gf_sub ( b, p->z, p->y );
  744. gf_mul ( c, b, a );
  745. gf_mlw ( b, c, -EDWARDS_D );
  746. gf_isqrt ( a, b );
  747. gf_mlw ( b, a, -EDWARDS_D );
  748. gf_mul ( c, b, a );
  749. gf_mul ( a, c, d );
  750. gf_add ( d, b, b );
  751. gf_mul ( c, d, p->z );
  752. cond_neg ( b, sgn_t_over_s^~hibit(c) );
  753. cond_neg ( c, sgn_t_over_s^~hibit(c) );
  754. gf_mul ( d, b, p->y );
  755. gf_add ( a, a, d );
  756. cond_neg( a, hibit(a)^sgn_s);
  757. /* ok, s = a; c = -t/s */
  758. gf_mul(b,c,a);
  759. gf_sub(b,ONE,b); /* t+1 */
  760. gf_sqr(c,a); /* s^2 */
  761. { /* identity adjustments */
  762. /* in case of identity, currently c=0, t=0, b=1, will encode to 1 */
  763. /* if hint is 0, -> 0 */
  764. /* if hint is to neg t/s, then go to infinity, effectively set s to 1 */
  765. decaf_bool_t is_identity = gf_eq(p->x,ZERO);
  766. cond_sel(c,c,ONE,is_identity & sgn_t_over_s);
  767. cond_sel(b,b,ZERO,is_identity & ~sgn_t_over_s & ~sgn_s); /* identity adjust */
  768. }
  769. gf_mlw(d,c,2*EDWARDS_D-1); /* $d = (2d-a)s^2 */
  770. gf_add(a,b,d); /* num? */
  771. gf_sub(d,b,d); /* den? */
  772. gf_mul(b,a,d); /* n*d */
  773. cond_sel(a,d,a,sgn_s);
  774. decaf_bool_t succ = gf_isqrt_chk(c,b,DECAF_TRUE);
  775. gf_mul(b,a,c);
  776. cond_neg(b, sgn_r0^hibit(b));
  777. succ &= ~(gf_eq(b,ZERO) & sgn_r0);
  778. gf_canon(b);
  779. int k=0, bits=0;
  780. decaf_dword_t buf=0;
  781. FOR_LIMB(i, {
  782. buf |= (decaf_dword_t)b->limb[i]<<bits;
  783. for (bits += LBITS; (bits>=8 || i==DECAF_448_LIMBS-1) && k<DECAF_448_SER_BYTES; bits-=8, buf>>=8) {
  784. recovered_hash[k++]=buf;
  785. }
  786. });
  787. return succ;
  788. }
  789. void decaf_448_point_debugging_torque (
  790. decaf_448_point_t q,
  791. const decaf_448_point_t p
  792. ) {
  793. gf_sub(q->x,ZERO,p->x);
  794. gf_sub(q->y,ZERO,p->y);
  795. gf_cpy(q->z,p->z);
  796. gf_cpy(q->t,p->t);
  797. }
  798. unsigned char decaf_448_point_from_hash_uniform (
  799. decaf_448_point_t pt,
  800. const unsigned char hashed_data[2*DECAF_448_SER_BYTES]
  801. ) {
  802. decaf_448_point_t pt2;
  803. unsigned char ret1 =
  804. decaf_448_point_from_hash_nonuniform(pt,hashed_data);
  805. unsigned char ret2 =
  806. decaf_448_point_from_hash_nonuniform(pt2,&hashed_data[DECAF_448_SER_BYTES]);
  807. decaf_448_point_add(pt,pt,pt2);
  808. return ret1 | (ret2<<4);
  809. }
  810. decaf_bool_t decaf_448_invert_elligator_uniform (
  811. unsigned char partial_hash[2*DECAF_448_SER_BYTES],
  812. const decaf_448_point_t p,
  813. unsigned char hint
  814. ) {
  815. decaf_448_point_t pt2;
  816. decaf_448_point_from_hash_nonuniform(pt2,&partial_hash[DECAF_448_SER_BYTES]);
  817. decaf_448_point_sub(pt2,p,pt2);
  818. return decaf_448_invert_elligator_nonuniform(partial_hash,pt2,hint);
  819. }
  820. decaf_bool_t decaf_448_point_valid (
  821. const decaf_448_point_t p
  822. ) {
  823. gf a,b,c;
  824. gf_mul(a,p->x,p->y);
  825. gf_mul(b,p->z,p->t);
  826. decaf_bool_t out = gf_eq(a,b);
  827. gf_sqr(a,p->x);
  828. gf_sqr(b,p->y);
  829. gf_sub(a,b,a);
  830. gf_sqr(b,p->t);
  831. gf_mlw(c,b,1-EDWARDS_D);
  832. gf_sqr(b,p->z);
  833. gf_sub(b,b,c);
  834. out &= gf_eq(a,b);
  835. out &= ~gf_eq(p->z,ZERO);
  836. return out;
  837. }
  838. void decaf_448_precompute (
  839. decaf_448_precomputed_s *a,
  840. const decaf_448_point_t b
  841. ) {
  842. decaf_448_point_copy(a->p[0],b);
  843. }
  844. decaf_bool_t decaf_448_direct_scalarmul (
  845. uint8_t scaled[DECAF_448_SER_BYTES],
  846. const uint8_t base[DECAF_448_SER_BYTES],
  847. const decaf_448_scalar_t scalar,
  848. decaf_bool_t allow_identity,
  849. decaf_bool_t short_circuit
  850. ) {
  851. decaf_448_point_t basep;
  852. decaf_bool_t succ = decaf_448_point_decode(basep, base, allow_identity);
  853. if (short_circuit & ~succ) return succ;
  854. decaf_448_point_scalarmul(basep, basep, scalar);
  855. decaf_448_point_encode(scaled, basep);
  856. return succ;
  857. }
  858. void decaf_448_precomputed_scalarmul (
  859. decaf_448_point_t a,
  860. const decaf_448_precomputed_s *b,
  861. const decaf_448_scalar_t scalar
  862. ) {
  863. decaf_448_point_scalarmul(a,b->p[0],scalar);
  864. }
  865. void decaf_448_base_double_scalarmul_non_secret (
  866. decaf_448_point_t combo,
  867. const decaf_448_scalar_t scalar1,
  868. const decaf_448_point_t base2,
  869. const decaf_448_scalar_t scalar2
  870. ) {
  871. decaf_448_point_double_scalarmul(combo, decaf_448_point_base, scalar1, base2, scalar2);
  872. }
  873. void decaf_448_point_destroy (
  874. decaf_448_point_t point
  875. ) {
  876. decaf_bzero(point, sizeof(decaf_448_point_t));
  877. }
  878. decaf_bool_t decaf_memeq (
  879. const void *data1_,
  880. const void *data2_,
  881. size_t size
  882. ) {
  883. const unsigned char *data1 = (const unsigned char *)data1_;
  884. const unsigned char *data2 = (const unsigned char *)data2_;
  885. unsigned char ret = 0;
  886. for (; size; size--, data1++, data2++) {
  887. ret |= *data1 ^ *data2;
  888. }
  889. return (((decaf_dword_t)ret) - 1) >> 8;
  890. }
  891. void decaf_448_precomputed_destroy (
  892. decaf_448_precomputed_s *pre
  893. ) {
  894. decaf_bzero(pre, sizeof_decaf_448_precomputed_s);
  895. }