Skip to content

Commit

Permalink
wasm example
Browse files Browse the repository at this point in the history
  • Loading branch information
eschorn1 committed Mar 8, 2024
1 parent c0bd11e commit d0c1b2b
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 62 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
**/corpus
/fuzz/.gitignore
/dudect/Cargo.lock
**/node_modules
**/dist
**/pkg
2 changes: 1 addition & 1 deletion dudect/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

Need to rework the rng
Need to rework the rng (to return hardcoded values)

~~~
See https://docs.rs/dudect-bencher/latest/dudect_bencher/
Expand Down
98 changes: 70 additions & 28 deletions fuzz/README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,77 @@

See <https://rust-fuzz.github.io/book/introduction.html>

~~~
$ rustup default nightly
$ head -c 6292 </dev/urandom > seed1
$ cargo fuzz run fuzz_all -j 4
$ cd fuzz # <this directory>
$ mkdir -p corpus/fuzz_all
$ head -c 6292 </dev/urandom > corpus/fuzz_all/seed1
$ cargo fuzz run fuzz_all -j 4 -- -max_total_time=300
(run twice)
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1973874562
INFO: Loaded 1 modules (33986 inline 8-bit counters): 33986 [0x55bac21089e0, 0x55bac2110ea2),
INFO: Loaded 1 PC tables (33986 PCs): 33986 [0x55bac2110ea8,0x55bac2195ac8),
INFO: Seed: 708871690
INFO: Loaded 1 modules (39289 inline 8-bit counters): 39289 [0x56391a65e620, 0x56391a667f99),
INFO: Loaded 1 PC tables (39289 PCs): 39289 [0x56391a667fa0,0x56391a701730),
INFO: -fork=4: fuzzing in separate process(s)
INFO: -fork=4: 118 seed inputs, starting to fuzz in /tmp/libFuzzerTemp.FuzzWithFork320486.dir
#327: cov: 3130 ft: 3130 corp: 118 exec/s 163 oom/timeout/crash: 0/0/0 time: 5s job: 1 dft_time: 0
#785: cov: 4503 ft: 3130 corp: 118 exec/s 152 oom/timeout/crash: 0/0/0 time: 6s job: 2 dft_time: 0
#1404: cov: 4504 ft: 3140 corp: 120 exec/s 154 oom/timeout/crash: 0/0/0 time: 7s job: 3 dft_time: 0
#2173: cov: 4507 ft: 3147 corp: 122 exec/s 153 oom/timeout/crash: 0/0/0 time: 8s job: 4 dft_time: 0
#3145: cov: 4508 ft: 3155 corp: 123 exec/s 162 oom/timeout/crash: 0/0/0 time: 11s job: 5 dft_time: 0
#4313: cov: 4508 ft: 3157 corp: 125 exec/s 166 oom/timeout/crash: 0/0/0 time: 13s job: 6 dft_time: 0
#5703: cov: 4509 ft: 3169 corp: 129 exec/s 173 oom/timeout/crash: 0/0/0 time: 16s job: 7 dft_time: 0
#7240: cov: 4509 ft: 3169 corp: 129 exec/s 170 oom/timeout/crash: 0/0/0 time: 18s job: 8 dft_time: 0
#9004: cov: 4509 ft: 3169 corp: 129 exec/s 176 oom/timeout/crash: 0/0/0 time: 22s job: 9 dft_time: 0
#10897: cov: 4509 ft: 3170 corp: 130 exec/s 172 oom/timeout/crash: 0/0/0 time: 25s job: 10 dft_time: 0
#12934: cov: 4510 ft: 3186 corp: 134 exec/s 169 oom/timeout/crash: 0/0/0 time: 28s job: 11 dft_time: 0
#15217: cov: 4510 ft: 3186 corp: 134 exec/s 175 oom/timeout/crash: 0/0/0 time: 31s job: 12 dft_time: 0
#17627: cov: 4510 ft: 3186 corp: 134 exec/s 172 oom/timeout/crash: 0/0/0 time: 36s job: 13 dft_time: 0
#20175: cov: 4510 ft: 3191 corp: 137 exec/s 169 oom/timeout/crash: 0/0/0 time: 40s job: 14 dft_time: 0
#22838: cov: 4510 ft: 3191 corp: 137 exec/s 166 oom/timeout/crash: 0/0/0 time: 44s job: 15 dft_time: 0
#25656: cov: 4510 ft: 3194 corp: 138 exec/s 165 oom/timeout/crash: 0/0/0 time: 48s job: 16 dft_time: 0
#28572: cov: 4510 ft: 3201 corp: 140 exec/s 162 oom/timeout/crash: 0/0/0 time: 54s job: 17 dft_time: 0
#31705: cov: 4510 ft: 3210 corp: 143 exec/s 164 oom/timeout/crash: 0/0/0 time: 60s job: 18 dft_time: 0
#35087: cov: 4510 ft: 3210 corp: 143 exec/s 169 oom/timeout/crash: 0/0/0 time: 65s job: 19 dft_time: 0
#38565: cov: 4510 ft: 3222 corp: 145 exec/s 165 oom/timeout/crash: 0/0/0 time: 70s job: 20 dft_time: 0
...
INFO: -fork=4: 106 seed inputs, starting to fuzz in /tmp/libFuzzerTemp.FuzzWithFork491405.dir
#375: cov: 3099 ft: 3099 corp: 106 exec/s 187 oom/timeout/crash: 0/0/0 time: 3s job: 1 dft_time: 0
... (new funcs) ...
#870: cov: 4821 ft: 3108 corp: 110 exec/s 165 oom/timeout/crash: 0/0/0 time: 4s job: 2 dft_time: 0
#1591: cov: 4823 ft: 3119 corp: 114 exec/s 180 oom/timeout/crash: 0/0/0 time: 5s job: 3 dft_time: 0
#2576: cov: 4826 ft: 3136 corp: 117 exec/s 197 oom/timeout/crash: 0/0/0 time: 6s job: 4 dft_time: 0
#3600: cov: 4827 ft: 3141 corp: 119 exec/s 170 oom/timeout/crash: 0/0/0 time: 10s job: 5 dft_time: 0
#4829: cov: 4828 ft: 3149 corp: 121 exec/s 175 oom/timeout/crash: 0/0/0 time: 12s job: 6 dft_time: 0
#6223: cov: 4829 ft: 3155 corp: 124 exec/s 174 oom/timeout/crash: 0/0/0 time: 14s job: 7 dft_time: 0
#7730: cov: 4829 ft: 3212 corp: 129 exec/s 167 oom/timeout/crash: 0/0/0 time: 16s job: 8 dft_time: 0
#9431: cov: 4830 ft: 3218 corp: 131 exec/s 170 oom/timeout/crash: 0/0/0 time: 20s job: 9 dft_time: 0
#11273: cov: 4831 ft: 3231 corp: 136 exec/s 167 oom/timeout/crash: 0/0/0 time: 23s job: 10 dft_time: 0
#13215: cov: 4831 ft: 3236 corp: 139 exec/s 161 oom/timeout/crash: 0/0/0 time: 26s job: 11 dft_time: 0
#15318: cov: 4831 ft: 3238 corp: 141 exec/s 161 oom/timeout/crash: 0/0/0 time: 29s job: 12 dft_time: 0
#17653: cov: 4831 ft: 3241 corp: 142 exec/s 166 oom/timeout/crash: 0/0/0 time: 35s job: 13 dft_time: 0
#20163: cov: 4831 ft: 3243 corp: 143 exec/s 167 oom/timeout/crash: 0/0/0 time: 38s job: 14 dft_time: 0
#22799: cov: 4831 ft: 3247 corp: 144 exec/s 164 oom/timeout/crash: 0/0/0 time: 42s job: 15 dft_time: 0
#25644: cov: 4831 ft: 3255 corp: 146 exec/s 167 oom/timeout/crash: 0/0/0 time: 47s job: 16 dft_time: 0
#28572: cov: 4831 ft: 3255 corp: 146 exec/s 162 oom/timeout/crash: 0/0/0 time: 53s job: 17 dft_time: 0
#31644: cov: 4831 ft: 3258 corp: 147 exec/s 161 oom/timeout/crash: 0/0/0 time: 58s job: 18 dft_time: 0
#34948: cov: 4831 ft: 3258 corp: 147 exec/s 165 oom/timeout/crash: 0/0/0 time: 63s job: 19 dft_time: 0
#38534: cov: 4831 ft: 3262 corp: 149 exec/s 170 oom/timeout/crash: 0/0/0 time: 68s job: 20 dft_time: 0
#42350: cov: 4831 ft: 3263 corp: 150 exec/s 173 oom/timeout/crash: 0/0/0 time: 76s job: 21 dft_time: 0
#45956: cov: 4831 ft: 3268 corp: 151 exec/s 156 oom/timeout/crash: 0/0/0 time: 81s job: 22 dft_time: 0
#50243: cov: 4831 ft: 3275 corp: 154 exec/s 178 oom/timeout/crash: 0/0/0 time: 87s job: 23 dft_time: 0
#54612: cov: 4831 ft: 3278 corp: 156 exec/s 174 oom/timeout/crash: 0/0/0 time: 93s job: 24 dft_time: 0
#59006: cov: 4831 ft: 3282 corp: 157 exec/s 169 oom/timeout/crash: 0/0/0 time: 102s job: 25 dft_time: 0
#63622: cov: 4831 ft: 3282 corp: 157 exec/s 170 oom/timeout/crash: 0/0/0 time: 109s job: 26 dft_time: 0
#68600: cov: 4831 ft: 3379 corp: 158 exec/s 177 oom/timeout/crash: 0/0/0 time: 116s job: 27 dft_time: 0
#73305: cov: 4831 ft: 3381 corp: 159 exec/s 162 oom/timeout/crash: 0/0/0 time: 123s job: 28 dft_time: 0
#78406: cov: 4831 ft: 3381 corp: 159 exec/s 170 oom/timeout/crash: 0/0/0 time: 132s job: 29 dft_time: 0
#83511: cov: 4831 ft: 3381 corp: 159 exec/s 164 oom/timeout/crash: 0/0/0 time: 140s job: 30 dft_time: 0
#88768: cov: 4831 ft: 3381 corp: 159 exec/s 164 oom/timeout/crash: 0/0/0 time: 149s job: 31 dft_time: 0
#94078: cov: 4831 ft: 3382 corp: 160 exec/s 160 oom/timeout/crash: 0/0/0 time: 157s job: 32 dft_time: 0
#99544: cov: 4831 ft: 3382 corp: 160 exec/s 160 oom/timeout/crash: 0/0/0 time: 167s job: 33 dft_time: 0
#105351: cov: 4831 ft: 3384 corp: 161 exec/s 165 oom/timeout/crash: 0/0/0 time: 176s job: 34 dft_time: 0
#111111: cov: 4831 ft: 3384 corp: 161 exec/s 160 oom/timeout/crash: 0/0/0 time: 185s job: 35 dft_time: 0
#117276: cov: 4831 ft: 3384 corp: 161 exec/s 166 oom/timeout/crash: 0/0/0 time: 194s job: 36 dft_time: 0
#123570: cov: 4831 ft: 3384 corp: 161 exec/s 165 oom/timeout/crash: 0/0/0 time: 205s job: 37 dft_time: 0
#130052: cov: 4831 ft: 3384 corp: 161 exec/s 166 oom/timeout/crash: 0/0/0 time: 215s job: 38 dft_time: 0
#137189: cov: 4831 ft: 3384 corp: 161 exec/s 178 oom/timeout/crash: 0/0/0 time: 226s job: 39 dft_time: 0
#144270: cov: 4831 ft: 3385 corp: 162 exec/s 172 oom/timeout/crash: 0/0/0 time: 236s job: 40 dft_time: 0
#151734: cov: 4831 ft: 3386 corp: 163 exec/s 177 oom/timeout/crash: 0/0/0 time: 248s job: 41 dft_time: 0
#158944: cov: 4831 ft: 3390 corp: 165 exec/s 167 oom/timeout/crash: 0/0/0 time: 259s job: 42 dft_time: 0
#166412: cov: 4831 ft: 3395 corp: 167 exec/s 169 oom/timeout/crash: 0/0/0 time: 270s job: 43 dft_time: 0
#173716: cov: 4831 ft: 3396 corp: 168 exec/s 162 oom/timeout/crash: 0/0/0 time: 281s job: 44 dft_time: 0
#181399: cov: 4831 ft: 3396 corp: 168 exec/s 167 oom/timeout/crash: 0/0/0 time: 294s job: 45 dft_time: 0
#189143: cov: 4831 ft: 3402 corp: 169 exec/s 164 oom/timeout/crash: 0/0/0 time: 306s job: 46 dft_time: 0
INFO: fuzzed for 307 seconds, wrapping up soon
INFO: exiting: 0 time: 307s
~~~

