]> git.codecow.com Git - Monocypher.git/commitdiff
Easier to use ge_madd() and ge_msub()
authorLoup Vaillant <loup@loup-vaillant.fr>
Thu, 23 Jan 2020 22:27:47 +0000 (23:27 +0100)
committerLoup Vaillant <loup@loup-vaillant.fr>
Thu, 23 Jan 2020 22:27:47 +0000 (23:27 +0100)
There are two main changes:

1. ge_madd() and ge_msub() now take a ge_precomp as second argument.
2. ge_msub() can now process secrets.

The pre-computed table have been adjusted accordingly. They're now
arrays of ge_precomp instead of being multiple arrays of fe.

We can also expect a (mostly negligible) performance increase:

- The new tables have slightly better locality.
- ge_msub() is the mirror of ge_madd() instead of using it.
- Using ge_msub() for signatures is now slightly more direct.

src/monocypher.c

index af85541a0e3dce870eedf200a93daf3a8bbd8ff6..e48f02bded3ef4e3ee92f5b368038c63733ee982 100644 (file)
@@ -1481,9 +1481,12 @@ static int is_above_L(const u8 a[32])
 
 // Point (group element, ge) in a twisted Edwards curve,
 // in extended projective coordinates.
-// x = X/Z, y = Y/Z, T = XY/Z
+// ge        : x  = X/Z, y  = Y/Z, T  = XY/Z
+// ge_cached : Yp = X+Y, Ym = X-Y, T2 = T*D2
+// ge_precomp: Z  = 1
 typedef struct { fe X;  fe Y;  fe Z; fe T;  } ge;
 typedef struct { fe Yp; fe Ym; fe Z; fe T2; } ge_cached;
+typedef struct { fe Yp; fe Ym;       fe T2; } ge_precomp;
 
 static void ge_zero(ge *p)
 {
@@ -1608,18 +1611,17 @@ static void ge_sub(ge *s, const ge *p, const ge_cached *q)
     ge_add(s, p, &neg);
 }
 
-static void ge_madd(ge *s, const ge *p, const fe yp, const fe ym, const fe t2,
-                    fe a, fe b)
+static void ge_madd(ge *s, const ge *p, const ge_precomp *q, fe a, fe b)
 {
     fe_add(a   , p->Y, p->X );
     fe_sub(b   , p->Y, p->X );
-    fe_mul(a   , a   , yp   );
-    fe_mul(b   , b   , ym   );
+    fe_mul(a   , a   , q->Yp);
+    fe_mul(b   , b   , q->Ym);
     fe_add(s->Y, a   , b    );
     fe_sub(s->X, a   , b    );
 
     fe_add(s->Z, p->Z, p->Z );
-    fe_mul(s->T, p->T, t2   );
+    fe_mul(s->T, p->T, q->T2);
     fe_add(a   , s->Z, s->T );
     fe_sub(b   , s->Z, s->T );
 
@@ -1629,14 +1631,24 @@ static void ge_madd(ge *s, const ge *p, const fe yp, const fe ym, const fe t2,
     fe_mul(s->Z, a   , b   );
 }
 
-// Internal buffers are not wiped! Inputs must not be secret!
-// => Use only to *check* signatures.
-static void ge_msub(ge *s, const ge *p, const fe yp, const fe ym, const fe t2,
-                    fe a, fe b)
+static void ge_msub(ge *s, const ge *p, const ge_precomp *q, fe a, fe b)
 {
-    fe n2;
-    fe_neg(n2, t2);
-    ge_madd(s, p, ym, yp, n2, a, b);
+    fe_add(a   , p->Y, p->X );
+    fe_sub(b   , p->Y, p->X );
+    fe_mul(a   , a   , q->Ym);
+    fe_mul(b   , b   , q->Yp);
+    fe_add(s->Y, a   , b    );
+    fe_sub(s->X, a   , b    );
+
+    fe_add(s->Z, p->Z, p->Z );
+    fe_mul(s->T, p->T, q->T2);
+    fe_sub(a   , s->Z, s->T );
+    fe_add(b   , s->Z, s->T );
+
+    fe_mul(s->T, s->X, s->Y);
+    fe_mul(s->X, s->X, b   );
+    fe_mul(s->Y, s->Y, a   );
+    fe_mul(s->Z, a   , b   );
 }
 
 static void ge_double(ge *s, const ge *p, ge *q)
@@ -1657,59 +1669,56 @@ static void ge_double(ge *s, const ge *p, ge *q)
     fe_mul(s->T, q->X , q->T);
 }
 
