diff --git a/Cargo.lock b/Cargo.lock index 55f008b..7b341cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -44,7 +53,10 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" name = "boringtun" version = "0.4.0" dependencies = [ + "aead", "base64", + "chacha20poly1305", + "criterion", "hex", "ip_network", "ip_network_table", @@ -65,7 +77,7 @@ name = "boringtun-cli" version = "0.1.0" dependencies = [ "boringtun", - "clap", + "clap 3.1.6", "daemonize", "tracing", "tracing-appender", @@ -78,6 +90,18 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426" +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + [[package]] name = "bumpalo" version = "3.9.1" @@ -96,6 +120,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "cast" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +dependencies = [ + "rustc_version", +] + [[package]] name = "cc" version = "1.0.72" @@ -114,6 +147,51 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chacha20" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01b72a433d0cf2aef113ba70f62634c56fddb0f244e6377185c56a7cadbd8f91" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b84ed6d1d5f7aa9bdde921a5090e0ca4d934d250ea3b402a5fab3a994e28a2a" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "bitflags", + "textwrap 0.11.0", + "unicode-width", +] + [[package]] name = "clap" version = "3.1.6" @@ -126,7 +204,7 @@ dependencies = [ "os_str_bytes", "strsim", "termcolor", - "textwrap", + "textwrap 0.15.0", ] [[package]] @@ -139,6 +217,51 @@ dependencies = [ "memchr", ] +[[package]] +name = "cpufeatures" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] + +[[package]] +name = "criterion" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +dependencies = [ + "atty", + "cast", + "clap 2.34.0", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_cbor", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +dependencies = [ + "cast", + "itertools", +] + [[package]] name = "crossbeam-channel" version = "0.5.2" @@ -149,6 +272,31 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "once_cell", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.7" @@ -159,6 +307,28 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + [[package]] name = "curve25519-dalek" version = "3.2.1" @@ -191,6 +361,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "generic-array" version = "0.14.5" @@ -212,6 +388,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "hashbrown" version = "0.11.2" @@ -265,6 +447,21 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + [[package]] name = "itoa" version = "1.0.1" @@ -358,6 +555,25 @@ dependencies = [ "memoffset", ] +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "num_threads" version = "0.1.3" @@ -373,6 +589,18 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "os_str_bytes" version = "6.0.0" @@ -411,6 +639,45 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +[[package]] +name = "plotters" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" + +[[package]] +name = "plotters-svg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "proc-macro2" version = "1.0.36" @@ -438,6 +705,30 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.10" @@ -447,6 +738,27 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + +[[package]] +name = "regex-syntax" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" + [[package]] name = "ring" version = "0.16.20" @@ -462,6 +774,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" + [[package]] name = "same-file" version = "1.0.6" @@ -477,6 +804,50 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "semver" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c" + +[[package]] +name = "serde" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +dependencies = [ + "itoa 1.0.1", + "ryu", + "serde", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -542,6 +913,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "textwrap" version = "0.15.0" @@ -583,11 +963,21 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d" dependencies = [ - "itoa", + "itoa 1.0.1", "libc", "num_threads", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tracing" version = "0.1.31" @@ -663,12 +1053,28 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "untrusted" version = "0.7.1" @@ -870,9 +1276,9 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81e8f13fef10b63c06356d65d416b070798ddabcadc10d3ece0c5be9b3c7eddb" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index fa52de5..d6f8ade 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,8 @@ members = ["boringtun", "boringtun-cli"] [profile.release] lto = true # Enable full link-time optimization. -codegen-units = 1 # Use only 1 codegen-unit to enable full optimizations. \ No newline at end of file +codegen-units = 1 # Use only 1 codegen-unit to enable full optimizations. + +[profile.bench] +lto = true # Enable full link-time optimization. +codegen-units = 1 # Use only 1 codegen-unit to enable full optimizations. diff --git a/README.md b/README.md index ccd70f2..606c19c 100644 --- a/README.md +++ b/README.md @@ -51,16 +51,6 @@ Testing this project has a few requirements: - `sudo`: required to create tunnels. When you run `cargo test` you'll be prompted for your password. - Docker: you can install it [here](https://www.docker.com/get-started). If you are on Ubuntu/Debian you can run `apt-get install docker.io`. -### Benchmarking - -To benchmark this project you can run this command: - -``` -cargo +nightly bench -``` - -This command depends on the unstable `test` feature of the Rust compiler. As a result, you'll need to use the `nightly` channel of Rust when you run it. - ## Supported platforms Target triple |Binary|Library| | diff --git a/boringtun/Cargo.toml b/boringtun/Cargo.toml index 0f0ff98..dd79ed0 100644 --- a/boringtun/Cargo.toml +++ b/boringtun/Cargo.toml @@ -23,6 +23,9 @@ rand_core = "0.5.1" [dev-dependencies] tracing-subscriber = "0.3" +criterion = { version = "0.3.5", features = ["html_reports"] } +chacha20poly1305 = "0.9.0" +aead = "0.4.3" [target.'cfg(target_os="android")'.dependencies] jni = "0.19.0" @@ -30,6 +33,6 @@ jni = "0.19.0" [target.'cfg(target_os="macos")'.dependencies] nix = "0.23.1" -[[example]] -name = "benchmarks" -path = "src/benchmarks_example.rs" +[[bench]] +name = "crypto_benches" +harness = false diff --git a/boringtun/benches/crypto_benches/blake2s_benching.rs b/boringtun/benches/crypto_benches/blake2s_benching.rs new file mode 100644 index 0000000..85a21ff --- /dev/null +++ b/boringtun/benches/crypto_benches/blake2s_benching.rs @@ -0,0 +1,23 @@ +use boringtun::crypto::Blake2s; +use criterion::{BenchmarkId, Criterion, Throughput}; + +pub fn bench_blake2s(c: &mut Criterion) { + let mut group = c.benchmark_group("blake2s"); + + group.sample_size(1000); + + for size in [128, 1024] { + group.throughput(Throughput::Bytes(size as u64)); + + group.bench_with_input(BenchmarkId::from_parameter(size), &size, |b, _| { + let buf_in = vec![0u8; size]; + + b.iter(|| { + Blake2s::new_hash().hash(&buf_in).finalize(); + buf_in.len() + }); + }); + } + + group.finish(); +} diff --git a/boringtun/benches/crypto_benches/chacha20poly1305_benching.rs b/boringtun/benches/crypto_benches/chacha20poly1305_benching.rs new file mode 100644 index 0000000..edde450 --- /dev/null +++ b/boringtun/benches/crypto_benches/chacha20poly1305_benching.rs @@ -0,0 +1,99 @@ +use aead::{AeadInPlace, NewAead}; +use criterion::{BenchmarkId, Criterion, Throughput}; +use rand_core::{OsRng, RngCore}; +use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; + +fn chacha20poly1305_ring(key_bytes: &[u8], buf: &mut [u8]) { + let len = buf.len(); + let n = len - 16; + + let key = LessSafeKey::new(UnboundKey::new(&CHACHA20_POLY1305, &key_bytes).unwrap()); + + let tag = key + .seal_in_place_separate_tag( + Nonce::assume_unique_for_key([0u8; 12]), + Aad::from(&[]), + &mut buf[..n], + ) + .unwrap(); + + buf[n..].copy_from_slice(tag.as_ref()) +} + +fn chacha20poly1305_non_ring(key_bytes: &[u8], buf: &mut [u8]) { + let len = buf.len(); + let n = len - 16; + + let aead = chacha20poly1305::ChaCha20Poly1305::new_from_slice(key_bytes).unwrap(); + let nonce = chacha20poly1305::Nonce::default(); + + let tag = aead + .encrypt_in_place_detached(&nonce, &[], &mut buf[..n]) + .unwrap(); + + buf[n..].copy_from_slice(tag.as_ref()); +} + +pub fn bench_chacha20poly1305(c: &mut Criterion) { + let mut group = c.benchmark_group("chacha20poly1305"); + + group.sample_size(1000); + + for size in [128, 192, 1400, 8192] { + group.throughput(Throughput::Bytes(size as u64)); + + group.bench_with_input( + BenchmarkId::new("chacha20poly1305_ring", size), + &size, + |b, i| { + let mut key = [0; 32]; + let mut buf = vec![0; i + 16]; + + let mut rng = OsRng::default(); + + rng.fill_bytes(&mut key); + rng.fill_bytes(&mut buf); + + b.iter(|| chacha20poly1305_ring(&key, &mut buf)); + }, + ); + + group.bench_with_input( + BenchmarkId::new("chacha20poly1305_non_ring", size), + &size, + |b, i| { + let mut key = [0; 32]; + let mut buf = vec![0; i + 16]; + + let mut rng = OsRng::default(); + + rng.fill_bytes(&mut key); + rng.fill_bytes(&mut buf); + + b.iter(|| chacha20poly1305_non_ring(&key, &mut buf)); + }, + ); + + group.bench_with_input( + BenchmarkId::new("chacha20poly1305_custom", size), + &size, + |b, _| { + let mut key = [0; 32]; + + let mut buf_in = vec![0u8; size]; + let mut buf_out = vec![0u8; size + 16]; + + let mut rng = OsRng::default(); + + rng.fill_bytes(&mut key); + rng.fill_bytes(&mut buf_in); + + let aead = boringtun::crypto::ChaCha20Poly1305::new_aead(&key); + + b.iter(|| aead.seal_wg(0, &[], &buf_in, &mut buf_out) - 16) + }, + ); + } + + group.finish(); +} diff --git a/boringtun/benches/crypto_benches/main.rs b/boringtun/benches/crypto_benches/main.rs new file mode 100644 index 0000000..0457f16 --- /dev/null +++ b/boringtun/benches/crypto_benches/main.rs @@ -0,0 +1,18 @@ +use blake2s_benching::bench_blake2s; +use chacha20poly1305_benching::bench_chacha20poly1305; +use x25519_public_key_benching::bench_x25519_public_key; +use x25519_shared_key_benching::bench_x25519_shared_key; + +mod blake2s_benching; +mod chacha20poly1305_benching; +mod x25519_public_key_benching; +mod x25519_shared_key_benching; + +criterion::criterion_group!( + crypto_benches, + bench_chacha20poly1305, + bench_blake2s, + bench_x25519_shared_key, + bench_x25519_public_key +); +criterion::criterion_main!(crypto_benches); diff --git a/boringtun/benches/crypto_benches/x25519_public_key_benching.rs b/boringtun/benches/crypto_benches/x25519_public_key_benching.rs new file mode 100644 index 0000000..5814d9b --- /dev/null +++ b/boringtun/benches/crypto_benches/x25519_public_key_benching.rs @@ -0,0 +1,30 @@ +use criterion::Criterion; +use rand_core::OsRng; + +pub fn bench_x25519_public_key(c: &mut Criterion) { + let mut group = c.benchmark_group("x25519_public_key"); + + group.sample_size(1000); + + group.bench_function("x25519_public_key_dalek", |b| { + b.iter(|| { + let secret_key = x25519_dalek::StaticSecret::new(OsRng); + let public_key = x25519_dalek::PublicKey::from(&secret_key); + + (secret_key, public_key) + }); + }); + + group.bench_function("x25519_public_key_ring", |b| { + let rng = ring::rand::SystemRandom::new(); + + b.iter(|| { + let my_private_key = + ring::agreement::EphemeralPrivateKey::generate(&ring::agreement::X25519, &rng) + .unwrap(); + my_private_key.compute_public_key().unwrap() + }); + }); + + group.finish(); +} diff --git a/boringtun/benches/crypto_benches/x25519_shared_key_benching.rs b/boringtun/benches/crypto_benches/x25519_shared_key_benching.rs new file mode 100644 index 0000000..c2af698 --- /dev/null +++ b/boringtun/benches/crypto_benches/x25519_shared_key_benching.rs @@ -0,0 +1,52 @@ +use criterion::{BatchSize, Criterion}; +use rand_core::OsRng; + +pub fn bench_x25519_shared_key(c: &mut Criterion) { + let mut group = c.benchmark_group("x25519_shared_key"); + + group.sample_size(1000); + + group.bench_function("x25519_shared_key_dalek", |b| { + let public_key = x25519_dalek::PublicKey::from(&x25519_dalek::StaticSecret::new(OsRng)); + + b.iter_batched( + || x25519_dalek::StaticSecret::new(OsRng), + |secret_key| secret_key.diffie_hellman(&public_key), + BatchSize::SmallInput, + ); + }); + + group.bench_function("x25519_shared_key_ring", |b| { + let rng = ring::rand::SystemRandom::new(); + + let peer_public_key = { + let peer_private_key = + ring::agreement::EphemeralPrivateKey::generate(&ring::agreement::X25519, &rng) + .unwrap(); + peer_private_key.compute_public_key().unwrap() + }; + let peer_public_key_alg = &ring::agreement::X25519; + + let my_public_key = + ring::agreement::UnparsedPublicKey::new(peer_public_key_alg, &peer_public_key); + + b.iter_batched( + || { + ring::agreement::EphemeralPrivateKey::generate(&ring::agreement::X25519, &rng) + .unwrap() + }, + |my_private_key| { + ring::agreement::agree_ephemeral( + my_private_key, + &my_public_key, + ring::error::Unspecified, + |_key_material| Ok(()), + ) + .unwrap() + }, + BatchSize::SmallInput, + ); + }); + + group.finish(); +} diff --git a/boringtun/benches/mod.rs b/boringtun/benches/mod.rs deleted file mode 100644 index 6520fd7..0000000 --- a/boringtun/benches/mod.rs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2019 Cloudflare, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#![feature(test)] -extern crate test; - -#[cfg(test)] -mod tests { - use boringtun::crypto::Blake2s; - use boringtun::crypto::ChaCha20Poly1305; - use rand_core::OsRng; - use test::{black_box, Bencher}; - use x25519_dalek::{PublicKey, StaticSecret}; - - #[bench] - fn bench_x25519_public_key(b: &mut Bencher) { - let secret_key = StaticSecret::new(OsRng); - - b.iter(|| { - black_box(PublicKey::from(&secret_key)); - }); - } - - #[bench] - fn bench_x25519_shared_key(b: &mut Bencher) { - let secret_key = StaticSecret::new(OsRng); - let public_key = PublicKey::from(&StaticSecret::new(OsRng)); - - b.iter(|| black_box(secret_key.diffie_hellman(&public_key))); - } - - #[bench] - fn bench_blake2s_hash_128b(b: &mut Bencher) { - let data = [0_u8; 128]; - b.iter(|| black_box(Blake2s::new_hash().hash(&data).finalize())); - } - - #[bench] - fn bench_blake2s_hash_1024b(b: &mut Bencher) { - let data = [0_u8; 1024]; - b.iter(|| black_box(Blake2s::new_hash().hash(&data).finalize())); - } - - #[bench] - fn bench_chacha20poly1305_seal_192b(b: &mut Bencher) { - let pc = ChaCha20Poly1305::new_aead(&[ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, - ]); - let pt = [0_u8; 192]; - let mut ct = [0_u8; 192 + 16]; - b.iter(|| { - black_box(pc.seal_wg(0, &[], &pt, &mut ct)); - }); - } - - #[bench] - fn bench_chacha20poly1305_open_192b(b: &mut Bencher) { - let pc = ChaCha20Poly1305::new_aead(&[ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, - ]); - let mut pt = [0_u8; 192]; - let mut ct = [0_u8; 192 + 16]; - - pc.seal_wg(0, &[], &pt, &mut ct); - - b.iter(|| { - black_box(pc.open_wg(0, &[], &ct, &mut pt).unwrap()); - }); - } - - #[bench] - fn bench_chacha20poly1305_seal_512b(b: &mut Bencher) { - let pc = ChaCha20Poly1305::new_aead(&[ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, - ]); - let pt = [0_u8; 512]; - let mut ct = [0_u8; 512 + 16]; - b.iter(|| { - black_box(pc.seal_wg(0, &[], &pt, &mut ct)); - }); - } - - #[bench] - fn bench_chacha20poly1305_seal_8192b(b: &mut Bencher) { - let pc = ChaCha20Poly1305::new_aead(&[ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, - ]); - let pt = [0_u8; 8192]; - let mut ct = [0_u8; 8192 + 16]; - b.iter(|| { - black_box(pc.seal_wg(0, &[], &pt, &mut ct)); - }); - } -} diff --git a/boringtun/src/benchmarks_example.rs b/boringtun/src/benchmarks_example.rs deleted file mode 100644 index 33ae2bd..0000000 --- a/boringtun/src/benchmarks_example.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2019 Cloudflare, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause -mod crypto; -mod ffi; -mod noise; -mod serialization; - -use ffi::benchmark::do_benchmark; -use std::io::prelude::Write; - -fn main() { - let mut i = 0; - while let Some(benchmark_name) = do_benchmark(true, i) { - print!("{}", benchmark_name); - std::io::stdout().flush().unwrap(); - let benchmark_result = do_benchmark(false, i).unwrap(); - println!("{}", benchmark_result); - i += 1; - } - println!("Done"); -} diff --git a/boringtun/src/crypto/chacha20poly1305/mod.rs b/boringtun/src/crypto/chacha20poly1305_custom/mod.rs similarity index 100% rename from boringtun/src/crypto/chacha20poly1305/mod.rs rename to boringtun/src/crypto/chacha20poly1305_custom/mod.rs diff --git a/boringtun/src/crypto/chacha20poly1305/poly1305.rs b/boringtun/src/crypto/chacha20poly1305_custom/poly1305.rs similarity index 100% rename from boringtun/src/crypto/chacha20poly1305/poly1305.rs rename to boringtun/src/crypto/chacha20poly1305_custom/poly1305.rs diff --git a/boringtun/src/crypto/chacha20poly1305/tests.rs b/boringtun/src/crypto/chacha20poly1305_custom/tests.rs similarity index 100% rename from boringtun/src/crypto/chacha20poly1305/tests.rs rename to boringtun/src/crypto/chacha20poly1305_custom/tests.rs diff --git a/boringtun/src/crypto/mod.rs b/boringtun/src/crypto/mod.rs index 32718dc..17ec5c2 100644 --- a/boringtun/src/crypto/mod.rs +++ b/boringtun/src/crypto/mod.rs @@ -4,9 +4,9 @@ //! Optimized cryptographic primitives for the WireGuard protocol. mod blake2s; -mod chacha20poly1305; +mod chacha20poly1305_custom; pub use blake2s::{constant_time_mac_check, Blake2s}; -pub use chacha20poly1305::ChaCha20Poly1305; +pub use chacha20poly1305_custom::ChaCha20Poly1305; pub use ring::rand::SystemRandom; diff --git a/boringtun/src/ffi/benchmark.rs b/boringtun/src/ffi/benchmark.rs deleted file mode 100644 index 9cd786a..0000000 --- a/boringtun/src/ffi/benchmark.rs +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2019 Cloudflare, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -/// This module implements benchmarking code for use with the FFI bindings -use crate::crypto::{Blake2s, ChaCha20Poly1305}; -use rand_core::OsRng; -use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; -use ring::{agreement, rand}; -use x25519_dalek::{PublicKey, StaticSecret}; - -use std::time::Instant; - -const ITR_DURATION: u64 = 1; -const ITRS: u64 = 3; - -// Format f64 with US locale decimal separators -// We don't care about speed or efficiency here -// Assumes that f64 in this context is always smaller than u64::MAX and larger than 0 -fn format_float(number: f64) -> String { - let fract = number.fract(); - let mut integer = number.trunc() as u64; - - let mut formatted = format!("{:.2}", fract); - if integer == 0 { - // Return with the leading 0 - return formatted; - } - // Strip the 0 - formatted = formatted[1..].to_string(); - - loop { - let remainder = integer % 1000; - integer /= 1000; - - if integer == 0 { - let mut new_str = format!("{:}", remainder); - new_str.push_str(&formatted); - formatted = new_str; - break; - } - - let mut new_str = format!(",{:03}", remainder); - new_str.push_str(&formatted); - formatted = new_str; - } - - formatted -} - -fn run_bench(test_func: &mut dyn FnMut() -> usize) -> f64 { - let mut best_time = std::f64::MAX; - - // Take the best result out of ITRS runs - for _ in 0..ITRS { - let start_time = Instant::now(); - let mut total_itr = 0; - loop { - for _ in 0..300 { - total_itr += test_func(); - } - // Check time every 300 iterations - let time_since_started = Instant::now().duration_since(start_time); - if time_since_started.as_secs() >= ITR_DURATION { - // Stop the benchmark after ITR_DURATION - let total_time = time_since_started.as_secs() as f64 - + f64::from(time_since_started.subsec_nanos()) * 1e-9; - best_time = best_time.min((total_itr as f64) / total_time); - break; - } - } - } - - best_time -} - -fn bench_x25519_shared_key(name: bool, _: usize) -> String { - if name { - return "X25519 Shared Key: ".to_string(); - } - - let secret_key = StaticSecret::new(OsRng); - let public_key = PublicKey::from(&StaticSecret::new(OsRng)); - - let result = run_bench(&mut move || { - let _ = secret_key.diffie_hellman(&public_key); - 1 - }); - - format!("{} ops/sec", format_float(result)) -} - -fn bench_x25519_public_key(name: bool, _: usize) -> String { - if name { - return "X25519 Public Key: ".to_string(); - } - - let secret_key = StaticSecret::new(OsRng); - - let result = run_bench(&mut move || { - let _ = PublicKey::from(&secret_key); - 1 - }); - - format!("{} ops/sec", format_float(result)) -} - -fn bench_blake2s(name: bool, n: usize) -> String { - if name { - return format!("Blake2s {}B: ", n); - } - - let buf_in = vec![0u8; n]; - - let result = run_bench(&mut move || { - Blake2s::new_hash().hash(&buf_in).finalize(); - buf_in.len() - }); - - format!("{} MiB/s", format_float(result / (1024. * 1024.))) -} - -fn bench_chacha20poly1305_ring(name: bool, n: usize) -> String { - if name { - return format!("(Ring) AEAD Seal {}B: ", n); - } - - let key = LessSafeKey::new(UnboundKey::new(&CHACHA20_POLY1305, &[0x0fu8; 32]).unwrap()); - let mut buf_in = vec![0u8; n + 16]; - - let result = run_bench(&mut move || { - let tag_len = CHACHA20_POLY1305.tag_len(); - let buf_len = buf_in.len(); - key.seal_in_place_separate_tag( - Nonce::assume_unique_for_key([0u8; 12]), - Aad::from(&[]), - &mut buf_in[..buf_len - tag_len], - ) - .map(|tag| { - buf_in[buf_len - tag_len..].copy_from_slice(tag.as_ref()); - buf_len - }) - .unwrap() - }); - - format!("{} MiB/s", format_float(result / (1024. * 1024.))) -} - -fn bench_chacha20poly1305(name: bool, n: usize) -> String { - if name { - return format!("AEAD Seal {}B: ", n); - } - - let aead = ChaCha20Poly1305::new_aead(&[0u8; 32]); - let buf_in = vec![0u8; n]; - let mut buf_out = vec![0u8; n + 16]; - - let result = run_bench(&mut move || aead.seal_wg(0, &[], &buf_in, &mut buf_out) - 16); - - format!("{} MiB/s", format_float(result / (1024. * 1024.))) -} - -fn bench_x25519_shared_key_ring(name: bool, _: usize) -> String { - if name { - return "(Ring) X25519 Shared Key: ".to_string(); - } - - let rng = rand::SystemRandom::new(); - - let peer_public_key = { - let peer_private_key = - agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); - peer_private_key.compute_public_key().unwrap() - }; - let peer_public_key_alg = &agreement::X25519; - - let result = run_bench(&mut move || { - let my_private_key = - agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); - let my_public_key = - agreement::UnparsedPublicKey::new(peer_public_key_alg, &peer_public_key); - - agreement::agree_ephemeral( - my_private_key, - &my_public_key, - ring::error::Unspecified, - |_key_material| Ok(()), - ) - .unwrap(); - 1 - }); - - format!("{} ops/sec", format_float(result)) -} - -fn bench_x25519_public_key_ring(name: bool, _: usize) -> String { - if name { - return "(Ring) X25519 Public Key: ".to_string(); - } - - let rng = rand::SystemRandom::new(); - - let result = run_bench(&mut move || { - let my_private_key = - agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng).unwrap(); - my_private_key.compute_public_key().unwrap(); - 1 - }); - format!("{} ops/sec", format_float(result)) -} - -type BenchFnc = fn(bool, usize) -> String; - -pub fn do_benchmark(name: bool, idx: usize) -> Option { - let benchmarks: Vec<(BenchFnc, usize)> = vec![ - (bench_x25519_public_key, 0), - (bench_x25519_shared_key, 0), - (bench_x25519_public_key_ring, 0), - (bench_x25519_shared_key_ring, 0), - (bench_blake2s, 128), - (bench_blake2s, 1024), - (bench_chacha20poly1305, 128), - (bench_chacha20poly1305, 192), - (bench_chacha20poly1305, 1400), - (bench_chacha20poly1305, 8192), - (bench_chacha20poly1305_ring, 128), - (bench_chacha20poly1305_ring, 192), - (bench_chacha20poly1305_ring, 1400), - (bench_chacha20poly1305_ring, 8192), - ]; - - if idx >= benchmarks.len() { - return None; - } - - let fnc = benchmarks[idx].0; - let param = benchmarks[idx].1; - Some(fnc(name, param)) -} diff --git a/boringtun/src/ffi/mod.rs b/boringtun/src/ffi/mod.rs index 29f8069..e78e714 100644 --- a/boringtun/src/ffi/mod.rs +++ b/boringtun/src/ffi/mod.rs @@ -6,8 +6,6 @@ #![allow(clippy::missing_safety_doc)] /// C bindings for the BoringTun library -pub mod benchmark; -use self::benchmark::do_benchmark; use super::noise::{Tunn, TunnResult}; use base64::{decode, encode}; use hex::encode as encode_hex; @@ -17,7 +15,6 @@ use x25519_dalek::{PublicKey, StaticSecret}; use crate::serialization::KeyBytes; use std::ffi::{CStr, CString}; -use std::mem; use std::os::raw::c_char; use std::panic; use std::ptr; @@ -322,16 +319,3 @@ pub unsafe extern "C" fn wireguard_stats(tunnel: *mut Tunn) -> stats { reserved: [0u8; 56], } } - -/// Performs an internal benchmark, and returns its result as a C-string. -#[no_mangle] -pub extern "C" fn benchmark(name: i32, idx: u32) -> *const c_char { - if let Some(s) = do_benchmark(name != 0, idx as usize) { - let s = CString::new(s).unwrap(); - let v = s.as_ptr(); - mem::forget(s); // This is a memory leak, but we assume it is rarely used anyway - v - } else { - ptr::null() - } -} diff --git a/boringtun/src/wireguard_ffi.h b/boringtun/src/wireguard_ffi.h index 9c12d53..f6cd31c 100644 --- a/boringtun/src/wireguard_ffi.h +++ b/boringtun/src/wireguard_ffi.h @@ -87,5 +87,3 @@ struct wireguard_result wireguard_force_handshake(struct wireguard_tunnel *tunne uint32_t dst_size); struct stats wireguard_stats(struct wireguard_tunnel *tunnel); - -const uint8_t *benchmark(int32_t name, uint32_t idx);