ge25519_multi_scalarmult.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include "fe25519.h"
  2. #include "sc25519.h"
  3. #include "ge25519.h"
  4. #include "index_heap.h"
  5. static void setneutral(ge25519 *r)
  6. {
  7. fe25519_setint(&r->x,0);
  8. fe25519_setint(&r->y,1);
  9. fe25519_setint(&r->z,1);
  10. fe25519_setint(&r->t,0);
  11. }
  12. static void ge25519_scalarmult_vartime_2limbs(ge25519 *r, ge25519 *p, sc25519 *s)
  13. {
  14. if (s->v[1] == 0 && s->v[0] == 1) /* This will happen most of the time after Bos-Coster */
  15. *r = *p;
  16. else if (s->v[1] == 0 && s->v[0] == 0) /* This won't ever happen, except for all scalars == 0 in Bos-Coster */
  17. setneutral(r);
  18. else
  19. {
  20. ge25519 d;
  21. unsigned long long mask = (1ULL << 63);
  22. int i = 1;
  23. while(!(mask & s->v[1]) && mask != 0)
  24. mask >>= 1;
  25. if(mask == 0)
  26. {
  27. mask = (1ULL << 63);
  28. i = 0;
  29. while(!(mask & s->v[0]) && mask != 0)
  30. mask >>= 1;
  31. }
  32. d = *p;
  33. mask >>= 1;
  34. for(;mask != 0;mask >>= 1)
  35. {
  36. ge25519_double(&d,&d);
  37. if(s->v[i] & mask)
  38. ge25519_add(&d,&d,p);
  39. }
  40. if(i==1)
  41. {
  42. mask = (1ULL << 63);
  43. for(;mask != 0;mask >>= 1)
  44. {
  45. ge25519_double(&d,&d);
  46. if(s->v[0] & mask)
  47. ge25519_add(&d,&d,p);
  48. }
  49. }
  50. *r = d;
  51. }
  52. }
  53. /* caller's responsibility to ensure npoints >= 5 */
  54. void ge25519_multi_scalarmult_vartime(ge25519_p3 *r, ge25519_p3 *p, sc25519 *s, const unsigned long long npoints)
  55. {
  56. unsigned long long pos[npoints];
  57. unsigned long long hlen=((npoints+1)/2)|1;
  58. unsigned long long max1, max2,i;
  59. heap_init(pos, hlen, s);
  60. for(i=0;;i++)
  61. {
  62. heap_get2max(pos, &max1, &max2, s);
  63. if((s[max1].v[3] == 0) || (sc25519_iszero_vartime(&s[max2]))) break;
  64. sc25519_sub_nored(&s[max1],&s[max1],&s[max2]);
  65. ge25519_add(&p[max2],&p[max2],&p[max1]);
  66. heap_rootreplaced(pos, hlen, s);
  67. }
  68. for(;;i++)
  69. {
  70. heap_get2max(pos, &max1, &max2, s);
  71. if((s[max1].v[2] == 0) || (sc25519_iszero_vartime(&s[max2]))) break;
  72. sc25519_sub_nored(&s[max1],&s[max1],&s[max2]);
  73. ge25519_add(&p[max2],&p[max2],&p[max1]);
  74. heap_rootreplaced_3limbs(pos, hlen, s);
  75. }
  76. /* We know that (npoints-1)/2 scalars are only 128-bit scalars */
  77. heap_extend(pos, hlen, npoints, s);
  78. hlen = npoints;
  79. for(;;i++)
  80. {
  81. heap_get2max(pos, &max1, &max2, s);
  82. if((s[max1].v[1] == 0) || (sc25519_iszero_vartime(&s[max2]))) break;
  83. sc25519_sub_nored(&s[max1],&s[max1],&s[max2]);
  84. ge25519_add(&p[max2],&p[max2],&p[max1]);
  85. heap_rootreplaced_2limbs(pos, hlen, s);
  86. }
  87. for(;;i++)
  88. {
  89. heap_get2max(pos, &max1, &max2, s);
  90. if(sc25519_iszero_vartime(&s[max2])) break;
  91. sc25519_sub_nored(&s[max1],&s[max1],&s[max2]);
  92. ge25519_add(&p[max2],&p[max2],&p[max1]);
  93. heap_rootreplaced_1limb(pos, hlen, s);
  94. }
  95. ge25519_scalarmult_vartime_2limbs(r, &p[max1], &s[max1]);
  96. }