12#include <botan/internal/cmce_decaps.h>
16Classic_McEliece_Polynomial Classic_McEliece_Decryptor::compute_goppa_syndrome(
17 const Classic_McEliece_Parameters& params,
18 const Classic_McEliece_Minimal_Polynomial& goppa_poly,
19 const Classic_McEliece_Field_Ordering& ordering,
21 BOTAN_ASSERT(params.n() == code_word.size(),
"Correct code word size");
22 std::vector<Classic_McEliece_GF> syndrome(2 * params.t(), params.gf(
CmceGfElem(0)));
24 auto alphas = ordering.alphas(params.n());
26 for(
size_t i = 0; i < params.n(); ++i) {
27 auto g_alpha = goppa_poly(alphas[i]);
28 auto r = (g_alpha * g_alpha).inv();
32 for(
size_t j = 0; j < 2 * params.t(); ++j) {
33 syndrome[j] += c_mask.if_set_return(r);
38 return Classic_McEliece_Polynomial(syndrome);
41Classic_McEliece_Polynomial Classic_McEliece_Decryptor::berlekamp_massey(
42 const Classic_McEliece_Parameters& params,
const Classic_McEliece_Polynomial& syndrome)
const {
44 std::vector<Classic_McEliece_GF> big_c(params.t() + 1, params.gf(
CmceGfElem(0)));
45 std::vector<Classic_McEliece_GF> big_b(params.t() + 1, params.gf(
CmceGfElem(0)));
53 for(
size_t big_n = 0, big_l = 0; big_n < 2 * params.t(); ++big_n) {
55 for(
size_t i = 0; i <= std::min(big_n, params.t()); ++i) {
56 d += big_c.at(i) * syndrome.coef_at(big_n - i);
64 adjust_big_c &= d_not_zero;
69 for(
size_t i = 0; i <= params.t(); ++i) {
71 big_c.at(i) += d_not_zero.if_set_return((f * big_b.at(i)));
74 big_l = adjust_big_c.select(uint16_t((big_n + 1) - big_l), uint16_t(big_l));
76 for(
size_t i = 0; i <= params.t(); ++i) {
77 big_b.at(i) = adjust_big_c.select(big_t.at(i), big_b.at(i));
80 b = adjust_big_c.select(d,
b);
83 std::rotate(big_b.rbegin(), big_b.rbegin() + 1, big_b.rend());
86 std::reverse(big_c.begin(), big_c.end());
88 return Classic_McEliece_Polynomial(big_c);
92 BOTAN_ASSERT(big_c.size() == m_key->params().m() * m_key->params().t(),
"Correct ciphertext input size");
93 big_c.resize(m_key->params().n());
96 compute_goppa_syndrome(m_key->params(), m_key->g(), m_key->field_ordering(), big_c.as<
secure_bitvector>());
97 const auto locator = berlekamp_massey(m_key->params(), syndrome);
99 std::vector<Classic_McEliece_GF> images;
100 const auto alphas = m_key->field_ordering().alphas(m_key->params().n());
102 alphas.begin(), alphas.end(), std::back_inserter(images), [&](
const auto& alpha) { return locator(alpha); });
106 e.get().reserve(m_key->params().n());
108 for(
const auto& image : images) {
114 const auto syndrome_from_e = compute_goppa_syndrome(m_key->params(), m_key->g(), m_key->field_ordering(), e.get());
116 for(
size_t i = 0; i < syndrome.degree() - 1; ++i) {
117 syndromes_are_eq &=
GF_Mask::is_equal(syndrome.coef_at(i), syndrome_from_e.coef_at(i));
120 decode_success &= syndromes_are_eq.elem_mask();
122 return {decode_success, std::move(e)};
126 std::span<const uint8_t> encapsulated_key) {
127 BOTAN_ARG_CHECK(out_shared_key.size() == m_key->params().hash_out_bytes(),
"Invalid shared key output size");
128 BOTAN_ARG_CHECK(encapsulated_key.size() == m_key->params().ciphertext_size(),
"Invalid ciphertext size");
132 auto [ct, c1] = [&]() -> std::pair<
CmceCodeWord, std::span<const uint8_t>> {
133 if(m_key->params().is_pc()) {
135 auto c0_ret = encaps_key_slicer.
take(m_key->params().encode_out_size());
136 auto c1_ret = encaps_key_slicer.
take(m_key->params().hash_out_bytes());
144 auto [decode_success_mask, maybe_e] = decode(ct);
147 decode_success_mask.select_n(e_bytes.data(), maybe_e.get().to_bytes().data(), m_key->s().data(), m_key->s().size());
148 uint8_t
b = decode_success_mask.select(1, 0);
150 auto hash_func = m_key->params().hash_func();
152 if(m_key->params().is_pc()) {
153 hash_func->update(0x02);
154 hash_func->update(e_bytes);
155 const auto c1_p = hash_func->final_stdvec();
157 eq_mask.
select_n(e_bytes.data(), e_bytes.data(), m_key->s().data(), m_key->s().size());
161 hash_func->update(
b);
162 hash_func->update(e_bytes);
163 hash_func->update(encapsulated_key);
164 hash_func->final(out_shared_key);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
std::span< const uint8_t > take(const size_t count)
static constexpr Mask< T > is_lte(T x, T y)
static constexpr Mask< T > set()
constexpr void select_n(T output[], const T x[], const T y[], size_t len) const
constexpr T select(T x, T y) const
static constexpr Mask< T > is_equal(T x, T y)
void raw_kem_decrypt(std::span< uint8_t > out_shared_key, std::span< const uint8_t > encapsulated_key) override
static GF_Mask expand(T v)
static GF_Mask is_equal(Classic_McEliece_GF a, Classic_McEliece_GF b)
static GF_Mask is_zero(Classic_McEliece_GF v)
constexpr auto scoped_poison(const Ts &... xs)
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
constexpr void unpoison(const T *p, size_t n)
Strong< secure_bitvector, struct CmceCodeWord_ > CmceCodeWord
Represents C of decapsulation.
bitvector_base< secure_allocator > secure_bitvector
Strong< secure_bitvector, struct CmceErrorVector_ > CmceErrorVector
Represents e of encapsulation.
Strong< uint16_t, struct CmceGfElem_ > CmceGfElem
Represents a GF(q) element.
std::vector< T, secure_allocator< T > > secure_vector