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.
 
 
 
 
 

329 lines
8.2 KiB

  1. /** @brief Decaf high-level functions. */
  2. #include "word.h"
  3. #include "constant_time.h"
  4. #include <decaf.h>
  5. /* Template stuff */
  6. #define API_NS(_id) $(c_ns)_##_id
  7. #define SCALAR_BITS $(C_NS)_SCALAR_BITS
  8. #define SCALAR_SER_BYTES $(C_NS)_SCALAR_BYTES
  9. #define SCALAR_LIMBS $(C_NS)_SCALAR_LIMBS
  10. #define scalar_t API_NS(scalar_t)
  11. static const decaf_word_t MONTGOMERY_FACTOR = (decaf_word_t)0x$("%x" % pow(-q,2**64-1,2**64))ull;
  12. static const scalar_t sc_p = {{{
  13. $(ser(q,64,"SC_LIMB"))
  14. }}}, sc_r2 = {{{
  15. $(ser(((2**128)**((scalar_bits+63)/64))%q,64,"SC_LIMB"))
  16. }}};
  17. /* End of template stuff */
  18. #define WBITS DECAF_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */
  19. const scalar_t API_NS(scalar_one) = {{{1}}}, API_NS(scalar_zero) = {{{0}}};
  20. /** {extra,accum} - sub +? p
  21. * Must have extra <= 1
  22. */
  23. static NOINLINE void sc_subx(
  24. scalar_t out,
  25. const decaf_word_t accum[SCALAR_LIMBS],
  26. const scalar_t sub,
  27. const scalar_t p,
  28. decaf_word_t extra
  29. ) {
  30. decaf_dsword_t chain = 0;
  31. unsigned int i;
  32. for (i=0; i<SCALAR_LIMBS; i++) {
  33. chain = (chain + accum[i]) - sub->limb[i];
  34. out->limb[i] = chain;
  35. chain >>= WBITS;
  36. }
  37. decaf_word_t borrow = chain+extra; /* = 0 or -1 */
  38. chain = 0;
  39. for (i=0; i<SCALAR_LIMBS; i++) {
  40. chain = (chain + out->limb[i]) + (p->limb[i] & borrow);
  41. out->limb[i] = chain;
  42. chain >>= WBITS;
  43. }
  44. }
  45. static NOINLINE void sc_montmul (
  46. scalar_t out,
  47. const scalar_t a,
  48. const scalar_t b
  49. ) {
  50. unsigned int i,j;
  51. decaf_word_t accum[SCALAR_LIMBS+1] = {0};
  52. decaf_word_t hi_carry = 0;
  53. for (i=0; i<SCALAR_LIMBS; i++) {
  54. decaf_word_t mand = a->limb[i];
  55. const decaf_word_t *mier = b->limb;
  56. decaf_dword_t chain = 0;
  57. for (j=0; j<SCALAR_LIMBS; j++) {
  58. chain += ((decaf_dword_t)mand)*mier[j] + accum[j];
  59. accum[j] = chain;
  60. chain >>= WBITS;
  61. }
  62. accum[j] = chain;
  63. mand = accum[0] * MONTGOMERY_FACTOR;
  64. chain = 0;
  65. mier = sc_p->limb;
  66. for (j=0; j<SCALAR_LIMBS; j++) {
  67. chain += (decaf_dword_t)mand*mier[j] + accum[j];
  68. if (j) accum[j-1] = chain;
  69. chain >>= WBITS;
  70. }
  71. chain += accum[j];
  72. chain += hi_carry;
  73. accum[j-1] = chain;
  74. hi_carry = chain >> WBITS;
  75. }
  76. sc_subx(out, accum, sc_p, sc_p, hi_carry);
  77. }
  78. void API_NS(scalar_mul) (
  79. scalar_t out,
  80. const scalar_t a,
  81. const scalar_t b
  82. ) {
  83. sc_montmul(out,a,b);
  84. sc_montmul(out,out,sc_r2);
  85. }
  86. /* PERF: could implement this */
  87. static INLINE void sc_montsqr (scalar_t out, const scalar_t a) {
  88. sc_montmul(out,a,a);
  89. }
  90. decaf_error_t API_NS(scalar_invert) (
  91. scalar_t out,
  92. const scalar_t a
  93. ) {
  94. /* Fermat's little theorem, sliding window.
  95. * Sliding window is fine here because the modulus isn't secret.
  96. */
  97. const int SCALAR_WINDOW_BITS = 3;
  98. scalar_t precmp[1<<SCALAR_WINDOW_BITS];
  99. const int LAST = (1<<SCALAR_WINDOW_BITS)-1;
  100. /* Precompute precmp = [a^1,a^3,...] */
  101. sc_montmul(precmp[0],a,sc_r2);
  102. if (LAST > 0) sc_montmul(precmp[LAST],precmp[0],precmp[0]);
  103. int i;
  104. for (i=1; i<=LAST; i++) {
  105. sc_montmul(precmp[i],precmp[i-1],precmp[LAST]);
  106. }
  107. /* Sliding window */
  108. unsigned residue = 0, trailing = 0, started = 0;
  109. for (i=SCALAR_BITS-1; i>=-SCALAR_WINDOW_BITS; i--) {
  110. if (started) sc_montsqr(out,out);
  111. decaf_word_t w = (i>=0) ? sc_p->limb[i/WBITS] : 0;
  112. if (i >= 0 && i<WBITS) {
  113. assert(w >= 2);
  114. w-=2;
  115. }
  116. residue = (residue<<1) | ((w>>(i%WBITS))&1);
  117. if (residue>>SCALAR_WINDOW_BITS != 0) {
  118. assert(trailing == 0);
  119. trailing = residue;
  120. residue = 0;
  121. }
  122. if (trailing > 0 && (trailing & ((1<<SCALAR_WINDOW_BITS)-1)) == 0) {
  123. if (started) {
  124. sc_montmul(out,out,precmp[trailing>>(SCALAR_WINDOW_BITS+1)]);
  125. } else {
  126. API_NS(scalar_copy)(out,precmp[trailing>>(SCALAR_WINDOW_BITS+1)]);
  127. started = 1;
  128. }
  129. trailing = 0;
  130. }
  131. trailing <<= 1;
  132. }
  133. assert(residue==0);
  134. assert(trailing==0);
  135. /* Demontgomerize */
  136. sc_montmul(out,out,API_NS(scalar_one));
  137. decaf_bzero(precmp, sizeof(precmp));
  138. return decaf_succeed_if(~API_NS(scalar_eq)(out,API_NS(scalar_zero)));
  139. }
  140. void API_NS(scalar_sub) (
  141. scalar_t out,
  142. const scalar_t a,
  143. const scalar_t b
  144. ) {
  145. sc_subx(out, a->limb, b, sc_p, 0);
  146. }
  147. void API_NS(scalar_add) (
  148. scalar_t out,
  149. const scalar_t a,
  150. const scalar_t b
  151. ) {
  152. decaf_dword_t chain = 0;
  153. unsigned int i;
  154. for (i=0; i<SCALAR_LIMBS; i++) {
  155. chain = (chain + a->limb[i]) + b->limb[i];
  156. out->limb[i] = chain;
  157. chain >>= WBITS;
  158. }
  159. sc_subx(out, out->limb, sc_p, sc_p, chain);
  160. }
  161. void
  162. API_NS(scalar_set_unsigned) (
  163. scalar_t out,
  164. uint64_t w
  165. ) {
  166. memset(out,0,sizeof(scalar_t));
  167. unsigned int i = 0;
  168. for (; i<sizeof(uint64_t)/sizeof(decaf_word_t); i++) {
  169. out->limb[i] = w;
  170. w >>= (sizeof(uint64_t) > sizeof(decaf_word_t)) ? 8*sizeof(decaf_word_t) : 0;
  171. }
  172. }
  173. decaf_bool_t
  174. API_NS(scalar_eq) (
  175. const scalar_t a,
  176. const scalar_t b
  177. ) {
  178. decaf_word_t diff = 0;
  179. unsigned int i;
  180. for (i=0; i<SCALAR_LIMBS; i++) {
  181. diff |= a->limb[i] ^ b->limb[i];
  182. }
  183. return mask_to_bool(word_is_zero(diff));
  184. }
  185. static INLINE void scalar_decode_short (
  186. scalar_t s,
  187. const unsigned char *ser,
  188. unsigned int nbytes
  189. ) {
  190. unsigned int i,j,k=0;
  191. for (i=0; i<SCALAR_LIMBS; i++) {
  192. decaf_word_t out = 0;
  193. for (j=0; j<sizeof(decaf_word_t) && k<nbytes; j++,k++) {
  194. out |= ((decaf_word_t)ser[k])<<(8*j);
  195. }
  196. s->limb[i] = out;
  197. }
  198. }
  199. decaf_error_t API_NS(scalar_decode)(
  200. scalar_t s,
  201. const unsigned char ser[SCALAR_SER_BYTES]
  202. ) {
  203. unsigned int i;
  204. scalar_decode_short(s, ser, SCALAR_SER_BYTES);
  205. decaf_dsword_t accum = 0;
  206. for (i=0; i<SCALAR_LIMBS; i++) {
  207. accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS;
  208. }
  209. /* Here accum == 0 or -1 */
  210. API_NS(scalar_mul)(s,s,API_NS(scalar_one)); /* ham-handed reduce */
  211. return decaf_succeed_if(~word_is_zero(accum));
  212. }
  213. void API_NS(scalar_destroy) (
  214. scalar_t scalar
  215. ) {
  216. decaf_bzero(scalar, sizeof(scalar_t));
  217. }
  218. void API_NS(scalar_decode_long)(
  219. scalar_t s,
  220. const unsigned char *ser,
  221. size_t ser_len
  222. ) {
  223. if (ser_len == 0) {
  224. API_NS(scalar_copy)(s, API_NS(scalar_zero));
  225. return;
  226. }
  227. size_t i;
  228. scalar_t t1, t2;
  229. i = ser_len - (ser_len%SCALAR_SER_BYTES);
  230. if (i==ser_len) i -= SCALAR_SER_BYTES;
  231. scalar_decode_short(t1, &ser[i], ser_len-i);
  232. if (ser_len == sizeof(scalar_t)) {
  233. assert(i==0);
  234. /* ham-handed reduce */
  235. API_NS(scalar_mul)(s,t1,API_NS(scalar_one));
  236. API_NS(scalar_destroy)(t1);
  237. return;
  238. }
  239. while (i) {
  240. i -= SCALAR_SER_BYTES;
  241. sc_montmul(t1,t1,sc_r2);
  242. ignore_result( API_NS(scalar_decode)(t2, ser+i) );
  243. API_NS(scalar_add)(t1, t1, t2);
  244. }
  245. API_NS(scalar_copy)(s, t1);
  246. API_NS(scalar_destroy)(t1);
  247. API_NS(scalar_destroy)(t2);
  248. }
  249. void API_NS(scalar_encode)(
  250. unsigned char ser[SCALAR_SER_BYTES],
  251. const scalar_t s
  252. ) {
  253. unsigned int i,j,k=0;
  254. for (i=0; i<SCALAR_LIMBS; i++) {
  255. for (j=0; j<sizeof(decaf_word_t); j++,k++) {
  256. ser[k] = s->limb[i] >> (8*j);
  257. }
  258. }
  259. }
  260. void API_NS(scalar_cond_sel) (
  261. scalar_t out,
  262. const scalar_t a,
  263. const scalar_t b,
  264. decaf_bool_t pick_b
  265. ) {
  266. constant_time_select(out,a,b,sizeof(scalar_t),bool_to_mask(pick_b),sizeof(out->limb[0]));
  267. }
  268. void API_NS(scalar_halve) (
  269. scalar_t out,
  270. const scalar_t a
  271. ) {
  272. decaf_word_t mask = -(a->limb[0] & 1);
  273. decaf_dword_t chain = 0;
  274. unsigned int i;
  275. for (i=0; i<SCALAR_LIMBS; i++) {
  276. chain = (chain + a->limb[i]) + (sc_p->limb[i] & mask);
  277. out->limb[i] = chain;
  278. chain >>= DECAF_WORD_BITS;
  279. }
  280. for (i=0; i<SCALAR_LIMBS-1; i++) {
  281. out->limb[i] = out->limb[i]>>1 | out->limb[i+1]<<(WBITS-1);
  282. }
  283. out->limb[i] = out->limb[i]>>1 | chain<<(WBITS-1);
  284. }