Botan 3.6.1
Crypto and TLS for C&
polyn_gf2m.cpp
Go to the documentation of this file.
1/*
2 * (C) Copyright Projet SECRET, INRIA, Rocquencourt
3 * (C) Bhaskar Biswas and Nicolas Sendrier
4 *
5 * (C) 2014 cryptosource GmbH
6 * (C) 2014 Falko Strenzke fstrenzke@cryptosource.de
7 * (C) 2015 Jack Lloyd
8 *
9 * Botan is released under the Simplified BSD License (see license.txt)
10 *
11 */
12
13#include <botan/internal/polyn_gf2m.h>
14
15#include <botan/exceptn.h>
16#include <botan/rng.h>
17#include <botan/internal/bit_ops.h>
18#include <botan/internal/code_based_util.h>
19#include <botan/internal/loadstor.h>
20
21namespace Botan {
22
23namespace {
24
25gf2m generate_gf2m_mask(gf2m a) {
26 gf2m result = (a != 0);
27 return ~(result - 1);
28}
29
30/**
31* number of leading zeros
32*/
33unsigned nlz_16bit(uint16_t x) {
34 unsigned n;
35 if(x == 0) {
36 return 16;
37 }
38 n = 0;
39 if(x <= 0x00FF) {
40 n = n + 8;
41 x = x << 8;
42 }
43 if(x <= 0x0FFF) {
44 n = n + 4;
45 x = x << 4;
46 }
47 if(x <= 0x3FFF) {
48 n = n + 2;
49 x = x << 2;
50 }
51 if(x <= 0x7FFF) {
52 n = n + 1;
53 }
54 return n;
55}
56} // namespace
57
59 int i = static_cast<int>(this->m_coeff.size()) - 1;
60 int result = 0;
61 uint32_t found_mask = 0;
62 uint32_t tracker_mask = 0xffff;
63 for(; i >= 0; i--) {
64 found_mask = expand_mask_16bit(this->m_coeff[i]);
65 result |= i & found_mask & tracker_mask;
66 // tracker mask shall become zero once found mask is set
67 // it shall remain zero from then on
68 tracker_mask = tracker_mask & ~found_mask;
69 }
70 const_cast<polyn_gf2m*>(this)->m_deg = result;
71 return result;
72}
73
75 uint8_t b[2];
76 rng.randomize(b, sizeof(b));
77 return make_uint16(b[1], b[0]);
78}
79
80gf2m random_code_element(uint16_t code_length, RandomNumberGenerator& rng) {
81 if(code_length == 0) {
82 throw Invalid_Argument("random_code_element() was supplied a code length of zero");
83 }
84 const unsigned nlz = nlz_16bit(code_length - 1);
85 const gf2m mask = (1 << (16 - nlz)) - 1;
86
87 gf2m result;
88
89 do {
90 result = random_gf2m(rng);
91 result &= mask;
92 } while(result >= code_length); // rejection sampling
93
94 return result;
95}
96
97polyn_gf2m::polyn_gf2m(const polyn_gf2m& other) = default;
98
99polyn_gf2m::polyn_gf2m(int d, const std::shared_ptr<GF2m_Field>& sp_field) :
100 m_deg(-1), m_coeff(d + 1), m_sp_field(sp_field) {}
101
102/**
103* doesn't save coefficients:
104*/
105void polyn_gf2m::realloc(uint32_t new_size) {
106 this->m_coeff = secure_vector<gf2m>(new_size);
107}
108
109polyn_gf2m::polyn_gf2m(const uint8_t* mem, uint32_t mem_len, const std::shared_ptr<GF2m_Field>& sp_field) :
110 m_deg(-1), m_sp_field(sp_field) {
111 if(mem_len % sizeof(gf2m)) {
112 throw Decoding_Error("illegal length of memory to decode ");
113 }
114
115 uint32_t size = (mem_len / sizeof(this->m_coeff[0]));
116 this->m_coeff = secure_vector<gf2m>(size);
117 this->m_deg = -1;
118 for(uint32_t i = 0; i < size; i++) {
119 this->m_coeff[i] = decode_gf2m(mem);
120 mem += sizeof(this->m_coeff[0]);
121 }
122 for(uint32_t i = 0; i < size; i++) {
123 if(this->m_coeff[i] >= (1 << sp_field->get_extension_degree())) {
124 throw Decoding_Error("error decoding polynomial");
125 }
126 }
127 this->get_degree();
128}
129
130polyn_gf2m::polyn_gf2m(const std::shared_ptr<GF2m_Field>& sp_field) : m_deg(-1), m_coeff(1), m_sp_field(sp_field) {}
131
133 const uint8_t* mem,
134 size_t mem_byte_len,
135 const std::shared_ptr<GF2m_Field>& sp_field) :
136 m_sp_field(sp_field) {
137 uint32_t j, k, l;
138 gf2m a;
139 uint32_t polyn_size;
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");
143 }
144 this->m_coeff = secure_vector<gf2m>(degree + 1);
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;
148
149 j = (l * ext_deg) % 8;
150 a = mem[k] >> j;
151 if(j + ext_deg > 8) {
152 a ^= mem[k + 1] << (8 - j);
153 }
154 if(j + ext_deg > 16) {
155 a ^= mem[k + 2] << (16 - j);
156 }
157 a &= ((1 << ext_deg) - 1);
158 (*this).set_coef(l, a);
159 }
160
161 this->get_degree();
162}
163
164void polyn_gf2m::set_to_zero() {
165 clear_mem(&this->m_coeff[0], this->m_coeff.size());
166 this->m_deg = -1;
167}
168
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)) {
172 --d;
173 }
174 const_cast<polyn_gf2m*>(this)->m_deg = d;
175 return d;
176}
177
178namespace {
179
180gf2m eval_aux(const gf2m* /*restrict*/ coeff, gf2m a, int d, const std::shared_ptr<GF2m_Field>& sp_field) {
181 gf2m b;
182 b = coeff[d--];
183 for(; d >= 0; --d) {
184 if(b != 0) {
185 b = sp_field->gf_mul(b, a) ^ coeff[d];
186 } else {
187 b = coeff[d];
188 }
189 }
190 return b;
191}
192
193} // namespace
194
195gf2m polyn_gf2m::eval(gf2m a) {
196 return eval_aux(&this->m_coeff[0], a, this->m_deg, this->m_sp_field);
197}
198
199// p will contain it's remainder modulo g
200void polyn_gf2m::remainder(polyn_gf2m& p, const polyn_gf2m& g) {
201 int i, j, d;
202 std::shared_ptr<GF2m_Field> m_sp_field = g.m_sp_field;
203 d = p.get_degree() - g.get_degree();
204 if(d >= 0) {
205 gf2m la = m_sp_field->gf_inv_rn(g.get_lead_coef());
206
207 const int p_degree = p.get_degree();
208
209 BOTAN_ASSERT(p_degree > 0, "Valid polynomial");
210
211 for(i = p_degree; d >= 0; --i, --d) {
212 if(p[i] != 0) {
213 gf2m lb = m_sp_field->gf_mul_rrn(la, p[i]);
214 for(j = 0; j < g.get_degree(); ++j) {
215 p[j + d] ^= m_sp_field->gf_mul_zrz(lb, g[j]);
216 }
217 (*&p).set_coef(i, 0);
218 }
219 }
220 p.set_degree(g.get_degree() - 1);
221 while((p.get_degree() >= 0) && (p[p.get_degree()] == 0)) {
222 p.set_degree(p.get_degree() - 1);
223 }
224 }
225}
226
227std::vector<polyn_gf2m> polyn_gf2m::sqmod_init(const polyn_gf2m& g) {
228 std::vector<polyn_gf2m> sq;
229 const int signed_deg = g.get_degree();
230 if(signed_deg <= 0) {
231 throw Invalid_Argument("cannot compute sqmod for such low degree");
232 }
233
234 const uint32_t d = static_cast<uint32_t>(signed_deg);
235 uint32_t t = g.m_deg;
236 // create t zero polynomials
237 uint32_t i;
238 for(i = 0; i < t; ++i) {
239 sq.push_back(polyn_gf2m(t + 1, g.get_sp_field()));
240 }
241 for(i = 0; i < d / 2; ++i) {
242 sq[i].set_degree(2 * i);
243 (*&sq[i]).set_coef(2 * i, 1);
244 }
245
246 for(; i < d; ++i) {
247 clear_mem(&sq[i].m_coeff[0], 2);
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);
251 }
252 return sq;
253}
254
255/*Modulo p square of a certain polynomial g, sq[] contains the square
256Modulo g of the base canonical polynomials of degree < d, where d is
257the degree of G. The table sq[] will be calculated by polyn_gf2m_sqmod_init*/
258polyn_gf2m polyn_gf2m::sqmod(const std::vector<polyn_gf2m>& sq, int d) {
259 int i, j;
260 gf2m la;
261 std::shared_ptr<GF2m_Field> sp_field = this->m_sp_field;
262
263 polyn_gf2m result(d - 1, sp_field);
264 // terms of low degree
265 for(i = 0; i < d / 2; ++i) {
266 (*&result).set_coef(i * 2, sp_field->gf_square((*this)[i]));
267 }
268
269 // terms of high degree
270 for(; i < d; ++i) {
271 gf2m lpi = (*this)[i];
272 if(lpi != 0) {
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]);
277 }
278 }
279 }
280
281 // Update degre
282 result.set_degree(d - 1);
283 while((result.get_degree() >= 0) && (result[result.get_degree()] == 0)) {
284 result.set_degree(result.get_degree() - 1);
285 }
286 return result;
287}
288
289// destructive
290polyn_gf2m polyn_gf2m::gcd_aux(polyn_gf2m& p1, polyn_gf2m& p2) {
291 if(p2.get_degree() == -1) {
292 return p1;
293 } else {
294 polyn_gf2m::remainder(p1, p2);
295 return polyn_gf2m::gcd_aux(p2, p1);
296 }
297}
298
299polyn_gf2m polyn_gf2m::gcd(const polyn_gf2m& p1, const polyn_gf2m& p2) {
300 polyn_gf2m a(p1);
301 polyn_gf2m b(p2);
302 if(a.get_degree() < b.get_degree()) {
303 return polyn_gf2m(polyn_gf2m::gcd_aux(b, a));
304 } else {
305 return polyn_gf2m(polyn_gf2m::gcd_aux(a, b));
306 }
307}
308
309// Returns the degree of the smallest factor
310size_t polyn_gf2m::degppf(const polyn_gf2m& g) {
312
313 const size_t ext_deg = g.m_sp_field->get_extension_degree();
314 const int d = g.get_degree();
315 std::vector<polyn_gf2m> u = polyn_gf2m::sqmod_init(g);
316
317 polyn_gf2m p(d - 1, g.m_sp_field);
318
319 p.set_degree(1);
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) {
323 polyn_gf2m r = p.sqmod(u, d);
324 if((i % ext_deg) == 0) {
325 r[1] ^= 1;
326 r.get_degree(); // The degree may change
327 s = polyn_gf2m::gcd(g, r);
328
329 if(s.get_degree() > 0) {
330 result = i / ext_deg;
331 break;
332 }
333 r[1] ^= 1;
334 r.get_degree(); // The degree may change
335 }
336 // No need for the exchange s
337 s = p;
338 p = r;
339 r = s;
340 }
341
342 return result;
343}
344
345void polyn_gf2m::patchup_deg_secure(uint32_t trgt_deg, gf2m patch_elem) {
346 uint32_t i;
347 if(this->m_coeff.size() < trgt_deg) {
348 return;
349 }
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);
354 equal_mask = expand_mask_16bit(equal);
355 patch_elem &= ~equal_mask;
356 }
357 this->calc_degree_secure();
358}
359
360// We suppose m_deg(g) >= m_deg(p)
361// v is the problem
362std::pair<polyn_gf2m, polyn_gf2m> polyn_gf2m::eea_with_coefficients(const polyn_gf2m& p,
363 const polyn_gf2m& g,
364 int break_deg) {
365 std::shared_ptr<GF2m_Field> m_sp_field = g.m_sp_field;
366 int i, j, dr, du, delta;
367 gf2m a;
368 polyn_gf2m aux;
369
370 // initialisation of the local variables
371 // r0 <- g, r1 <- p, u0 <- 0, u1 <- 1
372 dr = g.get_degree();
373
374 BOTAN_ASSERT(dr > 3, "Valid polynomial");
375
376 polyn_gf2m r0(dr, g.m_sp_field);
377 polyn_gf2m r1(dr - 1, g.m_sp_field);
378 polyn_gf2m u0(dr - 1, g.m_sp_field);
379 polyn_gf2m u1(dr - 1, g.m_sp_field);
380
381 r0 = g;
382 r1 = p;
383 u0.set_to_zero();
384 u1.set_to_zero();
385 (*&u1).set_coef(0, 1);
386 u1.set_degree(0);
387
388 // invariants:
389 // r1 = u1 * p + v1 * g
390 // r0 = u0 * p + v0 * g
391 // and m_deg(u1) = m_deg(g) - m_deg(r0)
392 // It stops when m_deg (r1) <t (m_deg (r0)> = t)
393 // And therefore m_deg (u1) = m_deg (g) - m_deg (r0) <m_deg (g) - break_deg
394 du = 0;
395 dr = r1.get_degree();
396 delta = r0.get_degree() - dr;
397
398 while(dr >= break_deg) {
399 for(j = delta; j >= 0; --j) {
400 a = m_sp_field->gf_div(r0[dr + j], r1[dr]);
401 if(a != 0) {
402 gf2m la = m_sp_field->gf_log(a);
403 // u0(z) <- u0(z) + a * u1(z) * z^j
404 for(i = 0; i <= du; ++i) {
405 u0[i + j] ^= m_sp_field->gf_mul_zrz(la, u1[i]);
406 }
407 // r0(z) <- r0(z) + a * r1(z) * z^j
408 for(i = 0; i <= dr; ++i) {
409 r0[i + j] ^= m_sp_field->gf_mul_zrz(la, r1[i]);
410 }
411 }
412 } // end loop over j
413
414 if(break_deg != 1) /* key eq. solving */
415 {
416 /* [ssms_icisc09] Countermeasure
417 * d_break from paper equals break_deg - 1
418 * */
419
420 volatile gf2m fake_elem = 0x01;
421 volatile gf2m cond1, cond2;
422 int trgt_deg = r1.get_degree() - 1;
425 if(!(g.get_degree() % 2)) {
426 /* t even */
427 cond1 = r0.get_degree() < break_deg - 1;
428 } else {
429 /* t odd */
430 cond1 = r0.get_degree() < break_deg;
431 cond2 = u0.get_degree() < break_deg - 1;
432 cond1 = cond1 & cond2;
433 }
434 /* expand cond1 to a full mask */
435 gf2m mask = generate_gf2m_mask(cond1);
436 fake_elem = fake_elem & mask;
437 r0.patchup_deg_secure(trgt_deg, fake_elem);
438 }
439 if(break_deg == 1) /* syndrome inversion */
440 {
441 volatile gf2m fake_elem = 0x00;
442 volatile uint32_t trgt_deg = 0;
445 /**
446 * countermeasure against the low weight attacks for w=4, w=6 and w=8.
447 * Higher values are not covered since for w=8 we already have a
448 * probability for a positive of 1/n^3 from random ciphertexts with the
449 * given weight. For w = 10 it would be 1/n^4 and so on. Thus attacks
450 * based on such high values of w are considered impractical.
451 *
452 * The outer test for the degree of u ( Omega in the paper ) needs not to
453 * be disguised. Each of the three is performed at most once per EEA
454 * (syndrome inversion) execution, the attacker knows this already when
455 * preparing the ciphertext with the given weight. Inside these three
456 * cases however, we must use timing neutral (branch free) operations to
457 * implement the condition detection and the counteractions.
458 *
459 */
460 if(u0.get_degree() == 4) {
461 uint32_t mask = 0;
462 /**
463 * Condition that the EEA would break now
464 */
465 int cond_r = r0.get_degree() == 0;
466 /**
467 * Now come the conditions for all odd coefficients of this sigma
468 * candiate. If they are all fulfilled, then we know that we have a low
469 * weight error vector, since the key-equation solving EEA is skipped if
470 * the degree of tau^2 is low (=m_deg(u0)) and all its odd cofficients are
471 * zero (they would cause "full-length" contributions from the square
472 * root computation).
473 */
474 // Condition for the coefficient to Y to be cancelled out by the
475 // addition of Y before the square root computation:
476 int cond_u1 = m_sp_field->gf_mul(u0.m_coeff[1], m_sp_field->gf_inv(r0.m_coeff[0])) == 1;
477
478 // Condition sigma_3 = 0:
479 int cond_u3 = u0.m_coeff[3] == 0;
480 // combine the conditions:
481 cond_r &= (cond_u1 & cond_u3);
482 // mask generation:
483 mask = expand_mask_16bit(cond_r);
484 trgt_deg = 2 & mask;
485 fake_elem = 1 & mask;
486 } else if(u0.get_degree() == 6) {
487 uint32_t mask = 0;
488 int cond_r = r0.get_degree() == 0;
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;
491
492 int cond_u5 = u0.m_coeff[5] == 0;
493
494 cond_r &= (cond_u1 & cond_u3 & cond_u5);
495 mask = expand_mask_16bit(cond_r);
496 trgt_deg = 4 & mask;
497 fake_elem = 1 & mask;
498 } else if(u0.get_degree() == 8) {
499 uint32_t mask = 0;
500 int cond_r = r0.get_degree() == 0;
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;
503
504 int cond_u5 = u0.m_coeff[5] == 0;
505
506 int cond_u7 = u0.m_coeff[7] == 0;
507
508 cond_r &= (cond_u1 & cond_u3 & cond_u5 & cond_u7);
509 mask = expand_mask_16bit(cond_r);
510 trgt_deg = 6 & mask;
511 fake_elem = 1 & mask;
512 }
513 r0.patchup_deg_secure(trgt_deg, fake_elem);
514 }
515 // exchange
516 aux = r0;
517 r0 = r1;
518 r1 = aux;
519 aux = u0;
520 u0 = u1;
521 u1 = aux;
522
523 du = du + delta;
524 delta = 1;
525 while(r1[dr - delta] == 0) {
526 delta++;
527 }
528
529 dr -= delta;
530 } /* end while loop (dr >= break_deg) */
531
532 u1.set_degree(du);
533 r1.set_degree(dr);
534 //return u1 and r1;
535 return std::make_pair(u1, r1); // coefficients u,v
536}
537
538polyn_gf2m::polyn_gf2m(size_t t, RandomNumberGenerator& rng, const std::shared_ptr<GF2m_Field>& sp_field) :
539 m_deg(static_cast<int>(t)), m_coeff(t + 1), m_sp_field(sp_field) {
540 this->set_coef(t, 1);
541 for(;;) {
542 for(size_t i = 0; i < t; ++i) {
543 this->set_coef(i, random_code_element(sp_field->get_cardinality(), rng));
544 }
545
546 const size_t degree = polyn_gf2m::degppf(*this);
547
548 if(degree >= t) {
549 break;
550 }
551 }
552}
553
554void polyn_gf2m::poly_shiftmod(const polyn_gf2m& g) {
555 if(g.get_degree() <= 1) {
556 throw Invalid_Argument("shiftmod cannot be called on polynomials of degree 1 or less");
557 }
558 std::shared_ptr<GF2m_Field> field = g.m_sp_field;
559
560 int t = g.get_degree();
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]);
564 }
565 this->m_coeff[0] = field->gf_mul(a, g.m_coeff[0]);
566}
567
568std::vector<polyn_gf2m> polyn_gf2m::sqrt_mod_init(const polyn_gf2m& g) {
569 uint32_t i, t;
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;
573 t = g.get_degree();
574 nb_polyn_sqrt_mat = t / 2;
575
576 std::vector<polyn_gf2m> sq_aux = polyn_gf2m::sqmod_init(g);
577
578 polyn_gf2m p(t - 1, g.get_sp_field());
579 p.set_degree(1);
580
581 (*&p).set_coef(1, 1);
582 // q(z) = 0, p(z) = z
583 for(i = 0; i < t * m_sp_field->get_extension_degree() - 1; ++i) {
584 // q(z) <- p(z)^2 mod g(z)
585 polyn_gf2m q = p.sqmod(sq_aux, t);
586 // q(z) <-> p(z)
587 polyn_gf2m aux = q;
588 q = p;
589 p = aux;
590 }
591 // p(z) = z^(2^(tm-1)) mod g(z) = sqrt(z) mod g(z)
592
593 for(i = 0; i < nb_polyn_sqrt_mat; ++i) {
594 result.push_back(polyn_gf2m(t - 1, g.get_sp_field()));
595 }
596
597 result[0] = p;
598 result[0].get_degree();
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();
603 }
604
605 return result;
606}
607
608std::vector<polyn_gf2m> syndrome_init(const polyn_gf2m& generator, const std::vector<gf2m>& support, int n) {
609 int i, j, t;
610 gf2m a;
611
612 std::shared_ptr<GF2m_Field> m_sp_field = generator.get_sp_field();
613
614 std::vector<polyn_gf2m> result;
615 t = generator.get_degree();
616
617 //g(z)=g_t+g_(t-1).z^(t-1)+......+g_1.z+g_0
618 //f(z)=f_(t-1).z^(t-1)+......+f_1.z+f_0
619
620 for(j = 0; j < n; j++) {
621 result.push_back(polyn_gf2m(t - 1, m_sp_field));
622
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]));
626 }
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));
630 }
631 }
632 return result;
633}
634
635polyn_gf2m::polyn_gf2m(const secure_vector<uint8_t>& encoded, const std::shared_ptr<GF2m_Field>& sp_field) :
636 m_sp_field(sp_field) {
637 if(encoded.size() % 2) {
638 throw Decoding_Error("encoded polynomial has odd length");
639 }
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);
643 }
644 get_degree();
645}
646
649
650 if(m_deg < 1) {
651 result.push_back(0);
652 result.push_back(0);
653 return result;
654 }
655
656 uint32_t len = m_deg + 1;
657 for(unsigned i = 0; i < len; i++) {
658 // "big endian" encoding of the GF(2^m) elements
659 result.push_back(get_byte<0>(m_coeff[i]));
660 result.push_back(get_byte<1>(m_coeff[i]));
661 }
662 return result;
663}
664
665void polyn_gf2m::swap(polyn_gf2m& other) noexcept {
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);
669}
670
671bool polyn_gf2m::operator==(const polyn_gf2m& other) const {
672 if(m_deg != other.m_deg || m_coeff != other.m_coeff) {
673 return false;
674 }
675 return true;
676}
677
678} // namespace Botan
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
void randomize(std::span< uint8_t > output)
Definition rng.h:53
secure_vector< uint8_t > encode() const
int get_degree() const
std::shared_ptr< GF2m_Field > get_sp_field() const
Definition polyn_gf2m.h:76
void set_coef(size_t i, gf2m v)
Definition polyn_gf2m.h:86
void swap(polyn_gf2m &other) noexcept
gf2m get_lead_coef() const
Definition polyn_gf2m.h:82
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)
Definition loadstor.h:75
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)
const SIMD_8x32 & b
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
gf2m decode_gf2m(const uint8_t *mem)
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:146
constexpr void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:120
uint16_t gf2m
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition loadstor.h:88