-static const fe window_Yp[8] = {
-    {25967493, -14356035, 29566456, 3660896, -12694345,
-     4014787, 27544626, -11754271, -6079156, 2047605},
-    {15636291, -9688557, 24204773, -7912398, 616977,
-     -16685262, 27787600, -14772189, 28944400, -1550024},
-    {10861363, 11473154, 27284546, 1981175, -30064349,
-     12577861, 32867885, 14515107, -15438304, 10819380},
-    {5153746, 9909285, 1723747, -2777874, 30523605,
-     5516873, 19480852, 5230134, -23952439, -15175766},
-    {-22518993, -6692182, 14201702, -8745502, -23510406,
-     8844726, 18474211, -1361450, -13062696, 13821877},
-    {-25154831, -4185821, 29681144, 7868801, -6854661,
-     -9423865, -12437364, -663000, -31111463, -16132436},
-    {-33521811, 3180713, -2394130, 14003687, -16903474,
-     -16270840, 17238398, 4729455, -18074513, 9256800},
-    {-3151181, -5046075, 9282714, 6866145, -31907062,
-     -863023, -18940575, 15033784, 25105118, -7894876},
-};
-static const fe window_Ym[8] = {
-    {-12545711, 934262, -2722910, 3049990, -727428,
-     9406986, 12720692, 5043384, 19500929, -15469378},
-    {16568933, 4717097, -11556148, -1102322, 15682896,
-     -11807043, 16354577, -11775962, 7689662, 11199574},
-    {4708026, 6336745, 20377586, 9066809, -11272109,
-     6594696, -25653668, 12483688, -12668491, 5581306},
-    {-30269007, -3463509, 7665486, 10083793, 28475525,
-     1649722, 20654025, 16520125, 30598449, 7715701},
-    {-6455177, -7839871, 3374702, -4740862, -27098617,
-     -10571707, 31655028, -7212327, 18853322, -14220951},
-    {25576264, -2703214, 7349804, -11814844, 16472782,
-     9300885, 3844789, 15725684, 171356, 6466918},
-    {-25182317, -4174131, 32336398, 5036987, -21236817,
-     11360617, 22616405, 9761698, -19827198, 630305},
-    {-24326370, 15950226, -31801215, -14592823, -11662737,
-     -5090925, 1573892, -2625887, 2198790, -15804619},
-};
-static const fe window_T2[8] = {
-    {-8738181, 4489570, 9688441, -14785194, 10184609,
-     -12363380, 29287919, 11864899, -24514362, -4438546},
-    {30464156, -5976125, -11779434, -15670865, 23220365,
-     15915852, 7512774, 10017326, -17749093, -9920357},
-    {19563160, 16186464, -29386857, 4097519, 10237984,
-     -4348115, 28542350, 13850243, -23678021, -15815942},
-    {28881845, 14381568, 9657904, 3680757, -20181635,
-     7843316, -31400660, 1370708, 29794553, -1409300},
-    {4566830, -12963868, -28974889, -12240689, -7602672,
-     -2830569, -8514358, -10431137, 2207753, -3209784},
-    {23103977, 13316479, 9739013, -16149481, 817875,
-     -15038942, 8965339, -14088058, -30714912, 16193877},
-    {-13720693, 2639453, -24237460, -7406481, 9494427,
-     -5774029, -6554551, -15960994, -2449256, -14291300},
-    {-3099351, 10324967, -2241613, 7453183, -5446979,
-     -2735503, -13812022, -16236442, -32461234, -12290683},
+// 5-bit signed window in cached format (Niels coordinates, Z=1)
+static const ge_precomp b_window[8] = {
+    {{25967493,-14356035,29566456,3660896,-12694345,
+      4014787,27544626,-11754271,-6079156,2047605,},
+     {-12545711,934262,-2722910,3049990,-727428,
+      9406986,12720692,5043384,19500929,-15469378,},
+     {-8738181,4489570,9688441,-14785194,10184609,
+      -12363380,29287919,11864899,-24514362,-4438546,},},
+    {{15636291,-9688557,24204773,-7912398,616977,
+      -16685262,27787600,-14772189,28944400,-1550024,},
+     {16568933,4717097,-11556148,-1102322,15682896,
+      -11807043,16354577,-11775962,7689662,11199574,},
+     {30464156,-5976125,-11779434,-15670865,23220365,
+      15915852,7512774,10017326,-17749093,-9920357,},},
+    {{10861363,11473154,27284546,1981175,-30064349,
+      12577861,32867885,14515107,-15438304,10819380,},
+     {4708026,6336745,20377586,9066809,-11272109,
+      6594696,-25653668,12483688,-12668491,5581306,},
+     {19563160,16186464,-29386857,4097519,10237984,
+      -4348115,28542350,13850243,-23678021,-15815942,},},
+    {{5153746,9909285,1723747,-2777874,30523605,
+      5516873,19480852,5230134,-23952439,-15175766,},
+     {-30269007,-3463509,7665486,10083793,28475525,
+      1649722,20654025,16520125,30598449,7715701,},
+     {28881845,14381568,9657904,3680757,-20181635,
+      7843316,-31400660,1370708,29794553,-1409300,},},
+    {{-22518993,-6692182,14201702,-8745502,-23510406,
+      8844726,18474211,-1361450,-13062696,13821877,},
+     {-6455177,-7839871,3374702,-4740862,-27098617,
+      -10571707,31655028,-7212327,18853322,-14220951,},
+     {4566830,-12963868,-28974889,-12240689,-7602672,
+      -2830569,-8514358,-10431137,2207753,-3209784,},},
+    {{-25154831,-4185821,29681144,7868801,-6854661,
+      -9423865,-12437364,-663000,-31111463,-16132436,},
+     {25576264,-2703214,7349804,-11814844,16472782,
+      9300885,3844789,15725684,171356,6466918,},
+     {23103977,13316479,9739013,-16149481,817875,
+      -15038942,8965339,-14088058,-30714912,16193877,},},
+    {{-33521811,3180713,-2394130,14003687,-16903474,
+      -16270840,17238398,4729455,-18074513,9256800,},
+     {-25182317,-4174131,32336398,5036987,-21236817,
+      11360617,22616405,9761698,-19827198,630305,},
+     {-13720693,2639453,-24237460,-7406481,9494427,
+      -5774029,-6554551,-15960994,-2449256,-14291300,},},
+    {{-3151181,-5046075,9282714,6866145,-31907062,
+      -863023,-18940575,15033784,25105118,-7894876,},
+     {-24326370,15950226,-31801215,-14592823,-11662737,
+      -5090925,1573892,-2625887,2198790,-15804619,},
+     {-3099351,10324967,-2241613,7453183,-5446979,
+      -2735503,-13812022,-16236442,-32461234,-12290683,},},
 };
 
 // Incremental sliding windows (left to right)
@@ -1802,122 +1811,113 @@ static void ge_double_scalarmult_vartime(ge *P, const u8 p[32], const u8 b[32])
         if (p_digit > 0) { ge_add(sum, sum, &cP[ p_digit / 2]); }
         if (p_digit < 0) { ge_sub(sum, sum, &cP[-p_digit / 2]); }
         fe t1, t2;
-        if (b_digit > 0) { ge_madd(sum, sum,
-                                   window_Yp[ b_digit / 2],
-                                   window_Ym[ b_digit / 2],
-                                   window_T2[ b_digit / 2], t1, t2); }
-        if (b_digit < 0) { ge_msub(sum, sum,
-                                   window_Yp[-b_digit / 2],
-                                   window_Ym[-b_digit / 2],
-                                   window_T2[-b_digit / 2], t1, t2); }
+        if (b_digit > 0) { ge_madd(sum, sum, b_window +  b_digit/2, t1, t2); }
+        if (b_digit < 0) { ge_msub(sum, sum, b_window + -b_digit/2, t1, t2); }
         i--;
     }
 }
 
 // 5-bit signed comb in cached format (Niels coordinates, Z=1)
