13#include <botan/internal/polyn_gf2m.h>
15#include <botan/exceptn.h>
17#include <botan/internal/bit_ops.h>
18#include <botan/internal/code_based_util.h>
19#include <botan/internal/loadstor.h>
26 gf2m result = (a != 0);
33unsigned nlz_16bit(uint16_t x) {
59 int i =
static_cast<int>(this->m_coeff.size()) - 1;
61 uint32_t found_mask = 0;
62 uint32_t tracker_mask = 0xffff;
65 result |= i & found_mask & tracker_mask;
68 tracker_mask = tracker_mask & ~found_mask;
81 if(code_length == 0) {
82 throw Invalid_Argument(
"random_code_element() was supplied a code length of zero");
84 const unsigned nlz = nlz_16bit(code_length - 1);
85 const gf2m mask = (1 << (16 - nlz)) - 1;
92 }
while(result >= code_length);
100 m_deg(-1), m_coeff(d + 1), m_sp_field(sp_field) {}
105void polyn_gf2m::realloc(uint32_t new_size) {
110 m_deg(-1), m_sp_field(sp_field) {
111 if(mem_len %
sizeof(
gf2m)) {
115 uint32_t size = (mem_len /
sizeof(this->m_coeff[0]));
118 for(uint32_t i = 0; i < size; i++) {
120 mem +=
sizeof(this->m_coeff[0]);
122 for(uint32_t i = 0; i < size; i++) {
123 if(this->m_coeff[i] >= (1 << sp_field->get_extension_degree())) {
135 const std::shared_ptr<GF2m_Field>& sp_field) :
136 m_sp_field(sp_field) {
140 polyn_size = degree + 1;
141 if(polyn_size * sp_field->get_extension_degree() > 8 * mem_byte_len) {
142 throw Decoding_Error(
"memory vector for polynomial has wrong size");
145 gf2m ext_deg =
static_cast<gf2m>(this->m_sp_field->get_extension_degree());
146 for(l = 0; l < polyn_size; l++) {
147 k = (l * ext_deg) / 8;
149 j = (l * ext_deg) % 8;
151 if(j + ext_deg > 8) {
152 a ^= mem[k + 1] << (8 - j);
154 if(j + ext_deg > 16) {
155 a ^= mem[k + 2] << (16 - j);
157 a &= ((1 << ext_deg) - 1);
158 (*this).set_coef(l, a);
164void polyn_gf2m::set_to_zero() {
165 clear_mem(&this->m_coeff[0], this->m_coeff.size());
169int polyn_gf2m::get_degree()
const {
170 int d =
static_cast<int>(this->m_coeff.size()) - 1;
171 while((d >= 0) && (this->m_coeff[d] == 0)) {
180gf2m eval_aux(
const gf2m* coeff,
gf2m a,
int d,
const std::shared_ptr<GF2m_Field>& sp_field) {
185 b = sp_field->gf_mul(b, a) ^ coeff[d];
196 return eval_aux(&this->m_coeff[0], a, this->m_deg, this->m_sp_field);
202 std::shared_ptr<GF2m_Field> m_sp_field = g.m_sp_field;
211 for(i = p_degree; d >= 0; --i, --d) {
213 gf2m lb = m_sp_field->gf_mul_rrn(la, p[i]);
215 p[j + d] ^= m_sp_field->gf_mul_zrz(lb, g[j]);
217 (*&p).set_coef(i, 0);
227std::vector<polyn_gf2m> polyn_gf2m::sqmod_init(
const polyn_gf2m& g) {
228 std::vector<polyn_gf2m> sq;
230 if(signed_deg <= 0) {
234 const uint32_t d =
static_cast<uint32_t
>(signed_deg);
235 uint32_t t = g.m_deg;
238 for(i = 0; i < t; ++i) {
241 for(i = 0; i < d / 2; ++i) {
242 sq[i].set_degree(2 * i);
243 (*&sq[i]).set_coef(2 * i, 1);
248 copy_mem(&sq[i].m_coeff[0] + 2, &sq[i - 1].m_coeff[0], d);
249 sq[i].set_degree(sq[i - 1].get_degree() + 2);
250 polyn_gf2m::remainder(sq[i], g);
258polyn_gf2m polyn_gf2m::sqmod(
const std::vector<polyn_gf2m>& sq,
int d) {
261 std::shared_ptr<GF2m_Field> sp_field = this->m_sp_field;
265 for(i = 0; i < d / 2; ++i) {
266 (*&result).set_coef(i * 2, sp_field->gf_square((*
this)[i]));
271 gf2m lpi = (*this)[i];
273 lpi = sp_field->gf_log(lpi);
274 la = sp_field->gf_mul_rrr(lpi, lpi);
275 for(j = 0; j < d; ++j) {
276 result[j] ^= sp_field->gf_mul_zrz(la, sq[i][j]);
282 result.set_degree(d - 1);
294 polyn_gf2m::remainder(p1, p2);
295 return polyn_gf2m::gcd_aux(p2, p1);
299polyn_gf2m polyn_gf2m::gcd(
const polyn_gf2m& p1,
const polyn_gf2m& p2) {
302 if(a.get_degree() <
b.get_degree()) {
303 return polyn_gf2m(polyn_gf2m::gcd_aux(b, a));
305 return polyn_gf2m(polyn_gf2m::gcd_aux(a, b));
313 const size_t ext_deg = g.m_sp_field->get_extension_degree();
315 std::vector<polyn_gf2m> u = polyn_gf2m::sqmod_init(g);
320 (*&p).set_coef(1, 1);
321 size_t result =
static_cast<size_t>(d);
322 for(
size_t i = 1; i <= (d / 2) * ext_deg; ++i) {
324 if((i % ext_deg) == 0) {
327 s = polyn_gf2m::gcd(g, r);
330 result = i / ext_deg;
345void polyn_gf2m::patchup_deg_secure(uint32_t trgt_deg,
gf2m patch_elem) {
347 if(this->m_coeff.size() < trgt_deg) {
350 for(i = 0; i < this->m_coeff.size(); i++) {
351 uint32_t equal, equal_mask;
352 this->m_coeff[i] |= patch_elem;
353 equal = (i == trgt_deg);
355 patch_elem &= ~equal_mask;
357 this->calc_degree_secure();
362std::pair<polyn_gf2m, polyn_gf2m> polyn_gf2m::eea_with_coefficients(
const polyn_gf2m& p,
365 std::shared_ptr<GF2m_Field> m_sp_field = g.m_sp_field;
366 int i, j, dr, du, delta;
385 (*&u1).set_coef(0, 1);
398 while(dr >= break_deg) {
399 for(j = delta; j >= 0; --j) {
400 a = m_sp_field->gf_div(r0[dr + j], r1[dr]);
402 gf2m la = m_sp_field->gf_log(a);
404 for(i = 0; i <= du; ++i) {
405 u0[i + j] ^= m_sp_field->gf_mul_zrz(la, u1[i]);
408 for(i = 0; i <= dr; ++i) {
409 r0[i + j] ^= m_sp_field->gf_mul_zrz(la, r1[i]);
420 volatile gf2m fake_elem = 0x01;
421 volatile gf2m cond1, cond2;
432 cond1 = cond1 & cond2;
435 gf2m mask = generate_gf2m_mask(cond1);
436 fake_elem = fake_elem & mask;
441 volatile gf2m fake_elem = 0x00;
442 volatile uint32_t trgt_deg = 0;
476 int cond_u1 = m_sp_field->gf_mul(u0.m_coeff[1], m_sp_field->gf_inv(r0.m_coeff[0])) == 1;
479 int cond_u3 = u0.m_coeff[3] == 0;
481 cond_r &= (cond_u1 & cond_u3);
485 fake_elem = 1 & mask;
489 int cond_u1 = m_sp_field->gf_mul(u0.m_coeff[1], m_sp_field->gf_inv(r0.m_coeff[0])) == 1;
490 int cond_u3 = u0.m_coeff[3] == 0;
492 int cond_u5 = u0.m_coeff[5] == 0;
494 cond_r &= (cond_u1 & cond_u3 & cond_u5);
497 fake_elem = 1 & mask;
501 int cond_u1 = m_sp_field->gf_mul(u0[1], m_sp_field->gf_inv(r0[0])) == 1;
502 int cond_u3 = u0.m_coeff[3] == 0;
504 int cond_u5 = u0.m_coeff[5] == 0;
506 int cond_u7 = u0.m_coeff[7] == 0;
508 cond_r &= (cond_u1 & cond_u3 & cond_u5 & cond_u7);
511 fake_elem = 1 & mask;
525 while(r1[dr - delta] == 0) {
535 return std::make_pair(u1, r1);
539 m_deg(static_cast<int>(t)), m_coeff(t + 1), m_sp_field(sp_field) {
542 for(
size_t i = 0; i < t; ++i) {
554void polyn_gf2m::poly_shiftmod(
const polyn_gf2m& g) {
556 throw Invalid_Argument(
"shiftmod cannot be called on polynomials of degree 1 or less");
558 std::shared_ptr<GF2m_Field> field = g.m_sp_field;
561 gf2m a = field->gf_div(this->m_coeff[t - 1], g.m_coeff[t]);
562 for(
int i = t - 1; i > 0; --i) {
563 this->m_coeff[i] = this->m_coeff[i - 1] ^ this->m_sp_field->gf_mul(a, g.m_coeff[i]);
565 this->m_coeff[0] = field->gf_mul(a, g.m_coeff[0]);
570 uint32_t nb_polyn_sqrt_mat;
571 std::shared_ptr<GF2m_Field> m_sp_field = g.m_sp_field;
572 std::vector<polyn_gf2m> result;
574 nb_polyn_sqrt_mat = t / 2;
583 for(i = 0; i < t * m_sp_field->get_extension_degree() - 1; ++i) {
593 for(i = 0; i < nb_polyn_sqrt_mat; ++i) {
599 for(i = 1; i < nb_polyn_sqrt_mat; i++) {
600 result[i] = result[i - 1];
601 result[i].poly_shiftmod(g);
602 result[i].get_degree();
612 std::shared_ptr<GF2m_Field> m_sp_field = generator.
get_sp_field();
614 std::vector<polyn_gf2m> result;
620 for(j = 0; j < n; j++) {
621 result.push_back(
polyn_gf2m(t - 1, m_sp_field));
623 (*&result[j]).set_coef(t - 1, 1);
624 for(i = t - 2; i >= 0; i--) {
625 (*&result[j]).set_coef(i, (generator)[i + 1] ^ m_sp_field->gf_mul(
lex_to_gray(support[j]), result[j][i + 1]));
627 a = ((generator)[0] ^ m_sp_field->gf_mul(
lex_to_gray(support[j]), result[j][0]));
628 for(i = 0; i < t; i++) {
629 (*&result[j]).set_coef(i, m_sp_field->gf_div(result[j][i], a));
636 m_sp_field(sp_field) {
637 if(encoded.size() % 2) {
638 throw Decoding_Error(
"encoded polynomial has odd length");
640 for(uint32_t i = 0; i < encoded.size(); i += 2) {
641 gf2m el = (encoded[i] << 8) | encoded[i + 1];
642 m_coeff.push_back(el);
656 uint32_t len = m_deg + 1;
657 for(
unsigned i = 0; i < len; i++) {
666 std::swap(this->m_deg, other.m_deg);
667 std::swap(this->m_sp_field, other.m_sp_field);
668 std::swap(this->m_coeff, other.m_coeff);
672 if(m_deg != other.m_deg || m_coeff != other.m_coeff) {
#define BOTAN_ASSERT(expr, assertion_made)
void randomize(std::span< uint8_t > output)
secure_vector< uint8_t > encode() const
std::shared_ptr< GF2m_Field > get_sp_field() const
void set_coef(size_t i, gf2m v)
void swap(polyn_gf2m &other) noexcept
gf2m get_lead_coef() const
void patchup_deg_secure(uint32_t trgt_deg, gf2m patch_elem)
static std::vector< polyn_gf2m > sqmod_init(const polyn_gf2m &g)
static std::vector< polyn_gf2m > sqrt_mod_init(const polyn_gf2m &g)
int calc_degree_secure() const
bool operator==(const polyn_gf2m &other) const
polyn_gf2m sqmod(const std::vector< polyn_gf2m > &sq, int d)
static size_t degppf(const polyn_gf2m &g)
constexpr uint8_t get_byte(T input)
gf2m lex_to_gray(gf2m lex)
uint16_t expand_mask_16bit(T tst)
gf2m random_code_element(uint16_t code_length, RandomNumberGenerator &rng)
std::vector< polyn_gf2m > syndrome_init(const polyn_gf2m &generator, const std::vector< gf2m > &support, int n)
gf2m random_gf2m(RandomNumberGenerator &rng)
std::vector< T, secure_allocator< T > > secure_vector
gf2m decode_gf2m(const uint8_t *mem)
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr void clear_mem(T *ptr, size_t n)
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)