Now generate a coverage report...

~~~
$ cargo fuzz coverage fuzz_all
$ cargo cov -- show target/x86_64-unknown-linux-gnu/coverage/x86_64-unknown-linux-gnu/release/fuzz_all \
--format=html -instr-profile=./coverage/fuzz_all/coverage.profdata > index.html
~~~
66 changes: 42 additions & 24 deletions fuzz/fuzz_targets/fuzz_all.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,53 @@
#![no_main]

use libfuzzer_sys::fuzz_target;
use fips204::ml_dsa_44;
use fips204::traits::{SerDes, Signer, Verifier};
use fips204::ml_dsa_44::{PrivateKey, PublicKey, KG, SIG_LEN};
use fips204::traits::{KeyGen, SerDes, Signer, Verifier};

fuzz_target!(|data: [u8; 2560+2420+1312]| { // sk_len + sig_len + pk_len = 6292

// Deserialize a 'fuzzy' secret key
let sk = ml_dsa_44::PrivateKey::try_from_bytes(data[0..2560].try_into().unwrap());

// Try to use 'fuzzy' sk (a decent (?) proportion will deserialize OK)
if let Ok(sk) = sk {
let _sig = sk.try_sign_ct(&[0u8, 1, 2, 3]);
// A good reference set
let (pk_good, sk_good) = KG::try_keygen_vt().unwrap();
let sig_good = sk_good.try_sign_ct(&[0u8, 1, 2, 3]).unwrap();

// Extract then deserialize a 'fuzzy' secret key
let sk_bytes = data[0..2560].try_into().unwrap();
let sk_fuzz = PrivateKey::try_from_bytes(sk_bytes);

// Extract a 'fuzzy' signature
let sig_fuzz: [u8; SIG_LEN] = data[2560..2560+2420].try_into().unwrap();

// Extract then deserialize a 'fuzzy' public key
let pk_bytes = data[2560+2420..2560+2420+1312].try_into().unwrap();
let pk_fuzz = PublicKey::try_from_bytes(pk_bytes);

// Try to use 'fuzzy' sk
if let Ok(ref sk) = sk_fuzz {
let sig1 = sk.try_sign_ct(&[0u8, 1, 2, 3]).unwrap();
let sk2 = KG::gen_expanded_private_vt(&sk).unwrap();
let sig2 = sk2.try_sign_ct(&[4u8, 5, 6, 7]).unwrap();
// ...with good pk
let res = pk_good.try_verify_vt(&[0u8, 1, 2, 3], &sig1);
assert!(res.is_err() || !res.unwrap());
let res = pk_good.try_verify_vt(&[0u8, 1, 2, 3], &sig2);
assert!(res.is_err() || !res.unwrap());
}

// Try to use 'fuzzy' pk
if let Ok(ref pk) = pk_fuzz {
let res = pk.try_verify_vt(&[0u8, 1, 2, 3], &sig_fuzz);
assert!(res.is_err() || !res.unwrap());
let pk2 = KG::gen_expanded_public_vt(&pk).unwrap();
let res = pk2.try_verify_vt(&[0u8, 1, 2, 3], &sig_fuzz);
assert!(res.is_err() || !res.unwrap());
// .. with good sig
let res = pk2.try_verify_vt(&[0u8, 1, 2, 3], &sig_good);
assert!(res.is_err() || !res.unwrap());
}

// Deserialize a 'fuzzy' signature
let sig: [u8; ml_dsa_44::SIG_LEN] = data[2560..2560+2420].try_into().unwrap();

// Try to use 'fuzzy' signature (a decent (?) proportion will deserialize OK)
let (pk, _) = ml_dsa_44::try_keygen_vt().unwrap(); // Get a good pk
let _v = pk.try_verify_vt(&[0u8, 1, 2, 3], &sig);


// Deserialize a 'fuzzy' public key
let pk = ml_dsa_44::PublicKey::try_from_bytes(data[2560+2420..2560+2420+1312].try_into().unwrap());

// Try to use 'fuzzy' pk (a decent (?) proportion will deserialize OK)
if let Ok(pk) = pk {
let (_, sk) = ml_dsa_44::try_keygen_vt().unwrap();
let sig2 = sk.try_sign_ct(&[0u8, 1, 2, 3]).unwrap();
let _v = pk.try_verify_vt(&[0u8, 1, 2, 3], &sig2);
// Try to use 'fuzzy' sk and 'fuzzy' pk
if let (Ok(sk), Ok(pk)) = (sk_fuzz, pk_fuzz) {
let _sig = sk.try_sign_ct(&[0u8, 1, 2, 3]).unwrap();
let _v = pk.try_verify_vt(&[0u8, 1, 2, 3], &sig_fuzz).unwrap();
}
});
8 changes: 5 additions & 3 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub(crate) const fn partial_reduce64(a: i64) -> i32 {
// cannot generate a carry (and thus we have maximum rounding-down error
// accumulated), or a = 2**31 - 2**22 - 1, which then suggests (0xFF) Q to
// be subtracted. Then, a - (a >> 23)*Q is 6283008 or 2**23 - 2**21 - 2**8.
// The negative result works out to -6283008. Note Q is 2**23 - 2**13 + 1. TODO: Recheck
// The negative result works out to -6283008. Note Q is 2**23 - 2**13 + 1. TODO: Recheck #s
#[inline(always)]
#[allow(clippy::inline_always)]
pub(crate) const fn partial_reduce32(a: i32) -> i32 {
Expand All @@ -56,7 +56,7 @@ pub(crate) const fn partial_reduce32(a: i32) -> i32 {


pub(crate) const fn full_reduce32(a: i32) -> i32 {
let x = partial_reduce32(a); // puts us within -Q to +Q
let x = partial_reduce32(a); // puts us within better than -Q to +Q
x + ((x >> 31) & Q) // add Q if negative
}

Expand Down Expand Up @@ -114,13 +114,15 @@ pub fn infinity_norm<const ROW: usize, const COL: usize>(w: &[[i32; COL]; ROW])
for row in w {
for element in row {
let z_q = center_mod(*element).abs();
result = if z_q > result { z_q } else { result };
result = if z_q > result { z_q } else { result }; // TODO: check CT
}
}
result
}


// ----- The following functions only run at compile time (thus, not CT etc) -----

/// HAC Algorithm 14.76 Right-to-left binary exponentiation mod Q.
const fn pow_mod_q(g: i32, e: u8) -> i32 {
let g = g as i64;
Expand Down
11 changes: 5 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@

// Roadmap
// 1. Clean up; resolve math
// 2. CT inspection
// 3. implement ct_cm4
// 4. rework fuzz harness to include expanded keys
// 5. Intensive/extensive pass on documentation
// 6. Revisit/expand unit testing; consider whether to test debug statements: release-vs-test
// 2. Closer CT inspection
// 3. Intensive/extensive pass on documentation
// 4. Revisit/expand unit testing; consider whether to test debug statements: release-vs-test


// Functionality map per FIPS 204 draft
Expand Down Expand Up @@ -59,7 +57,7 @@

// Note: many of the debug_assert()! and ensure()! guardrails will be removed when
// the specification is finalized and performance optimizations begin in earnest.

// The current situation is overkill.

mod conversion;
mod encodings;
Expand All @@ -73,6 +71,7 @@ mod types;
/// All functionality is covered by traits, such that consumers can utilize trait objects as desired.
pub mod traits;

// Applies across all security parameter sets
const Q: i32 = 8_380_417; // 2i32.pow(23) - 2i32.pow(13) + 1; See https://oeis.org/A234388
const ZETA: i32 = 1753; // See line 906 et al of FIPS 204
const D: u32 = 13;
Expand Down
Loading

0 comments on commit d0c1b2b

Please sign in to comment.