in FourQ_ARM_NEON/crypto_util.c [46:136]
ECCRYPTO_STATUS decode(const unsigned char* Pencoded, point_t P)
{ // Decode point P
// SECURITY NOTE: this function does not run in constant time.
velm_t r, t, t0, t1, t2, t3, t4, VPx0, VPx1;
v2elm_t u, v, u2, v2, one = {0};
digit_t sign_dec;
vpoint_extproj_t R;
vpoint_t VP;
unsigned int i, sign;
one[0] = 1;
memmove((unsigned char*)P->y, Pencoded, 32); // Decoding y-coordinate and sign
sign = (unsigned int)(Pencoded[31] >> 7);
P->y[1][NWORDS_FIELD-1] &= mask7fff;
from_std_to_ext(P->y, VP->y);
v2sqr1271(VP->y, u2);
v2mul1271(u2, (uint32_t*)&PARAMETER_d, v2);
v2sub1271(u2, one, u2);
v2add1271(v2, one, v2);
from_v2_to_v(u2, &u[0], &u[VWORDS_FIELD]);
from_v2_to_v(v2, &v[0], &v[VWORDS_FIELD]);
vsqr1271(&v[0], t0); // t0 = v0^2
vsqr1271(&v[VWORDS_FIELD], t1); // t1 = v1^2
vadd1271(t0, t1, t0); // t0 = t0+t1
vmul1271(&u[0], &v[0], t1); // t1 = u0*v0
vmul1271(&u[VWORDS_FIELD], &v[VWORDS_FIELD], t2); // t2 = u1*v1
vadd1271(t1, t2, t1); // t1 = t1+t2
vmul1271(&u[VWORDS_FIELD], &v[0], t2); // t2 = u1*v0
vmul1271(&u[0], &v[VWORDS_FIELD], t3); // t3 = u0*v1
vsub1271(t2, t3, t2); // t2 = t2-t3
vsqr1271(t1, t3); // t3 = t1^2
vsqr1271(t2, t4); // t4 = t2^2
vadd1271(t3, t4, t3); // t3 = t3+t4
for (i = 0; i < 125; i++) { // t3 = t3^(2^125)
vsqr1271(t3, t3);
}
vadd1271(t1, t3, t); // t = t1+t3
vmod1271(t, t);
if (is_zero_ct(t, VWORDS_FIELD) == true) {
vsub1271(t1, t3, t); // t = t1-t3
}
vadd1271(t, t, t); // t = 2*t
vsqr1271(t0, t3); // t3 = t0^2
vmul1271(t0, t3, t3); // t3 = t3*t0
vmul1271(t, t3, t3); // t3 = t3*t
vexp1251(t3, r); // r = t3^(2^125-1)
vmul1271(t0, r, t3); // t3 = t0*r
vmul1271(t, t3, VPx0); // x0 = t*t3
vsqr1271(VPx0, t1);
vmul1271(t0, t1, t1); // t1 = t0*x0^2
vdiv1271(VPx0); // x0 = x0/2
vmul1271(t2, t3, VPx1); // x1 = t3*t2
vsub1271(t, t1, t);
vmod1271(t, t);
if (is_zero_ct(t, VWORDS_FIELD) == false) { // If t != t1 then swap x0 and x1
memmove((unsigned char*)t0, (unsigned char*)VPx0, 20);
memmove((unsigned char*)VPx0, (unsigned char*)VPx1, 20);
memmove((unsigned char*)VPx1, t0, 20);
}
from_v_to_v2(VPx0, VPx1, VP->x);
v2mod1271(VP->x, VP->x);
if (is_zero_ct(VP->x, VWORDS_FIELD) == true) {
sign_dec = VP->x[2*VWORDS_FIELD-1] >> 22;
} else {
sign_dec = VP->x[2*VWORDS_FIELD-2] >> 22;
}
if (sign != (unsigned int)sign_dec) { // If sign of x-coordinate decoded != input sign bit, then negate x-coordinate
v2neg1271(VP->x);
}
v2mod1271(VP->x, R->x);
v2mod1271(VP->y, R->y);
if (ecc_point_validate(R) == false) {
v2neg1271_felm(R->x);
if (ecc_point_validate(R) == false) { // Final point validation
return ECCRYPTO_ERROR;
}
}
v2mod1271(R->x, R->x);
from_ext_to_std(R->x, P->x);
from_ext_to_std(R->y, P->y);
return ECCRYPTO_SUCCESS;
}