classic_mceliece_rust/
sk_gen.rs

1//! Generation of secret key
2
3use crate::gf::{gf_inv, gf_iszero, gf_mul, gf_mul_inplace, Gf};
4use crate::params::SYS_T;
5
6/// Take element `f` in `GF((2^m)^t)` and return minimal polynomial `out` of `f`
7/// Returns 0 for success and -1 for failure
8pub(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}