{"id":13546087,"url":"https://github.com/phayes/sidefuzz","last_synced_at":"2025-04-02T17:32:35.036Z","repository":{"id":47193958,"uuid":"181981287","full_name":"phayes/sidefuzz","owner":"phayes","description":"Fuzzer to automatically find side-channel (timing) vulnerabilities","archived":false,"fork":false,"pushed_at":"2021-06-16T13:30:52.000Z","size":295,"stargazers_count":114,"open_issues_count":10,"forks_count":8,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-19T00:00:46.583Z","etag":null,"topics":["constant-time","cryptography","dudect","fuzzing","rust","side-channel","wasm"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phayes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"patreon":"phayes","custom":"flattr.com/@phayes"}},"created_at":"2019-04-17T23:09:31.000Z","updated_at":"2024-11-09T03:40:58.000Z","dependencies_parsed_at":"2022-08-29T18:31:34.332Z","dependency_job_id":null,"html_url":"https://github.com/phayes/sidefuzz","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phayes%2Fsidefuzz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phayes%2Fsidefuzz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phayes%2Fsidefuzz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phayes%2Fsidefuzz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phayes","download_url":"https://codeload.github.com/phayes/sidefuzz/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246860263,"owners_count":20845634,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["constant-time","cryptography","dudect","fuzzing","rust","side-channel","wasm"],"created_at":"2024-08-01T12:00:31.323Z","updated_at":"2025-04-02T17:32:34.439Z","avatar_url":"https://github.com/phayes.png","language":"Rust","funding_links":["https://patreon.com/phayes","flattr.com/@phayes"],"categories":["Vulnerability Assessment","Rust"],"sub_categories":["Fuzzing"],"readme":"## SideFuzz: Fuzzing for side-channel vulnerabilities\n\n[![docs](https://docs.rs/sidefuzz/badge.svg)](https://docs.rs/sidefuzz)\n[![crates.io](https://meritbadge.herokuapp.com/sidefuzz)](https://crates.io/crates/sidefuzz)\n[![docs](https://docs.rs/sidefuzz/badge.svg)](https://docs.rs/sidefuzz)\n[![patreon](https://img.shields.io/badge/patreon-donate-green.svg)](https://patreon.com/phayes)\n[![flattr](https://img.shields.io/badge/flattr-donate-green.svg)](https://flattr.com/@phayes)\n\u003ca href=\"https://github.com/taibangle/awesome-china\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/phayes/awesome-china/master/badges/awesome-china.png\" width=\"98\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/taibangle/awesome-china\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/phayes/awesome-china/master/badges/很棒-中国.png\" width=\"66\"\u003e\u003c/a\u003e\n\nSideFuzz is an adaptive fuzzer that uses a genetic-algorithm optimizer in combination with t-statistics to find side-channel (timing) vulnerabilities in cryptography compiled to [wasm](https://webassembly.org).\n\nFuzzing Targets can be found here: https://github.com/phayes/sidefuzz-targets\n\n### How it works\n\nSideFuzz works by counting instructions executed in the [wasmi](https://github.com/paritytech/wasmi) wasm interpreter. It works in two phases:\n\n**Phase 1.** Uses a genetic-algorithm optimizer that tries to maximize the difference in instructions executed between two different inputs. It will continue optimizing until subsequent generations of input-pairs no longer produce any meaningful differences in the number of instructions executed. This means that it will optimize until it finds finds a local optimum in the fitness of input pairs.\n\n**Phase 2.** Once a local optimum is found, the leading input-pairs are sampled until either:\n\n- A large t-statistic (p = 0.001) is found, indicating that there is a statistically significant difference in running-time between the two inputs. This is indicative of a timing side-channel vulnerability; or\n\n- The t-statistic stays low, even after significant sampling. In this case the candidate input pairs are rejected and SideFuzz returns to phase 1, resuming the genetic-algorithm optimizer to find another local optimum.\n\n### What it gets you\n\nFuzzing with SideFuzz shows that your Rust code can be constant-time, but doesn't show that it _is_ constant-time on all architectures. This is because LLVM backends [can and will](http://www.reparaz.net/oscar/misc/cmov.html) ruin constant-time Rust / LLVM-IR when compiling to machine-code. SideFuzz should be considered a \"good first step\" to be followed up with [dudect-bencher](https://crates.io/crates/dudect-bencher) and [ctgrind](https://github.com/RustCrypto/utils/tree/master/ctgrind). It should also be noted that proper compiler support for constant-time code-generation is an unsolved problem in the Rust ecosystem. There have been some ideas around using [cranelift](https://github.com/CraneStation/cranelift) for constant-time code generation, but things are still in the brainstorming phase.\n\n## Installation\n\n```\nrustup target add wasm32-unknown-unknown\ngit clone git@github.com:phayes/sidefuzz.git\ncd sidefuzz \u0026\u0026 cargo install --path .\n```\n\n(Cannot currently do `cargo install sidefuzz` because of [this issue](https://github.com/phayes/sidefuzz/issues/12))\n\n## Creating a Rust fuzz target\n\nCreating a target in rust is very easy.\n\n```rust\n// lib.rs\n#[no_mangle]\npub extern \"C\" fn fuzz() {\n  let input = sidefuzz::fetch_input(32); // 32 bytes of of fuzzing input as a \u0026[u8]\n  sidefuzz::black_box(my_hopefully_constant_fn(input));\n}\n```\n\n```toml\n# Cargo.toml\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nsidefuzz = \"0.1.1\"\n```\n\nCompile and fuzz the target like so:\n\n```bash\ncargo build --release --target wasm32-unknown-unknown                # Always build in release mode\nsidefuzz fuzz ./target/wasm32-unknown-unknown/release/my_target.wasm # Fuzzing!\n```\n\nResults can be checked like so:\n\n```bash\nsidefuzz check my_target.wasm 01250bf9 ff81f7b3\n```\n\nWhen fixing variable-time code, sidefuzz can also help with `sidefuzz count` to quickly count the number of instructions executed by the target.\n\n```bash\nsidefuzz count my_target.wasm 01250bf9\n```\n\n## Creating a fuzz target in other languages\n\nSideFuzz works with Go, C, C++ and other langauges that compile to wasm.\n\nThe wasm module should provide four exports:\n\n1. Memory exported to \"memory\"\n\n2. A function named \"fuzz\". This function will be repeatedly called during the fuzzing process.\n\n3. A function named \"input_pointer\" that returns an i32 pointer to a location in linear memory where we can can write an array of input bytes. The \"fuzz\" function should read this array of bytes as input for it's fuzzing.\n\n4. A function named \"input_len\" that returns an i32 with the desired length of input in bytes.\n\n## FAQ\n\n#### 1. Why wasm?\n\nWeb Assembly allows us to precisely track the number of instructions executed, the type of instructions executed, and the amount of memory used. This is much more precise than other methods such as tracking wall-time or counting CPU cycles.\n\n#### 2. Why do I always need to build in release mode?\n\nMany constant-time functions include calls to variable-time `debug_assert!()` functions that get removed during a release build. Rust's and LLVM optimizer may also mangle supposedly constant-time code in the name of optimization, introducing subtle timing vulnerabilities. Running in release mode let's us surface these issues.\n\n#### 3. I need an RNG (Random Number Generator). What do?\n\nYou should make use of a PRNG with a static seed. While this is a bad idea for production code, it's great for fuzzing. See the [rsa_encrypt_pkcs1v15_message target](https://github.com/phayes/sidefuzz-targets/blob/master/rsa_encrypt_pkcs1v15_message/src/lib.rs) for an example on how to do this.\n\n#### 4. What's up with `black_box` ?\n\n`sidefuzz::black_box` is used to avoid dead-code elimination. Because we are interested in exercising the fuzzed code instead of getting results from it, the exported `fuzz` function doesn't return anything. The Rust optimizer sees all functions that don't return as dead-code and will try to eliminate them as part of it's optimizations. `black_box` is a function that is opaque to the optimizer, allowing us to exercise functions that don't return without them being optimized away. It should be used whenever calling a function that doesn't return anything or where we are ignoring the output returned.\n\n#### 5. The fuzzer gave me invalid inputs, what now?\n\nYou should panic (causing a wasm trap). This will signal to the fuzzer that the inputs are invalid.\n\n#### 6. I need to do some variable-time set-up. How do I do that?\n\nYou should use [`lazy_static`](https://crates.io/crates/lazy_static) to do any set-up work (like generating keys etc). The target is always run once to prime lazy statics before the real fuzzing starts.\n\n## Related Tools\n\n1. `dudect-bencher`. An implementation of the DudeCT constant-time function tester. In comparison to SideFuzz, this tool more closely adheres to the original dudect design. https://crates.io/crates/dudect-bencher\n\n2. `ctgrind`. Tool for checking that functions are constant time using Valgrind. https://github.com/RustCrypto/utils/tree/master/ctgrind\n\n## Further Reading\n\n1. \"DifFuzz: Differential Fuzzing for Side-Channel Analysis\", Nilizadeh, Noller, Păsăreanu.\n   https://arxiv.org/abs/1811.07005\n\n2. \"Dude, is my code constant time?\", Reparaz et al. https://eprint.iacr.org/2016/1123.pdf\n\n3. \"Rust, dudect and constant-time crypto in debug mode\", brycx.\n   https://brycx.github.io/2019/04/21/rust-dudect-constant-time-crypto.html\n\n## Contributors\n\n1.  Patrick Hayes ([linkedin](https://www.linkedin.com/in/patrickdhayes/)) ([github](https://github.com/phayes)) - Available for hire.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphayes%2Fsidefuzz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphayes%2Fsidefuzz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphayes%2Fsidefuzz/lists"}