-rw-r--r-- 3197 lib25519-20240321/crypto_multiscalar/ed25519/ref10/multiscalar.c raw
#include <string.h>
#include "ge.h"
#include "ge_p1p1_0.h"
#include "ge_frombytes_vartime.h"
#include "sc.h"
#include "crypto_verify_32.h"
#include "crypto_multiscalar.h"
static void slide(signed char *r,const unsigned char *a)
{
int i;
int b;
int k;
for (i = 0;i < 256;++i)
r[i] = 1 & (a[i >> 3] >> (i & 7));
for (i = 0;i < 256;++i)
if (r[i]) {
for (b = 1;b <= 6 && i + b < 256;++b) {
if (r[i + b]) {
if (r[i] + (r[i + b] << b) <= 15) {
r[i] += r[i + b] << b; r[i + b] = 0;
} else if (r[i] - (r[i + b] << b) >= -15) {
r[i] -= r[i + b] << b;
for (k = i + b;k < 256;++k) {
if (!r[k]) {
r[k] = 1;
break;
}
r[k] = 0;
}
} else
break;
}
}
}
}
#define MAXTODO 16
void crypto_multiscalar(
unsigned char *Q,
const unsigned char *n,
const unsigned char *P,
long long len
)
{
int ok = 1;
ge_p1p1 bigresult;
ge_p1p1_0(&bigresult);
while (len > 0) {
signed char nslide[MAXTODO][256];
ge_cached cP[MAXTODO][8]; /* P,3P,5P,7P,9P,11P,13P,15P */
long long todo = MAXTODO;
if (len < todo) todo = len;
for (long long j = 0;j < todo;++j) {
unsigned char nj[32];
ge_p3 Pj;
ge_p3 twoPj;
ge_p1p1 t;
ge_p3 u;
memcpy(nj,n,32);
sc_reduce(nj);
if (crypto_verify_32(nj,n)) ok = 0;
slide(nslide[j],nj);
ok &= ge_frombytes_vartime(&Pj,P);
ge_p3_to_cached(&cP[j][0],&Pj);
ge_p3_dbl(&t,&Pj); ge_p1p1_to_p3(&twoPj,&t);
ge_add(&t,&twoPj,&cP[j][0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&cP[j][1],&u);
ge_add(&t,&twoPj,&cP[j][1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&cP[j][2],&u);
ge_add(&t,&twoPj,&cP[j][2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&cP[j][3],&u);
ge_add(&t,&twoPj,&cP[j][3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&cP[j][4],&u);
ge_add(&t,&twoPj,&cP[j][4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&cP[j][5],&u);
ge_add(&t,&twoPj,&cP[j][5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&cP[j][6],&u);
ge_add(&t,&twoPj,&cP[j][6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&cP[j][7],&u);
P += 32;
n += 32;
--len;
}
{
ge_p1p1 result;
ge_p3 u;
ge_cached v;
int maybenonzero = 0;
ge_p1p1_0(&result);
for (long long i = 255;i >= 0;--i) {
ge_p2 t;
if (maybenonzero) {
ge_p1p1_to_p2(&t,&result);
ge_p2_dbl(&result,&t);
}
for (long long j = 0;j < todo;++j) {
signed char c = nslide[j][i];
if (!c) continue;
maybenonzero = 1;
if (c > 0) {
ge_p1p1_to_p3(&u,&result);
ge_add(&result,&u,&cP[j][c/2]);
} else {
ge_p1p1_to_p3(&u,&result);
ge_sub(&result,&u,&cP[j][(-c)/2]);
}
}
}
ge_p1p1_to_p3(&u,&result);
ge_p3_to_cached(&v,&u);
ge_p1p1_to_p3(&u,&bigresult);
ge_add(&bigresult,&u,&v);
}
}
{
ge_p2 t;
ge_p1p1_to_p2(&t,&bigresult);
ge_tobytes(Q,&t);
Q[32] = ok;
}
}