13 #include <botan/mceliece.h>
14 #include <botan/internal/mce_internal.h>
15 #include <botan/internal/code_based_util.h>
16 #include <botan/loadstor.h>
22 class binary_matrix
final
27 void row_xor(
size_t a,
size_t b);
28 secure_vector<size_t> row_reduced_echelon_form();
33 uint32_t coef(
size_t i,
size_t j)
38 void set_coef_to_one(
size_t i,
size_t j)
40 m_elem[(i) *
m_rwdcnt + (j) / 32] |= (
static_cast<uint32_t
>(1) << ((j) % 32)) ;
43 void toggle_coeff(
size_t i,
size_t j)
45 m_elem[(i) *
m_rwdcnt + (j) / 32] ^= (
static_cast<uint32_t
>(1) << ((j) % 32)) ;
48 size_t rows()
const {
return m_rown; }
50 size_t columns()
const {
return m_coln; }
61 binary_matrix::binary_matrix(
size_t rown,
size_t coln)
69 void binary_matrix::row_xor(
size_t a,
size_t b)
71 for(
size_t i = 0; i !=
m_rwdcnt; i++)
78 secure_vector<size_t> binary_matrix::row_reduced_echelon_form()
80 secure_vector<size_t> perm(
m_coln);
81 for(
size_t i = 0; i !=
m_coln; i++)
89 for(
size_t i = 0; i !=
m_rown; i++, max--)
91 bool found_row =
false;
93 for(
size_t j = i; !found_row && j !=
m_rown; j++)
109 perm[
m_coln -
m_rown - 1 - failcnt] =
static_cast<int>(max);
120 for(
size_t j=i+1;j<
m_rown;j++)
129 for(
size_t j = i; j != 0; --j)
141 void randomize_support(std::vector<gf2m>& L, RandomNumberGenerator& rng)
143 for(
size_t i = 0; i != L.size(); ++i)
148 std::swap(L[i], L[rnd % L.size()]);
152 std::unique_ptr<binary_matrix> generate_R(std::vector<gf2m> &L, polyn_gf2m* g, std::shared_ptr<GF2m_Field> sp_field,
size_t code_length,
size_t t)
160 const size_t r = t * sp_field->get_extension_degree();
162 binary_matrix H(r, code_length);
164 for(
size_t i = 0; i != code_length; i++)
167 x = sp_field->gf_inv(x);
169 for(
size_t j=0;j<t;j++)
171 for(
size_t k=0;k<sp_field->get_extension_degree();k++)
176 H.set_coef_to_one(j*sp_field->get_extension_degree()+ k,i);
183 secure_vector<size_t> perm = H.row_reduced_echelon_form();
186 throw Invalid_State(
"McEliece keygen failed - could not bring matrix to row reduced echelon form");
189 std::unique_ptr<binary_matrix> result(
new binary_matrix(code_length-r, r)) ;
190 for(
size_t i = 0; i < result->rows(); ++i)
192 for(
size_t j = 0; j < result->columns(); ++j)
194 if(H.coef(j, perm[i]))
196 result->toggle_coeff(i,j);
201 std::vector<gf2m> Laux(code_length);
202 for(
size_t i = 0; i < code_length; ++i)
204 Laux[i] = L[perm[i]];
207 for(
size_t i = 0; i < code_length; ++i)
217 const size_t codimension = t * ext_deg;
219 if(code_length <= codimension)
224 std::shared_ptr<GF2m_Field> sp_field(
new GF2m_Field(ext_deg));
227 std::vector<gf2m> L(code_length);
229 for(
size_t i = 0; i != L.size(); i++)
231 L[i] =
static_cast<gf2m>(i);
233 randomize_support(L, rng);
236 bool success =
false;
237 std::unique_ptr<binary_matrix> R;
246 R = generate_R(L, &g, sp_field, code_length, t);
255 std::vector<polyn_gf2m> F =
syndrome_init(g, L, static_cast<int>(code_length));
264 uint32_t* sk = H.data();
265 for(
size_t i = 0; i < code_length; ++i)
267 for(
size_t l = 0; l < t; ++l)
269 const size_t k = (l * ext_deg) / 32;
270 const uint8_t j = (l * ext_deg) % 32;
271 sk[k] ^=
static_cast<uint32_t
>(F[i].get_coef(l)) << j;
274 sk[k + 1] ^= F[i].get_coef(l) >> (32 - j);
283 std::vector<gf2m> Linv(code_length) ;
284 for(
size_t i = 0; i != Linv.size(); ++i)
286 Linv[L[i]] =
static_cast<gf2m>(i);
288 std::vector<uint8_t> pubmat(R->m_elem.size() * 4);
289 for(
size_t i = 0; i < R->m_elem.size(); i++)
291 store_le(R->m_elem[i], &pubmat[i*4]);
size_t bit_size_to_32bit_size(size_t bit_size)
int(* final)(unsigned char *, CTX *)
static std::vector< polyn_gf2m > sqrt_mod_init(const polyn_gf2m &g)
gf2m lex_to_gray(gf2m lex)
std::vector< uint32_t > m_elem
std::vector< polyn_gf2m > syndrome_init(polyn_gf2m const &generator, std::vector< gf2m > const &support, int n)
McEliece_PrivateKey generate_mceliece_key(RandomNumberGenerator &rng, size_t ext_deg, size_t code_length, size_t t)
gf2m random_gf2m(RandomNumberGenerator &rng)
void store_le(uint16_t in, uint8_t out[2])