13#include <botan/mceliece.h>
15#include <botan/internal/code_based_util.h>
16#include <botan/internal/loadstor.h>
17#include <botan/internal/mce_internal.h>
18#include <botan/internal/polyn_gf2m.h>
24class binary_matrix
final {
26 binary_matrix(
size_t m_rown,
size_t m_coln);
28 void row_xor(
size_t a,
size_t b);
34 uint32_t coef(
size_t i,
size_t j) {
return (m_elem[(i)*m_rwdcnt + (j) / 32] >> (j % 32)) & 1; }
36 void set_coef_to_one(
size_t i,
size_t j) {
37 m_elem[(i)*m_rwdcnt + (j) / 32] |= (
static_cast<uint32_t
>(1) << ((j) % 32));
40 void toggle_coeff(
size_t i,
size_t j) {
41 m_elem[(i)*m_rwdcnt + (j) / 32] ^= (
static_cast<uint32_t
>(1) << ((j) % 32));
44 size_t rows()
const {
return m_rown; }
46 size_t columns()
const {
return m_coln; }
48 const std::vector<uint32_t>& elem()
const {
return m_elem; }
54 std::vector<uint32_t> m_elem;
57binary_matrix::binary_matrix(
size_t rown,
size_t coln) {
60 m_rwdcnt = 1 + ((m_coln - 1) / 32);
61 m_elem = std::vector<uint32_t>(m_rown * m_rwdcnt);
64void binary_matrix::row_xor(
size_t a,
size_t b) {
65 for(
size_t i = 0; i != m_rwdcnt; i++) {
66 m_elem[a * m_rwdcnt + i] ^= m_elem[
b * m_rwdcnt + i];
72 secure_vector<size_t> perm(m_coln);
73 for(
size_t i = 0; i != m_coln; i++) {
79 size_t max = m_coln - 1;
80 for(
size_t i = 0; i != m_rown; i++, max--) {
81 bool found_row =
false;
83 for(
size_t j = i; !found_row && j != m_rown; j++) {
96 perm[m_coln - m_rown - 1 - failcnt] =
static_cast<int>(max);
103 perm[i + m_coln - m_rown] = max;
104 for(
size_t j = i + 1; j < m_rown; j++)
112 for(
size_t j = i; j != 0; --j) {
113 if(coef(j - 1, max)) {
122void randomize_support(std::vector<gf2m>& L, RandomNumberGenerator& rng) {
123 for(
size_t i = 0; i != L.size(); ++i) {
127 std::swap(L[i], L[rnd % L.size()]);
131std::unique_ptr<binary_matrix> generate_R(
132 std::vector<gf2m>& L, polyn_gf2m* g,
const GF2m_Field& sp_field,
size_t code_length,
size_t t) {
139 const size_t r = t * sp_field.get_extension_degree();
141 binary_matrix H(r, code_length);
143 for(
size_t i = 0; i != code_length; i++) {
145 x = sp_field.gf_inv(x);
147 for(
size_t j = 0; j < t; j++) {
148 for(
size_t k = 0; k < sp_field.get_extension_degree(); k++) {
151 H.set_coef_to_one(j * sp_field.get_extension_degree() + k, i);
160 throw Invalid_State(
"McEliece keygen failed - could not bring matrix to row reduced echelon form");
163 auto result = std::make_unique<binary_matrix>(code_length - r, r);
164 for(
size_t i = 0; i < result->rows(); ++i) {
165 for(
size_t j = 0; j < result->columns(); ++j) {
166 if(H.coef(j, perm[i])) {
167 result->toggle_coeff(i, j);
172 std::vector<gf2m> Laux(code_length);
173 for(
size_t i = 0; i < code_length; ++i) {
174 Laux[i] = L[perm[i]];
177 for(
size_t i = 0; i < code_length; ++i) {
185 const size_t codimension = t * ext_deg;
187 if(code_length <= codimension) {
191 auto sp_field = std::make_shared<GF2m_Field>(ext_deg);
194 std::vector<gf2m> L(code_length);
196 for(
size_t i = 0; i != L.size(); i++) {
197 L[i] =
static_cast<gf2m>(i);
199 randomize_support(L, rng);
202 bool success =
false;
203 std::unique_ptr<binary_matrix> R;
210 R = generate_R(L, &g, *sp_field, code_length, t);
216 std::vector<polyn_gf2m> F =
syndrome_init(g, L,
static_cast<int>(code_length));
225 std::vector<uint32_t> H(co32 * code_length);
226 uint32_t* sk = H.data();
227 for(
size_t i = 0; i < code_length; ++i) {
228 for(
size_t l = 0; l < t; ++l) {
229 const size_t k = (l * ext_deg) / 32;
230 const size_t j = (l * ext_deg) % 32;
231 sk[k] ^=
static_cast<uint32_t
>(F[i].get_coef(l)) << j;
232 if(j + ext_deg > 32) {
234 sk[k + 1] ^= F[i].get_coef(l) >> (32 - j);
244 std::vector<gf2m> Linv(code_length);
245 for(
size_t i = 0; i != Linv.size(); ++i) {
246 Linv[L[i]] =
static_cast<gf2m>(i);
248 std::vector<uint8_t> pubmat(R->elem().size() * 4);
249 for(
size_t i = 0; i < R->elem().size(); i++) {
250 store_le(R->elem()[i], &pubmat[i * 4]);
static std::vector< polyn_gf2m > sqrt_mod_init(const polyn_gf2m &g)
int(* final)(unsigned char *, CTX *)
gf2m lex_to_gray(gf2m lex)
std::vector< polyn_gf2m > syndrome_init(const polyn_gf2m &generator, const std::vector< gf2m > &support, int n)
McEliece_PrivateKey generate_mceliece_key(RandomNumberGenerator &rng, size_t ext_deg, size_t code_length, size_t t)
constexpr auto store_le(ParamTs &&... params)
gf2m random_gf2m(RandomNumberGenerator &rng)
std::vector< T, secure_allocator< T > > secure_vector
size_t bit_size_to_32bit_size(size_t bit_size)