Coverage Report

Created: 2025-07-18 07:01

/src/fips203/fuzz/fuzz_targets/ml_kem_fuzz.rs
Line
Count
Source (jump to first uncovered line)
1
#![no_main]
2
use fips203::{
3
    ml_kem_1024, ml_kem_512, ml_kem_768,
4
    traits::{Decaps, Encaps, KeyGen, SerDes},
5
    RngCore, CryptoRng
6
};
7
use libfuzzer_sys::fuzz_target;
8
9
// Wrapper struct to help organize the fuzz input
10
1.00k
#[derive(arbitrary::Arbitrary, Debug)]
Unexecuted instantiation: <ml_kem_fuzz::FuzzInput as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#0}
<ml_kem_fuzz::FuzzInput as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#1}
Line
Count
Source
10
480
#[derive(arbitrary::Arbitrary, Debug)]
Unexecuted instantiation: <ml_kem_fuzz::FuzzInput as arbitrary::Arbitrary>::arbitrary_take_rest::{closure#2}
<ml_kem_fuzz::FuzzInput as arbitrary::Arbitrary>::try_size_hint::{closure#0}
Line
Count
Source
10
526
#[derive(arbitrary::Arbitrary, Debug)]
Unexecuted instantiation: <ml_kem_fuzz::FuzzInput as arbitrary::Arbitrary>::arbitrary::{closure#0}
Unexecuted instantiation: <ml_kem_fuzz::FuzzInput as arbitrary::Arbitrary>::arbitrary::{closure#1}
Unexecuted instantiation: <ml_kem_fuzz::FuzzInput as arbitrary::Arbitrary>::arbitrary::{closure#2}
11
struct FuzzInput {
12
    d: [u8; 32],
13
    z: [u8; 32],
14
    e: [u8; 32],
15
    ek_xor: [u8; ml_kem_1024::EK_LEN],
16
    dk_xor: [u8; ml_kem_1024::DK_LEN],
17
    ct_xor: [u8; ml_kem_1024::CT_LEN],
18
    sk_xor: [u8; fips203::SSK_LEN],
19
}
20
21
fuzz_target!(|input: FuzzInput| {
22
    // Generate keypair deterministically from fuzzer input
23
    let (ek1a, dk1a) = ml_kem_512::KG::keygen_from_seed(input.d, input.z);
24
    let (ek2a, dk2a) = ml_kem_768::KG::keygen_from_seed(input.d, input.z);
25
    let (ek3a, dk3a) = ml_kem_1024::KG::keygen_from_seed(input.d, input.z);
26
27
    // Serialize and deserialize encapsulation key; XOR
28
    let mut ek1a_bytes = ek1a.into_bytes();
29
384k
    ek1a_bytes.iter_mut().zip(input.ek_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
30
    let ek1b = match ml_kem_512::EncapsKey::try_from_bytes(ek1a_bytes) {
31
        Ok(k) => k,
32
        Err(_) => return,
33
    };
34
35
    let mut ek2a_bytes = ek2a.into_bytes();
36
539k
    ek2a_bytes.iter_mut().zip(input.ek_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
37
    let ek2b = match ml_kem_768::EncapsKey::try_from_bytes(ek2a_bytes) {
38
        Ok(k) => k,
39
        Err(_) => return,
40
    };
41
42
    let mut ek3a_bytes = ek3a.into_bytes();
43
699k
    ek3a_bytes.iter_mut().zip(input.ek_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
44
    let ek3b = match ml_kem_1024::EncapsKey::try_from_bytes(ek3a_bytes) {
45
        Ok(k) => k,
46
        Err(_) => return,
47
    };
48
49
    // Serialize and deserialize decapsulation key
50
    let mut dk1a_bytes = dk1a.into_bytes();
51
713k
    dk1a_bytes.iter_mut().zip(input.dk_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
52
    let dk1b = match ml_kem_512::DecapsKey::try_from_bytes(dk1a_bytes) {
53
        Ok(k) => k,
54
        Err(_) => return,
55
    };
56
57
    let mut dk2a_bytes = dk2a.into_bytes();
58
928k
    dk2a_bytes.iter_mut().zip(input.dk_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
59
    let dk2b = match ml_kem_768::DecapsKey::try_from_bytes(dk2a_bytes) {
60
        Ok(k) => k,
61
        Err(_) => return,
62
    };
63
64
    let mut dk3a_bytes = dk3a.into_bytes();
65
1.07M
    dk3a_bytes.iter_mut().zip(input.dk_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
66
    let dk3b = match ml_kem_1024::DecapsKey::try_from_bytes(dk3a_bytes) {
67
        Ok(k) => k,
68
        Err(_) => return,
69
    };
70
71
72
    let (ss1, ct1) = ek1b.encaps_from_seed(&input.e);
73
    let (ss2, ct2) = ek2b.encaps_from_seed(&input.e);
74
    let (ss3, ct3) = ek3b.encaps_from_seed(&input.e);
75
76
    // Serialize and deserialize ciphertext
77
    let mut ct1a_bytes = ct1.into_bytes();
78
238k
    ct1a_bytes.iter_mut().zip(input.ct_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
79
    let ct1b = match ml_kem_512::CipherText::try_from_bytes(ct1a_bytes) {
80
        Ok(c) => c,
81
        Err(_) => return,
82
    };
83
84
    let mut ct2a_bytes = ct2.into_bytes();
85
337k
    ct2a_bytes.iter_mut().zip(input.ct_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
86
    let ct2b = match ml_kem_768::CipherText::try_from_bytes(ct2a_bytes) {
87
        Ok(c) => c,
88
        Err(_) => return,
89
    };
90
91
    let mut ct3a_bytes = ct3.into_bytes();
92
486k
    ct3a_bytes.iter_mut().zip(input.ct_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
93
    let ct3b = match ml_kem_1024::CipherText::try_from_bytes(ct3a_bytes) {
94
        Ok(c) => c,
95
        Err(_) => return,
96
    };
97
98
    // Serialize and deserialize shared secret
99
    let mut sk1a_bytes = ss1.into_bytes();
100
9.92k
    sk1a_bytes.iter_mut().zip(input.sk_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
101
    let _sk1b = match fips203::SharedSecretKey::try_from_bytes(sk1a_bytes) {
102
        Ok(s) => s,
103
        Err(_) => return,
104
    };
105
106
    let mut sk2a_bytes = ss2.into_bytes();
107
9.92k
    sk2a_bytes.iter_mut().zip(input.sk_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
108
    let _sk2b = match fips203::SharedSecretKey::try_from_bytes(sk2a_bytes) {
109
        Ok(s) => s,
110
        Err(_) => return,
111
    };
112
113
    let mut sk3a_bytes = ss3.into_bytes();
114
9.92k
    sk3a_bytes.iter_mut().zip(input.sk_xor.iter()).for_each(|(x1, x2)| *x1 ^= x2);
115
    let _sk3b = match fips203::SharedSecretKey::try_from_bytes(sk3a_bytes) {
116
        Ok(s) => s,
117
        Err(_) => return,
118
    };
119
120
    // Test decapsulation
121
    let _ss2a = match dk1b.try_decaps(&ct1b) {
122
        Ok(s) => s,
123
        Err(_) => return,
124
    };
125
    let _ss2b = match dk2b.try_decaps(&ct2b) {
126
        Ok(s) => s,
127
        Err(_) => return,
128
    };
129
    let _ss2c = match dk3b.try_decaps(&ct3b) {
130
        Ok(s) => s,
131
        Err(_) => return,
132
    };
133
134
    // Verify shared secrets match
135
    //assert_eq!(ss1, ss2);
136
137
    // Test keypair validation
138
139
    // ----- CUSTOM RNG TO REPLAY VALUES -----
140
    struct TestRng {
141
        data: Vec<Vec<u8>>,
142
    }
143
144
    impl RngCore for TestRng {
145
0
        fn next_u32(&mut self) -> u32 { unimplemented!() }
146
147
0
        fn next_u64(&mut self) -> u64 { unimplemented!() }
148
149
1.89k
        fn fill_bytes(&mut self, out: &mut [u8]) {
150
1.89k
            let x = self.data.pop().expect("test rng problem");
151
1.89k
            out.copy_from_slice(&x)
152
1.89k
        }
153
154
1.89k
        fn try_fill_bytes(&mut self, out: &mut [u8]) -> Result<(), rand_core::Error> {
155
1.89k
            self.fill_bytes(out);
156
1.89k
            Ok(())
157
1.89k
        }
158
    }
159
160
    impl CryptoRng for TestRng {}
161
162
    impl TestRng {
163
270
        fn new() -> Self { TestRng { data: Vec::new() } }
164
165
2.70k
        fn push(&mut self, new_data: &[u8]) {
166
2.70k
            let x = new_data.to_vec();
167
2.70k
            self.data.push(x);
168
2.70k
        }
169
    }
170
171
172
    let mut rng = TestRng::new();
173
    rng.push(&input.d);
174
    let mut z = input.z;
175
270
    z.iter_mut().zip(input.ct_xor[0..1].iter()).for_each(|(x1, x2)| *x1 ^= x2);
176
    rng.push(&z);
177
    let (ek1a, dk1a) = match ml_kem_512::KG::try_keygen_with_rng(&mut rng) {
178
        Ok(k) => k,
179
        Err(_) => return,
180
    };
181
    rng.push(&input.d);
182
    rng.push(&z);
183
    ml_kem_512::KG::validate_keypair_with_rng_vartime(
184
        &mut rng,
185
        &ek1a.into_bytes(),
186
        &dk1a.into_bytes(),
187
    );
188
189
    rng.push(&input.d);
190
    rng.push(&z);
191
    let (ek2a, dk2a) = match ml_kem_768::KG::try_keygen_with_rng(&mut rng) {
192
        Ok(k) => k,
193
        Err(_) => return,
194
    };
195
    rng.push(&input.d);
196
    rng.push(&z);
197
    ml_kem_768::KG::validate_keypair_with_rng_vartime(
198
        &mut rng,
199
        &ek2a.into_bytes(),
200
        &dk2a.into_bytes(),
201
    );
202
203
    let (ek3a, dk3a) = match ml_kem_1024::KG::try_keygen() {
204
        Ok(k) => k,
205
        Err(_) => return,
206
    };
207
    let _ = ek3a.try_encaps();
208
    rng.push(&input.d);
209
    rng.push(&z);
210
    ml_kem_1024::KG::validate_keypair_with_rng_vartime(
211
        &mut rng,
212
        &ek3a.into_bytes(),
213
        &dk3a.into_bytes(),
214
    );
215
});