in src/kem.c [248:311]
int crypto_kem_dec(OUT unsigned char * ss,
IN const unsigned char *ct,
IN const unsigned char *sk)
{
// Public values, does not require a cleanup on exit
ct_t l_ct;
DEFER_CLEANUP(seeds_t seeds = {0}, seeds_cleanup);
DEFER_CLEANUP(ss_t l_ss, ss_cleanup);
DEFER_CLEANUP(aligned_sk_t l_sk, sk_cleanup);
DEFER_CLEANUP(e_t e, e_cleanup);
DEFER_CLEANUP(m_t m_prime, m_cleanup);
DEFER_CLEANUP(pad_e_t e_tmp, pad_e_cleanup);
DEFER_CLEANUP(pad_e_t e_prime, pad_e_cleanup);
// Copy the data from the input buffers. This is required in order to avoid
// alignment issues on non x86_64 processors.
bike_memcpy(&l_ct, ct, sizeof(l_ct));
bike_memcpy(&l_sk, sk, sizeof(l_sk));
// Generate a random error vector to be used in case of decoding failure
// (Note: possibly, a "fixed" zeroed error vector could suffice too,
// and serve this generation)
get_seeds(&seeds);
GUARD(generate_error_vector(&e_prime, &seeds.seed[0]));
// Decode and on success check if |e|=T (all in constant-time)
volatile uint32_t success_cond = (decode(&e, &l_ct, &l_sk) == SUCCESS);
success_cond &= secure_cmp32(T, r_bits_vector_weight(&e.val[0]) +
r_bits_vector_weight(&e.val[1]));
// Set appropriate error based on the success condition
uint8_t mask = ~secure_l32_mask(0, success_cond);
for(size_t i = 0; i < R_BYTES; i++) {
PE0_RAW(&e_prime)[i] &= u8_barrier(~mask);
PE0_RAW(&e_prime)[i] |= (u8_barrier(mask) & E0_RAW(&e)[i]);
PE1_RAW(&e_prime)[i] &= u8_barrier(~mask);
PE1_RAW(&e_prime)[i] |= (u8_barrier(mask) & E1_RAW(&e)[i]);
}
GUARD(reencrypt(&m_prime, &e_prime, &l_ct));
// Check if H(m') is equal to (e0', e1')
// (in constant-time)
GUARD(function_h(&e_tmp, &m_prime, &l_sk.pk));
success_cond = secure_cmp(PE0_RAW(&e_prime), PE0_RAW(&e_tmp), R_BYTES);
success_cond &= secure_cmp(PE1_RAW(&e_prime), PE1_RAW(&e_tmp), R_BYTES);
// Compute either K(m', C) or K(sigma, C) based on the success condition
mask = secure_l32_mask(0, success_cond);
for(size_t i = 0; i < M_BYTES; i++) {
m_prime.raw[i] &= u8_barrier(~mask);
m_prime.raw[i] |= (u8_barrier(mask) & l_sk.sigma.raw[i]);
}
// Generate the shared secret
GUARD(function_k(&l_ss, &m_prime, &l_ct));
// Copy the data into the output buffer
bike_memcpy(ss, &l_ss, sizeof(l_ss));
return SUCCESS;
}