Skip to main content

tfhe_csprng/generators/implem/soft/
generator.rs

1use crate::generators::aes_ctr::{AesCtrGenerator, AesCtrParams, ChildrenIterator, TableIndex};
2use crate::generators::implem::soft::block_cipher::SoftwareBlockCipher;
3use crate::generators::{ByteCount, BytesPerChild, ChildrenCount, ForkError, RandomGenerator};
4
5/// A random number generator using a software implementation.
6pub struct SoftwareRandomGenerator(pub(super) AesCtrGenerator<SoftwareBlockCipher>);
7
8/// The children iterator used by [`SoftwareRandomGenerator`].
9///
10/// Outputs children generators one by one.
11pub struct SoftwareChildrenIterator(ChildrenIterator<SoftwareBlockCipher>);
12
13impl Iterator for SoftwareChildrenIterator {
14    type Item = SoftwareRandomGenerator;
15
16    fn next(&mut self) -> Option<Self::Item> {
17        self.0.next().map(SoftwareRandomGenerator)
18    }
19}
20
21impl RandomGenerator for SoftwareRandomGenerator {
22    type ChildrenIter = SoftwareChildrenIterator;
23
24    fn new(params: impl Into<AesCtrParams>) -> Self {
25        SoftwareRandomGenerator(AesCtrGenerator::from_params(params))
26    }
27    fn remaining_bytes(&self) -> ByteCount {
28        self.0.remaining_bytes()
29    }
30    fn next_table_index(&self) -> Option<TableIndex> {
31        self.0.next_table_index()
32    }
33    fn try_fork(
34        &mut self,
35        n_children: ChildrenCount,
36        n_bytes: BytesPerChild,
37    ) -> Result<Self::ChildrenIter, ForkError> {
38        self.0
39            .try_fork(n_children, n_bytes)
40            .map(SoftwareChildrenIterator)
41    }
42}
43
44impl Iterator for SoftwareRandomGenerator {
45    type Item = u8;
46
47    fn next(&mut self) -> Option<Self::Item> {
48        self.0.next()
49    }
50}
51
52#[cfg(test)]
53mod test {
54    use super::*;
55    use crate::generators::aes_ctr::aes_ctr_generic_test;
56    use crate::generators::generator_generic_test;
57
58    // We use powerpc64 as the target to test behavior on big-endian
59    // However, we run these tests using an emulator. Thus, these get really slow
60    // so we skip them
61    #[cfg(not(target_arch = "powerpc64"))]
62    mod fork_tests {
63        use super::*;
64
65        #[test]
66        fn prop_fork_first_state_table_index() {
67            aes_ctr_generic_test::prop_fork_first_state_table_index::<SoftwareBlockCipher>();
68        }
69
70        #[test]
71        fn prop_fork_last_bound_table_index() {
72            aes_ctr_generic_test::prop_fork_last_bound_table_index::<SoftwareBlockCipher>();
73        }
74
75        #[test]
76        fn prop_fork_parent_bound_table_index() {
77            aes_ctr_generic_test::prop_fork_parent_bound_table_index::<SoftwareBlockCipher>();
78        }
79
80        #[test]
81        fn prop_fork_parent_state_table_index() {
82            aes_ctr_generic_test::prop_fork_parent_state_table_index::<SoftwareBlockCipher>();
83        }
84
85        #[test]
86        fn prop_fork() {
87            aes_ctr_generic_test::prop_fork::<SoftwareBlockCipher>();
88        }
89
90        #[test]
91        fn prop_fork_with_parent_continuation() {
92            aes_ctr_generic_test::prop_fork_with_parent_continuation::<SoftwareBlockCipher>();
93        }
94
95        #[test]
96        fn prop_fork_children_remaining_bytes() {
97            aes_ctr_generic_test::prop_fork_children_remaining_bytes::<SoftwareBlockCipher>();
98        }
99
100        #[test]
101        fn prop_fork_parent_remaining_bytes() {
102            aes_ctr_generic_test::prop_fork_parent_remaining_bytes::<SoftwareBlockCipher>();
103        }
104
105        #[test]
106        fn prop_different_offset_means_different_output() {
107            aes_ctr_generic_test::prop_different_offset_means_different_output::<SoftwareBlockCipher>(
108            );
109        }
110
111        #[test]
112        fn test_fork() {
113            generator_generic_test::test_fork_children::<SoftwareRandomGenerator>();
114        }
115
116        #[test]
117        fn test_roughly_uniform() {
118            generator_generic_test::test_roughly_uniform::<SoftwareRandomGenerator>();
119        }
120    }
121
122    #[test]
123    fn test_conformance_with_ctr_crate() {
124        aes_ctr_generic_test::test_conformance_with_ctr_crate::<SoftwareBlockCipher>();
125    }
126
127    #[test]
128    fn test_forking_conformance_with_ctr_crate() {
129        aes_ctr_generic_test::test_forking_conformance_with_ctr_crate::<SoftwareBlockCipher>();
130    }
131
132    #[test]
133    fn test_generator_determinism() {
134        generator_generic_test::test_generator_determinism::<SoftwareRandomGenerator>();
135    }
136
137    #[test]
138    #[should_panic(expected = "expected test panic")]
139    fn test_bounded_panic() {
140        generator_generic_test::test_bounded_none_should_panic::<SoftwareRandomGenerator>();
141    }
142
143    #[test]
144    fn test_vector() {
145        generator_generic_test::test_vectors::<SoftwareRandomGenerator>();
146    }
147
148    #[test]
149    fn test_vector_xof_seed() {
150        generator_generic_test::test_vectors_xof_seed::<SoftwareRandomGenerator>();
151    }
152
153    #[test]
154    fn test_vector_xof_seed_bytes() {
155        generator_generic_test::test_vectors_xof_seed_bytes::<SoftwareRandomGenerator>();
156    }
157}