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.
 
 
 
 
 

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