-static const fe comb_Yp[16] = {
-    {2615675, 9989699, 17617367, -13953520, -8802803,
-     1447286, -8909978, -270892, -12199203, -11617247},
-    {-1271192, 4785266, -29856067, -6036322, -10435381,
-     15493337, 20321440, -6036064, 15902131, 13420909},
-    {-26170888, -12891603, 9568996, -6197816, 26424622,
-     16308973, -4518568, -3771275, -15522557, 3991142},
-    {-25875044, 1958396, 19442242, -9809943, -26099408,
-     -18589, -30794750, -14100910, 4971028, -10535388},
-    {-13896937, -7357727, -12131124, 617289, -33188817,
-     10080542, 6402555, 10779157, 1176712, 2472642},
-    {71503, 12662254, -17008072, -8370006, 23408384,
-     -12897959, 32287612, 11241906, -16724175, 15336924},
-    {27397666, 4059848, 23573959, 8868915, -10602416,
-     -10456346, -22812831, -9666299, 31810345, -2695469},
-    {-3418193, -694531, 2320482, -11850408, -1981947,
-     -9606132, 23743894, 3933038, -25004889, -4478918},
-    {-4448372, 5537982, -4805580, 14016777, 15544316,
-     16039459, -7143453, -8003716, -21904564, 8443777},
-    {32495180, 15749868, 2195406, -15542321, -3213890,
-     -4030779, -2915317, 12751449, -1872493, 11926798},
-    {26779741, 12553580, -24344000, -4071926, -19447556,
-     -13464636, 21989468, 7826656, -17344881, 10055954},
-    {5848288, -1639207, -10452929, -11760637, 6484174,
-     -5895268, -11561603, 587105, -19220796, 14378222},
-    {32050187, 12536702, 9206308, -10016828, -13333241,
-     -4276403, -24225594, 14562479, -31803624, -9967812},
-    {23536033, -6219361, 199701, 4574817, 30045793,
-     7163081, -2244033, 883497, 10960746, -14779481},
-    {-8143354, -11558749, 15772067, 14293390, 5914956,
-     -16702904, -7410985, 7536196, 6155087, 16571424},
-    {6211591, -11166015, 24568352, 2768318, -10822221,
-     11922793, 33211827, 3852290, -13160369, -8855385},
-};
-static const fe comb_Ym[16] = {
-    {8873912, 14981221, 13714139, 6923085, 25481101,
-     4243739, 4646647, -203847, 9015725, -16205935},
-    {-1827892, 15407265, 2351140, -11810728, 28403158,
-     -1487103, -15057287, -4656433, -3780118, -1145998},
-    {-30623162, -11845055, -11327147, -16008347, 17564978,
-     -1449578, -20580262, 14113978, 29643661, 15580734},
-    {-15109423, 13348938, -14756006, 14132355, 30481360,
-     1830723, -240510, 9371801, -13907882, 8024264},
-    {25119567, 5628696, 10185251, -9279452, 683770,
-     -14523112, -7982879, -16450545, 1431333, -13253541},
-    {-8390493, 1276691, 19008763, -12736675, -9249429,
-     -12526388, 17434195, -13761261, 18962694, -1227728},
-    {26361856, -12366343, 8941415, 15163068, 7069802,
-     -7240693, -18656349, 8167008, 31106064, -1670658},
-    {-5677136, -11012483, -1246680, -6422709, 14772010,
-     1829629, -11724154, -15914279, -18177362, 1301444},
-    {937094, 12383516, -22597284, 7580462, -18767748,
-     13813292, -2323566, 13503298, 11510849, -10561992},
-    {28028043, 14715827, -6558532, -1773240, 27563607,
-     -9374554, 3201863, 8865591, -16953001, 7659464},
-    {13628467, 5701368, 4674031, 11935670, 11461401,
-     10699118, 31846435, -114971, -8269924, -14777505},
-    {-22124018, -12859127, 11966893, 1617732, 30972446,
-     -14350095, -21822286, 8369862, -29443219, -15378798},
-    {290131, -471434, 8840522, -2654851, 25963762,
-     -11578288, -7227978, 13847103, 30641797, 6003514},
-    {-23547482, -11475166, -11913550, 9374455, 22813401,
-     -5707910, 26635288, 9199956, 20574690, 2061147},
-    {9715324, 7036821, -17981446, -11505533, 26555178,
-     -3571571, 5697062, -14128022, 2795223, 9694380},
-    {14864569, -6319076, -3080, -8151104, 4994948,
-     -1572144, -41927, 9269803, 13881712, -13439497},
-};
-static const fe comb_T2[16] = {
-    {-18494317, 2686822, 18449263, -13905325, 5966562,
-     -3368714, 2738304, -8583315, 15987143, 12180258},
-    {-33336513, -13705917, -18473364, -5039204, -4268481,
-     -4136039, -8192211, -2935105, -19354402, 5995895},
-    {-19753139, -1729018, 21880604, 13471713, 28315373,
-     -8530159, -17492688, 11730577, -8790216, 3942124},
-    {17278020, 3905045, 29577748, 11151940, 18451761,
-     -6801382, 31480073, -13819665, 26308905, 10868496},
-    {26937294, 3313561, 28601532, -3497112, -22814130,
-     11073654, 8956359, -16757370, 13465868, 16623983},
-    {-5468054, 6059101, -31275300, 2469124, 26532937,
-     8152142, 6423741, -11427054, -15537747, -10938247},
-    {-11303505, -9659620, -12354748, -9331434, 19501116,
-     -9146390, -841918, -5315657, 8903828, 8839982},
-    {16603354, -215859, 1591180, 3775832, -705596,
-     -13913449, 26574704, 14963118, 19649719, 6562441},
-    {33188866, -12232360, -24929148, -6133828, 21818432,
-     11040754, -3041582, -3524558, -29364727, -10264096},
-    {-20704194, -12560423, -1235774, -785473, 13240395,
-     4831780, -472624, -3796899, 25480903, -15422283},
-    {-2204347, -16313180, -21388048, 7520851, -8697745,
-     -14460961, 20894017, 12210317, -475249, -2319102},
-    {-16407882, 4940236, -21194947, 10781753, 22248400,
-     14425368, 14866511, -7552907, 12148703, -7885797},
-    {16376744, 15908865, -30663553, 4663134, -30882819,
-     -10105163, 19294784, -10800440, -33259252, 2563437},
-    {30208741, 11594088, -15145888, 15073872, 5279309,
-     -9651774, 8273234, 4796404, -31270809, -13316433},
-    {-17802574, 14455251, 27149077, -7832700, -29163160,
-     -7246767, 17498491, -4216079, 31788733, -14027536},
-    {-25233439, -9389070, -6618212, -3268087, -521386,
-     -7350198, 21035059, -14970947, 25910190, 11122681},
+static const ge_precomp b_comb[16] = {
+    {{2615675,9989699,17617367,-13953520,-8802803,
+      1447286,-8909978,-270892,-12199203,-11617247,},
+     {8873912,14981221,13714139,6923085,25481101,
+      4243739,4646647,-203847,9015725,-16205935,},
+     {-18494317,2686822,18449263,-13905325,5966562,
+      -3368714,2738304,-8583315,15987143,12180258,},},
+    {{-1271192,4785266,-29856067,-6036322,-10435381,
+      15493337,20321440,-6036064,15902131,13420909,},
+     {-1827892,15407265,2351140,-11810728,28403158,
+      -1487103,-15057287,-4656433,-3780118,-1145998,},
+     {-33336513,-13705917,-18473364,-5039204,-4268481,
+      -4136039,-8192211,-2935105,-19354402,5995895,},},
+    {{-26170888,-12891603,9568996,-6197816,26424622,
+      16308973,-4518568,-3771275,-15522557,3991142,},
+     {-30623162,-11845055,-11327147,-16008347,17564978,
+      -1449578,-20580262,14113978,29643661,15580734,},
+     {-19753139,-1729018,21880604,13471713,28315373,
+      -8530159,-17492688,11730577,-8790216,3942124,},},
+    {{-25875044,1958396,19442242,-9809943,-26099408,
+      -18589,-30794750,-14100910,4971028,-10535388,},
+     {-15109423,13348938,-14756006,14132355,30481360,
+      1830723,-240510,9371801,-13907882,8024264,},
+     {17278020,3905045,29577748,11151940,18451761,
+      -6801382,31480073,-13819665,26308905,10868496,},},
+    {{-13896937,-7357727,-12131124,617289,-33188817,
+      10080542,6402555,10779157,1176712,2472642,},
+     {25119567,5628696,10185251,-9279452,683770,
+      -14523112,-7982879,-16450545,1431333,-13253541,},
+     {26937294,3313561,28601532,-3497112,-22814130,
+      11073654,8956359,-16757370,13465868,16623983,},},
+    {{71503,12662254,-17008072,-8370006,23408384,
+      -12897959,32287612,11241906,-16724175,15336924,},
+     {-8390493,1276691,19008763,-12736675,-9249429,
+      -12526388,17434195,-13761261,18962694,-1227728,},
+     {-5468054,6059101,-31275300,2469124,26532937,
+      8152142,6423741,-11427054,-15537747,-10938247,},},
+    {{27397666,4059848,23573959,8868915,-10602416,
+      -10456346,-22812831,-9666299,31810345,-2695469,},
+     {26361856,-12366343,8941415,15163068,7069802,
+      -7240693,-18656349,8167008,31106064,-1670658,},
+     {-11303505,-9659620,-12354748,-9331434,19501116,
+      -9146390,-841918,-5315657,8903828,8839982,},},
+    {{-3418193,-694531,2320482,-11850408,-1981947,
+      -9606132,23743894,3933038,-25004889,-4478918,},
+     {-5677136,-11012483,-1246680,-6422709,14772010,
+      1829629,-11724154,-15914279,-18177362,1301444,},
+     {16603354,-215859,1591180,3775832,-705596,
+      -13913449,26574704,14963118,19649719,6562441,},},
+    {{-4448372,5537982,-4805580,14016777,15544316,
+      16039459,-7143453,-8003716,-21904564,8443777,},
+     {937094,12383516,-22597284,7580462,-18767748,
+      13813292,-2323566,13503298,11510849,-10561992,},
+     {33188866,-12232360,-24929148,-6133828,21818432,
+      11040754,-3041582,-3524558,-29364727,-10264096,},},
+    {{32495180,15749868,2195406,-15542321,-3213890,
+      -4030779,-2915317,12751449,-1872493,11926798,},
+     {28028043,14715827,-6558532,-1773240,27563607,
+      -9374554,3201863,8865591,-16953001,7659464,},
+     {-20704194,-12560423,-1235774,-785473,13240395,
+      4831780,-472624,-3796899,25480903,-15422283,},},
+    {{26779741,12553580,-24344000,-4071926,-19447556,
+      -13464636,21989468,7826656,-17344881,10055954,},
+     {13628467,5701368,4674031,11935670,11461401,
+      10699118,31846435,-114971,-8269924,-14777505,},
+     {-2204347,-16313180,-21388048,7520851,-8697745,
+      -14460961,20894017,12210317,-475249,-2319102,},},
+    {{5848288,-1639207,-10452929,-11760637,6484174,
+      -5895268,-11561603,587105,-19220796,14378222,},
+     {-22124018,-12859127,11966893,1617732,30972446,
+      -14350095,-21822286,8369862,-29443219,-15378798,},
+     {-16407882,4940236,-21194947,10781753,22248400,
+      14425368,14866511,-7552907,12148703,-7885797,},},
+    {{32050187,12536702,9206308,-10016828,-13333241,
+      -4276403,-24225594,14562479,-31803624,-9967812,},
+     {290131,-471434,8840522,-2654851,25963762,
+      -11578288,-7227978,13847103,30641797,6003514,},
+     {16376744,15908865,-30663553,4663134,-30882819,
+      -10105163,19294784,-10800440,-33259252,2563437,},},
+    {{23536033,-6219361,199701,4574817,30045793,
+      7163081,-2244033,883497,10960746,-14779481,},
+     {-23547482,-11475166,-11913550,9374455,22813401,
+      -5707910,26635288,9199956,20574690,2061147,},
+     {30208741,11594088,-15145888,15073872,5279309,
+      -9651774,8273234,4796404,-31270809,-13316433,},},
+    {{-8143354,-11558749,15772067,14293390,5914956,
+      -16702904,-7410985,7536196,6155087,16571424,},
+     {9715324,7036821,-17981446,-11505533,26555178,
+      -3571571,5697062,-14128022,2795223,9694380,},
+     {-17802574,14455251,27149077,-7832700,-29163160,
+      -7246767,17498491,-4216079,31788733,-14027536,},},
+    {{6211591,-11166015,24568352,2768318,-10822221,
+      11922793,33211827,3852290,-13160369,-8855385,},
+     {14864569,-6319076,-3080,-8151104,4994948,
+      -1572144,-41927,9269803,13881712,-13439497,},
+     {-25233439,-9389070,-6618212,-3268087,-521386,
+      -7350198,21035059,-14970947,25910190,11122681,},},
 };
 
+
 // p = [scalar]B, where B is the base point
 static void ge_scalarmult_base(ge *p, const u8 scalar[32])
 {
@@ -1940,16 +1940,17 @@ static void ge_scalarmult_base(ge *p, const u8 scalar[32])
     mul_add(s_scalar, scalar, half_mod_L, half_ones);
 
     // Double and add ladder
-    fe yp, ym, t2, n2, a; // temporaries for addition
-    ge dbl;               // temporary for doubling
+    fe a, n2; // temporaries for addition
+    ge dbl;   // temporary for doubling
+    ge_precomp comb;
     ge_zero(p);
     for (int i = 50; i >= 0; i--) {
         if (i < 50) {
             ge_double(p, p, &dbl);
         }
-        fe_1(yp);
-        fe_1(ym);
-        fe_0(t2);
+        fe_1(comb.Yp);
+        fe_1(comb.Ym);
+        fe_0(comb.T2);
         u8 teeth = (u8)((scalar_bit(s_scalar, i)           ) +
                         (scalar_bit(s_scalar, i +  51) << 1) +
                         (scalar_bit(s_scalar, i + 102) << 2) +
@@ -1959,19 +1960,17 @@ static void ge_scalarmult_base(ge *p, const u8 scalar[32])
         u8 index = (teeth ^ (high - 1)) & 15;
         FOR (j, 0, 16) {
             i32 select = 1 & (((j ^ index) - 1) >> 8);
-            fe_ccopy(yp, comb_Yp[j], select);
-            fe_ccopy(ym, comb_Ym[j], select);
-            fe_ccopy(t2, comb_T2[j], select);
+            fe_ccopy(comb.Yp, b_comb[j].Yp, select);
+            fe_ccopy(comb.Ym, b_comb[j].Ym, select);
+            fe_ccopy(comb.T2, b_comb[j].T2, select);
         }
-
-        fe_neg(n2, t2);
-        fe_cswap(t2, n2, high);
-        fe_cswap(yp, ym, high);
-        ge_madd(p, p, ym, yp, n2, a, t2); // reuse t2 as temporary
+        fe_neg(n2, comb.T2);
+        fe_cswap(comb.T2, n2     , high);
+        fe_cswap(comb.Yp, comb.Ym, high);
+        ge_msub(p, p, &comb, a, n2); // reuse n2 as temporary
     }
-    WIPE_CTX(&dbl);
-    WIPE_BUFFER(yp);  WIPE_BUFFER(t2);  WIPE_BUFFER(a);
-    WIPE_BUFFER(ym);  WIPE_BUFFER(n2);
+    WIPE_CTX(&dbl); WIPE_CTX(&comb);
+    WIPE_BUFFER(a); WIPE_BUFFER(n2);
     WIPE_BUFFER(s_scalar);
 }