ECCRYPTO_STATUS decode()

in FourQ_ARM/crypto_util.c [46:127]


ECCRYPTO_STATUS decode(const unsigned char* Pencoded, point_t P)
{ // Decode point P
  // SECURITY NOTE: this function does not run in constant time.
    felm_t r, t, t0, t1, t2, t3, t4;
    f2elm_t u, v, one = {0};
    digit_t sign_dec;
    point_extproj_t R;
    unsigned int i, sign;

    one[0][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;

    fp2sqr1271(P->y, u);
    fp2mul1271(u, (felm_t*)&PARAMETER_d, v);
    fp2sub1271(u, one, u);
    fp2add1271(v, one, v);

    fpsqr1271(v[0], t0);                            // t0 = v0^2
    fpsqr1271(v[1], t1);                            // t1 = v1^2
    fpadd1271(t0, t1, t0);                          // t0 = t0+t1   
    fpmul1271(u[0], v[0], t1);                      // t1 = u0*v0
    fpmul1271(u[1], v[1], t2);                      // t2 = u1*v1 
    fpadd1271(t1, t2, t1);                          // t1 = t1+t2  
    fpmul1271(u[1], v[0], t2);                      // t2 = u1*v0
    fpmul1271(u[0], v[1], t3);                      // t3 = u0*v1
    fpsub1271(t2, t3, t2);                          // t2 = t2-t3    
    fpsqr1271(t1, t3);                              // t3 = t1^2    
    fpsqr1271(t2, t4);                              // t4 = t2^2
    fpadd1271(t3, t4, t3);                          // t3 = t3+t4
    for (i = 0; i < 125; i++) {                     // t3 = t3^(2^125)
        fpsqr1271(t3, t3);
    }

    fpadd1271(t1, t3, t);                           // t = t1+t3
    mod1271(t);
    if (is_zero_ct(t, NWORDS_FIELD) == true) {
        fpsub1271(t1, t3, t);                       // t = t1-t3
    }
    fpadd1271(t, t, t);                             // t = 2*t            
    fpsqr1271(t0, t3);                              // t3 = t0^2      
    fpmul1271(t0, t3, t3);                          // t3 = t3*t0   
    fpmul1271(t, t3, t3);                           // t3 = t3*t
    fpexp1251(t3, r);                               // r = t3^(2^125-1)  
    fpmul1271(t0, r, t3);                           // t3 = t0*r          
    fpmul1271(t, t3, P->x[0]);                      // x0 = t*t3 
    fpsqr1271(P->x[0], t1);
    fpmul1271(t0, t1, t1);                          // t1 = t0*x0^2 
    fpdiv1271(P->x[0]);                             // x0 = x0/2         
    fpmul1271(t2, t3, P->x[1]);                     // x1 = t3*t2  

    fpsub1271(t, t1, t);
    mod1271(t);
    if (is_zero_ct(t, NWORDS_FIELD) == false) {        // If t != t1 then swap x0 and x1       
        fpcopy1271(P->x[0], t0);
        fpcopy1271(P->x[1], P->x[0]);
        fpcopy1271(t0, P->x[1]);
    }
    
    mod1271(P->x[0]);
    if (is_zero_ct((digit_t*)P->x, NWORDS_FIELD) == true) {
        sign_dec = ((digit_t*)&P->x[1])[NWORDS_FIELD-1] >> (sizeof(digit_t)*8 - 2);
    } else {
        sign_dec = ((digit_t*)&P->x[0])[NWORDS_FIELD-1] >> (sizeof(digit_t)*8 - 2);
    }

    if (sign != (unsigned int)sign_dec) {           // If sign of x-coordinate decoded != input sign bit, then negate x-coordinate
        fp2neg1271(P->x);
    }

    point_setup(P, R);
    if (ecc_point_validate(R) == false) {
        fpneg1271(R->x[1]);
        fpcopy1271(R->x[1], P->x[1]);
        if (ecc_point_validate(R) == false) {       // Final point validation
            return ECCRYPTO_ERROR;
        }
    }

    return ECCRYPTO_SUCCESS;
}