/* computes [s1]p1 + [s2]p2 */ void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) { ge25519_p1p1 tp1p1; ge25519_p3 pre[16]; unsigned char b[127]; int i; /* precomputation s2 s1 */ setneutral(pre); /* 00 00 */ pre[1] = *p1; /* 00 01 */ dbl_p1p1(&tp1p1,(ge25519_p2 *)p1); p1p1_to_p3( &pre[2], &tp1p1); /* 00 10 */ add_p1p1(&tp1p1,&pre[1], &pre[2]); p1p1_to_p3( &pre[3], &tp1p1); /* 00 11 */ pre[4] = *p2; /* 01 00 */ add_p1p1(&tp1p1,&pre[1], &pre[4]); p1p1_to_p3( &pre[5], &tp1p1); /* 01 01 */ add_p1p1(&tp1p1,&pre[2], &pre[4]); p1p1_to_p3( &pre[6], &tp1p1); /* 01 10 */ add_p1p1(&tp1p1,&pre[3], &pre[4]); p1p1_to_p3( &pre[7], &tp1p1); /* 01 11 */ dbl_p1p1(&tp1p1,(ge25519_p2 *)p2); p1p1_to_p3( &pre[8], &tp1p1); /* 10 00 */ add_p1p1(&tp1p1,&pre[1], &pre[8]); p1p1_to_p3( &pre[9], &tp1p1); /* 10 01 */ dbl_p1p1(&tp1p1,(ge25519_p2 *)&pre[5]); p1p1_to_p3(&pre[10], &tp1p1); /* 10 10 */ add_p1p1(&tp1p1,&pre[3], &pre[8]); p1p1_to_p3(&pre[11], &tp1p1); /* 10 11 */ add_p1p1(&tp1p1,&pre[4], &pre[8]); p1p1_to_p3(&pre[12], &tp1p1); /* 11 00 */ add_p1p1(&tp1p1,&pre[1],&pre[12]); p1p1_to_p3(&pre[13], &tp1p1); /* 11 01 */ add_p1p1(&tp1p1,&pre[2],&pre[12]); p1p1_to_p3(&pre[14], &tp1p1); /* 11 10 */ add_p1p1(&tp1p1,&pre[3],&pre[12]); p1p1_to_p3(&pre[15], &tp1p1); /* 11 11 */ sc25519_2interleave2(b,s1,s2); /* scalar multiplication */ *r = pre[b[126]]; for (i = 125; i >= 0; i--) { dbl_p1p1(&tp1p1, (ge25519_p2 *)r); p1p1_to_p2((ge25519_p2 *) r, &tp1p1); dbl_p1p1(&tp1p1, (ge25519_p2 *)r); if(b[i] != 0) { p1p1_to_p3(r, &tp1p1); add_p1p1(&tp1p1, r, &pre[b[i]]); } if (i != 0) { p1p1_to_p2((ge25519_p2 *)r, &tp1p1); } else { p1p1_to_p3(r, &tp1p1); } } }
/* computes [s1]p1 + [s2]p2 */ void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) { ge25519_p1p1 tp1p1; ge25519_p3 pre; unsigned char b[255]; int i; add_p1p1(&tp1p1,p1,p2); p1p1_to_p3(&pre, &tp1p1); sc25519_2interleave1(b,s1,s2); if(b[254]==0) setneutral(r); else if(b[254]==1) *r = *p1; else if(b[254]==2) *r = *p2; else if(b[254]==3) *r = pre; /* scalar multiplication */ for(i=253;i>=0;i--) { dbl_p1p1(&tp1p1, (ge25519_p2 *)r); if(b[i]==1) { p1p1_to_p3(r, &tp1p1); add_p1p1(&tp1p1, r, p1); } else if(b[i]==2) { p1p1_to_p3(r, &tp1p1); add_p1p1(&tp1p1, r, p2); } else if(b[i]==3) { p1p1_to_p3(r, &tp1p1); add_p1p1(&tp1p1, r, &pre); } if(i != 0) p1p1_to_p2((ge25519_p2 *)r, &tp1p1); else p1p1_to_p3(r, &tp1p1); } }
/* computes [s1]p1 + [s2]p2 */ void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const sc25519 *s2) { signed char slide1[256], slide2[256]; ge25519_pniels pre1[PRE1_SIZE], neg; ge25519_p3 d1; ge25519_p1p1 t; ge25519_niels nneg; fe25519 d; int i; sc25519_slide(slide1, s1, S1_SWINDOWSIZE); sc25519_slide(slide2, s2, S2_SWINDOWSIZE); /* precomputation */ pre1[0] = *(ge25519_pniels *)p1; ge25519_dbl_p1p1(&t,(ge25519_p2 *)pre1); ge25519_p1p1_to_p3(&d1, &t); /* Convert pre[0] to projective Niels representation */ d = pre1[0].ysubx; fe25519_sub(&pre1[0].ysubx, &pre1[0].xaddy, &pre1[0].ysubx); fe25519_add(&pre1[0].xaddy, &pre1[0].xaddy, &d); fe25519_mul(&pre1[0].t2d, &pre1[0].t2d, &ec2d); for(i=0;i<PRE1_SIZE-1;i++) { ge25519_pnielsadd_p1p1(&t, &d1, &pre1[i]); ge25519_p1p1_to_pniels(&pre1[i+1], &t); } setneutral(r); for (i = 255;i >= 0;--i) { if (slide1[i] || slide2[i]) goto firstbit; } for(;i>=0;i--) { firstbit: ge25519_dbl_p1p1(&t, (ge25519_p2 *)r); if(slide1[i]>0) { ge25519_p1p1_to_p3(r, &t); ge25519_pnielsadd_p1p1(&t, r, &pre1[slide1[i]/2]); } else if(slide1[i]<0) { ge25519_p1p1_to_p3(r, &t); neg = pre1[-slide1[i]/2]; d = neg.ysubx; neg.ysubx = neg.xaddy; neg.xaddy = d; fe25519_neg(&neg.t2d, &neg.t2d); ge25519_pnielsadd_p1p1(&t, r, &neg); } if(slide2[i]>0) { ge25519_p1p1_to_p3(r, &t); ge25519_nielsadd_p1p1(&t, r, &pre2[slide2[i]/2]); } else if(slide2[i]<0) { ge25519_p1p1_to_p3(r, &t); nneg = pre2[-slide2[i]/2]; d = nneg.ysubx; nneg.ysubx = nneg.xaddy; nneg.xaddy = d; fe25519_neg(&nneg.t2d, &nneg.t2d); ge25519_nielsadd_p1p1(&t, r, &nneg); } ge25519_p1p1_to_p2((ge25519_p2 *)r, &t); } }