| 1 | #include "ge.h" |
| 2 | |
| 3 | static const fe d = { |
| 4 | #include "d.h" |
| 5 | } ; |
| 6 | |
| 7 | static const fe sqrtm1 = { |
| 8 | #include "sqrtm1.h" |
| 9 | } ; |
| 10 | |
| 11 | int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) |
| 12 | { |
| 13 | fe u; |
| 14 | fe v; |
| 15 | fe v3; |
| 16 | fe vxx; |
| 17 | fe check; |
| 18 | |
| 19 | fe_frombytes(h->Y,s); |
| 20 | fe_1(h->Z); |
| 21 | fe_sq(u,h->Y); |
| 22 | fe_mul(v,u,d); |
| 23 | fe_sub(u,u,h->Z); /* u = y^2-1 */ |
| 24 | fe_add(v,v,h->Z); /* v = dy^2+1 */ |
| 25 | |
| 26 | fe_sq(v3,v); |
| 27 | fe_mul(v3,v3,v); /* v3 = v^3 */ |
| 28 | fe_sq(h->X,v3); |
| 29 | fe_mul(h->X,h->X,v); |
| 30 | fe_mul(h->X,h->X,u); /* x = uv^7 */ |
| 31 | |
| 32 | fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ |
| 33 | fe_mul(h->X,h->X,v3); |
| 34 | fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ |
| 35 | |
| 36 | fe_sq(vxx,h->X); |
| 37 | fe_mul(vxx,vxx,v); |
| 38 | fe_sub(check,vxx,u); /* vx^2-u */ |
| 39 | if (fe_isnonzero(check)) { |
| 40 | fe_add(check,vxx,u); /* vx^2+u */ |
| 41 | if (fe_isnonzero(check)) return -1; |
| 42 | fe_mul(h->X,h->X,sqrtm1); |
| 43 | } |
| 44 | |
| 45 | if (fe_isnegative(h->X) == (s[31] >> 7)) |
| 46 | fe_neg(h->X,h->X); |
| 47 | |
| 48 | fe_mul(h->T,h->X,h->Y); |
| 49 | return 0; |
| 50 | } |
| 51 | |