From 526c93011934b0833d697a632de7d384f420e174 Mon Sep 17 00:00:00 2001 From: Prabhpreet Dua <615318+prabhpreet@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:12:44 +0530 Subject: [PATCH] Secret memory with memfd_secret (#321) Implements: - An additional allocator to use memfd_secret(2) and guard pages using mmap(2), implemented in quininer/memsec#16 - An allocator that abstracts away underlying allocators, and uses specified allocator set by rosenpass_secret_memory::policy functions (or a function that sets rosenpass_secret_memory::alloc::ALLOC_INIT - Updates to tests- integration, fuzz, bench: some tests use procspawn to spawn multiple processes with different allocator policies --- .github/workflows/qc.yaml | 8 +- Cargo.lock | 476 +++++++++++++----- Cargo.toml | 26 +- fuzz/Cargo.toml | 32 +- fuzz/fuzz_targets/box_secret_alloc_malloc.rs | 12 + .../fuzz_targets/box_secret_alloc_memfdsec.rs | 13 + ... => box_secret_alloc_memfdsec_mallocfb.rs} | 5 + fuzz/fuzz_targets/handle_msg.rs | 4 + fuzz/fuzz_targets/vec_secret_alloc_malloc.rs | 15 + .../fuzz_targets/vec_secret_alloc_memfdsec.rs | 15 + ... => vec_secret_alloc_memfdsec_mallocfb.rs} | 6 + rosenpass/Cargo.toml | 1 + rosenpass/benches/handshake.rs | 2 + rosenpass/src/cli.rs | 4 + rosenpass/src/protocol.rs | 39 +- rosenpass/tests/integration_test.rs | 3 +- rp/src/key.rs | 4 +- rp/src/main.rs | 3 + secret-memory/Cargo.toml | 1 + .../src/alloc/{memsec.rs => memsec/malloc.rs} | 56 ++- secret-memory/src/alloc/memsec/memfdsec.rs | 112 +++++ secret-memory/src/alloc/memsec/mod.rs | 2 + secret-memory/src/alloc/mod.rs | 88 +++- secret-memory/src/lib.rs | 3 + secret-memory/src/policy.rs | 82 +++ secret-memory/src/secret.rs | 176 ++++--- wireguard-broker/Cargo.toml | 1 + wireguard-broker/src/brokers/netlink.rs | 2 +- wireguard-broker/tests/integration.rs | 126 ++--- 29 files changed, 1010 insertions(+), 307 deletions(-) create mode 100644 fuzz/fuzz_targets/box_secret_alloc_malloc.rs create mode 100644 fuzz/fuzz_targets/box_secret_alloc_memfdsec.rs rename fuzz/fuzz_targets/{box_secret_alloc.rs => box_secret_alloc_memfdsec_mallocfb.rs} (50%) create mode 100644 fuzz/fuzz_targets/vec_secret_alloc_malloc.rs create mode 100644 fuzz/fuzz_targets/vec_secret_alloc_memfdsec.rs rename fuzz/fuzz_targets/{vec_secret_alloc.rs => vec_secret_alloc_memfdsec_mallocfb.rs} (55%) rename secret-memory/src/alloc/{memsec.rs => memsec/malloc.rs} (63%) create mode 100644 secret-memory/src/alloc/memsec/memfdsec.rs create mode 100644 secret-memory/src/alloc/memsec/mod.rs create mode 100644 secret-memory/src/policy.rs diff --git a/.github/workflows/qc.yaml b/.github/workflows/qc.yaml index 2f6fd64..e70e32c 100644 --- a/.github/workflows/qc.yaml +++ b/.github/workflows/qc.yaml @@ -176,8 +176,12 @@ jobs: cargo fuzz run fuzz_handle_msg -- -max_total_time=5 ulimit -s 8192000 && RUST_MIN_STACK=33554432000 && cargo fuzz run fuzz_kyber_encaps -- -max_total_time=5 cargo fuzz run fuzz_mceliece_encaps -- -max_total_time=5 - cargo fuzz run fuzz_box_secret_alloc -- -max_total_time=5 - cargo fuzz run fuzz_vec_secret_alloc -- -max_total_time=5 + cargo fuzz run fuzz_box_secret_alloc_malloc -- -max_total_time=5 + cargo fuzz run fuzz_box_secret_alloc_memfdsec -- -max_total_time=5 + cargo fuzz run fuzz_box_secret_alloc_memfdsec_mallocfb -- -max_total_time=5 + cargo fuzz run fuzz_vec_secret_alloc_malloc -- -max_total_time=5 + cargo fuzz run fuzz_vec_secret_alloc_memfdsec -- -max_total_time=5 + cargo fuzz run fuzz_vec_secret_alloc_memfdsec_mallocfb -- -max_total_time=5 codecov: runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 254740b..1de3337 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -142,7 +142,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi 0.1.19", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -153,17 +153,18 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", "rustc-demangle", + "serde", ] [[package]] @@ -172,6 +173,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.68.1" @@ -191,7 +201,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.60", + "syn 2.0.66", "which", ] @@ -260,9 +270,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" dependencies = [ "jobserver", "libc", @@ -278,6 +288,12 @@ dependencies = [ "nom", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -290,7 +306,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cipher", "cpufeatures", ] @@ -348,9 +364,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -400,7 +416,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -490,6 +506,15 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -511,9 +536,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -531,6 +556,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "ctrlc-async" version = "3.2.2" @@ -539,7 +574,7 @@ checksum = "598e9d68e769aa1283460a3b0ec0d049ccfb6170277aea37089fa3f58fd721a1" dependencies = [ "nix 0.23.2", "tokio", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -548,7 +583,7 @@ version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "curve25519-dalek-derive", "fiat-crypto", @@ -566,7 +601,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -581,12 +616,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ - "darling_core 0.20.8", - "darling_macro 0.20.8", + "darling_core 0.20.9", + "darling_macro 0.20.9", ] [[package]] @@ -605,16 +640,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.60", + "strsim 0.11.1", + "syn 2.0.66", ] [[package]] @@ -630,13 +665,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ - "darling_core 0.20.8", + "darling_core 0.20.9", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -647,7 +682,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -686,10 +721,10 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" dependencies = [ - "darling 0.20.8", + "darling 0.20.9", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -709,7 +744,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core 0.20.0", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -731,9 +766,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "embedded-io" @@ -762,9 +797,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -778,9 +813,21 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fiat-crypto" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi 0.3.9", +] [[package]] name = "fnv" @@ -788,6 +835,22 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags 1.3.2", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "futures" version = "0.3.30" @@ -844,7 +907,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -903,22 +966,33 @@ dependencies = [ "tokio", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "glob" @@ -932,7 +1006,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crunchy", ] @@ -1042,6 +1116,34 @@ dependencies = [ "generic-array", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "ipc-channel" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342d636452fbc2895574e0b319b23c014fd01c9ed71dcd87f6a4a8e2f948db4b" +dependencies = [ + "bincode", + "crossbeam-channel", + "fnv", + "lazy_static", + "libc", + "mio 0.6.23", + "rand 0.7.3", + "serde", + "tempfile", + "uuid", + "winapi 0.3.9", +] + [[package]] name = "is-terminal" version = "0.4.12" @@ -1092,6 +1194,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1106,9 +1218,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libfuzzer-sys" @@ -1127,15 +1239,15 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-targets 0.52.5", ] [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" @@ -1179,11 +1291,11 @@ dependencies = [ [[package]] name = "memsec" -version = "0.6.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa0916b001582d253822171bd23f4a0229d32b9507fae236f5da8cad515ba7c" +checksum = "c797b9d6bb23aab2fc369c65f871be49214f5c759af65bde26ffaaa2b646b492" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libc", "windows-sys 0.45.0", ] @@ -1196,13 +1308,32 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "0.8.11" @@ -1211,10 +1342,22 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "neli" version = "0.6.3" @@ -1240,6 +1383,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "netlink-packet-core" version = "0.7.0" @@ -1339,7 +1493,7 @@ checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags 1.3.2", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset 0.6.5", ] @@ -1351,7 +1505,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ "bitflags 2.5.0", - "cfg-if", + "cfg-if 1.0.0", "libc", ] @@ -1386,9 +1540,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" dependencies = [ "memchr", ] @@ -1432,9 +1586,9 @@ checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "parking_lot" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1446,7 +1600,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -1491,9 +1645,9 @@ checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits", "plotters-backend", @@ -1504,15 +1658,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] @@ -1548,23 +1702,38 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" dependencies = [ "unicode-ident", ] +[[package]] +name = "procspawn" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d59f115c63b1eed96002d9df8dfe022ba07e0d70b42890d34bc34f4342bae6b" +dependencies = [ + "backtrace", + "ctor", + "findshlibs", + "ipc-channel", + "libc", + "serde", + "winapi 0.3.9", +] + [[package]] name = "psm" version = "0.1.21" @@ -1583,6 +1752,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -1590,8 +1772,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -1601,7 +1793,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -1610,7 +1811,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -1683,9 +1893,10 @@ dependencies = [ "home", "log", "memoffset 0.9.1", - "mio", + "mio 0.8.11", "paste", - "rand", + "procspawn", + "rand 0.8.5", "rosenpass-cipher-traits", "rosenpass-ciphers", "rosenpass-constant-time", @@ -1728,7 +1939,7 @@ name = "rosenpass-constant-time" version = "0.1.0" dependencies = [ "memsec", - "rand", + "rand 0.8.5", "rosenpass-to", ] @@ -1766,7 +1977,8 @@ dependencies = [ "base64ct", "log", "memsec", - "rand", + "procspawn", + "rand 0.8.5", "rosenpass-to", "rosenpass-util", "tempfile", @@ -1801,9 +2013,10 @@ dependencies = [ "derive_builder 0.20.0", "env_logger", "log", - "mio", + "mio 0.8.11", "postcard", - "rand", + "procspawn", + "rand 0.8.5", "rosenpass-secret-memory", "rosenpass-to", "rosenpass-util", @@ -1860,9 +2073,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -1894,9 +2107,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1930,9 +2143,9 @@ checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" @@ -1951,14 +2164,14 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -1967,9 +2180,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -1996,7 +2209,7 @@ checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2061,10 +2274,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" dependencies = [ "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "psm", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2104,9 +2317,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -2119,7 +2332,7 @@ version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand", "rustix", "windows-sys 0.52.0", @@ -2163,7 +2376,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2185,7 +2398,7 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio", + "mio 0.8.11", "num_cpus", "parking_lot", "pin-project-lite", @@ -2203,7 +2416,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2220,9 +2433,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -2268,6 +2481,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "getrandom 0.2.15", +] + [[package]] name = "version_check" version = "0.9.4" @@ -2284,6 +2506,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2296,7 +2524,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -2311,7 +2539,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -2333,7 +2561,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2366,6 +2594,12 @@ dependencies = [ "rustix", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -2376,6 +2610,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2623,6 +2863,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "x25519-dalek" version = "2.0.1" @@ -2630,7 +2880,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", - "rand_core", + "rand_core 0.6.4", "serde", "zeroize", ] @@ -2653,7 +2903,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2673,5 +2923,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] diff --git a/Cargo.toml b/Cargo.toml index f2d376c..b7d5816 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,15 +12,11 @@ members = [ "fuzz", "secret-memory", "rp", - "wireguard-broker" -] - -default-members = [ - "rosenpass", - "rp", "wireguard-broker", ] +default-members = ["rosenpass", "rp", "wireguard-broker"] + [workspace.metadata.release] # ensure that adding `--package` as argument to `cargo release` still creates version tags in the form of `vx.y.z` tag-prefix = "" @@ -45,7 +41,7 @@ env_logger = "0.10.2" toml = "0.7.8" static_assertions = "1.1.0" allocator-api2 = "0.2.14" -memsec = "0.6.3" +memsec = { version="0.7.0", features = [ "alloc_ext", ] } rand = "0.8.5" typenum = "1.17.0" log = { version = "0.4.21" } @@ -54,9 +50,15 @@ serde = { version = "1.0.203", features = ["derive"] } arbitrary = { version = "1.3.2", features = ["derive"] } anyhow = { version = "1.0.86", features = ["backtrace", "std"] } mio = { version = "0.8.11", features = ["net", "os-poll"] } -oqs-sys = { version = "0.9.1", default-features = false, features = ['classic_mceliece', 'kyber'] } +oqs-sys = { version = "0.9.1", default-features = false, features = [ + 'classic_mceliece', + 'kyber', +] } blake2 = "0.10.6" -chacha20poly1305 = { version = "0.10.1", default-features = false, features = [ "std", "heapless" ] } +chacha20poly1305 = { version = "0.10.1", default-features = false, features = [ + "std", + "heapless", +] } zerocopy = { version = "0.7.34", features = ["derive"] } home = "0.5.9" derive_builder = "0.20.0" @@ -65,14 +67,16 @@ postcard= {version = "1.0.8", features = ["alloc"]} #Dev dependencies serial_test = "3.1.1" -tempfile="3" +tempfile = "3" stacker = "0.1.15" libfuzzer-sys = "0.4" test_bin = "0.4.0" criterion = "0.4.0" allocator-api2-tests = "0.2.15" +procspawn = {version = "1.0.0", features= ["test-support"]} + #Broker dependencies (might need cleanup or changes) wireguard-uapi = "3.0.0" command-fds = "0.2.3" -rustix = { version = "0.38.27", features = ["net"] } \ No newline at end of file +rustix = { version = "0.38.27", features = ["net"] } diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index e00d010..b214b95 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -48,13 +48,37 @@ test = false doc = false [[bin]] -name = "fuzz_box_secret_alloc" -path = "fuzz_targets/box_secret_alloc.rs" +name = "fuzz_box_secret_alloc_malloc" +path = "fuzz_targets/box_secret_alloc_malloc.rs" test = false doc = false [[bin]] -name = "fuzz_vec_secret_alloc" -path = "fuzz_targets/vec_secret_alloc.rs" +name = "fuzz_vec_secret_alloc_malloc" +path = "fuzz_targets/vec_secret_alloc_malloc.rs" test = false doc = false + +[[bin]] +name = "fuzz_box_secret_alloc_memfdsec" +path = "fuzz_targets/box_secret_alloc_memfdsec.rs" +test = false +doc = false + +[[bin]] +name = "fuzz_vec_secret_alloc_memfdsec" +path = "fuzz_targets/vec_secret_alloc_memfdsec.rs" +test = false +doc = false + +[[bin]] +name = "fuzz_box_secret_alloc_memfdsec_mallocfb" +path = "fuzz_targets/box_secret_alloc_memfdsec_mallocfb.rs" +test = false +doc = false + +[[bin]] +name = "fuzz_vec_secret_alloc_memfdsec_mallocfb" +path = "fuzz_targets/vec_secret_alloc_memfdsec_mallocfb.rs" +test = false +doc = false \ No newline at end of file diff --git a/fuzz/fuzz_targets/box_secret_alloc_malloc.rs b/fuzz/fuzz_targets/box_secret_alloc_malloc.rs new file mode 100644 index 0000000..5b82e1d --- /dev/null +++ b/fuzz/fuzz_targets/box_secret_alloc_malloc.rs @@ -0,0 +1,12 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use rosenpass_secret_memory::alloc::secret_box; +use rosenpass_secret_memory::policy::*; +use std::sync::Once; +static ONCE: Once = Once::new(); + +fuzz_target!(|data: &[u8]| { + ONCE.call_once(secret_policy_use_only_malloc_secrets); + let _ = secret_box(data); +}); diff --git a/fuzz/fuzz_targets/box_secret_alloc_memfdsec.rs b/fuzz/fuzz_targets/box_secret_alloc_memfdsec.rs new file mode 100644 index 0000000..75e41f5 --- /dev/null +++ b/fuzz/fuzz_targets/box_secret_alloc_memfdsec.rs @@ -0,0 +1,13 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use rosenpass_secret_memory::alloc::secret_box; +use rosenpass_secret_memory::policy::*; +use std::sync::Once; + +static ONCE: Once = Once::new(); + +fuzz_target!(|data: &[u8]| { + ONCE.call_once(secret_policy_use_only_memfd_secrets); + let _ = secret_box(data); +}); diff --git a/fuzz/fuzz_targets/box_secret_alloc.rs b/fuzz/fuzz_targets/box_secret_alloc_memfdsec_mallocfb.rs similarity index 50% rename from fuzz/fuzz_targets/box_secret_alloc.rs rename to fuzz/fuzz_targets/box_secret_alloc_memfdsec_mallocfb.rs index 872ef8f..59c11d3 100644 --- a/fuzz/fuzz_targets/box_secret_alloc.rs +++ b/fuzz/fuzz_targets/box_secret_alloc_memfdsec_mallocfb.rs @@ -2,7 +2,12 @@ use libfuzzer_sys::fuzz_target; use rosenpass_secret_memory::alloc::secret_box; +use rosenpass_secret_memory::policy::*; +use std::sync::Once; + +static ONCE: Once = Once::new(); fuzz_target!(|data: &[u8]| { + ONCE.call_once(secret_policy_try_use_memfd_secrets); let _ = secret_box(data); }); diff --git a/fuzz/fuzz_targets/handle_msg.rs b/fuzz/fuzz_targets/handle_msg.rs index b41c1d9..9fce5fb 100644 --- a/fuzz/fuzz_targets/handle_msg.rs +++ b/fuzz/fuzz_targets/handle_msg.rs @@ -6,9 +6,13 @@ use libfuzzer_sys::fuzz_target; use rosenpass::protocol::CryptoServer; use rosenpass_cipher_traits::Kem; use rosenpass_ciphers::kem::StaticKem; +use rosenpass_secret_memory::policy::*; use rosenpass_secret_memory::Secret; +use std::sync::Once; +static ONCE: Once = Once::new(); fuzz_target!(|rx_buf: &[u8]| { + ONCE.call_once(secret_policy_use_only_malloc_secrets); let sk = Secret::from_slice(&[0; StaticKem::SK_LEN]); let pk = Secret::from_slice(&[0; StaticKem::PK_LEN]); diff --git a/fuzz/fuzz_targets/vec_secret_alloc_malloc.rs b/fuzz/fuzz_targets/vec_secret_alloc_malloc.rs new file mode 100644 index 0000000..de2bf22 --- /dev/null +++ b/fuzz/fuzz_targets/vec_secret_alloc_malloc.rs @@ -0,0 +1,15 @@ +#![no_main] + +use std::sync::Once; + +use libfuzzer_sys::fuzz_target; +use rosenpass_secret_memory::alloc::secret_vec; +use rosenpass_secret_memory::policy::*; + +static ONCE: Once = Once::new(); + +fuzz_target!(|data: &[u8]| { + ONCE.call_once(secret_policy_use_only_malloc_secrets); + let mut vec = secret_vec(); + vec.extend_from_slice(data); +}); diff --git a/fuzz/fuzz_targets/vec_secret_alloc_memfdsec.rs b/fuzz/fuzz_targets/vec_secret_alloc_memfdsec.rs new file mode 100644 index 0000000..82b5cac --- /dev/null +++ b/fuzz/fuzz_targets/vec_secret_alloc_memfdsec.rs @@ -0,0 +1,15 @@ +#![no_main] + +use std::sync::Once; + +use libfuzzer_sys::fuzz_target; +use rosenpass_secret_memory::alloc::secret_vec; +use rosenpass_secret_memory::policy::*; + +static ONCE: Once = Once::new(); + +fuzz_target!(|data: &[u8]| { + ONCE.call_once(secret_policy_use_only_memfd_secrets); + let mut vec = secret_vec(); + vec.extend_from_slice(data); +}); diff --git a/fuzz/fuzz_targets/vec_secret_alloc.rs b/fuzz/fuzz_targets/vec_secret_alloc_memfdsec_mallocfb.rs similarity index 55% rename from fuzz/fuzz_targets/vec_secret_alloc.rs rename to fuzz/fuzz_targets/vec_secret_alloc_memfdsec_mallocfb.rs index 66b4ae2..d5a5f1a 100644 --- a/fuzz/fuzz_targets/vec_secret_alloc.rs +++ b/fuzz/fuzz_targets/vec_secret_alloc_memfdsec_mallocfb.rs @@ -1,9 +1,15 @@ #![no_main] +use std::sync::Once; + use libfuzzer_sys::fuzz_target; use rosenpass_secret_memory::alloc::secret_vec; +use rosenpass_secret_memory::policy::*; + +static ONCE: Once = Once::new(); fuzz_target!(|data: &[u8]| { + ONCE.call_once(secret_policy_try_use_memfd_secrets); let mut vec = secret_vec(); vec.extend_from_slice(data); }); diff --git a/rosenpass/Cargo.toml b/rosenpass/Cargo.toml index 4f4f77a..ce81cdc 100644 --- a/rosenpass/Cargo.toml +++ b/rosenpass/Cargo.toml @@ -49,6 +49,7 @@ criterion = { workspace = true } test_bin = { workspace = true } stacker = { workspace = true } serial_test = {workspace = true} +procspawn = {workspace = true} [features] enable_broker_api = ["rosenpass-wireguard-broker/enable_broker_api"] \ No newline at end of file diff --git a/rosenpass/benches/handshake.rs b/rosenpass/benches/handshake.rs index cb01fea..0399503 100644 --- a/rosenpass/benches/handshake.rs +++ b/rosenpass/benches/handshake.rs @@ -5,6 +5,7 @@ use rosenpass_cipher_traits::Kem; use rosenpass_ciphers::kem::StaticKem; use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets; fn handle( tx: &mut CryptoServer, @@ -56,6 +57,7 @@ fn make_server_pair() -> Result<(CryptoServer, CryptoServer)> { } fn criterion_benchmark(c: &mut Criterion) { + secret_policy_try_use_memfd_secrets(); let (mut a, mut b) = make_server_pair().unwrap(); c.bench_function("cca_secret_alloc", |bench| { bench.iter(|| { diff --git a/rosenpass/src/cli.rs b/rosenpass/src/cli.rs index 7ebeb9c..4c350ac 100644 --- a/rosenpass/src/cli.rs +++ b/rosenpass/src/cli.rs @@ -3,6 +3,7 @@ use clap::{Parser, Subcommand}; use rosenpass_cipher_traits::Kem; use rosenpass_ciphers::kem::StaticKem; use rosenpass_secret_memory::file::StoreSecret; +use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets; use rosenpass_util::file::{LoadValue, LoadValueB64}; use rosenpass_wireguard_broker::brokers::native_unix::{ NativeUnixBroker, NativeUnixBrokerConfigBaseBuilder, NativeUnixBrokerConfigBaseBuilderError, @@ -154,6 +155,9 @@ impl CliCommand { /// ## TODO /// - This method consumes the [`CliCommand`] value. It might be wise to use a reference... pub fn run(self, test_helpers: Option) -> anyhow::Result<()> { + //Specify secret policy + secret_policy_try_use_memfd_secrets(); + use CliCommand::*; match self { Man => { diff --git a/rosenpass/src/protocol.rs b/rosenpass/src/protocol.rs index fa238d8..a3c61c7 100644 --- a/rosenpass/src/protocol.rs +++ b/rosenpass/src/protocol.rs @@ -19,12 +19,16 @@ //! [CryptoServer]. //! //! ``` +//! use rosenpass_secret_memory::policy::*; //! use rosenpass_cipher_traits::Kem; //! use rosenpass_ciphers::kem::StaticKem; //! use rosenpass::{ //! protocol::{SSk, SPk, MsgBuf, PeerPtr, CryptoServer, SymKey}, //! }; //! # fn main() -> anyhow::Result<()> { +//! // Set security policy for storing secrets +//! +//! secret_policy_try_use_memfd_secrets(); //! //! // initialize secret and public key for peer a ... //! let (mut peer_a_sk, mut peer_a_pk) = (SSk::zero(), SPk::zero()); @@ -2145,6 +2149,7 @@ mod test { use std::{net::SocketAddrV4, thread::sleep, time::Duration}; use super::*; + use serial_test::serial; struct VecHostIdentifier(Vec); @@ -2166,7 +2171,21 @@ mod test { } } + fn setup_logging() { + use std::io::Write; + let mut log_builder = env_logger::Builder::from_default_env(); // sets log level filter from environment (or defaults) + log_builder.filter_level(log::LevelFilter::Info); + log_builder.format_timestamp_nanos(); + log_builder.format(|buf, record| { + let ts_format = buf.timestamp_nanos().to_string(); + writeln!(buf, "{}: {}", &ts_format[14..], record.args()) + }); + + let _ = log_builder.try_init(); + } + #[test] + #[serial] /// Ensure that the protocol implementation can deal with truncated /// messages and with overlong messages. /// @@ -2182,6 +2201,8 @@ mod test { /// Through all this, the handshake should still successfully terminate; /// i.e. an exchanged key must be produced in both servers. fn handles_incorrect_size_messages() { + setup_logging(); + rosenpass_secret_memory::secret_policy_try_use_memfd_secrets(); stacker::grow(8 * 1024 * 1024, || { const OVERSIZED_MESSAGE: usize = ((MAX_MESSAGE_LEN as f32) * 1.2) as usize; type MsgBufPlus = Public; @@ -2252,7 +2273,10 @@ mod test { } #[test] + #[serial] fn test_regular_exchange() { + setup_logging(); + rosenpass_secret_memory::secret_policy_try_use_memfd_secrets(); stacker::grow(8 * 1024 * 1024, || { type MsgBufPlus = Public; let (mut a, mut b) = make_server_pair().unwrap(); @@ -2296,7 +2320,7 @@ mod test { //B handles InitConf, sends EmptyData let HandleMsgResult { - resp, + resp: _, exchanged_with, } = b .handle_msg(&a_to_b_buf.as_slice()[..init_conf_len], &mut *b_to_a_buf) @@ -2310,7 +2334,10 @@ mod test { } #[test] + #[serial] fn test_regular_init_conf_retransmit() { + setup_logging(); + rosenpass_secret_memory::secret_policy_try_use_memfd_secrets(); stacker::grow(8 * 1024 * 1024, || { type MsgBufPlus = Public; let (mut a, mut b) = make_server_pair().unwrap(); @@ -2355,7 +2382,7 @@ mod test { //B handles InitConf, sends EmptyData let HandleMsgResult { - resp, + resp: _, exchanged_with, } = b .handle_msg(&a_to_b_buf.as_slice()[..init_conf_len], &mut *b_to_a_buf) @@ -2368,7 +2395,7 @@ mod test { //B handles InitConf again, sends EmptyData let HandleMsgResult { - resp, + resp: _, exchanged_with, } = b .handle_msg(&a_to_b_buf.as_slice()[..init_conf_len], &mut *b_to_a_buf) @@ -2382,7 +2409,10 @@ mod test { } #[test] + #[serial] fn cookie_reply_mechanism_responder_under_load() { + setup_logging(); + rosenpass_secret_memory::secret_policy_try_use_memfd_secrets(); stacker::grow(8 * 1024 * 1024, || { type MsgBufPlus = Public; let (mut a, mut b) = make_server_pair().unwrap(); @@ -2476,7 +2506,10 @@ mod test { } #[test] + #[serial] fn cookie_reply_mechanism_initiator_bails_on_message_under_load() { + setup_logging(); + rosenpass_secret_memory::secret_policy_try_use_memfd_secrets(); stacker::grow(8 * 1024 * 1024, || { type MsgBufPlus = Public; let (mut a, mut b) = make_server_pair().unwrap(); diff --git a/rosenpass/tests/integration_test.rs b/rosenpass/tests/integration_test.rs index f6e4b04..66925d6 100644 --- a/rosenpass/tests/integration_test.rs +++ b/rosenpass/tests/integration_test.rs @@ -6,7 +6,7 @@ use std::{ time::Duration, }; -use clap::{builder::Str, Parser}; +use clap::Parser; use rosenpass::{app_server::AppServerTestBuilder, cli::CliArgs}; use rosenpass_secret_memory::{Public, Secret}; use rosenpass_wireguard_broker::{WireguardBrokerMio, WG_KEY_LEN, WG_PEER_LEN}; @@ -275,6 +275,7 @@ fn check_exchange_under_dos() { fs::remove_dir_all(&tmpdir).unwrap(); } +#[allow(dead_code)] #[derive(Debug, Default)] struct MockBrokerInner { psk: Option>, diff --git a/rp/src/key.rs b/rp/src/key.rs index d151d69..8f1274c 100644 --- a/rp/src/key.rs +++ b/rp/src/key.rs @@ -102,6 +102,7 @@ mod tests { use std::fs; use rosenpass::protocol::{SPk, SSk}; + use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets; use rosenpass_secret_memory::Secret; use rosenpass_util::file::LoadValue; use rosenpass_util::file::LoadValueB64; @@ -110,7 +111,8 @@ mod tests { use crate::key::{genkey, pubkey, WG_B64_LEN}; #[test] - fn it_works() { + fn test_key_loopback() { + secret_policy_try_use_memfd_secrets(); let private_keys_dir = tempdir().unwrap(); fs::remove_dir(private_keys_dir.path()).unwrap(); diff --git a/rp/src/main.rs b/rp/src/main.rs index adb2e6d..68073a0 100644 --- a/rp/src/main.rs +++ b/rp/src/main.rs @@ -3,6 +3,7 @@ use std::process::exit; use cli::{Cli, Command}; use exchange::exchange; use key::{genkey, pubkey}; +use rosenpass_secret_memory::policy; mod cli; mod exchange; @@ -10,6 +11,8 @@ mod key; #[tokio::main] async fn main() { + policy::secret_policy_try_use_memfd_secrets(); + let cli = match Cli::parse(std::env::args().peekable()) { Ok(cli) => cli, Err(err) => { diff --git a/secret-memory/Cargo.toml b/secret-memory/Cargo.toml index 69e1edd..84e8268 100644 --- a/secret-memory/Cargo.toml +++ b/secret-memory/Cargo.toml @@ -23,3 +23,4 @@ log = { workspace = true } allocator-api2-tests = { workspace = true } tempfile = {workspace = true} base64ct = {workspace = true} +procspawn = {workspace = true} \ No newline at end of file diff --git a/secret-memory/src/alloc/memsec.rs b/secret-memory/src/alloc/memsec/malloc.rs similarity index 63% rename from secret-memory/src/alloc/memsec.rs rename to secret-memory/src/alloc/memsec/malloc.rs index eec4897..7e87d16 100644 --- a/secret-memory/src/alloc/memsec.rs +++ b/secret-memory/src/alloc/memsec/malloc.rs @@ -4,37 +4,41 @@ use std::ptr::NonNull; use allocator_api2::alloc::{AllocError, Allocator, Layout}; #[derive(Copy, Clone, Default)] -struct MemsecAllocatorContents; +struct MallocAllocatorContents; /// Memory allocation using using the memsec crate #[derive(Copy, Clone, Default)] -pub struct MemsecAllocator { - _dummy_private_data: MemsecAllocatorContents, +pub struct MallocAllocator { + _dummy_private_data: MallocAllocatorContents, } /// A box backed by the memsec allocator -pub type MemsecBox = allocator_api2::boxed::Box; +pub type MallocBox = allocator_api2::boxed::Box; /// A vector backed by the memsec allocator -pub type MemsecVec = allocator_api2::vec::Vec; +pub type MallocVec = allocator_api2::vec::Vec; -pub fn memsec_box(x: T) -> MemsecBox { - MemsecBox::::new_in(x, MemsecAllocator::new()) +pub fn malloc_box_try(x: T) -> Result, AllocError> { + MallocBox::::try_new_in(x, MallocAllocator::new()) } -pub fn memsec_vec() -> MemsecVec { - MemsecVec::::new_in(MemsecAllocator::new()) +pub fn malloc_box(x: T) -> MallocBox { + MallocBox::::new_in(x, MallocAllocator::new()) } -impl MemsecAllocator { +pub fn malloc_vec() -> MallocVec { + MallocVec::::new_in(MallocAllocator::new()) +} + +impl MallocAllocator { pub fn new() -> Self { Self { - _dummy_private_data: MemsecAllocatorContents, + _dummy_private_data: MallocAllocatorContents, } } } -unsafe impl Allocator for MemsecAllocator { +unsafe impl Allocator for MallocAllocator { fn allocate(&self, layout: Layout) -> Result, AllocError> { // Call memsec allocator let mem: Option> = unsafe { memsec::malloc_sized(layout.size()) }; @@ -48,8 +52,8 @@ unsafe impl Allocator for MemsecAllocator { // Ensure the right alignment is used let off = (mem.as_ptr() as *const u8).align_offset(layout.align()); if off != 0 { - log::error!("Allocation {layout:?} was requested but memsec returned allocation \ - with offset {off} from the requested alignment. Memsec always allocates values \ + log::error!("Allocation {layout:?} was requested but malloc-based memsec returned allocation \ + with offset {off} from the requested alignment. Malloc always allocates values \ at the end of a memory page for security reasons, custom alignments are not supported. \ You could try allocating an oversized value."); unsafe { memsec::free(mem) }; @@ -66,7 +70,7 @@ unsafe impl Allocator for MemsecAllocator { } } -impl fmt::Debug for MemsecAllocator { +impl fmt::Debug for MallocAllocator { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str("") } @@ -78,21 +82,21 @@ mod test { use super::*; - make_test! { test_sizes(MemsecAllocator::new()) } - make_test! { test_vec(MemsecAllocator::new()) } - make_test! { test_many_boxes(MemsecAllocator::new()) } + make_test! { test_sizes(MallocAllocator::new()) } + make_test! { test_vec(MallocAllocator::new()) } + make_test! { test_many_boxes(MallocAllocator::new()) } #[test] - fn memsec_allocation() { - let alloc = MemsecAllocator::new(); - memsec_allocation_impl::<0>(&alloc); - memsec_allocation_impl::<7>(&alloc); - memsec_allocation_impl::<8>(&alloc); - memsec_allocation_impl::<64>(&alloc); - memsec_allocation_impl::<999>(&alloc); + fn malloc_allocation() { + let alloc = MallocAllocator::new(); + malloc_allocation_impl::<0>(&alloc); + malloc_allocation_impl::<7>(&alloc); + malloc_allocation_impl::<8>(&alloc); + malloc_allocation_impl::<64>(&alloc); + malloc_allocation_impl::<999>(&alloc); } - fn memsec_allocation_impl(alloc: &MemsecAllocator) { + fn malloc_allocation_impl(alloc: &MallocAllocator) { let layout = Layout::new::<[u8; N]>(); let mem = alloc.allocate(layout).unwrap(); diff --git a/secret-memory/src/alloc/memsec/memfdsec.rs b/secret-memory/src/alloc/memsec/memfdsec.rs new file mode 100644 index 0000000..9ba58c9 --- /dev/null +++ b/secret-memory/src/alloc/memsec/memfdsec.rs @@ -0,0 +1,112 @@ +#![cfg(target_os = "linux")] +use std::fmt; +use std::ptr::NonNull; + +use allocator_api2::alloc::{AllocError, Allocator, Layout}; + +#[derive(Copy, Clone, Default)] +struct MemfdSecAllocatorContents; + +/// Memory allocation using using the memsec crate +#[derive(Copy, Clone, Default)] +pub struct MemfdSecAllocator { + _dummy_private_data: MemfdSecAllocatorContents, +} + +/// A box backed by the memsec allocator +pub type MemfdSecBox = allocator_api2::boxed::Box; + +/// A vector backed by the memsec allocator +pub type MemfdSecVec = allocator_api2::vec::Vec; + +pub fn memfdsec_box_try(x: T) -> Result, AllocError> { + MemfdSecBox::::try_new_in(x, MemfdSecAllocator::new()) +} + +pub fn memfdsec_box(x: T) -> MemfdSecBox { + MemfdSecBox::::new_in(x, MemfdSecAllocator::new()) +} + +pub fn memfdsec_vec() -> MemfdSecVec { + MemfdSecVec::::new_in(MemfdSecAllocator::new()) +} + +impl MemfdSecAllocator { + pub fn new() -> Self { + Self { + _dummy_private_data: MemfdSecAllocatorContents, + } + } +} + +unsafe impl Allocator for MemfdSecAllocator { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + // Call memsec allocator + let mem: Option> = unsafe { memsec::memfd_secret_sized(layout.size()) }; + + // Unwrap the option + let Some(mem) = mem else { + log::error!("Allocation {layout:?} was requested but memfd-based memsec returned a null pointer"); + return Err(AllocError); + }; + + // Ensure the right alignment is used + let off = (mem.as_ptr() as *const u8).align_offset(layout.align()); + if off != 0 { + log::error!("Allocation {layout:?} was requested but memfd-based memsec returned allocation \ + with offset {off} from the requested alignment. Memfd always allocates values \ + at the end of a memory page for security reasons, custom alignments are not supported. \ + You could try allocating an oversized value."); + unsafe { memsec::free_memfd_secret(mem) }; + return Err(AllocError); + }; + + Ok(mem) + } + + unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { + unsafe { + memsec::free_memfd_secret(ptr); + } + } +} + +impl fmt::Debug for MemfdSecAllocator { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str("") + } +} + +#[cfg(test)] +mod test { + use allocator_api2_tests::make_test; + + use super::*; + + make_test! { test_sizes(MemfdSecAllocator::new()) } + make_test! { test_vec(MemfdSecAllocator::new()) } + make_test! { test_many_boxes(MemfdSecAllocator::new()) } + + #[test] + fn memfdsec_allocation() { + let alloc = MemfdSecAllocator::new(); + memfdsec_allocation_impl::<0>(&alloc); + memfdsec_allocation_impl::<7>(&alloc); + memfdsec_allocation_impl::<8>(&alloc); + memfdsec_allocation_impl::<64>(&alloc); + memfdsec_allocation_impl::<999>(&alloc); + } + + fn memfdsec_allocation_impl(alloc: &MemfdSecAllocator) { + let layout = Layout::new::<[u8; N]>(); + let mem = alloc.allocate(layout).unwrap(); + + // https://libsodium.gitbook.io/doc/memory_management#guarded-heap-allocations + // promises us that allocated memory is initialized with the magic byte 0xDB + // and memsec promises to provide a reimplementation of the libsodium mechanism; + // it uses the magic value 0xD0 though + assert_eq!(unsafe { mem.as_ref() }, &[0xD0u8; N]); + let mem = NonNull::new(mem.as_ptr() as *mut u8).unwrap(); + unsafe { alloc.deallocate(mem, layout) }; + } +} diff --git a/secret-memory/src/alloc/memsec/mod.rs b/secret-memory/src/alloc/memsec/mod.rs new file mode 100644 index 0000000..3b1bc27 --- /dev/null +++ b/secret-memory/src/alloc/memsec/mod.rs @@ -0,0 +1,2 @@ +pub mod malloc; +pub mod memfdsec; diff --git a/secret-memory/src/alloc/mod.rs b/secret-memory/src/alloc/mod.rs index e97fd8d..791d148 100644 --- a/secret-memory/src/alloc/mod.rs +++ b/secret-memory/src/alloc/mod.rs @@ -1,6 +1,86 @@ pub mod memsec; -pub use crate::alloc::memsec::{ - memsec_box as secret_box, memsec_vec as secret_vec, MemsecAllocator as SecretAllocator, - MemsecBox as SecretBox, MemsecVec as SecretVec, -}; +use std::sync::OnceLock; + +use allocator_api2::alloc::{AllocError, Allocator}; +use memsec::malloc::MallocAllocator; + +#[cfg(target_os = "linux")] +use memsec::memfdsec::MemfdSecAllocator; + +static ALLOC_TYPE: OnceLock = OnceLock::new(); + +/// Sets the secret allocation type to use. +/// Intended usage at startup before secret allocation +/// takes place +pub fn set_secret_alloc_type(alloc_type: SecretAllocType) { + ALLOC_TYPE.set(alloc_type).unwrap(); +} + +pub fn get_or_init_secret_alloc_type(alloc_type: SecretAllocType) -> SecretAllocType { + *ALLOC_TYPE.get_or_init(|| alloc_type) +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SecretAllocType { + MemsecMalloc, + #[cfg(target_os = "linux")] + MemsecMemfdSec, +} + +pub struct SecretAlloc { + alloc_type: SecretAllocType, +} + +impl Default for SecretAlloc { + fn default() -> Self { + Self { + alloc_type: *ALLOC_TYPE.get().expect( + "Secret security policy not specified. \ + Run the specifying policy function in \ + rosenpass_secret_memory::policy or set a \ + custom policy by initializing \ + rosenpass_secret_memory::alloc::ALLOC_TYPE \ + before using secrets", + ), + } + } +} + +unsafe impl Allocator for SecretAlloc { + fn allocate( + &self, + layout: std::alloc::Layout, + ) -> Result, allocator_api2::alloc::AllocError> { + match self.alloc_type { + SecretAllocType::MemsecMalloc => MallocAllocator::default().allocate(layout), + #[cfg(target_os = "linux")] + SecretAllocType::MemsecMemfdSec => MemfdSecAllocator::default().allocate(layout), + } + } + + unsafe fn deallocate(&self, ptr: std::ptr::NonNull, layout: std::alloc::Layout) { + match self.alloc_type { + SecretAllocType::MemsecMalloc => MallocAllocator::default().deallocate(ptr, layout), + #[cfg(target_os = "linux")] + SecretAllocType::MemsecMemfdSec => MemfdSecAllocator::default().deallocate(ptr, layout), + } + } +} + +pub type SecretBox = allocator_api2::boxed::Box; + +/// A vector backed by the memsec allocator +pub type SecretVec = allocator_api2::vec::Vec; + +pub fn secret_box_try(x: T) -> Result, AllocError> { + SecretBox::::try_new_in(x, SecretAlloc::default()) +} + +pub fn secret_box(x: T) -> SecretBox { + SecretBox::::new_in(x, SecretAlloc::default()) +} + +pub fn secret_vec() -> SecretVec { + SecretVec::::new_in(SecretAlloc::default()) +} diff --git a/secret-memory/src/lib.rs b/secret-memory/src/lib.rs index b38ed75..7addfc0 100644 --- a/secret-memory/src/lib.rs +++ b/secret-memory/src/lib.rs @@ -9,3 +9,6 @@ pub use crate::public::Public; mod secret; pub use crate::secret::Secret; + +pub mod policy; +pub use crate::policy::*; diff --git a/secret-memory/src/policy.rs b/secret-memory/src/policy.rs new file mode 100644 index 0000000..4aad2b1 --- /dev/null +++ b/secret-memory/src/policy.rs @@ -0,0 +1,82 @@ +pub fn secret_policy_try_use_memfd_secrets() { + let alloc_type = { + #[cfg(target_os = "linux")] + { + if crate::alloc::memsec::memfdsec::memfdsec_box_try(0u8).is_ok() { + crate::alloc::SecretAllocType::MemsecMemfdSec + } else { + crate::alloc::SecretAllocType::MemsecMalloc + } + } + + #[cfg(not(target_os = "linux"))] + { + crate::alloc::SecretAllocType::MemsecMalloc + } + }; + assert_eq!( + alloc_type, + crate::alloc::get_or_init_secret_alloc_type(alloc_type) + ); + + log::info!("Secrets will be allocated using {:?}", alloc_type); +} + +#[cfg(target_os = "linux")] +pub fn secret_policy_use_only_memfd_secrets() { + let alloc_type = crate::alloc::SecretAllocType::MemsecMemfdSec; + + assert_eq!( + alloc_type, + crate::alloc::get_or_init_secret_alloc_type(alloc_type) + ); + + log::info!("Secrets will be allocated using {:?}", alloc_type); +} + +pub fn secret_policy_use_only_malloc_secrets() { + let alloc_type = crate::alloc::SecretAllocType::MemsecMalloc; + assert_eq!( + alloc_type, + crate::alloc::get_or_init_secret_alloc_type(alloc_type) + ); + + log::info!("Secrets will be allocated using {:?}", alloc_type); +} + +pub mod test { + #[macro_export] + macro_rules! test_spawn_process_with_policies { + ($body:block, $($f: expr),*) => { + $( + let handle = procspawn::spawn((), |_| { + + $f(); + + $body + + }); + handle.join().unwrap(); + )* + }; + } + + #[macro_export] + macro_rules! test_spawn_process_provided_policies { + ($body: block) => { + $crate::test_spawn_process_with_policies!( + $body, + $crate::policy::secret_policy_try_use_memfd_secrets, + $crate::secret_policy_use_only_malloc_secrets + ); + + #[cfg(target_os = "linux")] + { + $crate::test_spawn_process_with_policies!( + $body, + $crate::policy::secret_policy_use_only_memfd_secrets + ); + } + }; + } +} diff --git a/secret-memory/src/secret.rs b/secret-memory/src/secret.rs index 22d4516..6173de3 100644 --- a/secret-memory/src/secret.rs +++ b/secret-memory/src/secret.rs @@ -321,133 +321,147 @@ impl StoreSecret for Secret { #[cfg(test)] mod test { + use crate::test_spawn_process_provided_policies; + use super::*; use std::{fs, os::unix::fs::PermissionsExt}; use tempfile::tempdir; + procspawn::enable_test_support!(); + /// check that we can alloc using the magic pool #[test] fn secret_memory_pool_take() { - const N: usize = 0x100; - let mut pool = SecretMemoryPool::new(); - let secret: ZeroizingSecretBox<[u8; N]> = pool.take(); - assert_eq!(secret.as_ref(), &[0; N]); + test_spawn_process_provided_policies!({ + const N: usize = 0x100; + let mut pool = SecretMemoryPool::new(); + let secret: ZeroizingSecretBox<[u8; N]> = pool.take(); + assert_eq!(secret.as_ref(), &[0; N]); + }); } /// check that a secret lives, even if its [SecretMemoryPool] is deleted #[test] fn secret_memory_pool_drop() { - const N: usize = 0x100; - let mut pool = SecretMemoryPool::new(); - let secret: ZeroizingSecretBox<[u8; N]> = pool.take(); - std::mem::drop(pool); - assert_eq!(secret.as_ref(), &[0; N]); + test_spawn_process_provided_policies!({ + const N: usize = 0x100; + let mut pool = SecretMemoryPool::new(); + let secret: ZeroizingSecretBox<[u8; N]> = pool.take(); + std::mem::drop(pool); + assert_eq!(secret.as_ref(), &[0; N]); + }); } /// check that a secret can be reborn, freshly initialized with zero #[test] fn secret_memory_pool_release() { - const N: usize = 1; - let mut pool = SecretMemoryPool::new(); - let mut secret: ZeroizingSecretBox<[u8; N]> = pool.take(); - let old_secret_ptr = secret.as_ref().as_ptr(); + test_spawn_process_provided_policies!({ + const N: usize = 1; + let mut pool = SecretMemoryPool::new(); + let mut secret: ZeroizingSecretBox<[u8; N]> = pool.take(); + let old_secret_ptr = secret.as_ref().as_ptr(); - secret.as_mut()[0] = 0x13; - pool.release(secret); + secret.as_mut()[0] = 0x13; + pool.release(secret); - // now check that we get the same ptr - let new_secret: ZeroizingSecretBox<[u8; N]> = pool.take(); - assert_eq!(old_secret_ptr, new_secret.as_ref().as_ptr()); + // now check that we get the same ptr + let new_secret: ZeroizingSecretBox<[u8; N]> = pool.take(); + assert_eq!(old_secret_ptr, new_secret.as_ref().as_ptr()); - // and that the secret was zeroized - assert_eq!(new_secret.as_ref(), &[0; N]); + // and that the secret was zeroized + assert_eq!(new_secret.as_ref(), &[0; N]); + }); } /// test loading a secret from an example file, and then storing it again in a different file #[test] fn test_secret_load_store() { - const N: usize = 100; + test_spawn_process_provided_policies!({ + const N: usize = 100; - // Generate original random bytes - let original_bytes: [u8; N] = [rand::random(); N]; + // Generate original random bytes + let original_bytes: [u8; N] = [rand::random(); N]; - // Create a temporary directory - let temp_dir = tempdir().unwrap(); + // Create a temporary directory + let temp_dir = tempdir().unwrap(); - // Store the original secret to an example file in the temporary directory - let example_file = temp_dir.path().join("example_file"); - std::fs::write(example_file.clone(), &original_bytes).unwrap(); + // Store the original secret to an example file in the temporary directory + let example_file = temp_dir.path().join("example_file"); + std::fs::write(example_file.clone(), &original_bytes).unwrap(); - // Load the secret from the example file - let loaded_secret = Secret::load(&example_file).unwrap(); + // Load the secret from the example file + let loaded_secret = Secret::load(&example_file).unwrap(); - // Check that the loaded secret matches the original bytes - assert_eq!(loaded_secret.secret(), &original_bytes); + // Check that the loaded secret matches the original bytes + assert_eq!(loaded_secret.secret(), &original_bytes); - // Store the loaded secret to a different file in the temporary directory - let new_file = temp_dir.path().join("new_file"); - loaded_secret.store(&new_file).unwrap(); + // Store the loaded secret to a different file in the temporary directory + let new_file = temp_dir.path().join("new_file"); + loaded_secret.store(&new_file).unwrap(); - // Read the contents of the new file - let new_file_contents = fs::read(&new_file).unwrap(); + // Read the contents of the new file + let new_file_contents = fs::read(&new_file).unwrap(); - // Read the contents of the original file - let original_file_contents = fs::read(&example_file).unwrap(); + // Read the contents of the original file + let original_file_contents = fs::read(&example_file).unwrap(); - // Check that the contents of the new file match the original file - assert_eq!(new_file_contents, original_file_contents); + // Check that the contents of the new file match the original file + assert_eq!(new_file_contents, original_file_contents); + }); } /// test loading a base64 encoded secret from an example file, and then storing it again in a different file #[test] fn test_secret_load_store_base64() { - const N: usize = 100; - // Generate original random bytes - let original_bytes: [u8; N] = [rand::random(); N]; - // Create a temporary directory - let temp_dir = tempdir().unwrap(); - let example_file = temp_dir.path().join("example_file"); - let mut encoded_secret = [0u8; N * 2]; - let encoded_secret = b64_encode(&original_bytes, &mut encoded_secret).unwrap(); + test_spawn_process_provided_policies!({ + const N: usize = 100; + // Generate original random bytes + let original_bytes: [u8; N] = [rand::random(); N]; + // Create a temporary directory + let temp_dir = tempdir().unwrap(); + let example_file = temp_dir.path().join("example_file"); + let mut encoded_secret = [0u8; N * 2]; + let encoded_secret = b64_encode(&original_bytes, &mut encoded_secret).unwrap(); - std::fs::write(&example_file, encoded_secret).unwrap(); + std::fs::write(&example_file, encoded_secret).unwrap(); - // Load the secret from the example file - let loaded_secret = Secret::load_b64::<{ N * 2 }, _>(&example_file).unwrap(); - // Check that the loaded secret matches the original bytes - assert_eq!(loaded_secret.secret(), &original_bytes); + // Load the secret from the example file + let loaded_secret = Secret::load_b64::<{ N * 2 }, _>(&example_file).unwrap(); + // Check that the loaded secret matches the original bytes + assert_eq!(loaded_secret.secret(), &original_bytes); - // Store the loaded secret to a different file in the temporary directory - let new_file = temp_dir.path().join("new_file"); - loaded_secret.store_b64::<{ N * 2 }, _>(&new_file).unwrap(); + // Store the loaded secret to a different file in the temporary directory + let new_file = temp_dir.path().join("new_file"); + loaded_secret.store_b64::<{ N * 2 }, _>(&new_file).unwrap(); - // Read the contents of the new file - let new_file_contents = fs::read(&new_file).unwrap(); - // Read the contents of the original file - let original_file_contents = fs::read(&example_file).unwrap(); - // Check that the contents of the new file match the original file - assert_eq!(new_file_contents, original_file_contents); + // Read the contents of the new file + let new_file_contents = fs::read(&new_file).unwrap(); + // Read the contents of the original file + let original_file_contents = fs::read(&example_file).unwrap(); + // Check that the contents of the new file match the original file + assert_eq!(new_file_contents, original_file_contents); - //Check new file permissions are secret - let metadata = fs::metadata(&new_file).unwrap(); - assert_eq!(metadata.permissions().mode() & 0o000777, 0o600); + //Check new file permissions are secret + let metadata = fs::metadata(&new_file).unwrap(); + assert_eq!(metadata.permissions().mode() & 0o000777, 0o600); - // Store the loaded secret to a different file in the temporary directory for a second time - let new_file = temp_dir.path().join("new_file_writer"); - let new_file_writer = fopen_w(new_file.clone(), Visibility::Secret).unwrap(); - loaded_secret - .store_b64_writer::<{ N * 2 }, _>(&new_file_writer) - .unwrap(); + // Store the loaded secret to a different file in the temporary directory for a second time + let new_file = temp_dir.path().join("new_file_writer"); + let new_file_writer = fopen_w(new_file.clone(), Visibility::Secret).unwrap(); + loaded_secret + .store_b64_writer::<{ N * 2 }, _>(&new_file_writer) + .unwrap(); - // Read the contents of the new file - let new_file_contents = fs::read(&new_file).unwrap(); - // Read the contents of the original file - let original_file_contents = fs::read(&example_file).unwrap(); - // Check that the contents of the new file match the original file - assert_eq!(new_file_contents, original_file_contents); + // Read the contents of the new file + let new_file_contents = fs::read(&new_file).unwrap(); + // Read the contents of the original file + let original_file_contents = fs::read(&example_file).unwrap(); + // Check that the contents of the new file match the original file + assert_eq!(new_file_contents, original_file_contents); - //Check new file permissions are secret - let metadata = fs::metadata(&new_file).unwrap(); - assert_eq!(metadata.permissions().mode() & 0o000777, 0o600); + //Check new file permissions are secret + let metadata = fs::metadata(&new_file).unwrap(); + assert_eq!(metadata.permissions().mode() & 0o000777, 0o600); + }); } } diff --git a/wireguard-broker/Cargo.toml b/wireguard-broker/Cargo.toml index 62c94cb..7809b29 100644 --- a/wireguard-broker/Cargo.toml +++ b/wireguard-broker/Cargo.toml @@ -33,6 +33,7 @@ rosenpass-util = { workspace = true } [dev-dependencies] rand = {workspace = true} +procspawn = {workspace = true} [features] enable_broker_api=[] diff --git a/wireguard-broker/src/brokers/netlink.rs b/wireguard-broker/src/brokers/netlink.rs index 5bb32d2..7cfd2ee 100644 --- a/wireguard-broker/src/brokers/netlink.rs +++ b/wireguard-broker/src/brokers/netlink.rs @@ -77,7 +77,7 @@ impl WireGuardBroker for NetlinkWireGuardBroker { fn set_psk(&mut self, config: SerializedBrokerConfig) -> Result<(), Self::Error> { let config: NetworkBrokerConfig = config .try_into() - .map_err(|e| SetPskError::NoSuchInterface)?; + .map_err(|_e| SetPskError::NoSuchInterface)?; // Ensure that the peer exists by querying the device configuration // TODO: Use InvalidInterfaceError diff --git a/wireguard-broker/tests/integration.rs b/wireguard-broker/tests/integration.rs index 2d365eb..2166aab 100644 --- a/wireguard-broker/tests/integration.rs +++ b/wireguard-broker/tests/integration.rs @@ -53,82 +53,88 @@ mod integration_tests { } } + procspawn::enable_test_support!(); + #[test] fn test_psk_exchanges() { const TEST_RUNS: usize = 100; - let server_broker_inner = Arc::new(Mutex::new(MockServerBrokerInner::default())); - // Create a mock BrokerServer - let server_broker = MockServerBroker::new(server_broker_inner.clone()); + use rosenpass_secret_memory::test_spawn_process_provided_policies; - let mut server = BrokerServer::::new(server_broker); + test_spawn_process_provided_policies!({ + let server_broker_inner = Arc::new(Mutex::new(MockServerBrokerInner::default())); + // Create a mock BrokerServer + let server_broker = MockServerBroker::new(server_broker_inner.clone()); - let (client_socket, mut server_socket) = mio::net::UnixStream::pair().unwrap(); + let mut server = BrokerServer::::new(server_broker); + + let (client_socket, mut server_socket) = mio::net::UnixStream::pair().unwrap(); + + // Spawn a new thread to connect to the unix socket + let handle = std::thread::spawn(move || { + for _ in 0..TEST_RUNS { + // Wait for 8 bytes of length to come in + let mut length_buffer = [0; 8]; + + while let Err(_err) = server_socket.read_exact(&mut length_buffer) {} + + let length = u64::from_le_bytes(length_buffer) as usize; + + // Read the amount of length bytes into a buffer + let mut data_buffer = [0; REQUEST_MSG_BUFFER_SIZE]; + while let Err(_err) = server_socket.read_exact(&mut data_buffer[0..length]) {} + + let mut response = [0; RESPONSE_MSG_BUFFER_SIZE]; + server.handle_message(&data_buffer[0..length], &mut response)?; + } + Ok::<(), BrokerServerError>(()) + }); + + // Create a MioBrokerClient and send a psk + let mut client = MioBrokerClient::new(client_socket); - // Spawn a new thread to connect to the unix socket - let handle = std::thread::spawn(move || { for _ in 0..TEST_RUNS { - // Wait for 8 bytes of length to come in - let mut length_buffer = [0; 8]; + //Create psk of random 32 bytes + let psk = Secret::random(); + let peer_id = Public::random(); + let interface = "test"; + let config = SerializedBrokerConfig { + psk: &psk, + peer_id: &peer_id, + interface: interface.as_bytes(), + additional_params: &[], + }; + client.set_psk(config).unwrap(); - while let Err(_err) = server_socket.read_exact(&mut length_buffer) {} + //Sleep for a while to allow the server to process the message + std::thread::sleep(std::time::Duration::from_millis( + rand::thread_rng().gen_range(100..500), + )); - let length = u64::from_le_bytes(length_buffer) as usize; + let psk = psk.secret().to_owned(); - // Read the amount of length bytes into a buffer - let mut data_buffer = [0; REQUEST_MSG_BUFFER_SIZE]; - while let Err(_err) = server_socket.read_exact(&mut data_buffer[0..length]) {} + loop { + let mut lock = server_broker_inner.try_lock(); - let mut response = [0; RESPONSE_MSG_BUFFER_SIZE]; - server.handle_message(&data_buffer[0..length], &mut response)?; - } - Ok::<(), BrokerServerError>(()) - }); + if let Ok(ref mut inner) = lock { + // Check if the psk is received by the server + let received_psk = &inner.psk; + assert_eq!( + received_psk.as_ref().map(|psk| psk.secret().to_owned()), + Some(psk) + ); - // Create a MioBrokerClient and send a psk - let mut client = MioBrokerClient::new(client_socket); + let recieved_peer_id = inner.peer_id; + assert_eq!(recieved_peer_id, Some(peer_id)); - for _ in 0..TEST_RUNS { - //Create psk of random 32 bytes - let psk = Secret::random(); - let peer_id = Public::random(); - let interface = "test"; - let config = SerializedBrokerConfig { - psk: &psk, - peer_id: &peer_id, - interface: interface.as_bytes(), - additional_params: &[], - }; - client.set_psk(config).unwrap(); + let target_interface = &inner.interface; + assert_eq!(target_interface.as_deref(), Some(interface)); - //Sleep for a while to allow the server to process the message - std::thread::sleep(std::time::Duration::from_millis( - rand::thread_rng().gen_range(100..500), - )); - - let psk = psk.secret().to_owned(); - - loop { - let mut lock = server_broker_inner.try_lock(); - - if let Ok(ref mut inner) = lock { - // Check if the psk is received by the server - let received_psk = &inner.psk; - assert_eq!( - received_psk.as_ref().map(|psk| psk.secret().to_owned()), - Some(psk) - ); - - let recieved_peer_id = inner.peer_id; - assert_eq!(recieved_peer_id, Some(peer_id)); - - let target_interface = &inner.interface; - assert_eq!(target_interface.as_deref(), Some(interface)); - - break; + break; + } } } - } - handle.join().unwrap().unwrap(); + handle.join().unwrap().unwrap(); + }); } }