static void PKBDecompression_extended()

in src/compression/sidh_compressed.c [415:477]


static void PKBDecompression_extended(const unsigned char* SecretKeyA, const unsigned char* CompressedPKB, point_proj_t R, f2elm_t A, unsigned char* tphiBKA_t)
{ // Bob's PK decompression -- SIKE protocol
    uint64_t mask = (digit_t)(-1);
    unsigned char qnr, ind;
    f2elm_t A24,  Adiv2 = {0};
    digit_t tmp1[2*NWORDS_ORDER] = {0}, tmp2[2*NWORDS_ORDER] = {0}, inv[NWORDS_ORDER] = {0}, scal[2*NWORDS_ORDER] = {0};
    digit_t SKin[NWORDS_ORDER] = {0}, a0[NWORDS_ORDER] = {0}, a1[NWORDS_ORDER] = {0}, b0[NWORDS_ORDER] = {0}, b1[NWORDS_ORDER] = {0};
    point_proj_t Rs[3] = {0};

    mask >>= (MAXBITS_ORDER - OALICE_BITS);

    fp2_decode(&CompressedPKB[4*ORDER_A_ENCODED_BYTES], A);
    qnr = CompressedPKB[4*ORDER_A_ENCODED_BYTES + FP2_ENCODED_BYTES] & 0x01;
    ind = CompressedPKB[4*ORDER_A_ENCODED_BYTES + FP2_ENCODED_BYTES + 1];

    BuildEntangledXonly_Decomp(A, Rs, qnr, ind);
    fpcopy((digit_t*)Montgomery_one, (Rs[0]->Z)[0]);
    fpcopy((digit_t*)Montgomery_one, (Rs[1]->Z)[0]);
    
    fpadd(A[0], (digit_t*)Montgomery_one, A24[0]);
    fpcopy(A[1], A24[1]);
    fpadd(A24[0], (digit_t*)Montgomery_one, A24[0]);
    fp2div2(A24, A24);
    fp2div2(A24, A24);
       
    decode_to_digits(SecretKeyA, SKin, SECRETKEY_A_BYTES, NWORDS_ORDER);       
    decode_to_digits(&CompressedPKB[0], a0, ORDER_A_ENCODED_BYTES, NWORDS_ORDER);
    decode_to_digits(&CompressedPKB[ORDER_A_ENCODED_BYTES], b0, ORDER_A_ENCODED_BYTES, NWORDS_ORDER);
    decode_to_digits(&CompressedPKB[2*ORDER_A_ENCODED_BYTES], a1, ORDER_A_ENCODED_BYTES, NWORDS_ORDER);
    decode_to_digits(&CompressedPKB[3*ORDER_A_ENCODED_BYTES], b1, ORDER_A_ENCODED_BYTES, NWORDS_ORDER);

    if ( (a0[0] & 1) == 1) {
        multiply((digit_t*)SKin, b1, tmp1, NWORDS_ORDER);
        mp_add(tmp1, b0, tmp1, NWORDS_ORDER);
        tmp1[NWORDS_ORDER-1] &= (digit_t)mask;        
        multiply((digit_t*)SKin, a1, tmp2, NWORDS_ORDER);
        mp_add(tmp2, a0, tmp2, NWORDS_ORDER);
        tmp2[NWORDS_ORDER-1] &= (digit_t)mask; 
        inv_mod_orderA(tmp2, inv);
        multiply(tmp1, inv, scal, NWORDS_ORDER);
        scal[NWORDS_ORDER-1] &= (digit_t)mask;
        Ladder3pt_dual(Rs, scal, ALICE, R, A24);         
    } else {
        multiply((digit_t*)SKin, a1, tmp1, NWORDS_ORDER);
        mp_add(tmp1, a0, tmp1, NWORDS_ORDER);
        tmp1[NWORDS_ORDER-1] &= (digit_t)mask; 
        multiply((digit_t*)SKin, b1, tmp2, NWORDS_ORDER);
        mp_add(tmp2, b0, tmp2, NWORDS_ORDER);
        tmp2[NWORDS_ORDER-1] &= (digit_t)mask;
        inv_mod_orderA(tmp2, inv);
        multiply(inv, tmp1, scal, NWORDS_ORDER);
        scal[NWORDS_ORDER-1] &= (digit_t)mask;
        swap_points(Rs[0], Rs[1], 0-(digit_t)1);
        Ladder3pt_dual(Rs, scal, ALICE, R, A24);            
    }        
    
    fp2div2(A,Adiv2);
    xTPLe_fast(R, R, Adiv2, OBOB_EXPON);    
    
    fp2_encode(R->X, tphiBKA_t);
    fp2_encode(R->Z, &tphiBKA_t[FP2_ENCODED_BYTES]);
    encode_to_bytes(inv, &tphiBKA_t[2*FP2_ENCODED_BYTES], ORDER_A_ENCODED_BYTES);
}