13#include <botan/internal/polyn_gf2m.h>
14#include <botan/internal/code_based_util.h>
15#include <botan/internal/bit_ops.h>
17#include <botan/exceptn.h>
18#include <botan/internal/loadstor.h>
26 gf2m result = (a != 0);
33unsigned nlz_16bit(uint16_t x)
38 if(x <= 0x00FF) {n = n + 8; x = x << 8;}
39 if(x <= 0x0FFF) {n = n + 4; x = x << 4;}
40 if(x <= 0x3FFF) {n = n + 2; x = x << 2;}
41 if(x <= 0x7FFF) {n = n + 1;}
48 int i =
static_cast<int>(this->m_coeff.size()) - 1;
50 uint32_t found_mask = 0;
51 uint32_t tracker_mask = 0xffff;
55 result |= i & found_mask & tracker_mask;
58 tracker_mask = tracker_mask & ~found_mask;
75 throw Invalid_Argument(
"random_code_element() was supplied a code length of zero");
77 const unsigned nlz = nlz_16bit(code_length-1);
78 const gf2m mask = (1 << (16-nlz)) - 1;
86 }
while(result >= code_length);
103void polyn_gf2m::realloc(uint32_t new_size)
109 m_deg(-1), m_sp_field(sp_field)
111 if(mem_len %
sizeof(
gf2m))
116 uint32_t size = (mem_len /
sizeof(this->m_coeff[0])) ;
119 for(uint32_t i = 0; i < size; i++)
122 mem +=
sizeof(this->m_coeff[0]);
124 for(uint32_t i = 0; i < size; i++)
126 if(this->m_coeff[i] >= (1 << sp_field->get_extension_degree()))
136 m_deg(-1), m_coeff(1), m_sp_field(sp_field)
140 :m_sp_field(sp_field)
145 polyn_size = degree + 1;
146 if(polyn_size * sp_field->get_extension_degree() > 8 * mem_byte_len)
148 throw Decoding_Error(
"memory vector for polynomial has wrong size");
151 gf2m ext_deg =
static_cast<gf2m>(this->m_sp_field->get_extension_degree());
152 for (l = 0; l < polyn_size; l++)
154 k = (l * ext_deg) / 8;
156 j = (l * ext_deg) % 8;
160 a ^= mem[k + 1] << (8- j);
164 a ^= mem[k + 2] << (16- j);
166 a &= ((1 << ext_deg) - 1);
167 (*this).set_coef( l, a);
175 clear_mem(&this->m_coeff[0], this->m_coeff.size());
181 int d =
static_cast<int>(this->m_coeff.size()) - 1;
182 while ((d >= 0) && (this->m_coeff[d] == 0))
189static gf2m eval_aux(
const gf2m * coeff,
gf2m a,
int d,
const std::shared_ptr<GF2m_Field>& sp_field)
196 b = sp_field->gf_mul(b, a) ^ coeff[d];
207 return eval_aux(&this->m_coeff[0], a, this->m_deg, this->m_sp_field);
215 std::shared_ptr<GF2m_Field> m_sp_field = g.m_sp_field;
224 for (i = p_degree; d >= 0; --i, --d) {
226 gf2m lb = m_sp_field->gf_mul_rrn(la, p[i]);
229 p[j+d] ^= m_sp_field->gf_mul_zrz(lb, g[j]);
242 std::vector<polyn_gf2m> sq;
247 const uint32_t d =
static_cast<uint32_t
>(signed_deg);
248 uint32_t t = g.m_deg;
251 for (i = 0; i < t; ++i)
255 for (i = 0; i < d / 2; ++i)
257 sq[i].set_degree( 2 * i);
264 copy_mem(&sq[i].m_coeff[0] + 2, &sq[i - 1].m_coeff[0], d);
265 sq[i].set_degree( sq[i - 1].
get_degree() + 2);
266 polyn_gf2m::remainder(sq[i], g);
278 std::shared_ptr<GF2m_Field> sp_field = this->m_sp_field;
282 for (i = 0; i < d / 2; ++i)
284 (*&result).
set_coef( i * 2, sp_field->gf_square((*
this)[i]));
290 gf2m lpi = (*this)[i];
293 lpi = sp_field->gf_log(lpi);
294 la = sp_field->gf_mul_rrr(lpi, lpi);
295 for (j = 0; j < d; ++j)
297 result[j] ^= sp_field->gf_mul_zrz(la, sq[i][j]);
303 result.set_degree( d - 1);
316 polyn_gf2m::remainder(p1, p2);
317 return polyn_gf2m::gcd_aux(p2, p1);
322polyn_gf2m polyn_gf2m::gcd(polyn_gf2m
const& p1, polyn_gf2m
const& p2)
326 if (a.get_degree() < b.get_degree())
345 const size_t ext_deg = g.m_sp_field->get_extension_degree();
353 size_t result =
static_cast<size_t>(d);
354 for(
size_t i = 1; i <= (d / 2) * ext_deg; ++i)
357 if ((i % ext_deg) == 0)
361 s = polyn_gf2m::gcd( g, r);
365 result = i / ext_deg;
383 if(this->m_coeff.size() < trgt_deg)
387 for(i = 0; i < this->m_coeff.size(); i++)
389 uint32_t equal, equal_mask;
390 this->m_coeff[i] |= patch_elem;
391 equal = (i == trgt_deg);
393 patch_elem &= ~equal_mask;
402 std::shared_ptr<GF2m_Field> m_sp_field = g.m_sp_field;
403 int i, j, dr, du, delta;
437 while (dr >= break_deg)
440 for (j = delta; j >= 0; --j)
442 a = m_sp_field->gf_div(r0[dr + j], r1[dr]);
445 gf2m la = m_sp_field->gf_log(a);
447 for (i = 0; i <= du; ++i)
449 u0[i + j] ^= m_sp_field->gf_mul_zrz(la, u1[i]);
452 for (i = 0; i <= dr; ++i)
454 r0[i + j] ^= m_sp_field->gf_mul_zrz(la, r1[i]);
465 volatile gf2m fake_elem = 0x01;
466 volatile gf2m cond1, cond2;
480 cond1 = cond1 & cond2;
483 gf2m mask = generate_gf2m_mask(cond1);
484 fake_elem = fake_elem & mask;
489 volatile gf2m fake_elem = 0x00;
490 volatile uint32_t trgt_deg = 0;
525 int cond_u1 = m_sp_field->gf_mul(u0.m_coeff[1], m_sp_field->gf_inv(r0.m_coeff[0])) == 1;
528 int cond_u3 = u0.m_coeff[3] == 0;
530 cond_r &= (cond_u1 & cond_u3);
534 fake_elem = 1 & mask;
540 int cond_u1 = m_sp_field->gf_mul(u0.m_coeff[1], m_sp_field->gf_inv(r0.m_coeff[0])) == 1;
541 int cond_u3 = u0.m_coeff[3] == 0;
543 int cond_u5 = u0.m_coeff[5] == 0;
545 cond_r &= (cond_u1 & cond_u3 & cond_u5);
548 fake_elem = 1 & mask;
554 int cond_u1 = m_sp_field->gf_mul(u0[1], m_sp_field->gf_inv(r0[0])) == 1;
555 int cond_u3 = u0.m_coeff[3] == 0;
557 int cond_u5 = u0.m_coeff[5] == 0;
559 int cond_u7 = u0.m_coeff[7] == 0;
561 cond_r &= (cond_u1 & cond_u3 & cond_u5 & cond_u7);
564 fake_elem = 1 & mask;
569 aux = r0; r0 = r1; r1 = aux;
570 aux = u0; u0 = u1; u1 = aux;
574 while (r1[dr - delta] == 0)
587 return std::make_pair(u1,r1);
591 :m_deg(static_cast<int>(t)),
598 for(
size_t i = 0; i < t; ++i)
610void polyn_gf2m::poly_shiftmod(
const polyn_gf2m & g)
614 throw Invalid_Argument(
"shiftmod cannot be called on polynomials of degree 1 or less");
616 std::shared_ptr<GF2m_Field> field = g.m_sp_field;
619 gf2m a = field->gf_div(this->m_coeff[t-1], g.m_coeff[t]);
620 for (
int i = t - 1; i > 0; --i)
622 this->m_coeff[i] = this->m_coeff[i - 1] ^ this->m_sp_field->gf_mul(a, g.m_coeff[i]);
624 this->m_coeff[0] = field->gf_mul(a, g.m_coeff[0]);
630 uint32_t nb_polyn_sqrt_mat;
631 std::shared_ptr<GF2m_Field> m_sp_field = g.m_sp_field;
632 std::vector<polyn_gf2m> result;
634 nb_polyn_sqrt_mat = t/2;
644 for (i = 0; i < t * m_sp_field->get_extension_degree() - 1; ++i)
655 for (i = 0; i < nb_polyn_sqrt_mat; ++i)
662 for(i = 1; i < nb_polyn_sqrt_mat; i++)
664 result[i] = result[i - 1];
665 result[i].poly_shiftmod(g);
666 result[i].get_degree();
678 std::shared_ptr<GF2m_Field> m_sp_field = generator.
get_sp_field();
680 std::vector<polyn_gf2m> result;
688 result.push_back(
polyn_gf2m( t-1, m_sp_field));
690 (*&result[j]).set_coef(t-1,1);
693 (*&result[j]).set_coef(i, (generator)[i+1] ^
694 m_sp_field->gf_mul(
lex_to_gray(support[j]),result[j][i+1]));
696 a = ((generator)[0] ^ m_sp_field->gf_mul(
lex_to_gray(support[j]),result[j][0]));
699 (*&result[j]).set_coef(i, m_sp_field->gf_div(result[j][i],a));
706 const std::shared_ptr<GF2m_Field>& sp_field) :
709 if(encoded.size() % 2)
713 for(uint32_t i = 0; i < encoded.size(); i += 2)
715 gf2m el = (encoded[i] << 8) | encoded[i + 1];
716 m_coeff.push_back(el);
732 uint32_t len = m_deg+1;
733 for(
unsigned i = 0; i < len; i++)
736 result.push_back(get_byte<0>(m_coeff[i]));
737 result.push_back(get_byte<1>(m_coeff[i]));
744 std::swap(this->m_deg, other.m_deg);
745 std::swap(this->m_sp_field, other.m_sp_field);
746 std::swap(this->m_coeff, other.m_coeff);
751 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
static std::pair< polyn_gf2m, polyn_gf2m > eea_with_coefficients(const polyn_gf2m &p, const polyn_gf2m &g, int break_deg)
void set_coef(size_t i, gf2m v)
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)
void swap(polyn_gf2m &other)
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)
gf2m lex_to_gray(gf2m lex)
std::vector< polyn_gf2m > syndrome_init(polyn_gf2m const &generator, std::vector< gf2m > const &support, int n)
uint16_t expand_mask_16bit(T tst)
gf2m random_code_element(uint16_t code_length, RandomNumberGenerator &rng)
constexpr void copy_mem(T *out, const T *in, size_t n)
gf2m random_gf2m(RandomNumberGenerator &rng)
gf2m decode_gf2m(const uint8_t *mem)
std::vector< T, secure_allocator< T > > secure_vector
constexpr void clear_mem(T *ptr, size_t n)
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)