2 * transsip - the telephony toolkit
3 * By Daniel Borkmann <daniel@transsip.org>
4 * Copyright 2012 Daniel Borkmann <dborkma@tik.ee.ethz.ch>
5 * Subject to the GPL, version 2.
6 * Based on Bhaskar Biswas and Nicolas Sendrier McEliece
7 * implementation, LGPL 2.1.
18 struct polynomial
*poly_alloc(int d
)
20 struct polynomial
*p
= NULL
;
22 p
= xmalloc(sizeof(*p
));
25 p
->coeff
= xzmalloc(p
->size
* sizeof(gf16_t
));
30 struct polynomial
*poly_alloc_from_string(int d
, const unsigned char *str
,
33 struct polynomial
*p
= NULL
;
35 p
= xmalloc(sizeof(*p
));
38 p
->coeff
= xmemdup(str
, len
);
40 bug_on(p
->size
* sizeof(gf16_t
) != len
);
45 struct polynomial
*poly_copy(struct polynomial
*p
)
47 struct polynomial
*q
= NULL
;
49 q
= xmalloc(sizeof(*q
));
52 q
->coeff
= xzmalloc(q
->size
* sizeof(gf16_t
));
54 memcpy(q
->coeff
, p
->coeff
, p
->size
* sizeof(gf16_t
));
59 void poly_free(struct polynomial
*p
)
65 void poly_set_to_zero(struct polynomial
*p
)
67 memset(p
->coeff
, 0, p
->size
* sizeof(gf16_t
));
71 int poly_calcule_deg(struct polynomial
*p
)
75 while ((d
>= 0) && (p
->coeff
[d
] == gf_zero()))
83 void poly_set(struct polynomial
*p
, struct polynomial
*q
)
85 int d
= p
->size
- q
->size
;
88 memcpy(p
->coeff
, q
->coeff
, p
->size
* sizeof(gf16_t
));
91 memcpy(p
->coeff
, q
->coeff
, q
->size
* sizeof(gf16_t
));
92 memset(p
->coeff
+ q
->size
, 0, d
* sizeof(gf16_t
));
97 static gf16_t
poly_eval_aux(gf16_t
*coeff
, gf16_t a
, int d
)
102 for (; d
>= 0; --d
) {
104 b
= gf_add(gf_mul(b
, a
), coeff
[d
]);
112 struct polynomial
*poly_mul(struct polynomial
*p
, struct polynomial
*q
)
115 struct polynomial
*r
;
123 r
= poly_alloc(dp
+ dq
);
125 for (i
= 0; i
<= dp
; ++i
)
126 for (j
= 0; j
<= dq
; ++j
)
127 poly_addto_coeff(r
, i
+ j
, gf_mul(poly_coeff(p
, i
),
134 gf16_t
poly_eval(struct polynomial
*p
, gf16_t a
)
136 return poly_eval_aux(p
->coeff
, a
, poly_deg(p
));
139 /* p contain it's remainder modulo g */
140 void poly_rem(struct polynomial
*p
, struct polynomial
*g
)
145 d
= poly_deg(p
) - poly_deg(g
);
147 a
= gf_inv(poly_tete(g
));
149 for (i
= poly_deg(p
); d
>= 0; --i
, --d
) {
150 if (poly_coeff(p
, i
) != gf_zero()) {
151 b
= gf_mul_fast(a
, poly_coeff(p
, i
));
153 for (j
= 0; j
< poly_deg(g
); ++j
) {
154 poly_addto_coeff(p
, j
+ d
,
155 gf_mul_fast(b
, poly_coeff(g
, j
)));
158 poly_set_coeff(p
, i
, gf_zero());
162 poly_set_deg(p
, poly_deg(g
) - 1);
164 while ((poly_deg(p
) >= 0) &&
165 (poly_coeff(p
, poly_deg(p
)) == gf_zero()))
166 poly_set_deg(p
, poly_deg(p
) - 1);
170 void poly_sqmod_init(struct polynomial
*g
, struct polynomial
**sq
)
176 for (i
= 0; i
< d
/ 2; ++i
) {
177 /* sq[i] = x^(2i) mod g = x^(2i) */
178 poly_set_to_zero(sq
[i
]);
179 poly_set_deg(sq
[i
], 2 * i
);
180 poly_set_coeff(sq
[i
], 2 * i
, gf_unit());
184 /* sq[i] = x^(2i) mod g = (x^2 * sq[i-1]) mod g */
185 memset(sq
[i
]->coeff
, 0, 2 * sizeof(gf16_t
));
186 memcpy(sq
[i
]->coeff
+ 2, sq
[i
- 1]->coeff
, d
* sizeof(gf16_t
));
187 poly_set_deg(sq
[i
], poly_deg(sq
[i
- 1]) + 2);
193 * Modulo p square of a certain polynomial g, sq[] contains the square
194 * Modulo g of the base canonical polynomials of degree < d, where d is
195 * the degree of G. The table sq[] will be calculated by poly_sqmod_init
197 void poly_sqmod(struct polynomial
*res
, struct polynomial
*p
,
198 struct polynomial
**sq
, int d
)
203 poly_set_to_zero(res
);
205 /* terms of low degree */
206 for (i
= 0; i
< d
/ 2; ++i
)
207 poly_set_coeff(res
, i
* 2, gf_square(poly_coeff(p
, i
)));
209 /* terms of high degree */
211 if (poly_coeff(p
, i
) != gf_zero()) {
212 a
= gf_square(poly_coeff(p
, i
));
214 for (j
= 0; j
< d
; ++j
)
215 poly_addto_coeff(res
, j
,
216 gf_mul_fast(a
, poly_coeff(sq
[i
], j
)));
221 poly_set_deg(res
, d
- 1);
223 while ((poly_deg(res
) >= 0) &&
224 (poly_coeff(res
, poly_deg(res
)) == gf_zero()))
225 poly_set_deg(res
, poly_deg(res
) - 1);
229 static struct polynomial
*poly_gcd_aux(struct polynomial
*p1
,
230 struct polynomial
*p2
)
232 if (poly_deg(p2
) == -1)
236 return poly_gcd_aux(p2
, p1
);
240 struct polynomial
*poly_gcd(struct polynomial
*p1
, struct polynomial
*p2
)
242 struct polynomial
*a
, *b
, *c
;
247 if (poly_deg(a
) < poly_deg(b
))
248 c
= poly_copy(poly_gcd_aux(b
, a
));
250 c
= poly_copy(poly_gcd_aux(a
, b
));
258 struct polynomial
*poly_quo(struct polynomial
*p
, struct polynomial
*d
)
262 struct polynomial
*quo
, *rem
;
264 dd
= poly_calcule_deg(d
);
265 dp
= poly_calcule_deg(p
);
268 quo
= poly_alloc(dp
- dd
);
270 poly_set_deg(quo
, dp
- dd
);
272 a
= gf_inv(poly_coeff(d
, dd
));
274 for (i
= dp
; i
>= dd
; --i
) {
275 b
= gf_mul_fast(a
, poly_coeff(rem
, i
));
277 poly_set_coeff(quo
, i
- dd
, b
);
278 if (b
!= gf_zero()) {
279 poly_set_coeff(rem
, i
, gf_zero());
281 for (j
= i
- 1; j
>= i
- dd
; --j
)
282 poly_addto_coeff(rem
, j
,
283 gf_mul_fast(b
, poly_coeff(d
, dd
- i
+ j
)));
292 /* returns the degree of the smallest factor */
293 int poly_degppf(struct polynomial
*g
)
296 struct polynomial
**u
, *p
, *r
, *s
;
300 u
= malloc(d
* sizeof(*u
));
301 for (i
= 0; i
< d
; ++i
)
302 u
[i
] = poly_alloc(d
+ 1);
304 poly_sqmod_init(g
, u
);
306 p
= poly_alloc(d
- 1);
308 poly_set_coeff(p
, 1, gf_unit());
310 r
= poly_alloc(d
- 1);
313 for (i
= 1; i
<= (d
/ 2) * gf_extd(); ++i
) {
314 poly_sqmod(r
, p
, u
, d
);
316 /* r = x^(2^i) mod g */
317 if ((i
% gf_extd()) == 0) {
318 /* so 2^i = (2^m)^j (m ext. degree) */
319 poly_addto_coeff(r
, 1, gf_unit());
320 poly_calcule_deg(r
); /* the degree may change */
323 if (poly_deg(s
) > 0) {
330 poly_addto_coeff(r
, 1, gf_unit());
331 poly_calcule_deg(r
); /* the degree may change */
334 /* no need for the exchange s */
343 for (i
= 0; i
< d
; ++i
)
350 /* we suppose deg(g) >= deg(p) */
351 void poly_eeaux(struct polynomial
**u
, struct polynomial
**v
,
352 struct polynomial
*p
, struct polynomial
*g
, int t
)
354 int i
, j
, dr
, du
, delta
;
356 struct polynomial
*aux
, *r0
, *r1
, *u0
, *u1
;
358 /* initialisation of the local variables */
359 /* r0 <- g, r1 <- p, u0 <- 0, u1 <- 1 */
363 r1
= poly_alloc(dr
- 1);
364 u0
= poly_alloc(dr
- 1);
365 u1
= poly_alloc(dr
- 1);
369 poly_set_to_zero(u0
);
370 poly_set_to_zero(u1
);
371 poly_set_coeff(u1
, 0, gf_unit());
375 * r1 = u1 * p + v1 * g
376 * r0 = u0 * p + v0 * g
377 * and deg(u1) = deg(g) - deg(r0)
378 * it stops when deg (r1) <t (deg (r0)> = t)
379 * and therefore deg (u1) = deg (g) - deg (r0) <deg (g) - t
384 delta
= poly_deg(r0
) - dr
;
387 for (j
= delta
; j
>= 0; --j
) {
388 a
= gf_div(poly_coeff(r0
, dr
+ j
),
390 if (a
!= gf_zero()) {
391 /* u0(z) <- u0(z) + a * u1(z) * z^j */
392 for (i
= 0; i
<= du
; ++i
)
393 poly_addto_coeff(u0
, i
+ j
,
394 gf_mul_fast(a
, poly_coeff(u1
, i
)));
396 /* r0(z) <- r0(z) + a * r1(z) * z^j */
397 for (i
= 0; i
<= dr
; ++i
)
398 poly_addto_coeff(r0
, i
+ j
,
399 gf_mul_fast(a
, poly_coeff(r1
, i
)));
414 while (poly_coeff(r1
, dr
- delta
) == gf_zero())
419 poly_set_deg(u1
, du
);
420 poly_set_deg(r1
, dr
);
422 /* return u1 and r1 */
430 /* the field is already defined
431 * return a polynomial of degree t irreducible in the field */
432 struct polynomial
*poly_randgen_irred(int t
, int (*u8rnd
)(void))
435 struct polynomial
*g
;
439 poly_set_coeff(g
, t
, gf_unit());
443 for (i
= 0; i
< t
; ++i
)
444 poly_set_coeff(g
, i
, gf_rand(u8rnd
));
445 } while (poly_degppf(g
) < t
);
451 * p of degree <= deg(g)-1 */
452 static void poly_shiftmod(struct polynomial
*p
, struct polynomial
*g
)
458 a
= gf_div(p
->coeff
[t
- 1], g
->coeff
[t
]);
460 for (i
= t
- 1; i
> 0; --i
)
461 p
->coeff
[i
] = gf_add(p
->coeff
[i
- 1],
462 gf_mul(a
, g
->coeff
[i
]));
463 p
->coeff
[0] = gf_mul(a
, g
->coeff
[0]);
466 struct polynomial
**poly_sqrtmod_init(struct polynomial
*g
)
469 struct polynomial
**sqrt
, *aux
, *p
, *q
, **sq_aux
;
473 sq_aux
= xmalloc(t
* sizeof(*sq_aux
));
474 for (i
= 0; i
< t
; ++i
)
475 sq_aux
[i
] = poly_alloc(t
+ 1);
476 poly_sqmod_init(g
, sq_aux
);
478 q
= poly_alloc(t
- 1);
479 p
= poly_alloc(t
- 1);
482 poly_set_coeff(p
, 1, gf_unit());
483 /* q(z) = 0, p(z) = z */
484 for (i
= 0; i
< t
* gf_extd() - 1; ++i
) {
485 /* q(z) <- p(z)^2 mod g(z) */
486 poly_sqmod(q
, p
, sq_aux
, t
);
492 /* p(z) = z^(2^(tm-1)) mod g(z) = sqrt(z) mod g(z) */
494 sqrt
= xmalloc(t
* sizeof(*sqrt
));
495 for (i
= 0; i
< t
; ++i
)
496 sqrt
[i
] = poly_alloc(t
- 1);
498 poly_set(sqrt
[1], p
);
499 poly_calcule_deg(sqrt
[1]);
501 for(i
= 3; i
< t
; i
+= 2) {
502 poly_set(sqrt
[i
], sqrt
[i
- 2]);
503 poly_shiftmod(sqrt
[i
], g
);
504 poly_calcule_deg(sqrt
[i
]);
507 for (i
= 0; i
< t
; i
+= 2) {
508 poly_set_to_zero(sqrt
[i
]);
509 sqrt
[i
]->coeff
[i
/ 2] = gf_unit();
510 sqrt
[i
]->deg
= i
/ 2;
513 for (i
= 0; i
< t
; ++i
)
514 poly_free(sq_aux
[i
]);
523 struct polynomial
**poly_syndrome_init(struct polynomial
*generator
,
524 gf16_t
*support
, int n
)
528 struct polynomial
**F
;
530 F
= xmalloc(n
* sizeof(*F
));
531 t
= poly_deg(generator
);
533 /* g(z)=g_t+g_(t-1).z^(t-1)+......+g_1.z+g_0 */
534 /* f(z)=f_(t-1).z^(t-1)+......+f_1.z+f_0 */
536 for (j
= 0; j
< n
; ++j
) {
537 F
[j
] = poly_alloc(t
- 1);
538 poly_set_coeff(F
[j
], t
- 1, gf_unit());
540 for (i
= t
- 2; i
>= 0; --i
) {
541 poly_set_coeff(F
[j
], i
,
542 gf_add(poly_coeff(generator
, i
+ 1),
544 poly_coeff(F
[j
], i
+ 1))));
547 a
= gf_add(poly_coeff(generator
, 0),
548 gf_mul(support
[j
], poly_coeff(F
[j
], 0)));
550 for (i
= 0; i
< t
; ++i
) {
551 poly_set_coeff(F
[j
], i
, gf_div(poly_coeff(F
[j
], i
), a
));