classic_mceliece_rust/
sk_gen.rs1use crate::gf::{gf_inv, gf_iszero, gf_mul, gf_mul_inplace, Gf};
4use crate::params::SYS_T;
5
6pub(crate) fn genpoly_gen(out: &mut [Gf; SYS_T], f: &[Gf; SYS_T]) -> isize {
9 let mut mat = [[0u16; SYS_T]; SYS_T + 1];
10 mat[0][0] = 1;
11
12 mat[0][1..SYS_T].fill(0);
13
14 mat[1] = *f;
15
16 for j in 2..=SYS_T {
17 let (left, right) = mat.split_at_mut(j);
18 gf_mul_inplace(&mut right[0], &left[j - 1], f);
19 }
20
21 for j in 0..SYS_T {
22 for k in (j + 1)..SYS_T {
23 let mask = gf_iszero(mat[j][j]);
24
25 let mut c = j;
26 while c < SYS_T + 1 {
27 mat[c][j] ^= mat[c][k] & mask;
28 c += 1;
29 }
30 }
31
32 if mat[j][j] == 0 {
33 return -1;
34 }
35
36 let inv = gf_inv(mat[j][j]);
37
38 for itr_mat in mat.iter_mut() {
39 itr_mat[j] = gf_mul(itr_mat[j], inv);
40 }
41
42 for k in 0..SYS_T {
43 if k != j {
44 let t = mat[j][k];
45
46 for itr_mat in mat.iter_mut() {
47 itr_mat[k] ^= gf_mul(itr_mat[j], t);
48 }
49 }
50 }
51 }
52
53 out[0..SYS_T].copy_from_slice(&mat[SYS_T][0..SYS_T]);
54
55 0
56}
57
58#[cfg(test)]
59#[cfg(all(feature = "mceliece8192128f", test))]
60mod tests {
61 use super::*;
62 use crate::macros::sub;
63 use crate::test_utils::TestData;
64
65 #[test]
66 fn test_genpoly_gen() {
67 assert_eq!(SYS_T, 128);
68
69 let input_src = TestData::new().u16vec("mceliece8192128f_sk_gen_genpoly_1st_round_input");
70 let first_round_input = sub!(input_src, 0, 128, u16);
71 let first_round_output =
72 TestData::new().u16vec("mceliece8192128f_sk_gen_genpoly_1st_round_output");
73
74 let mut output = [0u16; SYS_T];
75
76 genpoly_gen(&mut output, first_round_input);
77
78 assert_eq!(&output, first_round_output.as_slice());
79 }
80}