diff --git a/Cargo.lock b/Cargo.lock index 039eb7baa..231c6f09b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,19 +4,19 @@ version = 4 [[package]] name = "aead" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99" dependencies = [ "crypto-common", - "generic-array", + "inout", ] [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] @@ -88,44 +88,50 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base64" -version = "0.22.1" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b25655df2c3cdd83c5e5b293b88acd880332b2ddadd7c30ac43144fdc0033da9" + +[[package]] +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" [[package]] name = "blake2" -version = "0.10.6" +version = "0.11.0-rc.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +checksum = "061f1a09225e328e1ffbb378d2d49923c0ca5fee19fb5ac1cc9c1e9d52b93690" dependencies = [ "digest", ] [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] @@ -137,24 +143,29 @@ dependencies = [ "blake2", "chacha20poly1305", "criterion", + "defmt", "etherparse", + "fugit", "hex", "hmac", "ip_network", "ip_network_table", "jni", "libc", - "mock_instant", + "lock_api", "nix", + "once_cell", "parking_lot", "portable-atomic", - "rand_core", + "rand", "ring", "socket2", - "thiserror 2.0.18", + "spin", + "thiserror 2.0.19", "tracing", "tracing-subscriber", "untrusted", + "winsafe", "x25519-dalek", ] @@ -172,15 +183,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cast" @@ -190,9 +201,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.61" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9" dependencies = [ "find-msvc-tools", "shlex", @@ -212,15 +223,15 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" -version = "0.9.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if", "cipher", @@ -229,15 +240,14 @@ dependencies = [ [[package]] name = "chacha20poly1305" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +checksum = "9b89e1c441e926b9c82a8d023f6e1b7ae0adcfaa7d621814e4d60789bac751cb" dependencies = [ "aead", "chacha20", "cipher", "poly1305", - "zeroize", ] [[package]] @@ -269,29 +279,29 @@ dependencies = [ [[package]] name = "cipher" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" dependencies = [ + "block-buffer", "crypto-common", "inout", - "zeroize", ] [[package]] name = "clap" -version = "4.6.1" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +checksum = "301b56658598e48f3648647ac6fc887be7e7108eddfa4e9b63fcf3ec58c0cadf" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.6.0" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +checksum = "94a65403d1a1bd28f7dc68eb8506e8874808ee5eecb59298de588e2e1407a078" dependencies = [ "anstream", "anstyle", @@ -305,6 +315,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "colorchoice" version = "1.0.5" @@ -323,9 +339,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -365,20 +381,26 @@ dependencies = [ "itertools", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -386,18 +408,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crunchy" @@ -407,20 +429,28 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" -version = "0.1.7" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ - "generic-array", + "hybrid-array", "rand_core", - "typenum", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", ] [[package]] name = "curve25519-dalek" -version = "4.1.3" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +checksum = "b5eed333089e2e1c1ac8c6c0398e5e2497b4c9926ca6d0365ed1e099afa5bc23" dependencies = [ "cfg-if", "cpufeatures", @@ -439,7 +469,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -451,31 +481,59 @@ dependencies = [ "libc", ] +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.19", +] + [[package]] name = "deranged" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", -] [[package]] name = "digest" -version = "0.10.7" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer", "crypto-common", - "subtle", + "ctutils", ] [[package]] name = "either" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" [[package]] name = "etherparse" @@ -488,9 +546,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.9" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" [[package]] name = "find-msvc-tools" @@ -498,23 +556,33 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fugit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88e2d6927cbdbbbdc85fc550cee539e63ae0f76445f13094833f63bb65b62f5" +dependencies = [ + "defmt", + "gcd", +] + [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" dependencies = [ "futures-core", "futures-task", @@ -523,14 +591,10 @@ dependencies = [ ] [[package]] -name = "generic-array" -version = "0.14.7" +name = "gcd" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" [[package]] name = "getrandom" @@ -543,6 +607,18 @@ dependencies = [ "wasi", ] +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core", +] + [[package]] name = "half" version = "2.7.1" @@ -562,20 +638,29 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hmac" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ "digest", ] +[[package]] +name = "hybrid-array" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +dependencies = [ + "typenum", +] + [[package]] name = "inout" -version = "0.1.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] @@ -660,18 +745,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "js-sys" -version = "0.3.97" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -683,9 +767,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "lock_api" @@ -698,29 +782,23 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - -[[package]] -name = "mock_instant" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9366861eb2a2c436c20b12c8dbec5f798cea6b47ad99216be0282942e2c81ea0" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "nix" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags", + "bitflags 2.13.1", "cfg-if", "cfg_aliases", "libc", @@ -737,9 +815,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-traits" @@ -755,6 +833,10 @@ name = "once_cell" version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +dependencies = [ + "critical-section", + "portable-atomic", +] [[package]] name = "once_cell_polyfill" @@ -768,12 +850,6 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - [[package]] name = "page_size" version = "0.6.0" @@ -843,20 +919,19 @@ dependencies = [ [[package]] name = "poly1305" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +checksum = "6e2d0073b297041425c7c3df6eb4792d598a15323fe63346852b092eca02904c" dependencies = [ "cpufeatures", - "opaque-debug", "universal-hash", ] [[package]] name = "portable-atomic" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" [[package]] name = "powerfmt" @@ -866,31 +941,44 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.45" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] [[package]] -name = "rand_core" -version = "0.6.4" +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "getrandom", + "getrandom 0.4.3", + "rand_core", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rayon" version = "1.12.0" @@ -917,14 +1005,14 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.13.1", ] [[package]] name = "regex" -version = "1.12.3" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -934,9 +1022,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "ca71a6a1a566e01ad6b3b87edcbf9bd3374c27e31978c1b4e38c9fa6412557d2" dependencies = [ "aho-corasick", "memchr", @@ -945,9 +1033,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "ring" @@ -957,7 +1045,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -974,9 +1062,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "same-file" @@ -1001,9 +1089,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -1011,29 +1099,29 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -1053,9 +1141,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "slab" @@ -1065,9 +1153,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "socket2" @@ -1079,6 +1167,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "spin" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8abadc99fd9c7bbb7d0ca2b31d72a067d0c0dcd7aad25ab8cac71ba91417694b" +dependencies = [ + "lock_api", +] + [[package]] name = "strsim" version = "0.11.1" @@ -1099,9 +1196,20 @@ checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" [[package]] name = "syn" -version = "2.0.117" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" dependencies = [ "proc-macro2", "quote", @@ -1119,11 +1227,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl 2.0.19", ] [[package]] @@ -1134,37 +1242,36 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "thiserror-impl" -version = "2.0.18" +version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "thread_local" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" dependencies = [ "cfg-if", ] [[package]] name = "time" -version = "0.3.47" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde_core", @@ -1174,15 +1281,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" dependencies = [ "num-conv", "time-core", @@ -1217,7 +1324,7 @@ checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" dependencies = [ "crossbeam-channel", "symlink", - "thiserror 2.0.18", + "thiserror 2.0.19", "time", "tracing-subscriber", ] @@ -1230,7 +1337,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] @@ -1270,9 +1377,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-ident" @@ -1282,12 +1389,12 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "universal-hash" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96" dependencies = [ "crypto-common", - "subtle", + "ctutils", ] [[package]] @@ -1308,12 +1415,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "walkdir" version = "2.5.0" @@ -1332,9 +1433,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasm-bindgen" -version = "0.2.120" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -1345,9 +1446,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.120" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1355,31 +1456,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.120" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.120" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.97" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -1504,60 +1605,52 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winsafe" +version = "0.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d3922ac07e168376bc6799e7896fc737ddb9538be7533ca44bc3463091db1ad" + [[package]] name = "x25519-dalek" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +checksum = "e7e8131a03190127fb2263afc72b322ecadae46b6ff8c6f399ff5d02f5559af6" dependencies = [ "curve25519-dalek", + "getrandom 0.4.3", "rand_core", - "serde", "zeroize", ] [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" [[package]] name = "zmij" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/boringtun-cli/src/main.rs b/boringtun-cli/src/main.rs index c3009e3c8..b14e22e68 100644 --- a/boringtun-cli/src/main.rs +++ b/boringtun-cli/src/main.rs @@ -128,7 +128,7 @@ fn main() { let log = matches.get_one::("log").unwrap(); let log_file = - File::create(log).unwrap_or_else(|_| panic!("Could not create log file {}", log)); + File::create(log).unwrap_or_else(|_| panic!("Could not create log file {log}")); let (non_blocking, guard) = tracing_appender::non_blocking(log_file); diff --git a/boringtun/Cargo.toml b/boringtun/Cargo.toml index c94bf6ae9..88854413c 100644 --- a/boringtun/Cargo.toml +++ b/boringtun/Cargo.toml @@ -14,52 +14,67 @@ documentation = "https://docs.rs/boringtun/0.7.1/boringtun/" edition = "2018" [features] -default = [] -device = ["socket2", "thiserror"] -jni-bindings = ["ffi-bindings", "jni"] -ffi-bindings = ["tracing-subscriber"] -# mocks std::time::Instant with mock_instant -mock-instant = ["mock_instant"] +default = ["std"] +alloc = [] +std = ["dep:nix", "dep:parking_lot", "dep:winsafe", "alloc", "once_cell/std"] +device = ["std", "socket2", "thiserror"] +jni-bindings = ["std", "ffi-bindings", "jni"] +ffi-bindings = ["std", "tracing-subscriber"] +defmt = ["dep:defmt", "fugit/defmt"] [dependencies] -base64 = "0.22" -hex = "0.4" +base64 = { version = "0.23.0", default-features = false } +hex = { version = "0.4", default-features = false } untrusted = "0.9.0" -libc = "0.2" -parking_lot = "0.12" +libc = { version = "0.2", default-features = false } +parking_lot = { version = "0.12.4", optional = true } +lock_api = "0.4.13" +spin = { version = "0.12.2" } +once_cell = { version = "1.19.0", default-features = false, features = [ + "critical-section", +] } portable-atomic = { version = "1.13.1", features = ["fallback"] } -tracing = "0.1.40" +tracing = { version = "0.1.40", default-features = false } tracing-subscriber = { version = "0.3", features = ["fmt"], optional = true } -ip_network = "0.4.1" -ip_network_table = "0.2.0" -ring = "0.17" -x25519-dalek = { version = "2.0.1", features = [ - "reusable_secrets", - "static_secrets", +ip_network = { version = "0.4.1", default-features = false } +ip_network_table = { version = "0.2.0", default-features = false } +ring = { version = "0.17.14", default-features = false } +x25519-dalek = { version = "3.0.0", features = [ + "getrandom", + "reusable_secrets", + "static_secrets", ] } -rand_core = { version = "0.6.4", features = ["getrandom"] } -chacha20poly1305 = "0.10.0-pre.1" -aead = "0.5.0-pre.2" -blake2 = "0.10" -hmac = "0.12" +rand = { version = "0.10.1", default-features = false, features = ["sys_rng"] } +chacha20poly1305 = { version = "0.11.0", default-features = false } +aead = "0.6.0-rc.2" +blake2 = { version = "0.11.0-rc.6", default-features = false } +hmac = "0.13.0" jni = { version = "0.19.0", optional = true } -mock_instant = { version = "0.3", optional = true } socket2 = { version = "0.4.7", features = ["all"], optional = true } thiserror = { version = "2", optional = true } +fugit = { version = "0.5", default-features = false } +defmt = { version = "1.1.1", optional = true, features = ["ip_in_core"] } [target.'cfg(unix)'.dependencies] -nix = { version = "0.31", default-features = false, features = [ +nix = { version = "0.31", optional = true, default-features = false, features = [ "time", "user", ] } +[target.'cfg(windows)'.dependencies] +winsafe = { version = "0.0.28", optional = true, default-features = false, features = [ + "kernel", +] } + [dev-dependencies] +base64 = { version = "0.23.0", default-features = false, features = ["alloc"] } etherparse = "0.13" +hex = { version = "0.4", default-features = false, features = ["alloc"] } tracing-subscriber = "0.3" criterion = { version = "0.8.2", features = ["html_reports"] } [lib] -crate-type = ["staticlib", "cdylib", "rlib"] +crate-type = ["rlib"] [[bench]] name = "crypto_benches" diff --git a/boringtun/benches/crypto_benches/blake2s_benching.rs b/boringtun/benches/crypto_benches/blake2s_benching.rs index 3698172e2..00e97486d 100644 --- a/boringtun/benches/crypto_benches/blake2s_benching.rs +++ b/boringtun/benches/crypto_benches/blake2s_benching.rs @@ -1,3 +1,4 @@ +use blake2::digest::consts::U16; use blake2::digest::{FixedOutput, KeyInit}; use blake2::{Blake2s256, Blake2sMac, Digest}; use criterion::{BenchmarkId, Criterion, Throughput}; @@ -77,7 +78,7 @@ pub fn bench_blake2s_keyed(c: &mut Criterion) { key }, |key| -> [u8; 16] { - let mut hmac = Blake2sMac::new_from_slice(&key).unwrap(); + let mut hmac = Blake2sMac::::new_from_slice(&key).unwrap(); blake2::digest::Update::update(&mut hmac, &buf_in); hmac.finalize_fixed().into() }, diff --git a/boringtun/benches/crypto_benches/chacha20poly1305_benching.rs b/boringtun/benches/crypto_benches/chacha20poly1305_benching.rs index ed857a77b..6e1f6ab3d 100644 --- a/boringtun/benches/crypto_benches/chacha20poly1305_benching.rs +++ b/boringtun/benches/crypto_benches/chacha20poly1305_benching.rs @@ -1,6 +1,7 @@ -use aead::{AeadInPlace, KeyInit}; +use aead::inout::InOutBuf; +use aead::{AeadInOut, KeyInit}; use criterion::{BenchmarkId, Criterion, Throughput}; -use rand_core::{OsRng, RngCore}; +use rand::{rngs::SysRng, TryRng}; use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; fn chacha20poly1305_ring(key_bytes: &[u8], buf: &mut [u8]) { @@ -28,7 +29,7 @@ fn chacha20poly1305_non_ring(key_bytes: &[u8], buf: &mut [u8]) { let nonce = chacha20poly1305::Nonce::default(); let tag = aead - .encrypt_in_place_detached(&nonce, &[], &mut buf[..n]) + .encrypt_inout_detached(&nonce, &[], InOutBuf::from(&mut buf[..n])) .unwrap(); buf[n..].copy_from_slice(tag.as_ref()); @@ -49,10 +50,10 @@ pub fn bench_chacha20poly1305(c: &mut Criterion) { let mut key = [0; 32]; let mut buf = vec![0; i + 16]; - let mut rng = OsRng::default(); + let mut rng = SysRng::default(); - rng.fill_bytes(&mut key); - rng.fill_bytes(&mut buf); + rng.try_fill_bytes(&mut key).unwrap(); + rng.try_fill_bytes(&mut buf).unwrap(); b.iter(|| chacha20poly1305_ring(&key, &mut buf)); }, @@ -65,10 +66,10 @@ pub fn bench_chacha20poly1305(c: &mut Criterion) { let mut key = [0; 32]; let mut buf = vec![0; i + 16]; - let mut rng = OsRng::default(); + let mut rng = SysRng::default(); - rng.fill_bytes(&mut key); - rng.fill_bytes(&mut buf); + rng.try_fill_bytes(&mut key).unwrap(); + rng.try_fill_bytes(&mut buf).unwrap(); b.iter(|| chacha20poly1305_non_ring(&key, &mut buf)); }, diff --git a/boringtun/benches/crypto_benches/x25519_public_key_benching.rs b/boringtun/benches/crypto_benches/x25519_public_key_benching.rs index 7e257595f..c5a484e85 100644 --- a/boringtun/benches/crypto_benches/x25519_public_key_benching.rs +++ b/boringtun/benches/crypto_benches/x25519_public_key_benching.rs @@ -1,5 +1,4 @@ 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"); @@ -8,7 +7,7 @@ pub fn bench_x25519_public_key(c: &mut Criterion) { group.bench_function("x25519_public_key_dalek", |b| { b.iter(|| { - let secret_key = x25519_dalek::StaticSecret::random_from_rng(OsRng); + let secret_key = x25519_dalek::StaticSecret::random(); let public_key = x25519_dalek::PublicKey::from(&secret_key); (secret_key, public_key) diff --git a/boringtun/benches/crypto_benches/x25519_shared_key_benching.rs b/boringtun/benches/crypto_benches/x25519_shared_key_benching.rs index a3c1145eb..5e1f51516 100644 --- a/boringtun/benches/crypto_benches/x25519_shared_key_benching.rs +++ b/boringtun/benches/crypto_benches/x25519_shared_key_benching.rs @@ -1,5 +1,4 @@ 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"); @@ -7,11 +6,10 @@ pub fn bench_x25519_shared_key(c: &mut Criterion) { group.sample_size(1000); group.bench_function("x25519_shared_key_dalek", |b| { - let public_key = - x25519_dalek::PublicKey::from(&x25519_dalek::StaticSecret::random_from_rng(OsRng)); + let public_key = x25519_dalek::PublicKey::from(&x25519_dalek::StaticSecret::random()); b.iter_batched( - || x25519_dalek::StaticSecret::random_from_rng(OsRng), + || x25519_dalek::StaticSecret::random(), |secret_key| secret_key.diffie_hellman(&public_key), BatchSize::SmallInput, ); diff --git a/boringtun/src/device/api.rs b/boringtun/src/device/api.rs index 0486de68b..91383a085 100644 --- a/boringtun/src/device/api.rs +++ b/boringtun/src/device/api.rs @@ -6,8 +6,9 @@ use super::drop_privileges::get_saved_ids; use super::{AllowedIP, Device, Error, SocketAddr}; use crate::device::Action; use crate::serialization::KeyBytes; +use crate::sleepyinstant::ClockDuration; use crate::x25519; -use hex::encode as encode_hex; +use hex::encode_to_slice as encode_hex; use libc::*; use std::fs::{create_dir, remove_file}; use std::io::{BufRead, BufReader, BufWriter, Write}; @@ -69,7 +70,7 @@ impl Device { _ => EIO, }; // The protocol requires to return an error code as the response, or zero on success - writeln!(writer, "errno={}\n", status).ok(); + writeln!(writer, "errno={status}\n").ok(); } Action::Continue // Indicates the worker thread should continue as normal }), @@ -99,7 +100,7 @@ impl Device { _ => EIO, }; // The protocol requires to return an error code as the response, or zero on success - writeln!(writer, "errno={}\n", status).ok(); + writeln!(writer, "errno={status}\n").ok(); } else { // The remote side is likely closed; we should trigger an exit. d.trigger_exit(); @@ -157,7 +158,10 @@ impl Device { fn api_get(writer: &mut BufWriter<&UnixStream>, d: &Device) -> i32 { // get command requires an empty line, but there is no reason to be religious about it if let Some(ref k) = d.key_pair { - writeln!(writer, "own_public_key={}", encode_hex(k.1.as_bytes())); + let mut output = [0u8; 64]; + encode_hex(k.1.as_bytes(), &mut output); + let hex_string = ::core::str::from_utf8(&output).unwrap(); + writeln!(writer, "own_public_key={}", hex_string); } if d.listen_port != 0 { @@ -165,38 +169,50 @@ fn api_get(writer: &mut BufWriter<&UnixStream>, d: &Device) -> i32 { } if let Some(fwmark) = d.fwmark { - writeln!(writer, "fwmark={}", fwmark); + writeln!(writer, "fwmark={fwmark}"); } for (k, p) in d.peers.iter() { let p = p.lock(); - writeln!(writer, "public_key={}", encode_hex(k.as_bytes())); + + let mut output = [0u8; 64]; + encode_hex(k.as_bytes(), &mut output); + let hex_string = ::core::str::from_utf8(&output).unwrap(); + writeln!(writer, "public_key={}", hex_string); if let Some(ref key) = p.preshared_key() { - writeln!(writer, "preshared_key={}", encode_hex(key)); + let mut output = [0u8; 64]; + encode_hex(*key, &mut output); + let hex_string = ::core::str::from_utf8(&output).unwrap(); + writeln!(writer, "preshared_key={}", hex_string); } if let Some(keepalive) = p.persistent_keepalive() { - writeln!(writer, "persistent_keepalive_interval={}", keepalive); + writeln!(writer, "persistent_keepalive_interval={keepalive}"); } if let Some(ref addr) = p.endpoint().addr { - writeln!(writer, "endpoint={}", addr); + writeln!(writer, "endpoint={addr}"); } for (ip, cidr) in p.allowed_ips() { - writeln!(writer, "allowed_ip={}/{}", ip, cidr); + writeln!(writer, "allowed_ip={ip}/{cidr}"); } if let Some(time) = p.time_since_last_handshake() { + let whole_secs = ClockDuration::from_secs(time.as_secs()); writeln!(writer, "last_handshake_time_sec={}", time.as_secs()); - writeln!(writer, "last_handshake_time_nsec={}", time.subsec_nanos()); + writeln!( + writer, + "last_handshake_time_nsec={}", + (time - whole_secs).as_nanos() + ); } let (_, tx_bytes, rx_bytes, ..) = p.tunnel.stats(); - writeln!(writer, "rx_bytes={}", rx_bytes); - writeln!(writer, "tx_bytes={}", tx_bytes); + writeln!(writer, "rx_bytes={rx_bytes}"); + writeln!(writer, "tx_bytes={tx_bytes}"); } 0 } @@ -260,7 +276,7 @@ fn api_set(reader: &mut BufReader<&UnixStream>, d: &mut LockReadGuard) - reader, device, x25519::PublicKey::from(key_bytes.0), - ) + ); } Err(_) => return EINVAL, }, diff --git a/boringtun/src/device/dev_lock.rs b/boringtun/src/device/dev_lock.rs index 1a700fab9..6076a2f63 100644 --- a/boringtun/src/device/dev_lock.rs +++ b/boringtun/src/device/dev_lock.rs @@ -26,7 +26,7 @@ impl Lock { impl Lock { /// Acquire a read lock pub fn read(&self) -> LockReadGuard { - let (ref lock, ref cvar) = &self.wants_write; + let (lock, cvar) = &self.wants_write; let mut wants_write = lock.lock(); while *wants_write { // We have a writer and we want to wait for it to go away @@ -64,7 +64,7 @@ impl<'a, T: ?Sized> LockReadGuard<'a, T> { ) -> Option { // First tell everyone that we want to write now, this will prevent any new reader from starting until we are done. { - let &(ref lock, cvar) = &self.wants_write; + let &(lock, cvar) = &self.wants_write; let mut wants_write = lock.lock(); RwLockReadGuard::unlocked(&mut self.inner, move || { @@ -90,7 +90,7 @@ impl<'a, T: ?Sized> LockReadGuard<'a, T> { })); // Finally signal other threads - let (ref lock, ref cvar) = &self.wants_write; + let (lock, cvar) = &self.wants_write; let mut wants_write = lock.lock(); *wants_write = false; cvar.notify_all(); diff --git a/boringtun/src/device/epoll.rs b/boringtun/src/device/epoll.rs index b6ecaf0b9..4cd810edc 100644 --- a/boringtun/src/device/epoll.rs +++ b/boringtun/src/device/epoll.rs @@ -301,7 +301,7 @@ impl EventPoll { unsafe { write( notification_event.trigger, - &(std::u64::MAX - 1).to_ne_bytes()[0] as *const u8 as _, + &(u64::MAX - 1).to_ne_bytes()[0] as *const u8 as _, 8, ) }; diff --git a/boringtun/src/device/integration_tests/mod.rs b/boringtun/src/device/integration_tests/mod.rs index b4e360c3d..8cdabf173 100644 --- a/boringtun/src/device/integration_tests/mod.rs +++ b/boringtun/src/device/integration_tests/mod.rs @@ -7,9 +7,9 @@ mod tests { use crate::device::{DeviceConfig, DeviceHandle}; use crate::x25519::{PublicKey, StaticSecret}; - use base64::encode as base64encode; + use base64::prelude::BASE64_STANDARD; + use base64::Engine; use hex::encode; - use rand_core::OsRng; use ring::rand::{SecureRandom, SystemRandom}; use std::fmt::Write as _; use std::io::{BufRead, BufReader, Read, Write}; @@ -87,7 +87,7 @@ mod tests { /// Create a new peer with a given endpoint and a list of allowed IPs fn new(endpoint: SocketAddr, allowed_ips: Vec) -> Peer { Peer { - key: StaticSecret::random_from_rng(OsRng), + key: StaticSecret::random(), endpoint, allowed_ips, container_name: None, @@ -110,11 +110,19 @@ mod tests { // The local endpoint port is the remote listen port let _ = writeln!(conf, "ListenPort = {}", self.endpoint.port()); // HACK: this should consume the key so it can't be reused instead of cloning and serializing - let _ = writeln!(conf, "PrivateKey = {}", base64encode(self.key.to_bytes())); + let _ = writeln!( + conf, + "PrivateKey = {}", + BASE64_STANDARD.encode(self.key.to_bytes()) + ); // We are the peer let _ = writeln!(conf, "[Peer]"); - let _ = writeln!(conf, "PublicKey = {}", base64encode(local_key.as_bytes())); + let _ = writeln!( + conf, + "PublicKey = {}", + BASE64_STANDARD.encode(local_key.as_bytes()) + ); let _ = writeln!(conf, "AllowedIPs = {}", local_addr); let _ = write!(conf, "Endpoint = 127.0.0.1:{}", local_port); @@ -463,7 +471,7 @@ mod tests { } #[test] - #[ignore] + /// Test if wireguard starts and creates a unix socket that we can read from fn test_wireguard_get() { let wg = WGHandle::init("192.0.2.0".parse().unwrap(), "::2".parse().unwrap()); @@ -472,11 +480,11 @@ mod tests { } #[test] - #[ignore] + /// Test if wireguard starts and creates a unix socket that we can use to set settings fn test_wireguard_set() { let port = next_port(); - let private_key = StaticSecret::random_from_rng(OsRng); + let private_key = StaticSecret::random(); let own_public_key = PublicKey::from(&private_key); let wg = WGHandle::init("192.0.2.0".parse().unwrap(), "::2".parse().unwrap()); @@ -494,7 +502,7 @@ mod tests { ) ); - let peer_key = StaticSecret::random_from_rng(OsRng); + let peer_key = StaticSecret::random(); let peer_pub_key = PublicKey::from(&peer_key); let endpoint = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(172, 0, 0, 1)), 50001); let allowed_ips = [ @@ -540,10 +548,10 @@ mod tests { /// Test if wireguard can handle simple ipv4 connections, don't use a connected socket #[test] - #[ignore] + fn test_wg_start_ipv4_non_connected() { let port = next_port(); - let private_key = StaticSecret::random_from_rng(OsRng); + let private_key = StaticSecret::random(); let public_key = PublicKey::from(&private_key); let addr_v4 = next_ip(); let addr_v6 = next_ip_v6(); @@ -587,10 +595,10 @@ mod tests { /// Test if wireguard can handle simple ipv4 connections #[test] - #[ignore] + fn test_wg_start_ipv4() { let port = next_port(); - let private_key = StaticSecret::random_from_rng(OsRng); + let private_key = StaticSecret::random(); let public_key = PublicKey::from(&private_key); let addr_v4 = next_ip(); let addr_v6 = next_ip_v6(); @@ -622,11 +630,11 @@ mod tests { } #[test] - #[ignore] + /// Test if wireguard can handle simple ipv6 connections fn test_wg_start_ipv6() { let port = next_port(); - let private_key = StaticSecret::random_from_rng(OsRng); + let private_key = StaticSecret::random(); let public_key = PublicKey::from(&private_key); let addr_v4 = next_ip(); let addr_v6 = next_ip_v6(); @@ -658,11 +666,10 @@ mod tests { /// Test if wireguard can handle connection with an ipv6 endpoint #[test] - #[ignore] #[cfg(target_os = "linux")] // Can't make docker work with ipv6 on macOS ATM fn test_wg_start_ipv6_endpoint() { let port = next_port(); - let private_key = StaticSecret::random_from_rng(OsRng); + let private_key = StaticSecret::random(); let public_key = PublicKey::from(&private_key); let addr_v4 = next_ip(); let addr_v6 = next_ip_v6(); @@ -697,11 +704,10 @@ mod tests { /// Test if wireguard can handle connection with an ipv6 endpoint #[test] - #[ignore] #[cfg(target_os = "linux")] // Can't make docker work with ipv6 on macOS ATM fn test_wg_start_ipv6_endpoint_not_connected() { let port = next_port(); - let private_key = StaticSecret::random_from_rng(OsRng); + let private_key = StaticSecret::random(); let public_key = PublicKey::from(&private_key); let addr_v4 = next_ip(); let addr_v6 = next_ip_v6(); @@ -747,10 +753,10 @@ mod tests { /// Test many concurrent connections #[test] - #[ignore] + fn test_wg_concurrent() { let port = next_port(); - let private_key = StaticSecret::random_from_rng(OsRng); + let private_key = StaticSecret::random(); let public_key = PublicKey::from(&private_key); let addr_v4 = next_ip(); let addr_v6 = next_ip_v6(); @@ -798,10 +804,10 @@ mod tests { /// Test many concurrent connections #[test] - #[ignore] + fn test_wg_concurrent_v6() { let port = next_port(); - let private_key = StaticSecret::random_from_rng(OsRng); + let private_key = StaticSecret::random(); let public_key = PublicKey::from(&private_key); let addr_v4 = next_ip(); let addr_v6 = next_ip_v6(); diff --git a/boringtun/src/device/mod.rs b/boringtun/src/device/mod.rs index b250f5e5d..b55b65371 100644 --- a/boringtun/src/device/mod.rs +++ b/boringtun/src/device/mod.rs @@ -44,7 +44,7 @@ use allowed_ips::AllowedIps; use parking_lot::Mutex; use peer::{AllowedIP, Peer}; use poll::{EventPoll, EventRef, WaitResult}; -use rand_core::{OsRng, RngCore}; +use rand::{rngs::SysRng, TryRng}; use socket2::{Domain, Protocol, Type}; use tun::TunSocket; @@ -316,7 +316,7 @@ impl Device { } // Update an existing peer - if self.peers.get(&pub_key).is_some() { + if self.peers.contains_key(&pub_key) { // We already have a peer, we need to merge the existing config into the newly created one panic!("Modifying existing peers is not yet supported. Remove and add again instead."); } @@ -726,7 +726,7 @@ impl Device { &mut t.dst_buf[..], ) { TunnResult::Done => {} - TunnResult::Err(e) => eprintln!("Decapsulate error {:?}", e), + TunnResult::Err(e) => eprintln!("Decapsulate error {e:?}"), TunnResult::WriteToNetwork(packet) => { flush = true; let _: Result<_, _> = udp.send(packet); @@ -787,11 +787,11 @@ impl Device { if ek == io::ErrorKind::Interrupted || ek == io::ErrorKind::WouldBlock { break; } - eprintln!("Fatal read error on tun interface: {:?}", e); + eprintln!("Fatal read error on tun interface: {e:?}"); return Action::Exit; } Err(e) => { - eprintln!("Unexpected error on tun interface: {:?}", e); + eprintln!("Unexpected error on tun interface: {e:?}"); return Action::Exit; } }; @@ -852,7 +852,7 @@ impl IndexLfsr { fn random_index() -> u32 { const LFSR_MAX: u32 = 0xffffff; // 24-bit seed loop { - let i = OsRng.next_u32() & LFSR_MAX; + let i = SysRng.try_next_u32().unwrap() & LFSR_MAX; if i > 0 { // LFSR seed must be non-zero return i; diff --git a/boringtun/src/device/peer.rs b/boringtun/src/device/peer.rs index 3bf3655bb..033e6601f 100644 --- a/boringtun/src/device/peer.rs +++ b/boringtun/src/device/peer.rs @@ -4,11 +4,11 @@ use parking_lot::RwLock; use socket2::{Domain, Protocol, Type}; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; -use std::str::FromStr; - use crate::device::{AllowedIps, Error}; use crate::noise::{Tunn, TunnResult}; +use crate::sleepyinstant::ClockDuration; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; +use std::str::FromStr; #[derive(Default, Debug)] pub struct Endpoint { @@ -152,7 +152,7 @@ impl Peer { self.allowed_ips.iter().map(|(_, ip, cidr)| (ip, cidr)) } - pub fn time_since_last_handshake(&self) -> Option { + pub fn time_since_last_handshake(&self) -> Option { self.tunnel.time_since_last_handshake() } diff --git a/boringtun/src/ffi/mod.rs b/boringtun/src/ffi/mod.rs index 1e5a2a9f3..f10d1776c 100644 --- a/boringtun/src/ffi/mod.rs +++ b/boringtun/src/ffi/mod.rs @@ -8,22 +8,24 @@ //! C bindings for the BoringTun library use super::noise::{Tunn, TunnResult}; use crate::x25519::{PublicKey, StaticSecret}; -use base64::{decode, encode}; -use hex::encode as encode_hex; +use base64::prelude::BASE64_STANDARD; +use base64::Engine; +use hex::encode_to_slice as encode_hex; use libc::{raise, SIGSEGV}; -use parking_lot::Mutex; -use rand_core::OsRng; +use lock_api::Mutex; +use parking_lot::RawMutex; use tracing; use tracing_subscriber::fmt; use crate::serialization::KeyBytes; -use std::ffi::{CStr, CString}; +use core::ffi::CStr; +use core::ptr; +use core::ptr::null_mut; +use core::slice; +use std::ffi::CString; use std::io::{Error, ErrorKind, Write}; use std::os::raw::c_char; use std::panic; -use std::ptr; -use std::ptr::null_mut; -use std::slice; use std::sync::Once; static PANIC_HOOK: Once = Once::new(); @@ -99,7 +101,7 @@ pub struct x25519_key { #[no_mangle] pub extern "C" fn x25519_secret_key() -> x25519_key { x25519_key { - key: StaticSecret::random_from_rng(OsRng).to_bytes(), + key: StaticSecret::random().to_bytes(), } } @@ -118,7 +120,7 @@ pub extern "C" fn x25519_public_key(private_key: x25519_key) -> x25519_key { /// The memory has to be freed by calling `x25519_key_to_str_free` #[no_mangle] pub extern "C" fn x25519_key_to_base64(key: x25519_key) -> *const c_char { - let encoded_key = encode(key.key); + let encoded_key = BASE64_STANDARD.encode(key.key); CString::into_raw(CString::new(encoded_key).unwrap()) } @@ -127,8 +129,9 @@ pub extern "C" fn x25519_key_to_base64(key: x25519_key) -> *const c_char { /// The memory has to be freed by calling `x25519_key_to_str_free` #[no_mangle] pub extern "C" fn x25519_key_to_hex(key: x25519_key) -> *const c_char { - let encoded_key = encode_hex(key.key); - CString::into_raw(CString::new(encoded_key).unwrap()) + let mut encoded_key = [0u8; 64]; + encode_hex(key.key, &mut encoded_key).expect("buffer is exactly sized for the input"); + CString::into_raw(CString::new(&encoded_key[..]).unwrap()) } /// Frees memory of the string given by `x25519_key_to_hex` or `x25519_key_to_base64` @@ -147,7 +150,7 @@ pub unsafe extern "C" fn check_base64_encoded_x25519_key(key: *const c_char) -> Ok(string) => string, }; - if let Ok(key) = decode(utf8_key) { + if let Ok(key) = BASE64_STANDARD.decode(utf8_key) { let len = key.len(); let mut zero = 0u8; for b in key { @@ -247,7 +250,7 @@ pub unsafe extern "C" fn new_tunnel( preshared_key: *const c_char, keep_alive: u16, index: u32, -) -> *mut Mutex { +) -> *mut Mutex { let c_str = CStr::from_ptr(static_private); let static_private = match c_str.to_str() { Err(_) => return ptr::null_mut(), @@ -313,7 +316,7 @@ pub unsafe extern "C" fn new_tunnel( /// Drops the Tunn object #[no_mangle] -pub unsafe extern "C" fn tunnel_free(tunnel: *mut Mutex) { +pub unsafe extern "C" fn tunnel_free(tunnel: *mut Mutex) { drop(Box::from_raw(tunnel)); } @@ -321,7 +324,7 @@ pub unsafe extern "C" fn tunnel_free(tunnel: *mut Mutex) { /// For more details check noise::tunnel_to_network functions. #[no_mangle] pub unsafe extern "C" fn wireguard_write( - tunnel: *const Mutex, + tunnel: *const Mutex, src: *const u8, src_size: u32, dst: *mut u8, @@ -338,7 +341,7 @@ pub unsafe extern "C" fn wireguard_write( /// For more details check noise::network_to_tunnel functions. #[no_mangle] pub unsafe extern "C" fn wireguard_read( - tunnel: *const Mutex, + tunnel: *const Mutex, src: *const u8, src_size: u32, dst: *mut u8, @@ -355,7 +358,7 @@ pub unsafe extern "C" fn wireguard_read( /// Recommended interval: 100ms. #[no_mangle] pub unsafe extern "C" fn wireguard_tick( - tunnel: *const Mutex, + tunnel: *const Mutex, dst: *mut u8, dst_size: u32, ) -> wireguard_result { @@ -368,7 +371,7 @@ pub unsafe extern "C" fn wireguard_tick( /// Force the tunnel to initiate a new handshake, dst buffer must be at least 148 byte long. #[no_mangle] pub unsafe extern "C" fn wireguard_force_handshake( - tunnel: *const Mutex, + tunnel: *const Mutex, dst: *mut u8, dst_size: u32, ) -> wireguard_result { @@ -383,7 +386,7 @@ pub unsafe extern "C" fn wireguard_force_handshake( /// Number of data bytes encapsulated /// Number of data bytes decapsulated #[no_mangle] -pub unsafe extern "C" fn wireguard_stats(tunnel: *const Mutex) -> stats { +pub unsafe extern "C" fn wireguard_stats(tunnel: *const Mutex) -> stats { let tunnel = tunnel.as_ref().unwrap().lock(); let (time, tx_bytes, rx_bytes, estimated_loss, estimated_rtt) = tunnel.stats(); stats { diff --git a/boringtun/src/jni.rs b/boringtun/src/jni.rs index 7bc2bdcd7..58718f5b1 100644 --- a/boringtun/src/jni.rs +++ b/boringtun/src/jni.rs @@ -4,9 +4,9 @@ // temporary, we need to do some verification around these bindings later #![allow(clippy::missing_safety_doc)] +use core::ptr; /// JNI bindings for BoringTun library use std::os::raw::c_char; -use std::ptr; use jni::objects::{JByteBuffer, JClass, JString}; use jni::strings::JNIStr; @@ -62,7 +62,7 @@ pub unsafe extern "C" fn generate_public_key1( } let secret_key = x25519_key { - key: std::mem::transmute::<[i8; 32], [u8; 32]>(key_inner), + key: core::mem::transmute::<[i8; 32], [u8; 32]>(key_inner), }; match env.byte_array_from_slice(&x25519_public_key(secret_key).key) { @@ -86,7 +86,7 @@ pub unsafe extern "C" fn convert_x25519_key_to_hex( } let x25519_key = x25519_key { - key: std::mem::transmute::<[i8; 32], [u8; 32]>(key), + key: core::mem::transmute::<[i8; 32], [u8; 32]>(key), }; let output = match env.new_string(JNIStr::from_ptr(x25519_key_to_hex(x25519_key)).to_owned()) { @@ -112,7 +112,7 @@ pub unsafe extern "C" fn convert_x25519_key_to_base64( } let x25519_key = x25519_key { - key: std::mem::transmute::<[i8; 32], [u8; 32]>(key), + key: core::mem::transmute::<[i8; 32], [u8; 32]>(key), }; let output = match env.new_string(JNIStr::from_ptr(x25519_key_to_base64(x25519_key)).to_owned()) diff --git a/boringtun/src/lib.rs b/boringtun/src/lib.rs index 6ab410dc3..d328b9f2e 100644 --- a/boringtun/src/lib.rs +++ b/boringtun/src/lib.rs @@ -5,6 +5,12 @@ //! //! git clone https://github.com/cloudflare/boringtun.git +// Set `no_std` where `std` feature is disabled +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "alloc")] +extern crate alloc; + #[cfg(feature = "device")] pub mod device; @@ -14,8 +20,7 @@ pub mod ffi; pub mod jni; pub mod noise; -#[cfg(not(feature = "mock-instant"))] -pub(crate) mod sleepyinstant; +pub mod sleepyinstant; pub(crate) mod serialization; diff --git a/boringtun/src/noise/errors.rs b/boringtun/src/noise/errors.rs index 10513aefe..cf5626ab7 100644 --- a/boringtun/src/noise/errors.rs +++ b/boringtun/src/noise/errors.rs @@ -1,6 +1,7 @@ // Copyright (c) 2019 Cloudflare, Inc. All rights reserved. // SPDX-License-Identifier: BSD-3-Clause +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug)] pub enum WireGuardError { DestinationBufferTooSmall, diff --git a/boringtun/src/noise/handshake.rs b/boringtun/src/noise/handshake.rs index 40ed8037d..f8519d11a 100644 --- a/boringtun/src/noise/handshake.rs +++ b/boringtun/src/noise/handshake.rs @@ -4,20 +4,16 @@ use super::{HandshakeInit, HandshakeResponse, PacketCookieReply}; use crate::noise::errors::WireGuardError; use crate::noise::session::Session; -#[cfg(not(feature = "mock-instant"))] -use crate::sleepyinstant::Instant; +use crate::sleepyinstant::{ClockDuration, Instant}; use crate::x25519; -use aead::{Aead, Payload}; +use aead::array::Array; +use aead::AeadInOut; +use blake2::digest::consts::{U16, U24}; use blake2::digest::{FixedOutput, KeyInit}; use blake2::{Blake2s256, Blake2sMac, Digest}; use chacha20poly1305::XChaCha20Poly1305; -use rand_core::OsRng; +use core::convert::{TryFrom, TryInto}; use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; -use std::convert::TryInto; -use std::time::{Duration, SystemTime}; - -#[cfg(feature = "mock-instant")] -use mock_instant::Instant; pub(crate) const LABEL_MAC1: &[u8; 8] = b"mac1----"; pub(crate) const LABEL_COOKIE: &[u8; 8] = b"cookie--"; @@ -67,21 +63,21 @@ pub(crate) fn b2s_hmac2(key: &[u8], data1: &[u8], data2: &[u8]) -> [u8; 32] { #[inline] pub(crate) fn b2s_keyed_mac_16(key: &[u8], data1: &[u8]) -> [u8; 16] { - let mut hmac = Blake2sMac::new_from_slice(key).unwrap(); + let mut hmac = Blake2sMac::::new_from_slice(key).unwrap(); blake2::digest::Update::update(&mut hmac, data1); hmac.finalize_fixed().into() } #[inline] pub(crate) fn b2s_keyed_mac_16_2(key: &[u8], data1: &[u8], data2: &[u8]) -> [u8; 16] { - let mut hmac = Blake2sMac::new_from_slice(key).unwrap(); + let mut hmac = Blake2sMac::::new_from_slice(key).unwrap(); blake2::digest::Update::update(&mut hmac, data1); blake2::digest::Update::update(&mut hmac, data2); hmac.finalize_fixed().into() } pub(crate) fn b2s_mac_24(key: &[u8], data1: &[u8]) -> [u8; 24] { - let mut hmac = Blake2sMac::new_from_slice(key).unwrap(); + let mut hmac = Blake2sMac::::new_from_slice(key).unwrap(); blake2::digest::Update::update(&mut hmac, data1); hmac.finalize_fixed().into() } @@ -135,6 +131,10 @@ fn aead_chacha20_open( Ok(()) } +/// `aead_chacha20_open_inner` is only ever called during the handshake, on messages no larger +/// than a single encrypted static public key (`KEY_LEN` bytes) plus the AEAD tag. +const MAX_AEAD_OPEN_DATA_LEN: usize = KEY_LEN + 16; + #[inline] fn aead_chacha20_open_inner( buffer: &mut [u8], @@ -143,14 +143,16 @@ fn aead_chacha20_open_inner( data: &[u8], aad: &[u8], ) -> Result<(), ring::error::Unspecified> { - let key = LessSafeKey::new(UnboundKey::new(&CHACHA20_POLY1305, key).unwrap()); + let key = LessSafeKey::new(UnboundKey::new(&CHACHA20_POLY1305, key)?); - let mut inner_buffer = data.to_owned(); + let mut inner_buffer = [0u8; MAX_AEAD_OPEN_DATA_LEN]; + let inner_buffer = &mut inner_buffer[..data.len()]; + inner_buffer.copy_from_slice(data); let plaintext = key.open_in_place( Nonce::assume_unique_for_key(nonce), Aad::from(aad), - &mut inner_buffer, + inner_buffer, )?; buffer.copy_from_slice(plaintext); @@ -168,7 +170,7 @@ struct Tai64N { #[derive(Debug)] /// This struct computes a [Tai64N](https://cr.yp.to/libtai/tai64.html) timestamp from current system time struct TimeStamper { - duration_at_start: Duration, + duration_at_start: ClockDuration, instant_at_start: Instant, } @@ -176,9 +178,7 @@ impl TimeStamper { /// Create a new TimeStamper pub fn new() -> TimeStamper { TimeStamper { - duration_at_start: SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap(), + duration_at_start: Instant::now().duration_since_epoch(), instant_at_start: Instant::now(), } } @@ -188,8 +188,9 @@ impl TimeStamper { const TAI64_BASE: u64 = (1u64 << 62) + 37; let mut ext_stamp = [0u8; 12]; let stamp = Instant::now().duration_since(self.instant_at_start) + self.duration_at_start; + let whole_secs = ClockDuration::from_secs(stamp.as_secs()); ext_stamp[0..8].copy_from_slice(&(stamp.as_secs() + TAI64_BASE).to_be_bytes()); - ext_stamp[8..12].copy_from_slice(&stamp.subsec_nanos().to_be_bytes()); + ext_stamp[8..12].copy_from_slice(&((stamp - whole_secs).as_nanos() as u32).to_be_bytes()); ext_stamp } } @@ -206,7 +207,7 @@ impl Tai64N { return Err(WireGuardError::InvalidTai64nTimestamp); } - let (sec_bytes, nano_bytes) = buf.split_at(std::mem::size_of::()); + let (sec_bytes, nano_bytes) = buf.split_at(size_of::()); let secs = u64::from_be_bytes(sec_bytes.try_into().unwrap()); let nano = u32::from_be_bytes(nano_bytes.try_into().unwrap()); @@ -244,8 +245,8 @@ struct NoiseParams { preshared_key: Option<[u8; KEY_LEN]>, } -impl std::fmt::Debug for NoiseParams { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Debug for NoiseParams { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("NoiseParams") .field("static_public", &self.static_public) .field("static_private", &"") @@ -265,8 +266,8 @@ struct HandshakeInitSentState { time_sent: Instant, } -impl std::fmt::Debug for HandshakeInitSentState { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Debug for HandshakeInitSentState { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("HandshakeInitSentState") .field("local_index", &self.local_index) .field("hash", &self.hash) @@ -549,7 +550,7 @@ impl Handshake { // initiator.hash = HASH(initiator.hash || msg.encrypted_timestamp) hash = b2s_hash(&hash, packet.encrypted_timestamp); - self.previous = std::mem::replace( + self.previous = core::mem::replace( &mut self.state, HandshakeState::InitReceived { chaining_key, @@ -662,18 +663,20 @@ impl Handshake { // msg.encrypted_cookie = XAEAD(HASH(LABEL_COOKIE || responder.static_public), msg.nonce, cookie, last_received_msg.mac1) let key = b2s_hash(LABEL_COOKIE, self.params.peer_static_public.as_bytes()); // TODO: pre-compute - let payload = Payload { - aad: &mac1[0..16], - msg: packet.encrypted_cookie, - }; - let plaintext = XChaCha20Poly1305::new_from_slice(&key) + let (encrypted_cookie, tag) = packet.encrypted_cookie.split_at(16); + let mut cookie = [0u8; 16]; + cookie.copy_from_slice(encrypted_cookie); + + XChaCha20Poly1305::new_from_slice(&key) .unwrap() - .decrypt(packet.nonce.into(), payload) + .decrypt_inout_detached( + <&Array<_, _>>::try_from(packet.nonce).unwrap(), + &mac1[0..16], + (&mut cookie[..]).into(), + <&Array<_, _>>::try_from(tag).unwrap(), + ) .map_err(|_| WireGuardError::InvalidAeadTag)?; - let cookie = plaintext - .try_into() - .map_err(|_| WireGuardError::InvalidPacket)?; self.cookies.write_cookie = Some(cookie); Ok(()) } @@ -728,7 +731,7 @@ impl Handshake { let mut hash = INITIAL_CHAIN_HASH; hash = b2s_hash(&hash, self.params.peer_static_public.as_bytes()); // initiator.ephemeral_private = DH_GENERATE() - let ephemeral_private = x25519::ReusableSecret::random_from_rng(OsRng); + let ephemeral_private = x25519::ReusableSecret::random(); // msg.message_type = 1 // msg.reserved_zero = { 0, 0, 0 } message_type.copy_from_slice(&super::HANDSHAKE_INIT.to_le_bytes()); @@ -772,7 +775,7 @@ impl Handshake { hash = b2s_hash(&hash, encrypted_timestamp); let time_now = Instant::now(); - self.previous = std::mem::replace( + self.previous = core::mem::replace( &mut self.state, HandshakeState::InitSent(HandshakeInitSentState { local_index, @@ -794,7 +797,7 @@ impl Handshake { return Err(WireGuardError::DestinationBufferTooSmall); } - let state = std::mem::replace(&mut self.state, HandshakeState::None); + let state = core::mem::replace(&mut self.state, HandshakeState::None); let (mut chaining_key, mut hash, peer_ephemeral_public, peer_index) = match state { HandshakeState::InitReceived { chaining_key, @@ -814,7 +817,7 @@ impl Handshake { let (encrypted_nothing, _) = rest.split_at_mut(16); // responder.ephemeral_private = DH_GENERATE() - let ephemeral_private = x25519::ReusableSecret::random_from_rng(OsRng); + let ephemeral_private = x25519::ReusableSecret::random(); let local_index = self.inc_index(); // msg.message_type = 2 // msg.reserved_zero = { 0, 0, 0 } @@ -882,7 +885,11 @@ impl Handshake { #[cfg(test)] mod tests { + extern crate std; + use super::*; + use alloc::vec; + use std::eprintln; #[test] fn chacha20_seal_rfc7530_test_vector() { diff --git a/boringtun/src/noise/mod.rs b/boringtun/src/noise/mod.rs index 76e377b63..78d907965 100644 --- a/boringtun/src/noise/mod.rs +++ b/boringtun/src/noise/mod.rs @@ -14,11 +14,12 @@ use crate::noise::rate_limiter::RateLimiter; use crate::noise::timers::{TimerName, Timers}; use crate::x25519; -use std::collections::VecDeque; -use std::convert::{TryFrom, TryInto}; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -use std::sync::Arc; -use std::time::Duration; +use crate::sleepyinstant::ClockDuration; +use alloc::collections::VecDeque; +use alloc::sync::Arc; +use alloc::vec::Vec; +use core::convert::{TryFrom, TryInto}; +use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// The default value to use for rate limiting, when no other rate limiter is defined const PEER_HANDSHAKE_RATE_LIMIT: u64 = 10; @@ -41,6 +42,7 @@ const MAX_QUEUE_DEPTH: usize = 256; /// number of sessions in the ring, better keep a PoT const N_SESSIONS: usize = 8; +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug)] pub enum TunnResult<'a> { Done, @@ -153,7 +155,7 @@ impl Tunn { nonce: &src[8..32], encrypted_cookie: &src[32..64], }), - (DATA, DATA_OVERHEAD_SZ..=std::usize::MAX) => Packet::PacketData(PacketData { + (DATA, DATA_OVERHEAD_SZ..=usize::MAX) => Packet::PacketData(PacketData { receiver_idx: u32::from_le_bytes(src[4..8].try_into().unwrap()), counter: u64::from_le_bytes(src[8..16].try_into().unwrap()), encrypted_encapsulated_packet: &src[16..], @@ -574,7 +576,7 @@ impl Tunn { /// * Time since last handshake in seconds /// * Data bytes sent /// * Data bytes received - pub fn stats(&self) -> (Option, usize, usize, f32, Option) { + pub fn stats(&self) -> (Option, usize, usize, f32, Option) { let time = self.time_since_last_handshake(); let tx_bytes = self.tx_bytes; let rx_bytes = self.rx_bytes; @@ -587,20 +589,22 @@ impl Tunn { #[cfg(test)] mod tests { - #[cfg(feature = "mock-instant")] - use crate::noise::timers::{REKEY_AFTER_TIME, REKEY_TIMEOUT}; + extern crate std; + + use std::vec; + use std::vec::Vec; use super::*; - use rand_core::{OsRng, RngCore}; + use rand::{rngs::SysRng, TryRng}; fn create_two_tuns() -> (Tunn, Tunn) { - let my_secret_key = x25519_dalek::StaticSecret::random_from_rng(OsRng); + let my_secret_key = x25519_dalek::StaticSecret::random(); let my_public_key = x25519_dalek::PublicKey::from(&my_secret_key); - let my_idx = OsRng.next_u32(); + let my_idx = SysRng.try_next_u32().unwrap(); - let their_secret_key = x25519_dalek::StaticSecret::random_from_rng(OsRng); + let their_secret_key = x25519_dalek::StaticSecret::random(); let their_public_key = x25519_dalek::PublicKey::from(&their_secret_key); - let their_idx = OsRng.next_u32(); + let their_idx = SysRng.try_next_u32().unwrap(); let my_tun = Tunn::new(my_secret_key, their_public_key, None, None, my_idx, None); @@ -675,20 +679,6 @@ mod tests { packet } - #[cfg(feature = "mock-instant")] - fn update_timer_results_in_handshake(tun: &mut Tunn) { - let mut dst = vec![0u8; 2048]; - let result = tun.update_timers(&mut dst); - assert!(matches!(result, TunnResult::WriteToNetwork(_))); - let packet_data = if let TunnResult::WriteToNetwork(data) = result { - data - } else { - unreachable!(); - }; - let packet = Tunn::parse_incoming_packet(packet_data).unwrap(); - assert!(matches!(packet, Packet::HandshakeInit(_))); - } - #[test] fn create_two_tunnels_linked_to_eachother() { let (_my_tun, _their_tun) = create_two_tuns(); @@ -729,43 +719,6 @@ mod tests { assert!(matches!(their_tun.update_timers(&mut []), TunnResult::Done)); } - #[test] - #[cfg(feature = "mock-instant")] - fn new_handshake_after_two_mins() { - let (mut my_tun, mut their_tun) = create_two_tuns_and_handshake(); - let mut my_dst = [0u8; 1024]; - - // Advance time 1 second and "send" 1 packet so that we send a handshake - // after the timeout - mock_instant::MockClock::advance(Duration::from_secs(1)); - assert!(matches!(their_tun.update_timers(&mut []), TunnResult::Done)); - assert!(matches!( - my_tun.update_timers(&mut my_dst), - TunnResult::Done - )); - let sent_packet_buf = create_ipv4_udp_packet(); - let data = my_tun.encapsulate(&sent_packet_buf, &mut my_dst); - assert!(matches!(data, TunnResult::WriteToNetwork(_))); - - //Advance to timeout - mock_instant::MockClock::advance(REKEY_AFTER_TIME); - assert!(matches!(their_tun.update_timers(&mut []), TunnResult::Done)); - update_timer_results_in_handshake(&mut my_tun); - } - - #[test] - #[cfg(feature = "mock-instant")] - fn handshake_no_resp_rekey_timeout() { - let (mut my_tun, _their_tun) = create_two_tuns(); - - let init = create_handshake_init(&mut my_tun); - let packet = Tunn::parse_incoming_packet(&init).unwrap(); - assert!(matches!(packet, Packet::HandshakeInit(_))); - - mock_instant::MockClock::advance(REKEY_TIMEOUT); - update_timer_results_in_handshake(&mut my_tun) - } - #[test] fn one_ip_packet() { let (mut my_tun, mut their_tun) = create_two_tuns_and_handshake(); diff --git a/boringtun/src/noise/rate_limiter.rs b/boringtun/src/noise/rate_limiter.rs index 421d5680f..cc04ba0f1 100644 --- a/boringtun/src/noise/rate_limiter.rs +++ b/boringtun/src/noise/rate_limiter.rs @@ -2,27 +2,30 @@ use super::handshake::{b2s_hash, b2s_keyed_mac_16, b2s_keyed_mac_16_2, b2s_mac_2 use crate::noise::handshake::{LABEL_COOKIE, LABEL_MAC1}; use crate::noise::{HandshakeInit, HandshakeResponse, Packet, Tunn, TunnResult, WireGuardError}; -#[cfg(feature = "mock-instant")] -use mock_instant::Instant; +use core::convert::TryFrom; +use core::net::IpAddr; use portable_atomic::{AtomicU64, Ordering}; -use std::net::IpAddr; -#[cfg(not(feature = "mock-instant"))] -use crate::sleepyinstant::Instant; +use crate::sleepyinstant::{ClockDuration, Instant}; -use aead::generic_array::GenericArray; -use aead::{AeadInPlace, KeyInit}; +use aead::array::Array; +use aead::{AeadInOut, KeyInit}; use chacha20poly1305::{Key, XChaCha20Poly1305}; -use parking_lot::Mutex; -use rand_core::{OsRng, RngCore}; +use lock_api::Mutex; +#[cfg(feature = "std")] +use parking_lot::RawMutex; +use rand::{rngs::SysRng, TryRng}; use ring::constant_time::verify_slices_are_equal; -const COOKIE_REFRESH: u64 = 128; // Use 128 and not 120 so the compiler can optimize out the division +#[cfg(not(feature = "std"))] +type RawMutex = spin::Mutex<()>; + +const COOKIE_REFRESH: ClockDuration = ClockDuration::from_secs(128); // Use 128 and not 120 so the compiler can optimize out the division const COOKIE_SIZE: usize = 16; const COOKIE_NONCE_SIZE: usize = 24; /// How often should reset count in seconds -const RESET_PERIOD: u64 = 1; +const RESET_PERIOD: ClockDuration = ClockDuration::from_secs(1); type Cookie = [u8; COOKIE_SIZE]; @@ -40,7 +43,7 @@ pub struct RateLimiter { /// The key we use to derive the cookie secret_key: [u8; 16], start_time: Instant, - /// A single 64 bit counter (should suffice for many years) + /// A single usize bit counter (should suffice for many years) nonce_ctr: AtomicU64, mac1_key: [u8; 32], cookie_key: Key, @@ -48,13 +51,13 @@ pub struct RateLimiter { /// The counter since last reset count: AtomicU64, /// The time last reset was performed on this rate limiter - last_reset: Mutex, + last_reset: Mutex, } impl RateLimiter { pub fn new(public_key: &crate::x25519::PublicKey, limit: u64) -> Self { let mut secret_key = [0u8; 16]; - OsRng.fill_bytes(&mut secret_key); + SysRng.try_fill_bytes(&mut secret_key).unwrap(); RateLimiter { nonce_key: Self::rand_bytes(), secret_key, @@ -70,7 +73,7 @@ impl RateLimiter { fn rand_bytes() -> [u8; 32] { let mut key = [0u8; 32]; - OsRng.fill_bytes(&mut key); + SysRng.try_fill_bytes(&mut key).unwrap(); key } @@ -79,7 +82,7 @@ impl RateLimiter { // The rate limiter is not very accurate, but at the scale we care about it doesn't matter much let current_time = Instant::now(); let mut last_reset_time = self.last_reset.lock(); - if current_time.duration_since(*last_reset_time).as_secs() >= RESET_PERIOD { + if current_time.duration_since(*last_reset_time) >= RESET_PERIOD { self.count.store(0, Ordering::SeqCst); *last_reset_time = current_time; } @@ -96,7 +99,8 @@ impl RateLimiter { // The current cookie for a given IP is the MAC(responder.changing_secret_every_two_minutes, initiator.ip_address) // First we derive the secret from the current time, the value of cur_counter would change with time. - let cur_counter = Instant::now().duration_since(self.start_time).as_secs() / COOKIE_REFRESH; + let cur_counter = + Instant::now().duration_since(self.start_time).as_secs() / COOKIE_REFRESH.as_secs(); // Next we derive the cookie b2s_keyed_mac_16_2(&self.secret_key, &cur_counter.to_le_bytes(), &addr_bytes) @@ -137,11 +141,11 @@ impl RateLimiter { let cipher = XChaCha20Poly1305::new(&self.cookie_key); - let iv = GenericArray::from_slice(nonce); + let iv = <&Array<_, _>>::try_from(&*nonce).unwrap(); encrypted_cookie[..16].copy_from_slice(&cookie); let tag = cipher - .encrypt_in_place_detached(iv, mac1, &mut encrypted_cookie[..16]) + .encrypt_inout_detached(iv, mac1, (&mut encrypted_cookie[..16]).into()) .map_err(|_| WireGuardError::DestinationBufferTooSmall)?; encrypted_cookie[16..].copy_from_slice(&tag); diff --git a/boringtun/src/noise/session.rs b/boringtun/src/noise/session.rs index d547b9819..72f74889b 100644 --- a/boringtun/src/noise/session.rs +++ b/boringtun/src/noise/session.rs @@ -3,21 +3,26 @@ use super::PacketData; use crate::noise::errors::WireGuardError; -use parking_lot::Mutex; +use lock_api::Mutex; +#[cfg(feature = "std")] +use parking_lot::RawMutex; use portable_atomic::{AtomicU64, Ordering}; use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; +#[cfg(not(feature = "std"))] +type RawMutex = spin::Mutex<()>; + pub struct Session { pub(crate) receiving_index: u32, sending_index: u32, receiver: LessSafeKey, sender: LessSafeKey, sending_key_counter: AtomicU64, - receiving_key_counter: Mutex, + receiving_key_counter: Mutex, } -impl std::fmt::Debug for Session { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Debug for Session { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!( f, "Session: {}<- ->{}", @@ -198,7 +203,7 @@ impl Session { panic!("The destination buffer is too small"); } - let sending_key_counter = self.sending_key_counter.fetch_add(1, Ordering::Relaxed) as u64; + let sending_key_counter = self.sending_key_counter.fetch_add(1, Ordering::Relaxed); let (message_type, rest) = dst.split_at_mut(4); let (receiver_index, rest) = rest.split_at_mut(4); diff --git a/boringtun/src/noise/timers.rs b/boringtun/src/noise/timers.rs index 6b91d5767..c8cad816a 100644 --- a/boringtun/src/noise/timers.rs +++ b/boringtun/src/noise/timers.rs @@ -3,25 +3,19 @@ use super::errors::WireGuardError; use crate::noise::{Tunn, TunnResult}; -use std::mem; -use std::ops::{Index, IndexMut}; - -use std::time::Duration; - -#[cfg(feature = "mock-instant")] -use mock_instant::Instant; - -#[cfg(not(feature = "mock-instant"))] +use crate::sleepyinstant::ClockDuration; use crate::sleepyinstant::Instant; +use core::mem; +use core::ops::{Index, IndexMut}; // Some constants, represent time in seconds // https://www.wireguard.com/papers/wireguard.pdf#page=14 -pub(crate) const REKEY_AFTER_TIME: Duration = Duration::from_secs(120); -const REJECT_AFTER_TIME: Duration = Duration::from_secs(180); -const REKEY_ATTEMPT_TIME: Duration = Duration::from_secs(90); -pub(crate) const REKEY_TIMEOUT: Duration = Duration::from_secs(5); -const KEEPALIVE_TIMEOUT: Duration = Duration::from_secs(10); -const COOKIE_EXPIRATION_TIME: Duration = Duration::from_secs(120); +pub(crate) const REKEY_AFTER_TIME: ClockDuration = ClockDuration::from_secs(120); +const REJECT_AFTER_TIME: ClockDuration = ClockDuration::from_secs(180); +const REKEY_ATTEMPT_TIME: ClockDuration = ClockDuration::from_secs(90); +pub(crate) const REKEY_TIMEOUT: ClockDuration = ClockDuration::from_secs(5); +const KEEPALIVE_TIMEOUT: ClockDuration = ClockDuration::from_secs(10); +const COOKIE_EXPIRATION_TIME: ClockDuration = ClockDuration::from_secs(120); #[derive(Debug)] pub enum TimerName { @@ -48,14 +42,15 @@ pub enum TimerName { use self::TimerName::*; +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Debug)] pub struct Timers { /// Is the owner of the timer the initiator or the responder for the last handshake? is_initiator: bool, /// Start time of the tunnel time_started: Instant, - timers: [Duration; TimerName::Top as usize], - pub(super) session_timers: [Duration; super::N_SESSIONS], + timers: [ClockDuration; TimerName::Top as usize], + pub(super) session_timers: [ClockDuration; super::N_SESSIONS], /// Did we receive data without sending anything back? want_keepalive: bool, /// Did we send data without hearing back? @@ -70,8 +65,8 @@ impl Timers { Timers { is_initiator: false, time_started: Instant::now(), - timers: Default::default(), - session_timers: Default::default(), + timers: [ClockDuration::from_ticks(0); TimerName::Top as usize], + session_timers: [ClockDuration::from_ticks(0); super::N_SESSIONS], want_keepalive: Default::default(), want_handshake: Default::default(), persistent_keepalive: usize::from(persistent_keepalive.unwrap_or(0)), @@ -96,14 +91,14 @@ impl Timers { } impl Index for Timers { - type Output = Duration; - fn index(&self, index: TimerName) -> &Duration { + type Output = ClockDuration; + fn index(&self, index: TimerName) -> &ClockDuration { &self.timers[index as usize] } } impl IndexMut for Timers { - fn index_mut(&mut self, index: TimerName) -> &mut Duration { + fn index_mut(&mut self, index: TimerName) -> &mut ClockDuration { &mut self.timers[index as usize] } } @@ -149,11 +144,11 @@ impl Tunn { self.timers.clear(); } - fn update_session_timers(&mut self, time_now: Duration) { + fn update_session_timers(&mut self, time_now: ClockDuration) { let timers = &mut self.timers; for (i, t) in timers.session_timers.iter_mut().enumerate() { - if time_now - *t > REJECT_AFTER_TIME { + if time_now.saturating_sub(*t) > REJECT_AFTER_TIME { if let Some(session) = self.sessions[i].take() { tracing::debug!( message = "SESSION_EXPIRED(REJECT_AFTER_TIME)", @@ -198,14 +193,14 @@ impl Tunn { // Clear cookie after COOKIE_EXPIRATION_TIME if self.handshake.has_cookie() - && now - self.timers[TimeCookieReceived] >= COOKIE_EXPIRATION_TIME + && now.saturating_sub(self.timers[TimeCookieReceived]) >= COOKIE_EXPIRATION_TIME { self.handshake.clear_cookie(); } // All ephemeral private keys and symmetric session keys are zeroed out after // (REJECT_AFTER_TIME * 3) ms if no new keys have been exchanged. - if now - session_established >= REJECT_AFTER_TIME * 3 { + if now.saturating_sub(session_established) >= REJECT_AFTER_TIME * 3 { tracing::error!("CONNECTION_EXPIRED(REJECT_AFTER_TIME * 3)"); self.handshake.set_expired(); self.clear_all(); @@ -214,7 +209,7 @@ impl Tunn { if let Some(time_init_sent) = self.handshake.timer() { // Handshake Initiation Retransmission - if now - handshake_started >= REKEY_ATTEMPT_TIME { + if now.saturating_sub(handshake_started) >= REKEY_ATTEMPT_TIME { // After REKEY_ATTEMPT_TIME ms of trying to initiate a new handshake, // the retries give up and cease, and clear all existing packets queued // up to be sent. If a packet is explicitly queued up to be sent, then @@ -242,7 +237,7 @@ impl Tunn { // responder of the handshake, it does not re-initiate a new handshake // after REKEY_AFTER_TIME ms like the original initiator does. if session_established < data_packet_sent - && now - session_established >= REKEY_AFTER_TIME + && now.saturating_sub(session_established) >= REKEY_AFTER_TIME { tracing::debug!("HANDSHAKE(REKEY_AFTER_TIME (on send))"); handshake_initiation_required = true; @@ -253,7 +248,7 @@ impl Tunn { // - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT ms old, we initiate a new // handshake. if session_established < data_packet_received - && now - session_established + && now.saturating_sub(session_established) >= REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT { tracing::warn!( @@ -269,7 +264,7 @@ impl Tunn { // packet after from that peer for (KEEPALIVE + REKEY_TIMEOUT) ms, // we initiate a new handshake. if data_packet_sent > aut_packet_received - && now - aut_packet_received >= KEEPALIVE_TIMEOUT + REKEY_TIMEOUT + && now.saturating_sub(aut_packet_received) >= KEEPALIVE_TIMEOUT + REKEY_TIMEOUT && mem::replace(&mut self.timers.want_handshake, false) { tracing::warn!("HANDSHAKE(KEEPALIVE + REKEY_TIMEOUT)"); @@ -280,7 +275,7 @@ impl Tunn { // If a packet has been received from a given peer, but we have not sent one back // to the given peer in KEEPALIVE ms, we send an empty packet. if data_packet_received > aut_packet_sent - && now - aut_packet_sent >= KEEPALIVE_TIMEOUT + && now.saturating_sub(aut_packet_sent) >= KEEPALIVE_TIMEOUT && mem::replace(&mut self.timers.want_keepalive, false) { tracing::debug!("KEEPALIVE(KEEPALIVE_TIMEOUT)"); @@ -289,8 +284,8 @@ impl Tunn { // Persistent KEEPALIVE if persistent_keepalive > 0 - && (now - self.timers[TimePersistentKeepalive] - >= Duration::from_secs(persistent_keepalive as _)) + && (now.saturating_sub(self.timers[TimePersistentKeepalive]) + >= ClockDuration::from_secs(persistent_keepalive as u64)) { tracing::debug!("KEEPALIVE(PERSISTENT_KEEPALIVE)"); self.timer_tick(TimePersistentKeepalive); @@ -311,13 +306,13 @@ impl Tunn { TunnResult::Done } - pub fn time_since_last_handshake(&self) -> Option { + pub fn time_since_last_handshake(&self) -> Option { let current_session = self.current; if self.sessions[current_session % super::N_SESSIONS].is_some() { let duration_since_tun_start = Instant::now().duration_since(self.timers.time_started); let duration_since_session_established = self.timers[TimeSessionEstablished]; - Some(duration_since_tun_start - duration_since_session_established) + Some(duration_since_tun_start.saturating_sub(duration_since_session_established)) } else { None } diff --git a/boringtun/src/serialization.rs b/boringtun/src/serialization.rs index e6920f8b6..9838ae066 100644 --- a/boringtun/src/serialization.rs +++ b/boringtun/src/serialization.rs @@ -1,6 +1,8 @@ +use base64::Engine; + pub(crate) struct KeyBytes(pub [u8; 32]); -impl std::str::FromStr for KeyBytes { +impl core::str::FromStr for KeyBytes { type Err = &'static str; /// Can parse a secret key from a hex or base64 encoded string. @@ -17,10 +19,8 @@ impl std::str::FromStr for KeyBytes { } 43 | 44 => { // Try to parse as base64 - if let Ok(decoded_key) = base64::decode(s) { - if decoded_key.len() == internal.len() { - internal[..].copy_from_slice(&decoded_key); - } else { + if let Ok(len) = base64::prelude::BASE64_STANDARD.decode_slice(s, &mut internal) { + if len != internal.len() { return Err("Illegal character in key"); } } diff --git a/boringtun/src/sleepyinstant/mod.rs b/boringtun/src/sleepyinstant/mod.rs index 542beea38..296b67889 100644 --- a/boringtun/src/sleepyinstant/mod.rs +++ b/boringtun/src/sleepyinstant/mod.rs @@ -1,20 +1,73 @@ #![forbid(unsafe_code)] //! Attempts to provide the same functionality as std::time::Instant, except it //! uses a timer which accounts for time when the system is asleep -use std::time::Duration; -#[cfg(target_os = "windows")] +#[cfg(all(unix, feature = "std"))] +mod unix; +#[cfg(all(unix, feature = "std"))] +use unix::now as clock_now; + +#[cfg(all(windows, feature = "std"))] mod windows; -#[cfg(target_os = "windows")] -use windows as inner; +#[cfg(all(windows, feature = "std"))] +use windows::now as clock_now; -#[cfg(unix)] -mod unix; -#[cfg(unix)] -use unix as inner; +#[cfg(not(feature = "std"))] +use lock_api::Mutex; +#[cfg(not(feature = "std"))] +use once_cell::sync::Lazy; + +#[cfg(not(feature = "std"))] +type RawMutex = spin::Mutex<()>; + +/// [`ClockDuration`] and [`ClockInstant`] tick once per nanosecond: `NOM / DENOM` seconds per +/// tick, i.e. `1 / 1_000_000_000`. Named once here so the tick rate has a single source of +/// truth instead of a literal repeated at every use. +const NOM: u64 = 1; +const DENOM: u64 = 1_000_000_000; + +/// The unit used for measuring spans of time between two [`Instant`]s. +pub type ClockDuration = fugit::Duration; + +/// A monotonic point in time, counted in ticks from whatever epoch the clock source uses. +type ClockInstant = fugit::Instant; + +/// A source of time for [`Instant::now`] on targets without `std`. +/// +/// Implementations report the time elapsed since a fixed epoch, e.g. a hardware RTC's reading +/// relative to the Unix epoch, or a free-running timer/counter since boot. [`Instant`] only +/// requires that successive readings never go backwards. +#[cfg(not(feature = "std"))] +pub trait WallClock { + fn now(&mut self) -> ClockDuration; +} + +#[cfg(not(feature = "std"))] +static BORING_CLOCK: Lazy>> = + Lazy::new(|| Mutex::new(None)); + +/// Register the wall clock used by [`Instant::now`] on targets without `std`. +/// +/// Must be called once at startup before any tunnel is used; every subsequent +/// [`Instant::now`] call reads through this clock. Since this takes a `'static` reference +/// rather than owning the clock, callers without a heap allocator can obtain one via a +/// statically allocated cell (e.g. `static_cell::StaticCell`) instead of `Box::leak`. +#[cfg(not(feature = "std"))] +pub fn set_wall_clock(clock: &'static mut (dyn WallClock + Send + Sync)) { + *BORING_CLOCK.lock() = Some(clock); +} + +#[cfg(not(feature = "std"))] +fn clock_now() -> ClockInstant { + let mut clock = BORING_CLOCK.lock(); + let clock = clock + .as_mut() + .expect("no wall clock registered; call sleepyinstant::set_wall_clock() at startup"); + ClockInstant::from_ticks(clock.now().as_ticks()) +} /// A measurement of a monotonically nondecreasing clock. -/// Opaque and useful only with [`Duration`]. +/// Opaque and useful only with [`ClockDuration`]. /// /// Instants are always guaranteed, barring [platform bugs], to be no less than any previously /// measured instant when created, and are often useful for tasks such as measuring @@ -25,53 +78,50 @@ use unix as inner; /// some seconds may be longer than others). An instant may jump forwards or /// experience time dilation (slow down or speed up), but it will never go /// backwards. -/// -/// Instants are opaque types that can only be compared to one another. There is -/// no method to get "the number of seconds" from an instant. Instead, it only -/// allows measuring the duration between two instants (or comparing two -/// instants). -/// -/// The size of an `Instant` struct may vary depending on the target operating -/// system. -/// +#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[derive(Clone, Copy, Debug)] -pub struct Instant { - t: inner::Instant, -} +pub struct Instant(ClockInstant); impl Instant { /// Returns an instant corresponding to "now". pub fn now() -> Self { - Self { - t: inner::Instant::now(), - } + Self(clock_now()) } /// Returns the amount of time elapsed from another instant to this one, /// or zero duration if that instant is later than this one. - /// - /// # Panics - /// - /// panics when `earlier` was later than `self`. - pub fn duration_since(&self, earlier: Instant) -> Duration { - self.t.duration_since(earlier.t) + pub fn duration_since(&self, earlier: Instant) -> ClockDuration { + self.0 + .checked_duration_since(earlier.0) + .unwrap_or(ClockDuration::from_ticks(0)) } /// Returns the amount of time elapsed since this instant was created. - pub fn elapsed(&self) -> Duration { + pub fn elapsed(&self) -> ClockDuration { Self::now().duration_since(*self) } + + /// Returns the amount of time elapsed since the clock's epoch to this instant. + /// + /// The epoch is whatever fixed reference point the underlying clock source uses (e.g. + /// system boot for the unix/windows monotonic clocks); it is not guaranteed to relate to + /// the Unix epoch except on targets whose wall clock backs [`Instant`] directly. + pub fn duration_since_epoch(&self) -> ClockDuration { + self.0.duration_since_epoch() + } } #[cfg(test)] mod tests { + extern crate std; + use super::*; #[test] fn time_increments_after_sleep() { - let sleep_time = Duration::from_millis(10); + let sleep_time = ClockDuration::from_millis(10); let start = Instant::now(); - std::thread::sleep(sleep_time); + std::thread::sleep(sleep_time.into()); assert!(start.elapsed() >= sleep_time); } } diff --git a/boringtun/src/sleepyinstant/unix.rs b/boringtun/src/sleepyinstant/unix.rs index 819c2c0f2..f6d5a9d09 100644 --- a/boringtun/src/sleepyinstant/unix.rs +++ b/boringtun/src/sleepyinstant/unix.rs @@ -1,6 +1,4 @@ -use std::time::Duration; - -use nix::sys::time::TimeSpec; +use crate::sleepyinstant::{ClockDuration, ClockInstant}; use nix::time::{clock_gettime, ClockId}; #[cfg(any( @@ -20,41 +18,10 @@ const CLOCK_ID: ClockId = ClockId::CLOCK_MONOTONIC; )))] const CLOCK_ID: ClockId = ClockId::CLOCK_BOOTTIME; -#[derive(Clone, Copy, Debug)] -pub(crate) struct Instant { - t: TimeSpec, -} - -impl Instant { - pub(crate) fn now() -> Self { - // std::time::Instant unwraps as well, so feel safe doing so here - let t = clock_gettime(CLOCK_ID).unwrap(); - Self { t } - } - - fn checked_duration_since(&self, earlier: Instant) -> Option { - const NANOSECOND: nix::libc::c_long = 1_000_000_000; - let (tv_sec, tv_nsec) = if self.t.tv_nsec() < earlier.t.tv_nsec() { - ( - self.t.tv_sec() - earlier.t.tv_sec() - 1, - self.t.tv_nsec() - earlier.t.tv_nsec() + NANOSECOND, - ) - } else { - ( - self.t.tv_sec() - earlier.t.tv_sec(), - self.t.tv_nsec() - earlier.t.tv_nsec(), - ) - }; - - if tv_sec < 0 { - None - } else { - Some(Duration::new(tv_sec as _, tv_nsec as _)) - } - } - - pub(crate) fn duration_since(&self, earlier: Instant) -> Duration { - self.checked_duration_since(earlier) - .unwrap_or(Duration::ZERO) - } +pub(super) fn now() -> ClockInstant { + // std::time::Instant unwraps as well, so feel safe doing so here + let t = clock_gettime(CLOCK_ID).unwrap(); + let elapsed = + ClockDuration::from_secs(t.tv_sec() as u64) + ClockDuration::from_ticks(t.tv_nsec() as u64); + ClockInstant::from_ticks(elapsed.as_ticks()) } diff --git a/boringtun/src/sleepyinstant/windows.rs b/boringtun/src/sleepyinstant/windows.rs index ac852292f..73b0664da 100644 --- a/boringtun/src/sleepyinstant/windows.rs +++ b/boringtun/src/sleepyinstant/windows.rs @@ -1 +1,9 @@ -pub(crate) use std::time::Instant; +use crate::sleepyinstant::{ClockDuration, ClockInstant}; + +/// `winsafe::GetTickCount64` is a safe wrapper around the Win32 API of the same name: the +/// number of milliseconds since system startup, which (like Linux's `CLOCK_BOOTTIME`) keeps +/// advancing across system sleep. +pub(super) fn now() -> ClockInstant { + let elapsed = ClockDuration::from_millis(winsafe::GetTickCount64()); + ClockInstant::from_ticks(elapsed.as_ticks()) +}