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);
}