mirror of
https://github.com/rosenpass/rosenpass.git
synced 2026-02-27 22:13:12 -08:00
Compare commits
3 Commits
dev/broker
...
dev/broker
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75176a66ee | ||
|
|
08cae26df0 | ||
|
|
f3590645e9 |
7
.dockerignore
Normal file
7
.dockerignore
Normal file
@@ -0,0 +1,7 @@
|
||||
examples/
|
||||
target/
|
||||
flake.*
|
||||
.ci
|
||||
.direnv
|
||||
.git
|
||||
.github
|
||||
36
.github/workflows/qc.yaml
vendored
36
.github/workflows/qc.yaml
vendored
@@ -25,34 +25,6 @@ jobs:
|
||||
- name: Run ShellCheck
|
||||
uses: ludeeus/action-shellcheck@master
|
||||
|
||||
rustfmt:
|
||||
name: Rust Format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run Rust Formatting Script
|
||||
run: bash format_rust_code.sh --mode check
|
||||
|
||||
cargo-bench:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Install libsodium
|
||||
run: sudo apt-get install -y libsodium-dev
|
||||
# liboqs requires quite a lot of stack memory, thus we adjust
|
||||
# the default stack size picked for new threads (which is used
|
||||
# by `cargo test`) to be _big enough_. Setting it to 8 MiB
|
||||
- run: RUST_MIN_STACK=8388608 cargo bench --no-run --workspace
|
||||
|
||||
cargo-audit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -121,7 +93,7 @@ jobs:
|
||||
# liboqs requires quite a lot of stack memory, thus we adjust
|
||||
# the default stack size picked for new threads (which is used
|
||||
# by `cargo test`) to be _big enough_. Setting it to 8 MiB
|
||||
- run: RUST_MIN_STACK=8388608 cargo test --workspace
|
||||
- run: RUST_MIN_STACK=8388608 cargo test
|
||||
|
||||
cargo-test-nix-devshell-x86_64-linux:
|
||||
runs-on:
|
||||
@@ -144,7 +116,7 @@ jobs:
|
||||
with:
|
||||
name: rosenpass
|
||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
- run: nix develop --command cargo test --workspace
|
||||
- run: nix develop --command cargo test
|
||||
|
||||
cargo-fuzz:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -174,5 +146,5 @@ 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_sodium_alloc -- -max_total_time=5
|
||||
cargo fuzz run fuzz_vec_sodium_alloc -- -max_total_time=5
|
||||
|
||||
543
Cargo.lock
generated
543
Cargo.lock
generated
@@ -18,14 +18,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.5.2"
|
||||
name = "adler32"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"generic-array",
|
||||
"heapless",
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -39,18 +46,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.14"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4f263788a35611fba42eb41ff811c5d0360c58b97402570312a350736e2542e"
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2-tests"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82e6d832cc75b9841b21c847420f1334645387f088324f34eac923a98efa3d89"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
]
|
||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
@@ -124,15 +122,6 @@ dependencies = [
|
||||
"derive_arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-polyfill"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
@@ -206,24 +195,6 @@ version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build-deps"
|
||||
version = "0.1.4"
|
||||
@@ -245,6 +216,12 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
@@ -276,30 +253,6 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chacha20"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chacha20poly1305"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
|
||||
dependencies = [
|
||||
"aead",
|
||||
"chacha20",
|
||||
"cipher",
|
||||
"poly1305",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.1"
|
||||
@@ -327,17 +280,6 @@ dependencies = [
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.6.1"
|
||||
@@ -426,12 +368,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.12"
|
||||
name = "command-fds"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
|
||||
checksum = "f190f3c954f7bca3c6296d0ec561c739bdbe6c7e990294ed168d415f6e1b5b01"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"nix",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core2"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -479,12 +431,6 @@ dependencies = [
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.3"
|
||||
@@ -518,16 +464,6 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.12.4"
|
||||
@@ -563,6 +499,12 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dary_heap"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7762d17f1241643615821a8455a0b2c3e803784b058693d990b11f2dce25a0ca"
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.3.2"
|
||||
@@ -605,17 +547,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.3"
|
||||
@@ -659,14 +590,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.23"
|
||||
version = "0.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
||||
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"windows-sys 0.52.0",
|
||||
"redox_syscall 0.3.5",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -694,16 +625,6 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.11"
|
||||
@@ -733,57 +654,33 @@ version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.7.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
|
||||
dependencies = [
|
||||
"atomic-polyfill",
|
||||
"hash32",
|
||||
"rustc_version",
|
||||
"spin",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f54046de71e77899abc5fee9a9ada4b6299e0829cf26cf47cdfe2163be3d33a"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"tar",
|
||||
"ureq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
@@ -850,15 +747,6 @@ dependencies = [
|
||||
"hashbrown 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
@@ -921,6 +809,30 @@ version = "0.2.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
|
||||
[[package]]
|
||||
name = "libflate"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7d5654ae1795afc7ff76f4365c2c8791b0feb18e8996a96adad8ffd7c3b2bf"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
"core2",
|
||||
"crc32fast",
|
||||
"dary_heap",
|
||||
"libflate_lz77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libflate_lz77"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be5f52fb8c451576ec6b79d3f4deb327398bc05bbdbd99021a6e77a4c855d524"
|
||||
dependencies = [
|
||||
"core2",
|
||||
"hashbrown 0.13.2",
|
||||
"rle-decode-fast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libfuzzer-sys"
|
||||
version = "0.4.7"
|
||||
@@ -942,6 +854,23 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libsodium-sys-stable"
|
||||
version = "1.20.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1d164bc6f9139c5f95efb4f0be931b2bd5a9edf7e4e3c945d26b95ab8fa669b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libflate",
|
||||
"minisign-verify",
|
||||
"pkg-config",
|
||||
"tar",
|
||||
"ureq",
|
||||
"vcpkg",
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.12"
|
||||
@@ -985,6 +914,12 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "minisign-verify"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
@@ -1031,6 +966,17 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.27.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@@ -1050,6 +996,16 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi 0.3.3",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
@@ -1071,12 +1027,6 @@ version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "oqs-sys"
|
||||
version = "0.8.0"
|
||||
@@ -1095,6 +1045,29 @@ version = "6.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.4.1",
|
||||
"smallvec",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
@@ -1113,6 +1086,18 @@ version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.5"
|
||||
@@ -1141,17 +1126,6 @@ dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "poly1305"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
|
||||
dependencies = [
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@@ -1245,6 +1219,15 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
@@ -1285,9 +1268,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.7"
|
||||
version = "0.17.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
|
||||
checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"getrandom",
|
||||
@@ -1297,15 +1280,22 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rle-decode-fast"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422"
|
||||
|
||||
[[package]]
|
||||
name = "rosenpass"
|
||||
version = "0.2.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.4.10",
|
||||
"command-fds",
|
||||
"criterion",
|
||||
"env_logger",
|
||||
"hermit",
|
||||
"libsodium-sys-stable",
|
||||
"log",
|
||||
"memoffset",
|
||||
"mio",
|
||||
@@ -1316,9 +1306,11 @@ dependencies = [
|
||||
"rosenpass-constant-time",
|
||||
"rosenpass-lenses",
|
||||
"rosenpass-secret-memory",
|
||||
"rosenpass-sodium",
|
||||
"rosenpass-to",
|
||||
"rosenpass-util",
|
||||
"rosenpass-wireguard-broker",
|
||||
"rustix",
|
||||
"serde",
|
||||
"stacker",
|
||||
"static_assertions",
|
||||
@@ -1336,13 +1328,11 @@ name = "rosenpass-ciphers"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"blake2",
|
||||
"chacha20poly1305",
|
||||
"rosenpass-constant-time",
|
||||
"rosenpass-oqs",
|
||||
"rosenpass-secret-memory",
|
||||
"rosenpass-sodium",
|
||||
"rosenpass-to",
|
||||
"rosenpass-util",
|
||||
"static_assertions",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -1364,6 +1354,7 @@ dependencies = [
|
||||
"rosenpass-cipher-traits",
|
||||
"rosenpass-ciphers",
|
||||
"rosenpass-secret-memory",
|
||||
"rosenpass-sodium",
|
||||
"rosenpass-to",
|
||||
"stacker",
|
||||
]
|
||||
@@ -1390,16 +1381,28 @@ dependencies = [
|
||||
name = "rosenpass-secret-memory"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"allocator-api2-tests",
|
||||
"anyhow",
|
||||
"log",
|
||||
"lazy_static",
|
||||
"libsodium-sys-stable",
|
||||
"rand",
|
||||
"rosenpass-sodium",
|
||||
"rosenpass-to",
|
||||
"rosenpass-util",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rosenpass-sodium"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"anyhow",
|
||||
"libsodium-sys-stable",
|
||||
"log",
|
||||
"rosenpass-to",
|
||||
"rosenpass-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rosenpass-to"
|
||||
version = "0.1.0"
|
||||
@@ -1413,8 +1416,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
"static_assertions",
|
||||
"typenum",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1431,6 +1433,7 @@ dependencies = [
|
||||
"rosenpass-to",
|
||||
"rosenpass-util",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"wireguard-uapi",
|
||||
]
|
||||
|
||||
@@ -1446,15 +1449,6 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.27"
|
||||
@@ -1470,9 +1464,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.21.10"
|
||||
version = "0.21.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
|
||||
checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
@@ -1521,12 +1515,6 @@ dependencies = [
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.193"
|
||||
@@ -1573,20 +1561,36 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
@@ -1613,12 +1617,6 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
@@ -1718,6 +1716,36 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.7.8"
|
||||
@@ -1752,17 +1780,11 @@ dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.15"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
||||
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
@@ -1779,16 +1801,6 @@ dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
@@ -1802,7 +1814,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"flate2",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls",
|
||||
@@ -1828,6 +1839,12 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
@@ -2118,15 +2135,47 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.1.1"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbc6ab6ec1907d1a901cdbcd2bd4cb9e7d64ce5c9739cbb97d3c391acd8c7fae"
|
||||
checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
"flate2",
|
||||
]
|
||||
|
||||
15
Cargo.toml
15
Cargo.toml
@@ -7,6 +7,7 @@ members = [
|
||||
"ciphers",
|
||||
"util",
|
||||
"constant-time",
|
||||
"sodium",
|
||||
"oqs",
|
||||
"to",
|
||||
"fuzz",
|
||||
@@ -28,6 +29,7 @@ tag-prefix = ""
|
||||
rosenpass = { path = "rosenpass" }
|
||||
rosenpass-util = { path = "util" }
|
||||
rosenpass-constant-time = { path = "constant-time" }
|
||||
rosenpass-sodium = { path = "sodium" }
|
||||
rosenpass-cipher-traits = { path = "cipher-traits" }
|
||||
rosenpass-ciphers = { path = "ciphers" }
|
||||
rosenpass-to = { path = "to" }
|
||||
@@ -43,22 +45,23 @@ doc-comment = "0.3.3"
|
||||
base64 = "0.21.5"
|
||||
zeroize = "1.7.0"
|
||||
memoffset = "0.9.0"
|
||||
lazy_static = "1.4.0"
|
||||
thiserror = "1.0.50"
|
||||
paste = "1.0.14"
|
||||
env_logger = "0.10.1"
|
||||
toml = "0.7.8"
|
||||
static_assertions = "1.1.0"
|
||||
allocator-api2 = "0.2.14"
|
||||
allocator-api2-tests = "0.2.14"
|
||||
allocator-api2 = "0.2.16"
|
||||
rand = "0.8.5"
|
||||
wireguard-uapi = "3.0.0"
|
||||
typenum = "1.17.0"
|
||||
command-fds = "0.2.3"
|
||||
rustix = { version = "0.38.27", features = ["net"] }
|
||||
tokio = { version = "1.34.0", features = ["sync", "full", "mio"] }
|
||||
log = { version = "0.4.20" }
|
||||
clap = { version = "4.4.10", features = ["derive"] }
|
||||
serde = { version = "1.0.193", features = ["derive"] }
|
||||
arbitrary = { version = "1.3.2", features = ["derive"] }
|
||||
anyhow = { version = "1.0.75", features = ["backtrace", "std"] }
|
||||
mio = { version = "0.8.9", features = ["net"] }
|
||||
mio = { version = "0.8.9", features = ["net", "os-poll"] }
|
||||
libsodium-sys-stable= { version = "1.20.4", features = ["use-pkg-config"] }
|
||||
oqs-sys = { version = "0.8", default-features = false, features = ['classic_mceliece', 'kyber'] }
|
||||
blake2 = "0.10.6"
|
||||
chacha20poly1305 = { version = "0.10.1", default-features = false, features = [ "std", "heapless" ] }
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
This identity hiding process tests whether the rosenpass protocol is able to protect the identity of an initiator or responder.
|
||||
The participants in the test are trusted initiators, trusted responders and compromised initiators and responders.
|
||||
The test consists of two phases. In the first phase all of the participants can communicate with each other using the rosenpass protocol.
|
||||
An attacker observes the first phase and is able to intercept and modify messages and choose participants to communicate with each other
|
||||
|
||||
In the second phase if the anonymity of an initiator is being tested then one of two trusted initiators is chosen.
|
||||
The chosen initiator communicates directly with a trusted responder.
|
||||
If an attacker can determine which initiator was chosen then the anonymity of the initiator has been compromised.
|
||||
Otherwise the protocol has successfully protected the initiators’ identity.
|
||||
|
||||
If the anonymity of a responder is being tested then one of two trusted responders is chosen instead.
|
||||
Then an initiator communicates directly with the chosen responder.
|
||||
If an attacker can determine which responder was chosen then the anonymity of the responder is compromised.
|
||||
Otherwise the protocol successfully protects the identity of a responder.
|
||||
|
||||
The Proverif code treats the public key as synonymous with identity.
|
||||
In the above test when a responder or initiator is chosen what is actually chosen is the public/private key pair to use for communication.
|
||||
Traditionally when a responder or initiator is chosen they would be chosen randomly.
|
||||
The way Proverif makes a "choice" is by simulating multiple processes, one process per choice
|
||||
Then the processes are compared and if an association between a public key and a process can be made the test fails.
|
||||
As the choice is at least as bad as choosing the worst possible option the credibility of the test is maintained.
|
||||
The drawback is that Proverif is only able to tell if the identity can be brute forced but misses any probabilistic associations.
|
||||
As usual Proverif also assumes perfect encryption and in particular assumes encryption cannot be linked to identity.
|
||||
|
||||
One of the tradeoffs made here is that the choice function in Proverif is slow but this is in favour of being able to write more precise tests.
|
||||
Another issue is the choice function does not work with queries so a test needs to be run for each set of assumptions.
|
||||
In this case the test uses secure rng and a fresh secure biscuit key.
|
||||
*/
|
||||
|
||||
|
||||
#include "config.mpv"
|
||||
|
||||
#define CHAINING_KEY_EVENTS 1
|
||||
#define MESSAGE_TRANSMISSION_EVENTS 1
|
||||
#define SESSION_START_EVENTS 0
|
||||
#define RANDOMIZED_CALL_IDS 0
|
||||
#undef FULL_MODEL
|
||||
#undef SIMPLE_MODEL
|
||||
#define SIMPLE_MODEL 1
|
||||
|
||||
#include "prelude/basic.mpv"
|
||||
#include "crypto/key.mpv"
|
||||
#include "rosenpass/oracles.mpv"
|
||||
#include "crypto/kem.mpv"
|
||||
|
||||
#define INITIATOR_TEST
|
||||
#define NEW_TRUSTED_SEED(name) \
|
||||
new MCAT(name, _secret_seed):seed_prec; \
|
||||
name <- make_trusted_seed(MCAT(name, _secret_seed)); \
|
||||
|
||||
free D:channel [private].
|
||||
free secure_biscuit_no:Atom [private].
|
||||
free secure_sidi,secure_sidr:SessionId [private].
|
||||
free secure_psk:key [private].
|
||||
free initiator1, initiator2:kem_sk_prec.
|
||||
free responder1, responder2:kem_sk_prec.
|
||||
|
||||
let secure_init_hello(initiator: kem_sk_tmpl, sidi : SessionId, psk: key_tmpl, responder: kem_sk_tmpl) =
|
||||
NEW_TRUSTED_SEED(seski_trusted_seed)
|
||||
NEW_TRUSTED_SEED(ssptr_trusted_seed)
|
||||
Oinitiator_inner(sidi, initiator, psk, responder, seski_trusted_seed, ssptr_trusted_seed, D).
|
||||
|
||||
let secure_resp_hello(initiator: kem_sk_tmpl, responder: kem_sk_tmpl, sidr:SessionId, sidi:SessionId, biscuit_no:Atom, psk:key_tmpl) =
|
||||
in(D, Envelope(k, IH2b(InitHello(=sidi, epki, sctr, pidiC, auth))));
|
||||
ih <- InitHello(sidi, epki, sctr, pidiC, auth);
|
||||
NEW_TRUSTED_SEED(septi_trusted_seed)
|
||||
NEW_TRUSTED_SEED(sspti_trusted_seed)
|
||||
Oinit_hello_inner(sidr, biscuit_no, responder, psk, initiator, septi_trusted_seed, sspti_trusted_seed, ih, D).
|
||||
|
||||
let secure_init_conf(initiator: kem_sk_tmpl, responder: kem_sk_tmpl, psk:key_tmpl, sidi:SessionId, sidr:SessionId) =
|
||||
in(D, Envelope(k3, IC2b(InitConf(=sidi, =sidr, biscuit, auth3))));
|
||||
ic <- InitConf(sidi,sidr,biscuit, auth3);
|
||||
NEW_TRUSTED_SEED(seski_trusted_seed)
|
||||
NEW_TRUSTED_SEED(ssptr_trusted_seed)
|
||||
Oinit_conf_inner(initiator, psk, responder, ic).
|
||||
|
||||
let secure_communication(initiator: kem_sk_tmpl, responder:kem_sk_tmpl) =
|
||||
secure_key <- prepare_key(secure_psk);
|
||||
(!secure_init_hello(initiator, secure_sidi, secure_key, responder))
|
||||
| !secure_resp_hello(initiator, responder, secure_sidr, secure_sidi, secure_biscuit_no, secure_key)
|
||||
| !(secure_init_conf(initiator, responder, secure_key, secure_sidi, secure_sidr)).
|
||||
|
||||
let pipeChannel(D:channel, C:channel) =
|
||||
in(D, b:bits);
|
||||
out(C, b).
|
||||
|
||||
fun kem_private(kem_pk): kem_sk
|
||||
reduc forall sk_tmpl:kem_sk;
|
||||
kem_private(kem_pub(sk_tmpl)) = sk_tmpl[private].
|
||||
|
||||
let secretCommunication() =
|
||||
#ifdef INITIATOR_TEST
|
||||
initiator_pk <- choice[setup_kem_pk(make_trusted_kem_sk(initiator1)), setup_kem_pk(make_trusted_kem_sk(initiator2))];
|
||||
initiator_seed <- prepare_kem_sk(kem_private(initiator_pk));
|
||||
#else
|
||||
initiator_seed <- prepare_kem_sk(trusted_kem_sk(initiator1));
|
||||
#endif
|
||||
#ifdef RESPONDER_TEST
|
||||
responder_pk <- choice[setup_kem_pk(make_trusted_kem_sk(responder1)), setup_kem_pk(make_trusted_kem_sk(responder2))];
|
||||
responder_seed <- prepare_kem_sk(kem_private(responder_pk));
|
||||
#else
|
||||
responder_seed <- prepare_kem_sk(trusted_kem_sk(responder1));
|
||||
#endif
|
||||
secure_communication(initiator_seed, responder_seed) | !pipeChannel(D, C).
|
||||
|
||||
let reveal_pks() =
|
||||
out(C, setup_kem_pk(make_trusted_kem_sk(responder1)));
|
||||
out(C, setup_kem_pk(make_trusted_kem_sk(responder2)));
|
||||
out(C, setup_kem_pk(make_trusted_kem_sk(initiator1)));
|
||||
out(C, setup_kem_pk(make_trusted_kem_sk(initiator2))).
|
||||
|
||||
let rosenpass_main2() =
|
||||
REP(INITIATOR_BOUND, Oinitiator)
|
||||
| REP(RESPONDER_BOUND, Oinit_hello)
|
||||
| REP(RESPONDER_BOUND, Oinit_conf).
|
||||
|
||||
let identity_hiding_main() =
|
||||
0 | reveal_pks() | rosenpass_main2() | phase 1; secretCommunication().
|
||||
|
||||
let main = identity_hiding_main.
|
||||
@@ -47,16 +47,14 @@ CK_EV( event OskOinit_conf(key, key). )
|
||||
MTX_EV( event ICRjct(InitConf_t, key, kem_sk, kem_pk). )
|
||||
SES_EV( event ResponderSession(InitConf_t, key). )
|
||||
event ConsumeBiscuit(Atom, kem_sk, kem_pk, Atom).
|
||||
|
||||
let Oinit_conf_inner(Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t) =
|
||||
let Oinit_conf() =
|
||||
in(C, Cinit_conf(Ssskm, Spsk, Sspkt, ic));
|
||||
#if RANDOMIZED_CALL_IDS
|
||||
new call:Atom;
|
||||
#else
|
||||
call <- Cinit_conf(Ssskm, Spsk, Sspkt, ic);
|
||||
#endif
|
||||
|
||||
SETUP_HANDSHAKE_STATE()
|
||||
|
||||
eski <- kem_sk0;
|
||||
epki <- kem_pk0;
|
||||
let try_ = (
|
||||
@@ -74,10 +72,6 @@ let Oinit_conf_inner(Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:Ini
|
||||
0
|
||||
#endif
|
||||
).
|
||||
|
||||
let Oinit_conf() =
|
||||
in(C, Cinit_conf(Ssskm, Spsk, Sspkt, ic));
|
||||
Oinit_conf_inner(Ssskm, Spsk, Sspkt, ic).
|
||||
|
||||
restriction biscuit_no:Atom, sskm:kem_sk, spkr:kem_pk, ad1:Atom, ad2:Atom;
|
||||
event(ConsumeBiscuit(biscuit_no, sskm, spkr, ad1)) && event(ConsumeBiscuit(biscuit_no, sskm, spkr, ad2))
|
||||
@@ -91,8 +85,8 @@ CK_EV( event OskOresp_hello(key, key, key). )
|
||||
MTX_EV( event RHRjct(RespHello_t, key, kem_sk, kem_pk). )
|
||||
MTX_EV( event ICSent(RespHello_t, InitConf_t, key, kem_sk, kem_pk). )
|
||||
SES_EV( event InitiatorSession(RespHello_t, key). )
|
||||
let Oresp_hello(HS_DECL_ARGS, C_in:channel) =
|
||||
in(C_in, Cresp_hello(RespHello(sidr, =sidi, ecti, scti, biscuit, auth)));
|
||||
let Oresp_hello(HS_DECL_ARGS) =
|
||||
in(C, Cresp_hello(RespHello(sidr, =sidi, ecti, scti, biscuit, auth)));
|
||||
rh <- RespHello(sidr, sidi, ecti, scti, biscuit, auth);
|
||||
/* try */ let ic = (
|
||||
ck_ini <- ck;
|
||||
@@ -104,7 +98,7 @@ let Oresp_hello(HS_DECL_ARGS, C_in:channel) =
|
||||
SES_EV( event InitiatorSession(rh, osk); )
|
||||
ic
|
||||
/* success */ ) in (
|
||||
out(C_in, Envelope(create_mac(spkt, IC2b(ic)), IC2b(ic)))
|
||||
out(C, ic)
|
||||
/* fail */ ) else (
|
||||
#if MESSAGE_TRANSMISSION_EVENTS
|
||||
event RHRjct(rh, psk, sski, spkr)
|
||||
@@ -122,8 +116,8 @@ MTX_EV( event IHRjct(InitHello_t, key, kem_sk, kem_pk). )
|
||||
MTX_EV( event RHSent(InitHello_t, RespHello_t, key, kem_sk, kem_pk). )
|
||||
event ConsumeSidr(SessionId, Atom).
|
||||
event ConsumeBn(Atom, kem_sk, kem_pk, Atom).
|
||||
|
||||
let Oinit_hello_inner(sidm:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt: kem_sk_tmpl, Septi: seed_tmpl, Sspti: seed_tmpl, ih: InitHello_t, C_out:channel) =
|
||||
let Oinit_hello() =
|
||||
in(C, Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih));
|
||||
#if RANDOMIZED_CALL_IDS
|
||||
new call:Atom;
|
||||
#else
|
||||
@@ -131,19 +125,14 @@ let Oinit_hello_inner(sidm:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:k
|
||||
#endif
|
||||
// TODO: This is ugly
|
||||
let InitHello(sidi, epki, sctr, pidiC, auth) = ih in
|
||||
|
||||
SETUP_HANDSHAKE_STATE()
|
||||
|
||||
eski <- kem_sk0;
|
||||
|
||||
event ConsumeBn(biscuit_no, sskm, spkt, call);
|
||||
event ConsumeSidr(sidr, call);
|
||||
|
||||
epti <- rng_key(setup_seed(Septi)); // RHR4
|
||||
spti <- rng_key(setup_seed(Sspti)); // RHR5
|
||||
event ConsumeBn(biscuit_no, sskm, spkt, call);
|
||||
event ConsumeSidr(sidr, call);
|
||||
event ConsumeSeed(Epti, setup_seed(Septi), call);
|
||||
event ConsumeSeed(Spti, setup_seed(Sspti), call);
|
||||
|
||||
let rh = (
|
||||
INITHELLO_CONSUME()
|
||||
ck_ini <- ck;
|
||||
@@ -152,8 +141,7 @@ let Oinit_hello_inner(sidm:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:k
|
||||
MTX_EV( event RHSent(ih, rh, psk, sskr, spki); )
|
||||
rh
|
||||
/* success */ ) in (
|
||||
out(C_out, Envelope(create_mac(spkt, RH2b(rh)), RH2b(rh)))
|
||||
|
||||
out(C, rh)
|
||||
/* fail */ ) else (
|
||||
#if MESSAGE_TRANSMISSION_EVENTS
|
||||
event IHRjct(ih, psk, sskr, spki)
|
||||
@@ -162,10 +150,6 @@ let Oinit_hello_inner(sidm:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:k
|
||||
#endif
|
||||
).
|
||||
|
||||
let Oinit_hello() =
|
||||
in(C, Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih));
|
||||
Oinit_hello_inner(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih, C).
|
||||
|
||||
restriction sid:SessionId, ad1:Atom, ad2:Atom;
|
||||
event(ConsumeSidr(sid, ad1)) && event(ConsumeSidr(sid, ad2))
|
||||
==> ad1 = ad2.
|
||||
@@ -183,34 +167,26 @@ CK_EV( event OskOinitiator_ck(key). )
|
||||
CK_EV( event OskOinitiator(key, key, kem_sk, kem_pk, key). )
|
||||
MTX_EV( event IHSent(InitHello_t, key, kem_sk, kem_pk). )
|
||||
event ConsumeSidi(SessionId, Atom).
|
||||
|
||||
let Oinitiator_inner(sidi: SessionId, Ssskm: kem_sk_tmpl, Spsk: key_tmpl, Sspkt: kem_sk_tmpl, Seski: seed_tmpl, Ssptr: seed_tmpl, C_out:channel) =
|
||||
#if RANDOMIZED_CALL_IDS
|
||||
new call:Atom;
|
||||
#else
|
||||
call <- Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr);
|
||||
#endif
|
||||
|
||||
SETUP_HANDSHAKE_STATE()
|
||||
|
||||
sidr <- sid0;
|
||||
|
||||
RNG_KEM_PAIR(eski, epki, Seski) // IHI3
|
||||
sptr <- rng_key(setup_seed(Ssptr)); // IHI5
|
||||
event ConsumeSidi(sidi, call);
|
||||
event ConsumeSeed(Sptr, setup_seed(Ssptr), call);
|
||||
event ConsumeSeed(Eski, setup_seed(Seski), call);
|
||||
|
||||
INITHELLO_PRODUCE()
|
||||
CK_EV( event OskOinitiator_ck(ck); )
|
||||
CK_EV( event OskOinitiator(ck, psk, sski, spkr, sptr); )
|
||||
MTX_EV( event IHSent(ih, psk, sski, spkr); )
|
||||
out(C_out, Envelope(create_mac(spkt, IH2b(ih)), IH2b(ih)));
|
||||
Oresp_hello(HS_PASS_ARGS, C_out).
|
||||
|
||||
let Oinitiator() =
|
||||
in(C, Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr));
|
||||
Oinitiator_inner(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr, C).
|
||||
#if RANDOMIZED_CALL_IDS
|
||||
new call:Atom;
|
||||
#else
|
||||
call <- Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr);
|
||||
#endif
|
||||
SETUP_HANDSHAKE_STATE()
|
||||
RNG_KEM_PAIR(eski, epki, Seski) // IHI3
|
||||
sidr <- sid0;
|
||||
sptr <- rng_key(setup_seed(Ssptr)); // IHI5
|
||||
event ConsumeSidi(sidi, call);
|
||||
event ConsumeSeed(Sptr, setup_seed(Ssptr), call);
|
||||
event ConsumeSeed(Eski, setup_seed(Seski), call);
|
||||
INITHELLO_PRODUCE()
|
||||
CK_EV( event OskOinitiator_ck(ck); )
|
||||
CK_EV( event OskOinitiator(ck, psk, sski, spkr, sptr); )
|
||||
MTX_EV( event IHSent(ih, psk, sski, spkr); )
|
||||
out(C, ih);
|
||||
Oresp_hello(HS_PASS_ARGS).
|
||||
|
||||
restriction sid:SessionId, ad1:Atom, ad2:Atom;
|
||||
event(ConsumeSidi(sid, ad1)) && event(ConsumeSidi(sid, ad2))
|
||||
|
||||
@@ -2,12 +2,6 @@
|
||||
#include "crypto/kem.mpv"
|
||||
#include "rosenpass/handshake_state.mpv"
|
||||
|
||||
fun Envelope(
|
||||
key,
|
||||
bits
|
||||
): bits [data].
|
||||
letfun create_mac(pk:kem_pk, payload:bits) = lprf2(MAC, kem_pk2b(pk), payload).
|
||||
|
||||
type InitHello_t.
|
||||
fun InitHello(
|
||||
SessionId, // sidi
|
||||
@@ -17,8 +11,6 @@ fun InitHello(
|
||||
bits // auth
|
||||
) : InitHello_t [data].
|
||||
|
||||
fun IH2b(InitHello_t) : bitstring [typeConverter].
|
||||
|
||||
#define INITHELLO_PRODUCE() \
|
||||
ck <- lprf1(CK_INIT, kem_pk2b(spkr)); /* IHI1 */ \
|
||||
/* not handled here */ /* IHI2 */ \
|
||||
@@ -49,9 +41,7 @@ fun RespHello(
|
||||
bits // auth
|
||||
) : RespHello_t [data].
|
||||
|
||||
fun RH2b(RespHello_t) : bitstring [typeConverter].
|
||||
|
||||
#define RESPHELLO_PRODUCE() \
|
||||
#define RESPHELLO_PRODUCE() \
|
||||
/* not handled here */ /* RHR1 */ \
|
||||
MIX2(sid2b(sidr), sid2b(sidi)) /* RHR3 */ \
|
||||
ENCAPS_AND_MIX(ecti, epki, epti) /* RHR4 */ \
|
||||
@@ -77,8 +67,6 @@ fun InitConf(
|
||||
bits // auth
|
||||
) : InitConf_t [data].
|
||||
|
||||
fun IC2b(InitConf_t) : bitstring [typeConverter].
|
||||
|
||||
#define INITCONF_PRODUCE() \
|
||||
MIX2(sid2b(sidi), sid2b(sidr)) /* ICI3 */ \
|
||||
ENCRYPT_AND_MIX(auth, empty) /* ICI4 */ \
|
||||
|
||||
@@ -11,12 +11,10 @@ readme = "readme.md"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
rosenpass-sodium = { workspace = true }
|
||||
rosenpass-to = { workspace = true }
|
||||
rosenpass-constant-time = { workspace = true }
|
||||
rosenpass-secret-memory = { workspace = true }
|
||||
rosenpass-oqs = { workspace = true }
|
||||
rosenpass-util = { workspace = true }
|
||||
static_assertions = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
chacha20poly1305 = { workspace = true }
|
||||
blake2 = { workspace = true }
|
||||
|
||||
@@ -9,12 +9,14 @@ const_assert!(KEY_LEN == hash_domain::KEY_LEN);
|
||||
|
||||
/// Authenticated encryption with associated data
|
||||
pub mod aead {
|
||||
pub use crate::subtle::chacha20poly1305_ietf::{decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN};
|
||||
pub use rosenpass_sodium::aead::chacha20poly1305_ietf::{
|
||||
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
|
||||
};
|
||||
}
|
||||
|
||||
/// Authenticated encryption with associated data with a constant nonce
|
||||
pub mod xaead {
|
||||
pub use crate::subtle::xchacha20poly1305_ietf::{
|
||||
pub use rosenpass_sodium::aead::xchacha20poly1305_ietf::{
|
||||
decrypt, encrypt, KEY_LEN, NONCE_LEN, TAG_LEN,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use blake2::digest::crypto_common::generic_array::GenericArray;
|
||||
use blake2::digest::crypto_common::typenum::U32;
|
||||
use blake2::digest::crypto_common::KeySizeUser;
|
||||
use blake2::digest::{FixedOutput, Mac, OutputSizeUser};
|
||||
use blake2::Blake2bMac;
|
||||
|
||||
use rosenpass_to::{ops::copy_slice, with_destination, To};
|
||||
use rosenpass_util::typenum2const;
|
||||
|
||||
type Impl = Blake2bMac<U32>;
|
||||
|
||||
type KeyLen = <Impl as KeySizeUser>::KeySize;
|
||||
type OutLen = <Impl as OutputSizeUser>::OutputSize;
|
||||
|
||||
const KEY_LEN: usize = typenum2const! { KeyLen };
|
||||
const OUT_LEN: usize = typenum2const! { OutLen };
|
||||
|
||||
pub const KEY_MIN: usize = KEY_LEN;
|
||||
pub const KEY_MAX: usize = KEY_LEN;
|
||||
pub const OUT_MIN: usize = OUT_LEN;
|
||||
pub const OUT_MAX: usize = OUT_LEN;
|
||||
|
||||
#[inline]
|
||||
pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a {
|
||||
with_destination(|out: &mut [u8]| {
|
||||
let mut h = Impl::new_from_slice(key)?;
|
||||
h.update(data);
|
||||
|
||||
// Jesus christ, blake2 crate, your usage of GenericArray might be nice and fancy
|
||||
// but it introduces a ton of complexity. This cost me half an hour just to figure
|
||||
// out the right way to use the imports while allowing for zeroization.
|
||||
// An API based on slices might actually be simpler.
|
||||
let mut tmp = Zeroizing::new([0u8; OUT_LEN]);
|
||||
let mut tmp = GenericArray::from_mut_slice(tmp.as_mut());
|
||||
h.finalize_into(&mut tmp);
|
||||
copy_slice(tmp.as_ref()).to(out);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
use rosenpass_to::ops::copy_slice;
|
||||
use rosenpass_to::To;
|
||||
use rosenpass_util::typenum2const;
|
||||
|
||||
use chacha20poly1305::aead::generic_array::GenericArray;
|
||||
use chacha20poly1305::ChaCha20Poly1305 as AeadImpl;
|
||||
use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
|
||||
|
||||
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
|
||||
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
||||
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
||||
|
||||
#[inline]
|
||||
pub fn encrypt(
|
||||
ciphertext: &mut [u8],
|
||||
key: &[u8],
|
||||
nonce: &[u8],
|
||||
ad: &[u8],
|
||||
plaintext: &[u8],
|
||||
) -> anyhow::Result<()> {
|
||||
let nonce = GenericArray::from_slice(nonce);
|
||||
let (ct, mac) = ciphertext.split_at_mut(ciphertext.len() - TAG_LEN);
|
||||
copy_slice(plaintext).to(ct);
|
||||
let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(&nonce, ad, ct)?;
|
||||
copy_slice(&mac_value[..]).to(mac);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decrypt(
|
||||
plaintext: &mut [u8],
|
||||
key: &[u8],
|
||||
nonce: &[u8],
|
||||
ad: &[u8],
|
||||
ciphertext: &[u8],
|
||||
) -> anyhow::Result<()> {
|
||||
let nonce = GenericArray::from_slice(nonce);
|
||||
let (ct, mac) = ciphertext.split_at(ciphertext.len() - TAG_LEN);
|
||||
let tag = GenericArray::from_slice(mac);
|
||||
copy_slice(ct).to(plaintext);
|
||||
AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(&nonce, ad, plaintext, tag)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
use anyhow::ensure;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
use rosenpass_constant_time::xor;
|
||||
use rosenpass_sodium::hash::blake2b;
|
||||
use rosenpass_to::{ops::copy_slice, with_destination, To};
|
||||
|
||||
use crate::subtle::blake2b;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
pub const KEY_LEN: usize = 32;
|
||||
pub const KEY_MIN: usize = KEY_LEN;
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
pub mod blake2b;
|
||||
pub mod chacha20poly1305_ietf;
|
||||
pub mod incorrect_hmac_blake2b;
|
||||
pub mod xchacha20poly1305_ietf;
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
use rosenpass_to::ops::copy_slice;
|
||||
use rosenpass_to::To;
|
||||
use rosenpass_util::typenum2const;
|
||||
|
||||
use chacha20poly1305::aead::generic_array::GenericArray;
|
||||
use chacha20poly1305::XChaCha20Poly1305 as AeadImpl;
|
||||
use chacha20poly1305::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
|
||||
|
||||
pub const KEY_LEN: usize = typenum2const! { <AeadImpl as KeySizeUser>::KeySize };
|
||||
pub const TAG_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::TagSize };
|
||||
pub const NONCE_LEN: usize = typenum2const! { <AeadImpl as AeadCore>::NonceSize };
|
||||
|
||||
#[inline]
|
||||
pub fn encrypt(
|
||||
ciphertext: &mut [u8],
|
||||
key: &[u8],
|
||||
nonce: &[u8],
|
||||
ad: &[u8],
|
||||
plaintext: &[u8],
|
||||
) -> anyhow::Result<()> {
|
||||
let nonce = GenericArray::from_slice(nonce);
|
||||
let (n, ct_mac) = ciphertext.split_at_mut(NONCE_LEN);
|
||||
let (ct, mac) = ct_mac.split_at_mut(ct_mac.len() - TAG_LEN);
|
||||
copy_slice(nonce).to(n);
|
||||
copy_slice(plaintext).to(ct);
|
||||
let mac_value = AeadImpl::new_from_slice(key)?.encrypt_in_place_detached(&nonce, ad, ct)?;
|
||||
copy_slice(&mac_value[..]).to(mac);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decrypt(
|
||||
plaintext: &mut [u8],
|
||||
key: &[u8],
|
||||
ad: &[u8],
|
||||
ciphertext: &[u8],
|
||||
) -> anyhow::Result<()> {
|
||||
let (n, ct_mac) = ciphertext.split_at(NONCE_LEN);
|
||||
let (ct, mac) = ct_mac.split_at(ct_mac.len() - TAG_LEN);
|
||||
let nonce = GenericArray::from_slice(n);
|
||||
let tag = GenericArray::from_slice(mac);
|
||||
copy_slice(ct).to(plaintext);
|
||||
AeadImpl::new_from_slice(key)?.decrypt_in_place_detached(&nonce, ad, plaintext, tag)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
use core::hint::black_box;
|
||||
|
||||
use rosenpass_to::{with_destination, To};
|
||||
|
||||
/// Xors the source into the destination
|
||||
@@ -18,61 +16,11 @@ use rosenpass_to::{with_destination, To};
|
||||
///
|
||||
/// If source and destination are of different sizes.
|
||||
#[inline]
|
||||
pub fn xor(src: &[u8]) -> impl To<[u8], ()> + '_ {
|
||||
pub fn xor<'a>(src: &'a [u8]) -> impl To<[u8], ()> + 'a {
|
||||
with_destination(|dst: &mut [u8]| {
|
||||
assert!(black_box(src.len()) == black_box(dst.len()));
|
||||
assert!(src.len() == dst.len());
|
||||
for (dv, sv) in dst.iter_mut().zip(src.iter()) {
|
||||
*black_box(dv) ^= black_box(*sv);
|
||||
*dv ^= *sv;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn memcmp(a: &[u8], b: &[u8]) -> bool {
|
||||
a == b
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn compare(a: &[u8], b: &[u8]) -> i32 {
|
||||
assert!(a.len() == b.len());
|
||||
a.cmp(b) as i32
|
||||
}
|
||||
|
||||
/// Interpret the given slice as a little-endian unsigned integer
|
||||
/// and increment that integer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use rosenpass_constant_time::increment as inc;
|
||||
/// use rosenpass_to::To;
|
||||
///
|
||||
/// fn testcase(v: &[u8], correct: &[u8]) {
|
||||
/// let mut v = v.to_owned();
|
||||
/// inc(&mut v);
|
||||
/// assert_eq!(&v, correct);
|
||||
/// }
|
||||
///
|
||||
/// testcase(b"", b"");
|
||||
/// testcase(b"\x00", b"\x01");
|
||||
/// testcase(b"\x01", b"\x02");
|
||||
/// testcase(b"\xfe", b"\xff");
|
||||
/// testcase(b"\xff", b"\x00");
|
||||
/// testcase(b"\x00\x00", b"\x01\x00");
|
||||
/// testcase(b"\x01\x00", b"\x02\x00");
|
||||
/// testcase(b"\xfe\x00", b"\xff\x00");
|
||||
/// testcase(b"\xff\x00", b"\x00\x01");
|
||||
/// testcase(b"\x00\x00\x00\x00\x00\x00", b"\x01\x00\x00\x00\x00\x00");
|
||||
/// testcase(b"\x00\xa3\x00\x77\x00\x00", b"\x01\xa3\x00\x77\x00\x00");
|
||||
/// testcase(b"\xff\xa3\x00\x77\x00\x00", b"\x00\xa4\x00\x77\x00\x00");
|
||||
/// testcase(b"\xff\xff\xff\x77\x00\x00", b"\x00\x00\x00\x78\x00\x00");
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn increment(v: &mut [u8]) {
|
||||
let mut carry = 1u8;
|
||||
for val in v.iter_mut() {
|
||||
let (v, c) = black_box(*val).overflowing_add(black_box(carry));
|
||||
*black_box(val) = v;
|
||||
*black_box(&mut carry) = black_box(black_box(c) as u8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ If you are not specifically tasked with developing post-quantum secure systems,
|
||||
you probably do not need this tool.
|
||||
.Ss COMMANDS
|
||||
.Bl -tag -width Ds
|
||||
.It Ar gen-keys --secret-key <file-path> --public-key <file-path>
|
||||
.It Ar keygen private-key <file-path> public-key <file-path>
|
||||
Generate a keypair to use in the exchange command later.
|
||||
Send the public-key file to your communication partner and keep the private-key
|
||||
file secret!
|
||||
|
||||
18
examples/broker-in-podman-container/Dockerfile
Normal file
18
examples/broker-in-podman-container/Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
||||
FROM rust:slim as build
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential \
|
||||
cmake \
|
||||
pkg-config \
|
||||
libclang-dev \
|
||||
libsodium-dev
|
||||
|
||||
WORKDIR /code
|
||||
COPY . /code
|
||||
|
||||
RUN cargo install --path rosenpass --root / --bins \
|
||||
&& cargo install --path wireguard-broker --root / --bins
|
||||
# RUN apt-get install -y libcap2-bin \
|
||||
# setcap CAP_NET_ADMIN=+eip "$(which rosenpass-wireguard-broker-privileged)"
|
||||
|
||||
CMD rosenpass
|
||||
11
examples/broker-in-podman-container/podman-compose.yml
Normal file
11
examples/broker-in-podman-container/podman-compose.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
rosenpass:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: ./examples/broker-in-podman-container/Dockerfile
|
||||
env:
|
||||
RUST_LOG: trace
|
||||
volumes:
|
||||
./peer-a:/config
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Parse command line options
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--mode)
|
||||
mode="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check if mode is specified
|
||||
if [ -z "$mode" ]; then
|
||||
echo "Please specify the mode using --mode option. Valid modes are 'check' and 'fix'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Find all Markdown files in the current directory and its subdirectories
|
||||
mapfile -t md_files < <(find . -type f -name "*.md")
|
||||
|
||||
count=0
|
||||
# Iterate through each Markdown file
|
||||
for file in "${md_files[@]}"; do
|
||||
# Use awk to extract Rust code blocks enclosed within triple backticks
|
||||
rust_code_blocks=$(awk '/```rust/{flag=1; next}/```/{flag=0} flag' "$file")
|
||||
|
||||
# Count the number of Rust code blocks
|
||||
num_fences=$(awk '/```rust/{f=1} f{if(/```/){f=0; count++}} END{print count}' "$file")
|
||||
|
||||
if [ -n "$rust_code_blocks" ]; then
|
||||
echo "Processing Rust code in $file"
|
||||
# Iterate through each Rust code block
|
||||
for ((i=1; i <= num_fences ; i++)); do
|
||||
# Extract individual Rust code block using awk
|
||||
current_rust_block=$(awk -v i="$i" '/```rust/{f=1; if (++count == i) next} f&&/```/{f=0;next} f' "$file")
|
||||
# Variable to check if we have added the main function
|
||||
add_main=0
|
||||
# Check if the Rust code block is already inside a function
|
||||
if ! echo "$current_rust_block" | grep -q "fn main()"; then
|
||||
# If not, wrap it in a main function
|
||||
current_rust_block=$'fn main() {\n'"$current_rust_block"$'\n}'
|
||||
add_main=1
|
||||
fi
|
||||
if [ "$mode" == "check" ]; then
|
||||
# Apply changes to the Rust code block
|
||||
formatted_rust_code=$(echo "$current_rust_block" | rustfmt)
|
||||
# Use rustfmt to format the Rust code block, remove first and last lines, and remove the first 4 spaces if added main function
|
||||
if [ "$add_main" == 1 ]; then
|
||||
formatted_rust_code=$(echo "$formatted_rust_code" | sed '1d;$d' | sed 's/^ //')
|
||||
current_rust_block=$(echo "$current_rust_block" | sed '1d;')
|
||||
current_rust_block=$(echo "$current_rust_block" | sed '$d')
|
||||
fi
|
||||
if [ "$formatted_rust_code" == "$current_rust_block" ]; then
|
||||
echo "No changes needed in Rust code block $i in $file"
|
||||
else
|
||||
echo -e "\nChanges needed in Rust code block $i in $file:\n"
|
||||
echo "$formatted_rust_code"
|
||||
count=+1
|
||||
fi
|
||||
|
||||
elif [ "$mode" == "fix" ]; then
|
||||
# Replace current_rust_block with formatted_rust_code in the file
|
||||
formatted_rust_code=$(echo "$current_rust_block" | rustfmt)
|
||||
# Use rustfmt to format the Rust code block, remove first and last lines, and remove the first 4 spaces if added main function
|
||||
if [ "$add_main" == 1 ]; then
|
||||
formatted_rust_code=$(echo "$formatted_rust_code" | sed '1d;$d' | sed 's/^ //')
|
||||
current_rust_block=$(echo "$current_rust_block" | sed '1d;')
|
||||
current_rust_block=$(echo "$current_rust_block" | sed '$d')
|
||||
fi
|
||||
# Check if the formatted code is the same as the current Rust code block
|
||||
if [ "$formatted_rust_code" == "$current_rust_block" ]; then
|
||||
echo "No changes needed in Rust code block $i in $file"
|
||||
else
|
||||
echo "Formatting Rust code block $i in $file"
|
||||
# Replace current_rust_block with formatted_rust_code in the file
|
||||
# Use awk to find the line number of the pattern
|
||||
|
||||
start_line=$(grep -n "^\`\`\`rust" "$file" | sed -n "${i}p" | cut -d: -f1)
|
||||
end_line=$(grep -n "^\`\`\`" "$file" | awk -F: -v start_line="$start_line" '$1 > start_line {print $1; exit;}')
|
||||
|
||||
if [ -n "$start_line" ] && [ -n "$end_line" ]; then
|
||||
# Print lines before the Rust code block
|
||||
head -n "$((start_line - 1))" "$file"
|
||||
|
||||
# Print the formatted Rust code block
|
||||
echo "\`\`\`rust"
|
||||
echo "$formatted_rust_code"
|
||||
echo "\`\`\`"
|
||||
|
||||
# Print lines after the Rust code block
|
||||
tail -n +"$((end_line + 1))" "$file"
|
||||
else
|
||||
# Rust code block not found or end line not found
|
||||
cat "$file"
|
||||
fi > tmpfile && mv tmpfile "$file"
|
||||
|
||||
fi
|
||||
else
|
||||
echo "Unknown mode: $mode. Valid modes are 'check' and 'fix'."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
# CI failure if changes are needed
|
||||
if [ $count -gt 0 ]; then
|
||||
echo "CI failed: Changes needed in Rust code blocks."
|
||||
exit 1
|
||||
fi
|
||||
@@ -12,6 +12,7 @@ arbitrary = { workspace = true }
|
||||
libfuzzer-sys = { workspace = true }
|
||||
stacker = { workspace = true }
|
||||
rosenpass-secret-memory = { workspace = true }
|
||||
rosenpass-sodium = { workspace = true }
|
||||
rosenpass-ciphers = { workspace = true }
|
||||
rosenpass-cipher-traits = { workspace = true }
|
||||
rosenpass-to = { workspace = true }
|
||||
@@ -48,13 +49,13 @@ test = false
|
||||
doc = false
|
||||
|
||||
[[bin]]
|
||||
name = "fuzz_box_secret_alloc"
|
||||
path = "fuzz_targets/box_secret_alloc.rs"
|
||||
name = "fuzz_box_sodium_alloc"
|
||||
path = "fuzz_targets/box_sodium_alloc.rs"
|
||||
test = false
|
||||
doc = false
|
||||
|
||||
[[bin]]
|
||||
name = "fuzz_vec_secret_alloc"
|
||||
path = "fuzz_targets/vec_secret_alloc.rs"
|
||||
name = "fuzz_vec_sodium_alloc"
|
||||
path = "fuzz_targets/vec_sodium_alloc.rs"
|
||||
test = false
|
||||
doc = false
|
||||
|
||||
@@ -5,6 +5,7 @@ extern crate rosenpass;
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
|
||||
use rosenpass_ciphers::aead;
|
||||
use rosenpass_sodium::init as sodium_init;
|
||||
|
||||
#[derive(arbitrary::Arbitrary, Debug)]
|
||||
pub struct Input {
|
||||
@@ -15,6 +16,8 @@ pub struct Input {
|
||||
}
|
||||
|
||||
fuzz_target!(|input: Input| {
|
||||
sodium_init().unwrap();
|
||||
|
||||
let mut ciphertext: Vec<u8> = Vec::with_capacity(input.plaintext.len() + 16);
|
||||
ciphertext.resize(input.plaintext.len() + 16, 0);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ extern crate rosenpass;
|
||||
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
|
||||
use rosenpass_ciphers::subtle::blake2b;
|
||||
use rosenpass_sodium::{hash::blake2b, init as sodium_init};
|
||||
use rosenpass_to::To;
|
||||
|
||||
#[derive(arbitrary::Arbitrary, Debug)]
|
||||
@@ -14,6 +14,8 @@ pub struct Blake2b {
|
||||
}
|
||||
|
||||
fuzz_target!(|input: Blake2b| {
|
||||
sodium_init().unwrap();
|
||||
|
||||
let mut out = [0u8; 32];
|
||||
|
||||
blake2b::hash(&input.key, &input.data).to(&mut out).unwrap();
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#![no_main]
|
||||
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use rosenpass_secret_memory::alloc::secret_box;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let _ = secret_box(data);
|
||||
});
|
||||
12
fuzz/fuzz_targets/box_sodium_alloc.rs
Normal file
12
fuzz/fuzz_targets/box_sodium_alloc.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
#![no_main]
|
||||
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use rosenpass_sodium::{
|
||||
alloc::{Alloc as SodiumAlloc, Box as SodiumBox},
|
||||
init,
|
||||
};
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let _ = init();
|
||||
let _ = SodiumBox::new_in(data, SodiumAlloc::new());
|
||||
});
|
||||
@@ -5,8 +5,11 @@ use libfuzzer_sys::fuzz_target;
|
||||
|
||||
use rosenpass::protocol::CryptoServer;
|
||||
use rosenpass_secret_memory::Secret;
|
||||
use rosenpass_sodium::init as sodium_init;
|
||||
|
||||
fuzz_target!(|rx_buf: &[u8]| {
|
||||
sodium_init().unwrap();
|
||||
|
||||
let sk = Secret::from_slice(&[0; 13568]);
|
||||
let pk = Secret::from_slice(&[0; 524160]);
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#![no_main]
|
||||
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use rosenpass_secret_memory::alloc::secret_vec;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let mut vec = secret_vec();
|
||||
vec.extend_from_slice(data);
|
||||
});
|
||||
13
fuzz/fuzz_targets/vec_sodium_alloc.rs
Normal file
13
fuzz/fuzz_targets/vec_sodium_alloc.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
#![no_main]
|
||||
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use rosenpass_sodium::{
|
||||
alloc::{Alloc as SodiumAlloc, Vec as SodiumVec},
|
||||
init,
|
||||
};
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let _ = init();
|
||||
let mut vec = SodiumVec::new_in(SodiumAlloc::new());
|
||||
vec.extend_from_slice(data);
|
||||
});
|
||||
@@ -16,6 +16,7 @@ harness = false
|
||||
[dependencies]
|
||||
rosenpass-util = { workspace = true }
|
||||
rosenpass-constant-time = { workspace = true }
|
||||
rosenpass-sodium = { workspace = true }
|
||||
rosenpass-ciphers = { workspace = true }
|
||||
rosenpass-cipher-traits = { workspace = true }
|
||||
rosenpass-to = { workspace = true }
|
||||
@@ -25,6 +26,7 @@ rosenpass-wireguard-broker = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
static_assertions = { workspace = true }
|
||||
memoffset = { workspace = true }
|
||||
libsodium-sys-stable = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
log = { workspace = true }
|
||||
@@ -34,9 +36,8 @@ toml = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
mio = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "hermit")'.dependencies]
|
||||
hermit = { version = "0.8", features = ["pci", "pci-ids", "acpi", "fsgsbase", "tcp", "rtl8139"]}
|
||||
command-fds = { workspace = true }
|
||||
rustix = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = { workspace = true }
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use anyhow::Result;
|
||||
use rosenpass::protocol::{CryptoServer, HandleMsgResult, MsgBuf, PeerPtr, SPk, SSk, SymKey};
|
||||
|
||||
use rosenpass_cipher_traits::Kem;
|
||||
use rosenpass_ciphers::kem::StaticKem;
|
||||
use rosenpass::pqkem::KEM;
|
||||
use rosenpass::{
|
||||
pqkem::StaticKEM,
|
||||
protocol::{CryptoServer, HandleMsgResult, MsgBuf, PeerPtr, SPk, SSk, SymKey},
|
||||
sodium::sodium_init,
|
||||
};
|
||||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
@@ -39,7 +41,7 @@ fn hs(ini: &mut CryptoServer, res: &mut CryptoServer) -> Result<()> {
|
||||
|
||||
fn keygen() -> Result<(SSk, SPk)> {
|
||||
let (mut sk, mut pk) = (SSk::zero(), SPk::zero());
|
||||
StaticKem::keygen(sk.secret_mut(), pk.secret_mut())?;
|
||||
StaticKEM::keygen(sk.secret_mut(), pk.secret_mut())?;
|
||||
Ok((sk, pk))
|
||||
}
|
||||
|
||||
@@ -56,6 +58,7 @@ fn make_server_pair() -> Result<(CryptoServer, CryptoServer)> {
|
||||
}
|
||||
|
||||
fn criterion_benchmark(c: &mut Criterion) {
|
||||
sodium_init().unwrap();
|
||||
let (mut a, mut b) = make_server_pair().unwrap();
|
||||
c.bench_function("cca_secret_alloc", |bench| {
|
||||
bench.iter(|| {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::io::{ErrorKind, Write};
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, TcpStream};
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::path::PathBuf;
|
||||
use std::slice;
|
||||
use std::time::Duration;
|
||||
@@ -352,7 +353,7 @@ impl AppServer {
|
||||
sk: SSk,
|
||||
pk: SPk,
|
||||
addrs: Vec<SocketAddr>,
|
||||
psk_broker_socket: TcpStream,
|
||||
psk_broker_socket: UnixStream,
|
||||
verbosity: Verbosity,
|
||||
) -> anyhow::Result<Self> {
|
||||
// setup mio
|
||||
@@ -362,7 +363,7 @@ impl AppServer {
|
||||
|
||||
// Create the Wireguard broker connection
|
||||
let psk_broker = {
|
||||
let mut sock = mio::net::TcpStream::from_std(psk_broker_socket);
|
||||
let mut sock = mio::net::UnixStream::from_std(psk_broker_socket);
|
||||
mio_poll.registry().register(
|
||||
&mut sock,
|
||||
dispenser.get_token(),
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
use std::io::{BufReader, Read};
|
||||
use std::net::TcpStream;
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::thread;
|
||||
|
||||
use anyhow::{bail, ensure, Context};
|
||||
use clap::Parser;
|
||||
use command_fds::{CommandFdExt, FdMapping};
|
||||
use log::{error, info};
|
||||
use rustix::fd::AsRawFd;
|
||||
use rustix::net::{socketpair, AddressFamily, SocketFlags, SocketType};
|
||||
|
||||
use rosenpass_cipher_traits::Kem;
|
||||
use rosenpass_ciphers::kem::StaticKem;
|
||||
@@ -145,7 +151,7 @@ impl Cli {
|
||||
// Manual arg parsing, since clap wants to prefix flags with "--"
|
||||
let mut args = args.into_iter();
|
||||
loop {
|
||||
match (args.next().as_deref(), args.next()) {
|
||||
match (args.next().as_ref().map(String::as_str), args.next()) {
|
||||
(Some("private-key"), Some(opt)) | (Some("secret-key"), Some(opt)) => {
|
||||
secret_key = Some(opt.into());
|
||||
}
|
||||
@@ -266,7 +272,46 @@ impl Cli {
|
||||
let pk = SPk::load(&config.public_key)?;
|
||||
|
||||
// Spawn the psk broker and use socketpair(2) to connect with them
|
||||
let psk_broker_socket = TcpStream::connect("127.0.0.1:8001")?;
|
||||
let psk_broker_socket = {
|
||||
let (ours, theirs) = socketpair(
|
||||
AddressFamily::UNIX,
|
||||
SocketType::STREAM,
|
||||
SocketFlags::empty(),
|
||||
None,
|
||||
)?;
|
||||
|
||||
// Setup our end of the socketpair
|
||||
let ours = UnixStream::from(ours);
|
||||
ours.set_nonblocking(true)?;
|
||||
|
||||
// Start the PSK broker
|
||||
let mut child = Command::new("rosenpass-wireguard-broker-socket-handler")
|
||||
.args(["--stream-fd", "3"])
|
||||
.fd_mappings(vec![FdMapping {
|
||||
parent_fd: theirs.as_raw_fd(),
|
||||
child_fd: 3,
|
||||
}])?
|
||||
.spawn()?;
|
||||
|
||||
// Handle the PSK broker crashing
|
||||
thread::spawn(move || {
|
||||
let status = child.wait();
|
||||
|
||||
if let Ok(status) = status {
|
||||
if status.success() {
|
||||
// Maybe they are doing double forking?
|
||||
info!("PSK broker exited.");
|
||||
} else {
|
||||
error!("PSK broker exited with an error ({status:?})");
|
||||
}
|
||||
} else {
|
||||
error!("Wait on PSK broker process failed ({status:?})");
|
||||
}
|
||||
});
|
||||
|
||||
ours
|
||||
};
|
||||
|
||||
// start an application server
|
||||
let mut srv = std::boxed::Box::<AppServer>::new(AppServer::new(
|
||||
sk,
|
||||
|
||||
@@ -374,7 +374,7 @@ mod test {
|
||||
use super::*;
|
||||
|
||||
fn split_str(s: &str) -> Vec<String> {
|
||||
s.split(' ').map(|s| s.to_string()).collect()
|
||||
s.split(" ").map(|s| s.to_string()).collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
use log::error;
|
||||
use rosenpass::cli::Cli;
|
||||
use rosenpass_util::attempt;
|
||||
use std::process::exit;
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
use hermit as _;
|
||||
|
||||
/// Catches errors, prints them through the logger, then exits
|
||||
pub fn main() {
|
||||
// default to displaying warning and error log messages only
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init();
|
||||
|
||||
match Cli::run() {
|
||||
let res = attempt!({
|
||||
rosenpass_sodium::init()?;
|
||||
Cli::run()
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
error!("{e}");
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
//! };
|
||||
//! # fn main() -> anyhow::Result<()> {
|
||||
//!
|
||||
//! // always initialize libsodium before anything
|
||||
//! rosenpass_sodium::init()?;
|
||||
//!
|
||||
//! // initialize secret and public key for peer a ...
|
||||
//! let (mut peer_a_sk, mut peer_a_pk) = (SSk::zero(), SPk::zero());
|
||||
//! StaticKem::keygen(peer_a_sk.secret_mut(), peer_a_pk.secret_mut())?;
|
||||
@@ -65,25 +68,21 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
use crate::{hash_domains, msgs::*};
|
||||
use anyhow::{bail, ensure, Context, Result};
|
||||
use rosenpass_cipher_traits::Kem;
|
||||
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
|
||||
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
||||
use rosenpass_lenses::LenseView;
|
||||
use rosenpass_secret_memory::{Public, Secret};
|
||||
use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase};
|
||||
use std::collections::hash_map::{
|
||||
Entry::{Occupied, Vacant},
|
||||
HashMap,
|
||||
};
|
||||
use std::convert::Infallible;
|
||||
|
||||
use anyhow::{bail, ensure, Context, Result};
|
||||
|
||||
use rosenpass_cipher_traits::Kem;
|
||||
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
|
||||
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
||||
use rosenpass_constant_time as constant_time;
|
||||
use rosenpass_lenses::LenseView;
|
||||
use rosenpass_secret_memory::{Public, Secret};
|
||||
use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase};
|
||||
|
||||
use crate::{hash_domains, msgs::*};
|
||||
|
||||
// CONSTANTS & SETTINGS //////////////////////////
|
||||
|
||||
/// Size required to fit any message in binary form
|
||||
@@ -1194,7 +1193,7 @@ where
|
||||
let expected = hash_domains::mac()?
|
||||
.mix(srv.spkm.secret())?
|
||||
.mix(self.until_mac())?;
|
||||
Ok(constant_time::memcmp(
|
||||
Ok(rosenpass_sodium::helpers::memcmp(
|
||||
self.mac(),
|
||||
&expected.into_value()[..16],
|
||||
))
|
||||
@@ -1301,7 +1300,7 @@ impl HandshakeState {
|
||||
.into_value();
|
||||
|
||||
// consume biscuit no
|
||||
constant_time::increment(&mut *srv.biscuit_ctr);
|
||||
rosenpass_sodium::helpers::increment(&mut *srv.biscuit_ctr);
|
||||
|
||||
// The first bit of the nonce indicates which biscuit key was used
|
||||
// TODO: This is premature optimization. Remove!
|
||||
@@ -1364,7 +1363,8 @@ impl HandshakeState {
|
||||
// indicates retransmission
|
||||
// TODO: Handle retransmissions without involving the crypto code
|
||||
ensure!(
|
||||
constant_time::compare(biscuit.biscuit_no(), &*peer.get(srv).biscuit_used) >= 0,
|
||||
rosenpass_sodium::helpers::compare(biscuit.biscuit_no(), &*peer.get(srv).biscuit_used)
|
||||
>= 0,
|
||||
"Rejecting biscuit: Outdated biscuit number"
|
||||
);
|
||||
|
||||
@@ -1641,7 +1641,7 @@ impl CryptoServer {
|
||||
core.decrypt_and_mix(&mut [0u8; 0], ic.auth())?;
|
||||
|
||||
// ICR5
|
||||
if constant_time::compare(&*biscuit_no, &*peer.get(self).biscuit_used) > 0 {
|
||||
if rosenpass_sodium::helpers::compare(&*biscuit_no, &*peer.get(self).biscuit_used) > 0 {
|
||||
// ICR6
|
||||
peer.get_mut(self).biscuit_used = biscuit_no;
|
||||
|
||||
@@ -1757,6 +1757,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() {
|
||||
rosenpass_sodium::init().unwrap();
|
||||
|
||||
stacker::grow(8 * 1024 * 1024, || {
|
||||
const OVERSIZED_MESSAGE: usize = ((MAX_MESSAGE_LEN as f32) * 1.2) as usize;
|
||||
type MsgBufPlus = Public<OVERSIZED_MESSAGE>;
|
||||
@@ -1768,10 +1770,14 @@ mod test {
|
||||
|
||||
// Process the entire handshake
|
||||
let mut msglen = Some(me.initiate_handshake(PEER0, &mut *resbuf).unwrap());
|
||||
while let Some(l) = msglen {
|
||||
std::mem::swap(&mut me, &mut they);
|
||||
std::mem::swap(&mut msgbuf, &mut resbuf);
|
||||
msglen = test_incorrect_sizes_for_msg(&mut me, &*msgbuf, l, &mut *resbuf);
|
||||
loop {
|
||||
if let Some(l) = msglen {
|
||||
std::mem::swap(&mut me, &mut they);
|
||||
std::mem::swap(&mut msgbuf, &mut resbuf);
|
||||
msglen = test_incorrect_sizes_for_msg(&mut me, &*msgbuf, l, &mut *resbuf);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
@@ -1798,8 +1804,8 @@ mod test {
|
||||
}
|
||||
|
||||
let res = srv.handle_msg(&msgbuf[..l], resbuf);
|
||||
assert!(res.is_err()); // handle_msg should raise an error
|
||||
assert!(!resbuf.iter().any(|x| *x != 0)); // resbuf should not have been changed
|
||||
assert!(matches!(res, Err(_))); // handle_msg should raise an error
|
||||
assert!(!resbuf.iter().find(|x| **x != 0).is_some()); // resbuf should not have been changed
|
||||
}
|
||||
|
||||
// Apply the proper handle_msg operation
|
||||
|
||||
@@ -30,8 +30,11 @@ fn generate_keys() {
|
||||
|
||||
fn find_udp_socket() -> u16 {
|
||||
for port in 1025..=u16::MAX {
|
||||
if UdpSocket::bind(("127.0.0.1", port)).is_ok() {
|
||||
return port;
|
||||
match UdpSocket::bind(("127.0.0.1", port)) {
|
||||
Ok(_) => {
|
||||
return port;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
panic!("no free UDP port found");
|
||||
@@ -51,9 +54,9 @@ fn check_exchange() {
|
||||
for (secret_key_path, pub_key_path) in secret_key_paths.iter().zip(public_key_paths.iter()) {
|
||||
let output = test_bin::get_test_bin(BIN)
|
||||
.args(["gen-keys", "--secret-key"])
|
||||
.arg(secret_key_path)
|
||||
.arg(&secret_key_path)
|
||||
.arg("--public-key")
|
||||
.arg(pub_key_path)
|
||||
.arg(&pub_key_path)
|
||||
.output()
|
||||
.expect("Failed to start {BIN}");
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "1.74.1"
|
||||
@@ -12,11 +12,9 @@ readme = "readme.md"
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
rosenpass-to = { workspace = true }
|
||||
rosenpass-sodium = { workspace = true }
|
||||
rosenpass-util = { workspace = true }
|
||||
libsodium-sys-stable = { workspace = true }
|
||||
lazy_static = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
allocator-api2 = { workspace = true }
|
||||
log = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
allocator-api2-tests = { workspace = true }
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
use std::fmt;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use allocator_api2::alloc::{AllocError, Allocator, Layout, Global};
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
struct MemsecAllocatorContents;
|
||||
|
||||
/// Memory allocation using using the memsec crate
|
||||
#[derive(Copy, Clone, Default)]
|
||||
pub struct MemsecAllocator {
|
||||
global: Global
|
||||
}
|
||||
|
||||
/// A box backed by the memsec allocator
|
||||
pub type MemsecBox<T> = allocator_api2::boxed::Box<T, MemsecAllocator>;
|
||||
|
||||
/// A vector backed by the memsec allocator
|
||||
pub type MemsecVec<T> = allocator_api2::vec::Vec<T, MemsecAllocator>;
|
||||
|
||||
pub fn memsec_box<T>(x: T) -> MemsecBox<T> {
|
||||
MemsecBox::<T>::new_in(x, MemsecAllocator::new())
|
||||
}
|
||||
|
||||
pub fn memsec_vec<T>() -> MemsecVec<T> {
|
||||
MemsecVec::<T>::new_in(MemsecAllocator::new())
|
||||
}
|
||||
|
||||
impl MemsecAllocator {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
global: Global
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Allocator for MemsecAllocator {
|
||||
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||
self.global.allocate(layout)
|
||||
}
|
||||
|
||||
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
|
||||
unsafe { self.global.deallocate(ptr, _layout) }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for MemsecAllocator {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.write_str("<memsec based Rust allocator>")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use allocator_api2_tests::make_test;
|
||||
|
||||
use super::*;
|
||||
|
||||
make_test! { test_sizes(MemsecAllocator::new()) }
|
||||
make_test! { test_vec(MemsecAllocator::new()) }
|
||||
make_test! { test_many_boxes(MemsecAllocator::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 memsec_allocation_impl<const N: usize>(alloc: &MemsecAllocator) {
|
||||
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) };
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
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,
|
||||
};
|
||||
@@ -2,8 +2,6 @@ pub mod debug;
|
||||
pub mod file;
|
||||
pub mod rand;
|
||||
|
||||
pub mod alloc;
|
||||
|
||||
mod public;
|
||||
pub use crate::public::Public;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ pub struct Public<const N: usize> {
|
||||
impl<const N: usize> Public<N> {
|
||||
/// Create a new [Public] from a byte slice
|
||||
pub fn from_slice(value: &[u8]) -> Self {
|
||||
copy_slice(value).to_this(Self::zero)
|
||||
copy_slice(value).to_this(|| Self::zero())
|
||||
}
|
||||
|
||||
/// Create a new [Public] from a byte array
|
||||
|
||||
@@ -1,96 +1,21 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::fmt;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Context;
|
||||
use rand::{Fill as Randomize, Rng};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
use rosenpass_util::b64::b64_reader;
|
||||
use rosenpass_util::file::{fopen_r, LoadValue, LoadValueB64, ReadExactToEnd};
|
||||
use rosenpass_util::functional::mutating;
|
||||
|
||||
use crate::alloc::{secret_box, SecretBox, SecretVec};
|
||||
use crate::file::StoreSecret;
|
||||
use anyhow::Context;
|
||||
use lazy_static::lazy_static;
|
||||
use rand::{Fill as Randomize, Rng};
|
||||
use rosenpass_sodium::alloc::{Alloc as SodiumAlloc, Box as SodiumBox, Vec as SodiumVec};
|
||||
use rosenpass_util::{
|
||||
b64::b64_reader,
|
||||
file::{fopen_r, LoadValue, LoadValueB64, ReadExactToEnd},
|
||||
functional::mutating,
|
||||
};
|
||||
use std::{collections::HashMap, convert::TryInto, fmt, path::Path, sync::Mutex};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
// This might become a problem in library usage; it's effectively a memory
|
||||
// leak which probably isn't a problem right now because most memory will
|
||||
// be reused…
|
||||
thread_local! {
|
||||
static SECRET_CACHE: RefCell<SecretMemoryPool> = RefCell::new(SecretMemoryPool::new());
|
||||
}
|
||||
|
||||
fn with_secret_memory_pool<Fn, R>(mut f: Fn) -> R
|
||||
where
|
||||
Fn: FnMut(Option<&mut SecretMemoryPool>) -> R,
|
||||
{
|
||||
// This acquires the SECRET_CACHE
|
||||
SECRET_CACHE
|
||||
.try_with(|cell| {
|
||||
// And acquires the inner reference
|
||||
cell.try_borrow_mut()
|
||||
.as_deref_mut()
|
||||
// To call the given function
|
||||
.map(|pool| f(Some(pool)))
|
||||
.ok()
|
||||
})
|
||||
.ok()
|
||||
.flatten()
|
||||
// Failing that, the given function is called with None
|
||||
.unwrap_or_else(|| f(None))
|
||||
}
|
||||
|
||||
// Wrapper around SecretBox that applies automatic zeroization
|
||||
#[derive(Debug)]
|
||||
struct ZeroizingSecretBox<T: Zeroize + ?Sized>(Option<SecretBox<T>>);
|
||||
|
||||
impl<T: Zeroize> ZeroizingSecretBox<T> {
|
||||
fn new(boxed: T) -> Self {
|
||||
ZeroizingSecretBox(Some(secret_box(boxed)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zeroize + ?Sized> ZeroizingSecretBox<T> {
|
||||
fn from_secret_box(inner: SecretBox<T>) -> Self {
|
||||
Self(Some(inner))
|
||||
}
|
||||
|
||||
fn take(mut self) -> SecretBox<T> {
|
||||
self.0.take().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zeroize + ?Sized> ZeroizeOnDrop for ZeroizingSecretBox<T> {}
|
||||
impl<T: Zeroize + ?Sized> Zeroize for ZeroizingSecretBox<T> {
|
||||
fn zeroize(&mut self) {
|
||||
if let Some(inner) = &mut self.0 {
|
||||
let inner: &mut SecretBox<T> = inner; // type annotation
|
||||
inner.zeroize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zeroize + ?Sized> Drop for ZeroizingSecretBox<T> {
|
||||
fn drop(&mut self) {
|
||||
self.zeroize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zeroize + ?Sized> Deref for ZeroizingSecretBox<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
self.0.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zeroize + ?Sized> DerefMut for ZeroizingSecretBox<T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
self.0.as_mut().unwrap()
|
||||
}
|
||||
lazy_static! {
|
||||
static ref SECRET_CACHE: Mutex<SecretMemoryPool> = Mutex::new(SecretMemoryPool::new());
|
||||
}
|
||||
|
||||
/// Pool that stores secret memory allocations
|
||||
@@ -98,9 +23,12 @@ impl<T: Zeroize + ?Sized> DerefMut for ZeroizingSecretBox<T> {
|
||||
/// Allocation of secret memory is expensive. Thus, this struct provides a
|
||||
/// pool of secret memory, readily available to yield protected, slices of
|
||||
/// memory.
|
||||
///
|
||||
/// Further information about the protection in place can be found in in the
|
||||
/// [libsodium documentation](https://libsodium.gitbook.io/doc/memory_management#guarded-heap-allocations)
|
||||
#[derive(Debug)] // TODO check on Debug derive, is that clever
|
||||
struct SecretMemoryPool {
|
||||
pool: HashMap<usize, Vec<ZeroizingSecretBox<[u8]>>>,
|
||||
pool: HashMap<usize, Vec<SodiumBox<[u8]>>>,
|
||||
}
|
||||
|
||||
impl SecretMemoryPool {
|
||||
@@ -113,37 +41,33 @@ impl SecretMemoryPool {
|
||||
}
|
||||
|
||||
/// Return secret back to the pool for future re-use
|
||||
pub fn release<const N: usize>(&mut self, mut sec: ZeroizingSecretBox<[u8; N]>) {
|
||||
pub fn release<const N: usize>(&mut self, mut sec: SodiumBox<[u8; N]>) {
|
||||
sec.zeroize();
|
||||
|
||||
// This conversion sequence is weird but at least it guarantees
|
||||
// that the heap allocation is preserved according to the docs
|
||||
let sec: SecretVec<u8> = sec.take().into();
|
||||
let sec: SecretBox<[u8]> = sec.into();
|
||||
let sec: SodiumVec<u8> = sec.into();
|
||||
let sec: SodiumBox<[u8]> = sec.into();
|
||||
|
||||
self.pool
|
||||
.entry(N)
|
||||
.or_default()
|
||||
.push(ZeroizingSecretBox::from_secret_box(sec));
|
||||
self.pool.entry(N).or_default().push(sec);
|
||||
}
|
||||
|
||||
/// Take protected memory from the pool, allocating new one if no suitable
|
||||
/// chunk is found in the inventory.
|
||||
///
|
||||
/// The secret is guaranteed to be full of nullbytes
|
||||
pub fn take<const N: usize>(&mut self) -> ZeroizingSecretBox<[u8; N]> {
|
||||
pub fn take<const N: usize>(&mut self) -> SodiumBox<[u8; N]> {
|
||||
let entry = self.pool.entry(N).or_default();
|
||||
let inner = match entry.pop() {
|
||||
None => secret_box([0u8; N]),
|
||||
Some(sec) => sec.take().try_into().unwrap(),
|
||||
};
|
||||
ZeroizingSecretBox::from_secret_box(inner)
|
||||
match entry.pop() {
|
||||
None => SodiumBox::new_in([0u8; N], SodiumAlloc::default()),
|
||||
Some(sec) => sec.try_into().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Storage for secret data
|
||||
/// Storeage for a secret backed by [rosenpass_sodium::alloc::Alloc]
|
||||
pub struct Secret<const N: usize> {
|
||||
storage: Option<ZeroizingSecretBox<[u8; N]>>,
|
||||
storage: Option<SodiumBox<[u8; N]>>,
|
||||
}
|
||||
|
||||
impl<const N: usize> Secret<N> {
|
||||
@@ -157,12 +81,9 @@ impl<const N: usize> Secret<N> {
|
||||
pub fn zero() -> Self {
|
||||
// Using [SecretMemoryPool] here because this operation is expensive,
|
||||
// yet it is used in hot loops
|
||||
let buf = with_secret_memory_pool(|pool| {
|
||||
pool.map(|p| p.take())
|
||||
.unwrap_or_else(|| ZeroizingSecretBox::new([0u8; N]))
|
||||
});
|
||||
|
||||
Self { storage: Some(buf) }
|
||||
Self {
|
||||
storage: Some(SECRET_CACHE.lock().unwrap().take()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new [Secret] that is randomized
|
||||
@@ -186,6 +107,13 @@ impl<const N: usize> Secret<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> ZeroizeOnDrop for Secret<N> {}
|
||||
impl<const N: usize> Zeroize for Secret<N> {
|
||||
fn zeroize(&mut self) {
|
||||
self.secret_mut().zeroize();
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Randomize for Secret<N> {
|
||||
fn try_fill<R: Rng + ?Sized>(&mut self, rng: &mut R) -> Result<(), rand::Error> {
|
||||
// Zeroize self first just to make sure the barriers from the zeroize create take
|
||||
@@ -196,26 +124,11 @@ impl<const N: usize> Randomize for Secret<N> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> ZeroizeOnDrop for Secret<N> {}
|
||||
impl<const N: usize> Zeroize for Secret<N> {
|
||||
fn zeroize(&mut self) {
|
||||
if let Some(inner) = &mut self.storage {
|
||||
inner.zeroize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> Drop for Secret<N> {
|
||||
fn drop(&mut self) {
|
||||
with_secret_memory_pool(|pool| {
|
||||
if let Some((pool, secret)) = pool.zip(self.storage.take()) {
|
||||
pool.release(secret);
|
||||
}
|
||||
});
|
||||
|
||||
// This should be unnecessary: The pool has one item – the inner secret – which
|
||||
// zeroizes itself on drop. Calling it should not do any harm though…
|
||||
self.zeroize()
|
||||
self.storage
|
||||
.take()
|
||||
.map(|sec| SECRET_CACHE.lock().unwrap().release(sec));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,18 +197,20 @@ mod test {
|
||||
/// check that we can alloc using the magic pool
|
||||
#[test]
|
||||
fn secret_memory_pool_take() {
|
||||
rosenpass_sodium::init().unwrap();
|
||||
const N: usize = 0x100;
|
||||
let mut pool = SecretMemoryPool::new();
|
||||
let secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
||||
let secret: SodiumBox<[u8; N]> = pool.take();
|
||||
assert_eq!(secret.as_ref(), &[0; N]);
|
||||
}
|
||||
|
||||
/// check that a secrete lives, even if its [SecretMemoryPool] is deleted
|
||||
#[test]
|
||||
fn secret_memory_pool_drop() {
|
||||
rosenpass_sodium::init().unwrap();
|
||||
const N: usize = 0x100;
|
||||
let mut pool = SecretMemoryPool::new();
|
||||
let secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
||||
let secret: SodiumBox<[u8; N]> = pool.take();
|
||||
std::mem::drop(pool);
|
||||
assert_eq!(secret.as_ref(), &[0; N]);
|
||||
}
|
||||
@@ -303,16 +218,17 @@ mod test {
|
||||
/// check that a secrete can be reborn, freshly initialized with zero
|
||||
#[test]
|
||||
fn secret_memory_pool_release() {
|
||||
rosenpass_sodium::init().unwrap();
|
||||
const N: usize = 1;
|
||||
let mut pool = SecretMemoryPool::new();
|
||||
let mut secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
||||
let mut secret: SodiumBox<[u8; N]> = pool.take();
|
||||
let old_secret_ptr = secret.as_ref().as_ptr();
|
||||
|
||||
secret.as_mut()[0] = 0x13;
|
||||
pool.release(secret);
|
||||
|
||||
// now check that we get the same ptr
|
||||
let new_secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
||||
let new_secret: SodiumBox<[u8; N]> = pool.take();
|
||||
assert_eq!(old_secret_ptr, new_secret.as_ref().as_ptr());
|
||||
|
||||
// and that the secret was zeroized
|
||||
|
||||
18
sodium/Cargo.toml
Normal file
18
sodium/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "rosenpass-sodium"
|
||||
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Rosenpass internal bindings to libsodium"
|
||||
homepage = "https://rosenpass.eu/"
|
||||
repository = "https://github.com/rosenpass/rosenpass"
|
||||
readme = "readme.md"
|
||||
|
||||
[dependencies]
|
||||
rosenpass-util = { workspace = true }
|
||||
rosenpass-to = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
libsodium-sys-stable = { workspace = true }
|
||||
log = { workspace = true }
|
||||
allocator-api2 = { workspace = true }
|
||||
5
sodium/readme.md
Normal file
5
sodium/readme.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Rosenpass internal libsodium bindings
|
||||
|
||||
Rosenpass internal library providing bindings to libsodium.
|
||||
|
||||
This is an internal library; not guarantee is made about its API at this point in time.
|
||||
63
sodium/src/aead/chacha20poly1305_ietf.rs
Normal file
63
sodium/src/aead/chacha20poly1305_ietf.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use libsodium_sys as libsodium;
|
||||
use std::ffi::c_ulonglong;
|
||||
use std::ptr::{null, null_mut};
|
||||
|
||||
pub const KEY_LEN: usize = libsodium::crypto_aead_chacha20poly1305_IETF_KEYBYTES as usize;
|
||||
pub const TAG_LEN: usize = libsodium::crypto_aead_chacha20poly1305_IETF_ABYTES as usize;
|
||||
pub const NONCE_LEN: usize = libsodium::crypto_aead_chacha20poly1305_IETF_NPUBBYTES as usize;
|
||||
|
||||
#[inline]
|
||||
pub fn encrypt(
|
||||
ciphertext: &mut [u8],
|
||||
key: &[u8],
|
||||
nonce: &[u8],
|
||||
ad: &[u8],
|
||||
plaintext: &[u8],
|
||||
) -> anyhow::Result<()> {
|
||||
assert!(ciphertext.len() == plaintext.len() + TAG_LEN);
|
||||
assert!(key.len() == KEY_LEN);
|
||||
assert!(nonce.len() == NONCE_LEN);
|
||||
let mut clen: u64 = 0;
|
||||
sodium_call!(
|
||||
crypto_aead_chacha20poly1305_ietf_encrypt,
|
||||
ciphertext.as_mut_ptr(),
|
||||
&mut clen,
|
||||
plaintext.as_ptr(),
|
||||
plaintext.len() as c_ulonglong,
|
||||
ad.as_ptr(),
|
||||
ad.len() as c_ulonglong,
|
||||
null(), // nsec is not used
|
||||
nonce.as_ptr(),
|
||||
key.as_ptr()
|
||||
)?;
|
||||
assert!(clen as usize == ciphertext.len());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decrypt(
|
||||
plaintext: &mut [u8],
|
||||
key: &[u8],
|
||||
nonce: &[u8],
|
||||
ad: &[u8],
|
||||
ciphertext: &[u8],
|
||||
) -> anyhow::Result<()> {
|
||||
assert!(ciphertext.len() == plaintext.len() + TAG_LEN);
|
||||
assert!(key.len() == KEY_LEN);
|
||||
assert!(nonce.len() == NONCE_LEN);
|
||||
let mut mlen: u64 = 0;
|
||||
sodium_call!(
|
||||
crypto_aead_chacha20poly1305_ietf_decrypt,
|
||||
plaintext.as_mut_ptr(),
|
||||
&mut mlen as *mut c_ulonglong,
|
||||
null_mut(), // nsec is not used
|
||||
ciphertext.as_ptr(),
|
||||
ciphertext.len() as c_ulonglong,
|
||||
ad.as_ptr(),
|
||||
ad.len() as c_ulonglong,
|
||||
nonce.as_ptr(),
|
||||
key.as_ptr()
|
||||
)?;
|
||||
assert!(mlen as usize == plaintext.len());
|
||||
Ok(())
|
||||
}
|
||||
2
sodium/src/aead/mod.rs
Normal file
2
sodium/src/aead/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod chacha20poly1305_ietf;
|
||||
pub mod xchacha20poly1305_ietf;
|
||||
63
sodium/src/aead/xchacha20poly1305_ietf.rs
Normal file
63
sodium/src/aead/xchacha20poly1305_ietf.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use libsodium_sys as libsodium;
|
||||
use std::ffi::c_ulonglong;
|
||||
use std::ptr::{null, null_mut};
|
||||
|
||||
pub const KEY_LEN: usize = libsodium::crypto_aead_xchacha20poly1305_IETF_KEYBYTES as usize;
|
||||
pub const TAG_LEN: usize = libsodium::crypto_aead_xchacha20poly1305_ietf_ABYTES as usize;
|
||||
pub const NONCE_LEN: usize = libsodium::crypto_aead_xchacha20poly1305_IETF_NPUBBYTES as usize;
|
||||
|
||||
#[inline]
|
||||
pub fn encrypt(
|
||||
ciphertext: &mut [u8],
|
||||
key: &[u8],
|
||||
nonce: &[u8],
|
||||
ad: &[u8],
|
||||
plaintext: &[u8],
|
||||
) -> anyhow::Result<()> {
|
||||
assert!(ciphertext.len() == plaintext.len() + NONCE_LEN + TAG_LEN);
|
||||
assert!(key.len() == libsodium::crypto_aead_xchacha20poly1305_IETF_KEYBYTES as usize);
|
||||
let (n, ct) = ciphertext.split_at_mut(NONCE_LEN);
|
||||
n.copy_from_slice(nonce);
|
||||
let mut clen: u64 = 0;
|
||||
sodium_call!(
|
||||
crypto_aead_xchacha20poly1305_ietf_encrypt,
|
||||
ct.as_mut_ptr(),
|
||||
&mut clen,
|
||||
plaintext.as_ptr(),
|
||||
plaintext.len() as c_ulonglong,
|
||||
ad.as_ptr(),
|
||||
ad.len() as c_ulonglong,
|
||||
null(), // nsec is not used
|
||||
nonce.as_ptr(),
|
||||
key.as_ptr()
|
||||
)?;
|
||||
assert!(clen as usize == ct.len());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decrypt(
|
||||
plaintext: &mut [u8],
|
||||
key: &[u8],
|
||||
ad: &[u8],
|
||||
ciphertext: &[u8],
|
||||
) -> anyhow::Result<()> {
|
||||
assert!(ciphertext.len() == plaintext.len() + NONCE_LEN + TAG_LEN);
|
||||
assert!(key.len() == KEY_LEN);
|
||||
let (n, ct) = ciphertext.split_at(NONCE_LEN);
|
||||
let mut mlen: u64 = 0;
|
||||
sodium_call!(
|
||||
crypto_aead_xchacha20poly1305_ietf_decrypt,
|
||||
plaintext.as_mut_ptr(),
|
||||
&mut mlen as *mut c_ulonglong,
|
||||
null_mut(), // nsec is not used
|
||||
ct.as_ptr(),
|
||||
ct.len() as c_ulonglong,
|
||||
ad.as_ptr(),
|
||||
ad.len() as c_ulonglong,
|
||||
n.as_ptr(),
|
||||
key.as_ptr()
|
||||
)?;
|
||||
assert!(mlen as usize == plaintext.len());
|
||||
Ok(())
|
||||
}
|
||||
95
sodium/src/alloc/allocator.rs
Normal file
95
sodium/src/alloc/allocator.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
use allocator_api2::alloc::{AllocError, Allocator, Layout};
|
||||
use libsodium_sys as libsodium;
|
||||
use std::fmt;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct AllocatorContents;
|
||||
|
||||
/// Memory allocation using sodium_malloc/sodium_free
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Alloc {
|
||||
_dummy_private_data: AllocatorContents,
|
||||
}
|
||||
|
||||
impl Alloc {
|
||||
pub fn new() -> Self {
|
||||
Alloc {
|
||||
_dummy_private_data: AllocatorContents,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Allocator for Alloc {
|
||||
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||
// Call sodium allocator
|
||||
let ptr = unsafe { libsodium::sodium_malloc(layout.size()) };
|
||||
|
||||
// Ensure the right allocation is used
|
||||
let off = ptr.align_offset(layout.align());
|
||||
if off != 0 {
|
||||
log::error!("Allocation {layout:?} was requested but libsodium returned allocation \
|
||||
with offset {off} from the requested alignment. Libsodium 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.");
|
||||
return Err(AllocError);
|
||||
}
|
||||
|
||||
// Convert to a pointer size
|
||||
let ptr = core::ptr::slice_from_raw_parts_mut(ptr as *mut u8, layout.size());
|
||||
|
||||
// Conversion to a *const u8, then to a &[u8]
|
||||
match NonNull::new(ptr) {
|
||||
None => {
|
||||
log::error!(
|
||||
"Allocation {layout:?} was requested but libsodium returned a null pointer"
|
||||
);
|
||||
Err(AllocError)
|
||||
}
|
||||
Some(ret) => Ok(ret),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
|
||||
unsafe {
|
||||
libsodium::sodium_free(ptr.as_ptr() as *mut c_void);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Alloc {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.write_str("<libsodium based Rust allocator>")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
/// checks that the can malloc with libsodium
|
||||
#[test]
|
||||
fn sodium_allocation() {
|
||||
crate::init().unwrap();
|
||||
let alloc = Alloc::new();
|
||||
sodium_allocation_impl::<0>(&alloc);
|
||||
sodium_allocation_impl::<7>(&alloc);
|
||||
sodium_allocation_impl::<8>(&alloc);
|
||||
sodium_allocation_impl::<64>(&alloc);
|
||||
sodium_allocation_impl::<999>(&alloc);
|
||||
}
|
||||
|
||||
fn sodium_allocation_impl<const N: usize>(alloc: &Alloc) {
|
||||
crate::init().unwrap();
|
||||
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
|
||||
assert_eq!(unsafe { mem.as_ref() }, &[0xDBu8; N]);
|
||||
|
||||
let mem = NonNull::new(mem.as_ptr() as *mut u8).unwrap();
|
||||
unsafe { alloc.deallocate(mem, layout) };
|
||||
}
|
||||
}
|
||||
10
sodium/src/alloc/mod.rs
Normal file
10
sodium/src/alloc/mod.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
//! Access to sodium_malloc/sodium_free
|
||||
|
||||
mod allocator;
|
||||
pub use allocator::Alloc;
|
||||
|
||||
/// A box backed by sodium_malloc
|
||||
pub type Box<T> = allocator_api2::boxed::Box<T, Alloc>;
|
||||
|
||||
/// A vector backed by sodium_malloc
|
||||
pub type Vec<T> = allocator_api2::vec::Vec<T, Alloc>;
|
||||
31
sodium/src/hash/blake2b.rs
Normal file
31
sodium/src/hash/blake2b.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use libsodium_sys as libsodium;
|
||||
use rosenpass_to::{with_destination, To};
|
||||
use std::ffi::c_ulonglong;
|
||||
use std::ptr::null;
|
||||
|
||||
pub const KEY_MIN: usize = libsodium::crypto_generichash_blake2b_KEYBYTES_MIN as usize;
|
||||
pub const KEY_MAX: usize = libsodium::crypto_generichash_blake2b_KEYBYTES_MAX as usize;
|
||||
pub const OUT_MIN: usize = libsodium::crypto_generichash_blake2b_BYTES_MIN as usize;
|
||||
pub const OUT_MAX: usize = libsodium::crypto_generichash_blake2b_BYTES_MAX as usize;
|
||||
|
||||
#[inline]
|
||||
pub fn hash<'a>(key: &'a [u8], data: &'a [u8]) -> impl To<[u8], anyhow::Result<()>> + 'a {
|
||||
with_destination(|out: &mut [u8]| {
|
||||
assert!(key.is_empty() || (KEY_MIN <= key.len() && key.len() <= KEY_MAX));
|
||||
assert!(OUT_MIN <= out.len() && out.len() <= OUT_MAX);
|
||||
let kptr = match key.len() {
|
||||
// NULL key
|
||||
0 => null(),
|
||||
_ => key.as_ptr(),
|
||||
};
|
||||
sodium_call!(
|
||||
crypto_generichash_blake2b,
|
||||
out.as_mut_ptr(),
|
||||
out.len(),
|
||||
data.as_ptr(),
|
||||
data.len() as c_ulonglong,
|
||||
kptr,
|
||||
key.len()
|
||||
)
|
||||
})
|
||||
}
|
||||
1
sodium/src/hash/mod.rs
Normal file
1
sodium/src/hash/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod blake2b;
|
||||
28
sodium/src/helpers.rs
Normal file
28
sodium/src/helpers.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
use libsodium_sys as libsodium;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
#[inline]
|
||||
pub fn memcmp(a: &[u8], b: &[u8]) -> bool {
|
||||
a.len() == b.len()
|
||||
&& unsafe {
|
||||
let r = libsodium::sodium_memcmp(
|
||||
a.as_ptr() as *const c_void,
|
||||
b.as_ptr() as *const c_void,
|
||||
a.len(),
|
||||
);
|
||||
r == 0
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn compare(a: &[u8], b: &[u8]) -> i32 {
|
||||
assert!(a.len() == b.len());
|
||||
unsafe { libsodium::sodium_compare(a.as_ptr(), b.as_ptr(), a.len()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn increment(v: &mut [u8]) {
|
||||
unsafe {
|
||||
libsodium::sodium_increment(v.as_mut_ptr(), v.len());
|
||||
}
|
||||
}
|
||||
21
sodium/src/lib.rs
Normal file
21
sodium/src/lib.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
use libsodium_sys as libsodium;
|
||||
|
||||
macro_rules! sodium_call {
|
||||
($name:ident, $($args:expr),*) => { ::rosenpass_util::attempt!({
|
||||
anyhow::ensure!(unsafe{libsodium::$name($($args),*)} > -1,
|
||||
"Error in libsodium's {}.", stringify!($name));
|
||||
Ok(())
|
||||
})};
|
||||
($name:ident) => { sodium_call!($name, ) };
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn init() -> anyhow::Result<()> {
|
||||
log::trace!("initializing libsodium");
|
||||
sodium_call!(sodium_init)
|
||||
}
|
||||
|
||||
pub mod aead;
|
||||
pub mod alloc;
|
||||
pub mod hash;
|
||||
pub mod helpers;
|
||||
109
to/README.md
109
to/README.md
@@ -12,17 +12,15 @@ The crate provides chained functions to simplify allocating the destination para
|
||||
For now this crate is experimental; patch releases are guaranteed not to contain any breaking changes, but minor releases may.
|
||||
|
||||
```rust
|
||||
use rosenpass_to::ops::copy_array;
|
||||
use rosenpass_to::{to, with_destination, To};
|
||||
use std::ops::BitXorAssign;
|
||||
use rosenpass_to::{To, to, with_destination};
|
||||
use rosenpass_to::ops::copy_array;
|
||||
|
||||
// Destination functions return some value that implements the To trait.
|
||||
// Unfortunately dealing with lifetimes is a bit more finicky than it would#
|
||||
// be without destination parameters
|
||||
fn xor_slice<'a, T>(src: &'a [T]) -> impl To<[T], ()> + 'a
|
||||
where
|
||||
T: BitXorAssign + Clone,
|
||||
{
|
||||
fn xor_slice<'a, T>(src: &'a[T]) -> impl To<[T], ()> + 'a
|
||||
where T: BitXorAssign + Clone {
|
||||
// Custom implementations of the to trait can be created, but the easiest
|
||||
with_destination(move |dst: &mut [T]| {
|
||||
assert!(src.len() == dst.len());
|
||||
@@ -67,7 +65,7 @@ assert_eq!(&dst[..], &flip01[..]);
|
||||
// The builtin function copy_array supports to_value() since its
|
||||
// destination parameter is a fixed size array, which can be allocated
|
||||
// using default()
|
||||
let dst: [u8; 4] = copy_array(flip01).to_value();
|
||||
let dst : [u8; 4] = copy_array(flip01).to_value();
|
||||
assert_eq!(&dst, flip01);
|
||||
```
|
||||
|
||||
@@ -86,9 +84,7 @@ Functions declared like this are more cumbersome to use when the destination par
|
||||
use std::ops::BitXorAssign;
|
||||
|
||||
fn xor_slice<T>(dst: &mut [T], src: &[T])
|
||||
where
|
||||
T: BitXorAssign + Clone,
|
||||
{
|
||||
where T: BitXorAssign + Clone {
|
||||
assert!(src.len() == dst.len());
|
||||
for (d, s) in dst.iter_mut().zip(src.iter()) {
|
||||
*d ^= s.clone();
|
||||
@@ -118,8 +114,8 @@ assert_eq!(&dst[..], &flip01[..]);
|
||||
There are a couple of ways to use a function with destination:
|
||||
|
||||
```rust
|
||||
use rosenpass_to::ops::{copy_array, copy_slice_least};
|
||||
use rosenpass_to::{to, To};
|
||||
use rosenpass_to::ops::{copy_array, copy_slice_least};
|
||||
|
||||
let mut dst = b" ".to_vec();
|
||||
|
||||
@@ -133,8 +129,7 @@ copy_slice_least(b"This is fin").to(&mut dst[..]);
|
||||
assert_eq!(&dst[..], b"This is fin");
|
||||
|
||||
// You can allocate the destination variable on the fly using `.to_this(...)`
|
||||
let tmp =
|
||||
copy_slice_least(b"This is new---").to_this(|| b"This will be overwritten".to_owned());
|
||||
let tmp = copy_slice_least(b"This is new---").to_this(|| b"This will be overwritten".to_owned());
|
||||
assert_eq!(&tmp[..], b"This is new---verwritten");
|
||||
|
||||
// You can allocate the destination variable on the fly `.collect(..)` if it implements default
|
||||
@@ -152,11 +147,8 @@ assert_eq!(&tmp[..], b"Fixed");
|
||||
The to crate provides basic functions with destination for copying data between slices and arrays.
|
||||
|
||||
```rust
|
||||
use rosenpass_to::ops::{
|
||||
copy_array, copy_slice, copy_slice_least, copy_slice_least_src, try_copy_slice,
|
||||
try_copy_slice_least_src,
|
||||
};
|
||||
use rosenpass_to::{to, To};
|
||||
use rosenpass_to::ops::{copy_array, copy_slice, copy_slice_least, copy_slice_least_src, try_copy_slice, try_copy_slice_least_src};
|
||||
|
||||
let mut dst = b" ".to_vec();
|
||||
|
||||
@@ -169,33 +161,18 @@ to(&mut dst[4..], copy_slice_least_src(b"!!!"));
|
||||
assert_eq!(&dst[..], b"Hell!!!orld");
|
||||
|
||||
// Copy a slice, copying as many bytes as possible
|
||||
to(
|
||||
&mut dst[6..],
|
||||
copy_slice_least(b"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
|
||||
);
|
||||
to(&mut dst[6..], copy_slice_least(b"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
|
||||
assert_eq!(&dst[..], b"Hell!!xxxxx");
|
||||
|
||||
// Copy a slice, will return None and abort if the sizes do not much
|
||||
assert_eq!(Some(()), to(&mut dst[..], try_copy_slice(b"Hello World")));
|
||||
assert_eq!(None, to(&mut dst[..], try_copy_slice(b"---")));
|
||||
assert_eq!(
|
||||
None,
|
||||
to(&mut dst[..], try_copy_slice(b"---------------------"))
|
||||
);
|
||||
assert_eq!(None, to(&mut dst[..], try_copy_slice(b"---------------------")));
|
||||
assert_eq!(&dst[..], b"Hello World");
|
||||
|
||||
// Copy a slice, will return None and abort if source is longer than destination
|
||||
assert_eq!(
|
||||
Some(()),
|
||||
to(&mut dst[4..], try_copy_slice_least_src(b"!!!"))
|
||||
);
|
||||
assert_eq!(
|
||||
None,
|
||||
to(
|
||||
&mut dst[4..],
|
||||
try_copy_slice_least_src(b"-------------------------")
|
||||
)
|
||||
);
|
||||
assert_eq!(Some(()), to(&mut dst[4..], try_copy_slice_least_src(b"!!!")));
|
||||
assert_eq!(None, to(&mut dst[4..], try_copy_slice_least_src(b"-------------------------")));
|
||||
assert_eq!(&dst[..], b"Hell!!!orld");
|
||||
|
||||
// Copy fixed size arrays all at once
|
||||
@@ -209,14 +186,12 @@ assert_eq!(&dst, b"Hello");
|
||||
The easiest way to declare a function with destination is to use the with_destination function.
|
||||
|
||||
```rust
|
||||
use rosenpass_to::{To, to, with_destination};
|
||||
use rosenpass_to::ops::copy_array;
|
||||
use rosenpass_to::{to, with_destination, To};
|
||||
|
||||
/// Copy the given slice to the start of a vector, reusing its memory if possible
|
||||
fn copy_to_vec<'a, T>(src: &'a [T]) -> impl To<Vec<T>, ()> + 'a
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
where T: Clone {
|
||||
with_destination(move |dst: &mut Vec<T>| {
|
||||
dst.clear();
|
||||
dst.extend_from_slice(src);
|
||||
@@ -242,9 +217,7 @@ The same pattern can be implemented without `to`, at the cost of being slightly
|
||||
```rust
|
||||
/// Copy the given slice to the start of a vector, reusing its memory if possible
|
||||
fn copy_to_vec<T>(dst: &mut Vec<T>, src: &[T])
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
where T: Clone {
|
||||
dst.clear();
|
||||
dst.extend_from_slice(src);
|
||||
}
|
||||
@@ -267,11 +240,11 @@ Alternative functions are returned, that return a `to::Beside` value, containing
|
||||
destination variable and the return value.
|
||||
|
||||
```rust
|
||||
use rosenpass_to::{to, with_destination, Beside, To};
|
||||
use std::cmp::{max, min};
|
||||
use std::cmp::{min, max};
|
||||
use rosenpass_to::{To, to, with_destination, Beside};
|
||||
|
||||
/// Copy an array of floats and calculate the average
|
||||
pub fn copy_and_average<'a>(src: &'a [f64]) -> impl To<[f64], f64> + 'a {
|
||||
pub fn copy_and_average<'a>(src: &'a[f64]) -> impl To<[f64], f64> + 'a {
|
||||
with_destination(move |dst: &mut [f64]| {
|
||||
assert!(src.len() == dst.len());
|
||||
let mut sum = 0f64;
|
||||
@@ -327,8 +300,8 @@ assert_eq!(tmp, Beside([42f64; 3], 42f64));
|
||||
When Beside values contain a `()`, `Option<()>`, or `Result<(), Error>` return value, they expose a special method called `.condense()`; this method consumes the Beside value and condenses destination and return value into one value.
|
||||
|
||||
```rust
|
||||
use rosenpass_to::Beside;
|
||||
use std::result::Result;
|
||||
use rosenpass_to::{Beside};
|
||||
|
||||
assert_eq!((), Beside((), ()).condense());
|
||||
|
||||
@@ -345,8 +318,8 @@ assert_eq!(Err(()), Beside(42, err_unit).condense());
|
||||
When condense is implemented for a type, `.to_this(|| ...)`, `.to_value()`, and `.collect::<...>()` on the `To` trait can be used even with a return value:
|
||||
|
||||
```rust
|
||||
use rosenpass_to::ops::try_copy_slice;
|
||||
use rosenpass_to::To;
|
||||
use rosenpass_to::ops::try_copy_slice;;
|
||||
|
||||
let tmp = try_copy_slice(b"Hello World").collect::<[u8; 11]>();
|
||||
assert_eq!(tmp, Some(*b"Hello World"));
|
||||
@@ -364,8 +337,8 @@ assert_eq!(tmp, None);
|
||||
The same naturally also works for Results, but the example is a bit harder to motivate:
|
||||
|
||||
```rust
|
||||
use rosenpass_to::{to, with_destination, To};
|
||||
use std::result::Result;
|
||||
use rosenpass_to::{to, To, with_destination};
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Default)]
|
||||
struct InvalidFloat;
|
||||
@@ -407,8 +380,8 @@ Condensation is implemented through a trait called CondenseBeside ([local](Conde
|
||||
If you can not implement this trait because its for an external type (see [orphan rule](https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type)), this crate welcomes contributions of new Condensation rules.
|
||||
|
||||
```rust
|
||||
use rosenpass_to::{To, with_destination, Beside, CondenseBeside};
|
||||
use rosenpass_to::ops::copy_slice;
|
||||
use rosenpass_to::{with_destination, Beside, CondenseBeside, To};
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Default)]
|
||||
struct MyTuple<Left, Right>(Left, Right);
|
||||
@@ -423,10 +396,7 @@ impl<Val, Right> CondenseBeside<Val> for MyTuple<(), Right> {
|
||||
}
|
||||
|
||||
fn copy_slice_and_return_something<'a, T, U>(src: &'a [T], something: U) -> impl To<[T], U> + 'a
|
||||
where
|
||||
T: Copy,
|
||||
U: 'a,
|
||||
{
|
||||
where T: Copy, U: 'a {
|
||||
with_destination(move |dst: &mut [T]| {
|
||||
copy_slice(src).to(dst);
|
||||
something
|
||||
@@ -447,7 +417,7 @@ Using `with_destination(...)` is convenient, but since it uses closures it resul
|
||||
Implementing the ToTrait manual is the right choice for library use cases.
|
||||
|
||||
```rust
|
||||
use rosenpass_to::{to, with_destination, To};
|
||||
use rosenpass_to::{to, To, with_destination};
|
||||
|
||||
struct TryCopySliceSource<'a, T: Copy> {
|
||||
src: &'a [T],
|
||||
@@ -455,20 +425,17 @@ struct TryCopySliceSource<'a, T: Copy> {
|
||||
|
||||
impl<'a, T: Copy> To<[T], Option<()>> for TryCopySliceSource<'a, T> {
|
||||
fn to(self, dst: &mut [T]) -> Option<()> {
|
||||
(self.src.len() == dst.len()).then(|| dst.copy_from_slice(self.src))
|
||||
(self.src.len() == dst.len())
|
||||
.then(|| dst.copy_from_slice(self.src))
|
||||
}
|
||||
}
|
||||
|
||||
fn try_copy_slice<'a, T>(src: &'a [T]) -> TryCopySliceSource<'a, T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
where T: Copy {
|
||||
TryCopySliceSource { src }
|
||||
}
|
||||
|
||||
let mut dst = try_copy_slice(b"Hello World")
|
||||
.collect::<[u8; 11]>()
|
||||
.unwrap();
|
||||
let mut dst = try_copy_slice(b"Hello World").collect::<[u8; 11]>().unwrap();
|
||||
assert_eq!(&dst[..], b"Hello World");
|
||||
assert_eq!(None, to(&mut dst[..], try_copy_slice(b"---")));
|
||||
```
|
||||
@@ -478,8 +445,8 @@ assert_eq!(None, to(&mut dst[..], try_copy_slice(b"---")));
|
||||
Destinations can also be used with methods. This example demonstrates using destinations in an extension trait for everything that implements `Borrow<[T]>` for any `T` and a concrete `To` trait implementation.
|
||||
|
||||
```rust
|
||||
use rosenpass_to::{to, with_destination, To};
|
||||
use std::borrow::Borrow;
|
||||
use rosenpass_to::{to, To, with_destination};
|
||||
|
||||
struct TryCopySliceSource<'a, T: Copy> {
|
||||
src: &'a [T],
|
||||
@@ -487,24 +454,24 @@ struct TryCopySliceSource<'a, T: Copy> {
|
||||
|
||||
impl<'a, T: Copy> To<[T], Option<()>> for TryCopySliceSource<'a, T> {
|
||||
fn to(self, dst: &mut [T]) -> Option<()> {
|
||||
(self.src.len() == dst.len()).then(|| dst.copy_from_slice(self.src))
|
||||
(self.src.len() == dst.len())
|
||||
.then(|| dst.copy_from_slice(self.src))
|
||||
}
|
||||
}
|
||||
|
||||
trait TryCopySliceExt<'a, T: Copy> {
|
||||
fn try_copy_slice(&'a self) -> TryCopySliceSource<'a, T>;
|
||||
fn try_copy_slice(&'a self) -> TryCopySliceSource<'a, T>;
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Copy, Ref: 'a + Borrow<[T]>> TryCopySliceExt<'a, T> for Ref {
|
||||
fn try_copy_slice(&'a self) -> TryCopySliceSource<'a, T> {
|
||||
TryCopySliceSource { src: self.borrow() }
|
||||
fn try_copy_slice(&'a self) -> TryCopySliceSource<'a, T> {
|
||||
TryCopySliceSource {
|
||||
src: self.borrow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut dst = b"Hello World"
|
||||
.try_copy_slice()
|
||||
.collect::<[u8; 11]>()
|
||||
.unwrap();
|
||||
let mut dst = b"Hello World".try_copy_slice().collect::<[u8; 11]>().unwrap();
|
||||
assert_eq!(&dst[..], b"Hello World");
|
||||
assert_eq!(None, to(&mut dst[..], b"---".try_copy_slice()));
|
||||
```
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{with_destination, To};
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if the two slices have different lengths.
|
||||
pub fn copy_slice<T>(origin: &[T]) -> impl To<[T], ()> + '_
|
||||
pub fn copy_slice<'a, T>(origin: &'a [T]) -> impl To<[T], ()> + 'a
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
@@ -23,7 +23,7 @@ where
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if destination is shorter than origin.
|
||||
pub fn copy_slice_least_src<T>(origin: &[T]) -> impl To<[T], ()> + '_
|
||||
pub fn copy_slice_least_src<'a, T>(origin: &'a [T]) -> impl To<[T], ()> + 'a
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
@@ -34,7 +34,7 @@ where
|
||||
/// destination.
|
||||
///
|
||||
/// Copies as much data as is present in the shorter slice.
|
||||
pub fn copy_slice_least<T>(origin: &[T]) -> impl To<[T], ()> + '_
|
||||
pub fn copy_slice_least<'a, T>(origin: &'a [T]) -> impl To<[T], ()> + 'a
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
@@ -47,7 +47,7 @@ where
|
||||
/// Function with destination that attempts to copy data from origin into the destination.
|
||||
///
|
||||
/// Will return None if the slices are of different lengths.
|
||||
pub fn try_copy_slice<T>(origin: &[T]) -> impl To<[T], Option<()>> + '_
|
||||
pub fn try_copy_slice<'a, T>(origin: &'a [T]) -> impl To<[T], Option<()>> + 'a
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
@@ -62,7 +62,7 @@ where
|
||||
/// Destination may be longer than origin.
|
||||
///
|
||||
/// Will return None if the destination is shorter than origin.
|
||||
pub fn try_copy_slice_least_src<T>(origin: &[T]) -> impl To<[T], Option<()>> + '_
|
||||
pub fn try_copy_slice_least_src<'a, T>(origin: &'a [T]) -> impl To<[T], Option<()>> + 'a
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
@@ -72,7 +72,7 @@ where
|
||||
}
|
||||
|
||||
/// Function with destination that copies all data between two array references.
|
||||
pub fn copy_array<T, const N: usize>(origin: &[T; N]) -> impl To<[T; N], ()> + '_
|
||||
pub fn copy_array<'a, T, const N: usize>(origin: &'a [T; N]) -> impl To<[T; N], ()> + 'a
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
|
||||
@@ -14,5 +14,4 @@ readme = "readme.md"
|
||||
[dependencies]
|
||||
base64 = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
typenum = { workspace = true }
|
||||
static_assertions = { workspace = true }
|
||||
rustix = { workspace = true }
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
use std::os::fd::{OwnedFd, RawFd};
|
||||
|
||||
/// Clone some file descriptor
|
||||
///
|
||||
/// If the file descriptor is invalid, an error will be raised.
|
||||
pub fn claim_fd(fd: RawFd) -> anyhow::Result<OwnedFd> {
|
||||
use rustix::{fd::BorrowedFd, io::dup};
|
||||
|
||||
// This is safe since [dup] will simply raise
|
||||
let fd = unsafe { dup(BorrowedFd::borrow_raw(fd))? };
|
||||
Ok(fd)
|
||||
}
|
||||
|
||||
@@ -6,21 +6,21 @@ use std::{fs::OpenOptions, path::Path};
|
||||
|
||||
/// Open a file writable
|
||||
pub fn fopen_w<P: AsRef<Path>>(path: P) -> std::io::Result<File> {
|
||||
OpenOptions::new()
|
||||
Ok(OpenOptions::new()
|
||||
.read(false)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(path)
|
||||
.open(path)?)
|
||||
}
|
||||
/// Open a file readable
|
||||
pub fn fopen_r<P: AsRef<Path>>(path: P) -> std::io::Result<File> {
|
||||
OpenOptions::new()
|
||||
Ok(OpenOptions::new()
|
||||
.read(true)
|
||||
.write(false)
|
||||
.create(false)
|
||||
.truncate(false)
|
||||
.open(path)
|
||||
.open(path)?)
|
||||
}
|
||||
|
||||
pub trait ReadExactToEnd {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
pub mod b64;
|
||||
pub mod fd;
|
||||
pub mod file;
|
||||
@@ -8,4 +6,3 @@ pub mod mem;
|
||||
pub mod ord;
|
||||
pub mod result;
|
||||
pub mod time;
|
||||
pub mod typenum;
|
||||
|
||||
@@ -35,30 +35,25 @@ pub trait GuaranteedValue {
|
||||
/// ```
|
||||
/// use std::num::Wrapping;
|
||||
/// use std::result::Result;
|
||||
/// use std::convert::Infallible;
|
||||
/// use std::ops::Add;
|
||||
/// use std::convert::Infallible
|
||||
///
|
||||
/// use rosenpass_util::result::{Guaranteed, GuaranteedValue};
|
||||
///
|
||||
/// trait FailableAddition: Sized {
|
||||
/// trait FailableAddition {
|
||||
/// type Error;
|
||||
/// fn failable_addition(&self, other: &Self) -> Result<Self, Self::Error>;
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
/// struct OverflowError;
|
||||
///
|
||||
/// impl<T> FailableAddition for Wrapping<T>
|
||||
/// where for <'a> &'a Wrapping<T>: Add<Output = Wrapping<T>> {
|
||||
/// impl<T> FailableAddition for Wrapping<T> {
|
||||
/// type Error = Infallible;
|
||||
/// fn failable_addition(&self, other: &Self) -> Guaranteed<Self> {
|
||||
/// Ok(self + other)
|
||||
/// self + other
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl FailableAddition for u32 {
|
||||
/// type Error = OverflowError;
|
||||
/// fn failable_addition(&self, other: &Self) -> Result<Self, Self::Error> {
|
||||
/// impl<T> FailableAddition for u32 {
|
||||
/// type Error = Infallible;
|
||||
/// fn failable_addition(&self, other: &Self) -> Guaranteed<Self> {
|
||||
/// match self.checked_add(*other) {
|
||||
/// Some(v) => Ok(v),
|
||||
/// None => Err(OverflowError),
|
||||
@@ -69,11 +64,10 @@ pub trait GuaranteedValue {
|
||||
/// fn failable_multiply<T>(a: &T, b: u32)
|
||||
/// -> Result<T, T::Error>
|
||||
/// where
|
||||
/// T: FailableAddition {
|
||||
/// assert!(b >= 2); // Acceptable only because this is for demonstration purposes
|
||||
/// T: FailableAddition<Error> {
|
||||
/// let mut accu = a.failable_addition(a)?;
|
||||
/// for _ in 2..b {
|
||||
/// accu = accu.failable_addition(a)?;
|
||||
/// for _ in ..(b-1) {
|
||||
/// accu.failable_addition(a)?;
|
||||
/// }
|
||||
/// Ok(accu)
|
||||
/// }
|
||||
@@ -81,12 +75,12 @@ pub trait GuaranteedValue {
|
||||
/// // We can use .guaranteed() with Wrapping<u32>, since the operation uses
|
||||
/// // the Infallible error type.
|
||||
/// // We can also use unwrap which just happens to not raise an error.
|
||||
/// assert_eq!(failable_multiply(&Wrapping(42u32), 3).guaranteed(), Wrapping(126));
|
||||
/// assert_eq!(failable_multiply(&Wrapping(42u32), 3).unwrap(), Wrapping(126));
|
||||
/// assert_eq!(failable_multiply(&Wrapping::new(42u32), 3).guaranteed(), 126);
|
||||
/// assert_eq!(failable_multiply(&Wrapping::new(42u32), 3).unwrap(), 126);
|
||||
///
|
||||
/// // We can not use .guaranteed() with u32, since there can be an error.
|
||||
/// // We can however use unwrap(), which may panic
|
||||
/// //assert_eq!(failable_multiply(&42u32, 3).guaranteed(), 126); // COMPILER ERROR
|
||||
/// assert_eq!(failable_multiply(&42u32, 3).guaranteed(), 126); // COMPILER ERROR
|
||||
/// assert_eq!(failable_multiply(&42u32, 3).unwrap(), 126);
|
||||
/// ```
|
||||
pub type Guaranteed<T> = Result<T, Infallible>;
|
||||
|
||||
@@ -1,341 +0,0 @@
|
||||
use typenum::bit::{B0, B1};
|
||||
use typenum::int::{NInt, PInt, Z0};
|
||||
use typenum::marker_traits as markers;
|
||||
use typenum::uint::{UInt, UTerm};
|
||||
|
||||
/// Convenience macro to convert type numbers to constant integers
|
||||
#[macro_export]
|
||||
macro_rules! typenum2const {
|
||||
($val:ty) => {
|
||||
typenum2const!($val as _)
|
||||
};
|
||||
($val:ty as $type:ty) => {
|
||||
<$val as $crate::typenum::IntoConst<$type>>::VALUE
|
||||
};
|
||||
}
|
||||
|
||||
/// Trait implemented by constant integers to facilitate conversion to constant integers
|
||||
pub trait IntoConst<T> {
|
||||
const VALUE: T;
|
||||
}
|
||||
|
||||
struct ConstApplyNegSign<T: AssociatedUnsigned, Param: IntoConst<<T as AssociatedUnsigned>::Type>>(
|
||||
*const T,
|
||||
*const Param,
|
||||
);
|
||||
struct ConstApplyPosSign<T: AssociatedUnsigned, Param: IntoConst<<T as AssociatedUnsigned>::Type>>(
|
||||
*const T,
|
||||
*const Param,
|
||||
);
|
||||
struct ConstLshift<T, Param: IntoConst<T>, const SHIFT: i32>(*const T, *const Param); // impl IntoConst<T>
|
||||
struct ConstAdd<T, Lhs: IntoConst<T>, Rhs: IntoConst<T>>(*const T, *const Lhs, *const Rhs); // impl IntoConst<T>
|
||||
|
||||
/// Assigns an unsigned type to a signed type
|
||||
trait AssociatedUnsigned {
|
||||
type Type;
|
||||
}
|
||||
|
||||
macro_rules! impl_into_const {
|
||||
( $from:ty as $to:ty := $impl:expr) => {
|
||||
impl IntoConst<$to> for $from {
|
||||
const VALUE: $to = $impl;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_numeric_into_const_common {
|
||||
($type:ty) => {
|
||||
impl_into_const! { Z0 as $type := 0 }
|
||||
impl_into_const! { B0 as $type := 0 }
|
||||
impl_into_const! { B1 as $type := 1 }
|
||||
impl_into_const! { UTerm as $type := 0 }
|
||||
|
||||
impl<Param: IntoConst<$type>, const SHIFT: i32> IntoConst<$type>
|
||||
for ConstLshift<$type, Param, SHIFT>
|
||||
{
|
||||
const VALUE: $type = Param::VALUE << SHIFT;
|
||||
}
|
||||
|
||||
impl<Lhs: IntoConst<$type>, Rhs: IntoConst<$type>> IntoConst<$type>
|
||||
for ConstAdd<$type, Lhs, Rhs>
|
||||
{
|
||||
const VALUE: $type =
|
||||
<Lhs as IntoConst<$type>>::VALUE + <Rhs as IntoConst<$type>>::VALUE;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_numeric_into_const_unsigned {
|
||||
($($to_list:ty),*) => {
|
||||
$( impl_numeric_into_const_unsigned! { @impl $to_list } )*
|
||||
};
|
||||
|
||||
(@impl $type:ty) => {
|
||||
impl_numeric_into_const_common!{ $type }
|
||||
|
||||
impl AssociatedUnsigned for $type {
|
||||
type Type = $type;
|
||||
}
|
||||
|
||||
impl<Param: IntoConst<$type>> IntoConst<$type> for ConstApplyPosSign<$type, Param> {
|
||||
const VALUE : $type = Param::VALUE;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_numeric_into_const_signed {
|
||||
($($to_list:ty : $unsigned_list:ty),*) => {
|
||||
$( impl_numeric_into_const_signed! { @impl $to_list : $unsigned_list} )*
|
||||
};
|
||||
|
||||
(@impl $type:ty : $unsigned:ty) => {
|
||||
impl_numeric_into_const_common!{ $type }
|
||||
|
||||
impl AssociatedUnsigned for $type {
|
||||
type Type = $unsigned;
|
||||
}
|
||||
|
||||
impl<Param: IntoConst<$unsigned>> IntoConst<$type> for ConstApplyPosSign<$type, Param> {
|
||||
const VALUE : $type = Param::VALUE as $type;
|
||||
}
|
||||
|
||||
impl<Param: IntoConst<$unsigned>> IntoConst<$type> for ConstApplyNegSign<$type, Param> {
|
||||
const VALUE : $type =
|
||||
if Param::VALUE == (1 as $unsigned).rotate_right(1) {
|
||||
// Handle the negative value without an associated positive value (e.g. -128
|
||||
// for i8)
|
||||
< $type >::MIN
|
||||
} else {
|
||||
-(Param::VALUE as $type)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_into_const! { B0 as bool := false }
|
||||
impl_into_const! { B1 as bool := true }
|
||||
impl_numeric_into_const_unsigned! { usize, u8, u16, u32, u64, u128 }
|
||||
impl_numeric_into_const_signed! { isize : usize, i8 : u8, i16 : u16, i32 : u32, i64 : u64, i128 : u128 }
|
||||
|
||||
// Unsigned type numbers to const integers
|
||||
impl<Ret, Rest, Bit> IntoConst<Ret> for UInt<Rest, Bit>
|
||||
where
|
||||
Rest: IntoConst<Ret>,
|
||||
Bit: IntoConst<Ret>,
|
||||
ConstLshift<Ret, Rest, 1>: IntoConst<Ret>,
|
||||
ConstAdd<Ret, ConstLshift<Ret, Rest, 1>, Bit>: IntoConst<Ret>,
|
||||
{
|
||||
const VALUE: Ret = <ConstAdd<Ret, ConstLshift<Ret, Rest, 1>, Bit> as IntoConst<Ret>>::VALUE;
|
||||
}
|
||||
|
||||
// Signed type numbers with positive sign to const integers
|
||||
impl<Ret, Unsigned> IntoConst<Ret> for PInt<Unsigned>
|
||||
where
|
||||
Ret: AssociatedUnsigned,
|
||||
Unsigned: markers::Unsigned + markers::NonZero + IntoConst<<Ret as AssociatedUnsigned>::Type>,
|
||||
ConstApplyPosSign<Ret, Unsigned>: IntoConst<Ret>,
|
||||
{
|
||||
const VALUE: Ret = <ConstApplyPosSign<Ret, Unsigned> as IntoConst<Ret>>::VALUE;
|
||||
}
|
||||
|
||||
// Signed type numbers with negative sign to const integers
|
||||
impl<Ret, Unsigned> IntoConst<Ret> for NInt<Unsigned>
|
||||
where
|
||||
Ret: AssociatedUnsigned,
|
||||
Unsigned: markers::Unsigned + markers::NonZero + IntoConst<<Ret as AssociatedUnsigned>::Type>,
|
||||
ConstApplyNegSign<Ret, Unsigned>: IntoConst<Ret>,
|
||||
{
|
||||
const VALUE: Ret = <ConstApplyNegSign<Ret, Unsigned> as IntoConst<Ret>>::VALUE;
|
||||
}
|
||||
|
||||
mod test {
|
||||
use static_assertions::const_assert_eq;
|
||||
use typenum::consts::*;
|
||||
use typenum::op;
|
||||
|
||||
macro_rules! test_const_conversion {
|
||||
// Type groups
|
||||
|
||||
(($($typenum:ty),*) >= u7 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as (u8, u16, u32, u64, u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as (i8, i16, i32, i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= u8 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as (u8, u16, u32, u64, u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as ( i16, i32, i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= u15 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( u16, u32, u64, u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as ( i16, i32, i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= u16 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( u16, u32, u64, u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as ( i32, i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= u31 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( u32, u64, u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as ( i32, i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= u32 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( u32, u64, u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as ( i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= u63 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( u64, u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as ( i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= u64 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( u64, u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as ( i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= u127 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as ( i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= u128 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( u128) = $const } )*
|
||||
$( test_const_conversion! { ($typenum) as ( ) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= i8 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as (i8, i16, i32, i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= i16 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( i16, i32, i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= i32 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( i32, i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= i64 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( i64, i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) >= i128 = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { ($typenum) as ( i128) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
// Basic operation
|
||||
|
||||
() => {};
|
||||
|
||||
(($($typenum:ty),*) as () = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) as ($type:ty) = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { @impl ($typenum) as ($type) = $const } )*
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(($($typenum:ty),*) as ($type_head:ty, $($type_tail:ty),*) = $const:expr $(; $($rest:tt)*)?) => {
|
||||
$( test_const_conversion! { @impl ($typenum) as ($type_head) = $const } )*
|
||||
test_const_conversion! { ($($typenum),*) as ($($type_tail),*) = $const }
|
||||
$( test_const_conversion! { $($rest)* } )?
|
||||
};
|
||||
|
||||
(@impl ($typenum:ty) as ($type:ty) = $const:expr $(; $($rest:tt)*)?) => {
|
||||
const_assert_eq!(typenum2const!($typenum as $type), $const);
|
||||
$( test_const_conversion!($($rest)*); )?
|
||||
};
|
||||
}
|
||||
|
||||
test_const_conversion! {
|
||||
(B0, False) as (bool, bool) = false;
|
||||
|
||||
(B0, U0, Z0) >= u7 = 0;
|
||||
(B1, U1, P1) >= u7 = 1;
|
||||
|
||||
(U2, P2) >= u7 = 2;
|
||||
(B1, True) as (bool) = true;
|
||||
(U3, P3) >= u7 = 3;
|
||||
(U8, P8) >= u7 = 8;
|
||||
(U127, P127) >= u7 = 127;
|
||||
(U220, P220) >= u8 = 220;
|
||||
(U255, P255) >= u8 = 255;
|
||||
(U1000, P1000) >= u15 = 1000;
|
||||
(U10000, P10000) >= u15 = 10000;
|
||||
(U16384, P16384) >= u15 = 16384;
|
||||
(U32768, P32768) >= u16 = 32768;
|
||||
(U65536, P65536) >= u31 = 65536;
|
||||
(U100000, P100000) >= u31 = 100000;
|
||||
(U1000000000, P1000000000) >= u31 = 1000000000;
|
||||
(U2147483648, P2147483648) >= u32 = 2147483648;
|
||||
(U1000000000000000000, P1000000000000000000) >= u63 = 1000000000000000000;
|
||||
(U1000000000000000000, P1000000000000000000) >= u63 = 1000000000000000000;
|
||||
|
||||
(U9223372036854775808) >= u64 = 9223372036854775808;
|
||||
(U10000000000000000000) >= u64 = 10000000000000000000;
|
||||
|
||||
(N10000) >= i16 = -10000;
|
||||
(N1000000) >= i32 = -1000000;
|
||||
(N1000000000) >= i32 = -1000000000;
|
||||
(N1000000000000) >= i64 = -1000000000000;
|
||||
}
|
||||
|
||||
const_assert_eq!(127, (!(1u8.rotate_right(1)) - 0) as _);
|
||||
const_assert_eq!(126, (!(1u8.rotate_right(1)) - 1) as _);
|
||||
const_assert_eq!(255, (!(0u8.rotate_right(1)) - 0) as _);
|
||||
const_assert_eq!(254, (!(0u8.rotate_right(1)) - 1) as _);
|
||||
|
||||
test_const_conversion! {
|
||||
(op!(pow(U2, U7) - U1)) >= u7 = (!(1u8.rotate_right(1)) - 0) as _;
|
||||
(op!(pow(U2, U7) - U2)) >= u7 = (!(1u8.rotate_right(1)) - 1) as _;
|
||||
(op!(pow(U2, U15) - U1)) >= u15 = (!(1u16.rotate_right(1)) - 0) as _;
|
||||
(op!(pow(U2, U15) - U2)) >= u15 = (!(1u16.rotate_right(1)) - 1) as _;
|
||||
(op!(pow(U2, U31) - U1)) >= u31 = (!(1u32.rotate_right(1)) - 0) as _;
|
||||
(op!(pow(U2, U31) - U2)) >= u31 = (!(1u32.rotate_right(1)) - 1) as _;
|
||||
(op!(pow(U2, U63) - U1)) >= u63 = (!(1u64.rotate_right(1)) - 0) as _;
|
||||
(op!(pow(U2, U63) - U2)) >= u63 = (!(1u64.rotate_right(1)) - 1) as _;
|
||||
(op!(pow(U2, U127) - U1)) >= u127 = (!(1u128.rotate_right(1)) - 0) as _;
|
||||
(op!(pow(U2, U127) - U2)) >= u127 = (!(1u128.rotate_right(1)) - 1) as _;
|
||||
|
||||
(op!(pow(U2, U8) - U1)) >= u8 = (u8::MAX - 0) as _;
|
||||
(op!(pow(U2, U8) - U2)) >= u8 = (u8::MAX - 1) as _;
|
||||
(op!(pow(U2, U16) - U1)) >= u16 = (u16::MAX - 0) as _;
|
||||
(op!(pow(U2, U16) - U2)) >= u16 = (u16::MAX - 1) as _;
|
||||
(op!(pow(U2, U32) - U1)) >= u32 = (u32::MAX - 0) as _;
|
||||
(op!(pow(U2, U32) - U2)) >= u32 = (u32::MAX - 1) as _;
|
||||
(op!(pow(U2, U64) - U1)) >= u64 = (u64::MAX - 0) as _;
|
||||
(op!(pow(U2, U64) - U2)) >= u64 = (u64::MAX - 1) as _;
|
||||
(op!(pow(U2, U128) - U1)) >= u128 = (u128::MAX - 0) as _;
|
||||
(op!(pow(U2, U128) - U2)) >= u128 = (u128::MAX - 1) as _;
|
||||
|
||||
(op!(Z0 - pow(P2, P7) + Z0)) >= i8 = (i8::MIN + 0) as _;
|
||||
(op!(Z0 - pow(P2, P7) + P1)) >= i8 = (i8::MIN + 1) as _;
|
||||
(op!(Z0 - pow(P2, P15) + Z0)) >= i16 = (i16::MIN + 0) as _;
|
||||
(op!(Z0 - pow(P2, P15) + P1)) >= i16 = (i16::MIN + 1) as _;
|
||||
(op!(Z0 - pow(P2, P31) + Z0)) >= i32 = (i32::MIN + 0) as _;
|
||||
(op!(Z0 - pow(P2, P31) + P1)) >= i32 = (i32::MIN + 1) as _;
|
||||
(op!(Z0 - pow(P2, P63) + Z0)) >= i64 = (i64::MIN + 0) as _;
|
||||
(op!(Z0 - pow(P2, P63) + P1)) >= i64 = (i64::MIN + 1) as _;
|
||||
(op!(Z0 - pow(P2, P127) + Z0)) >= i128 = (i128::MIN + 0) as _;
|
||||
(op!(Z0 - pow(P2, P127) + P1)) >= i128 = (i128::MIN + 1) as _;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ wireguard-uapi = { workspace = true }
|
||||
|
||||
# Socket handler only
|
||||
rosenpass-to = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
env_logger = { workspace = true }
|
||||
|
||||
@@ -17,7 +17,7 @@ pub struct MioBrokerClient {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MioBrokerClientIo {
|
||||
socket: mio::net::TcpStream,
|
||||
socket: mio::net::UnixStream,
|
||||
send_buf: VecDeque<u8>,
|
||||
receiving_size: bool,
|
||||
recv_buf: Vec<u8>,
|
||||
@@ -25,7 +25,7 @@ struct MioBrokerClientIo {
|
||||
}
|
||||
|
||||
impl MioBrokerClient {
|
||||
pub fn new(socket: mio::net::TcpStream) -> Self {
|
||||
pub fn new(socket: mio::net::UnixStream) -> Self {
|
||||
let io = MioBrokerClientIo {
|
||||
socket,
|
||||
send_buf: VecDeque::new(),
|
||||
@@ -155,7 +155,7 @@ impl MioBrokerClientIo {
|
||||
}
|
||||
}
|
||||
|
||||
fn raw_send(mut socket: &mio::net::TcpStream, data: &[u8]) -> anyhow::Result<usize> {
|
||||
fn raw_send(mut socket: &mio::net::UnixStream, data: &[u8]) -> anyhow::Result<usize> {
|
||||
let mut off = 0;
|
||||
|
||||
socket.try_io(|| {
|
||||
@@ -179,7 +179,7 @@ fn raw_send(mut socket: &mio::net::TcpStream, data: &[u8]) -> anyhow::Result<usi
|
||||
return Ok(off);
|
||||
}
|
||||
|
||||
fn raw_recv(mut socket: &mio::net::TcpStream, out: &mut [u8]) -> anyhow::Result<usize> {
|
||||
fn raw_recv(mut socket: &mio::net::UnixStream, out: &mut [u8]) -> anyhow::Result<usize> {
|
||||
let mut off = 0;
|
||||
|
||||
socket.try_io(|| {
|
||||
|
||||
@@ -12,3 +12,4 @@ pub trait WireGuardBroker {
|
||||
}
|
||||
|
||||
pub mod api;
|
||||
pub mod netlink;
|
||||
|
||||
103
wireguard-broker/src/netlink.rs
Normal file
103
wireguard-broker/src/netlink.rs
Normal file
@@ -0,0 +1,103 @@
|
||||
use wireguard_uapi::linux as wg;
|
||||
|
||||
use crate::api::msgs;
|
||||
use crate::WireGuardBroker;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum ConnectError {
|
||||
#[error(transparent)]
|
||||
ConnectError(#[from] wg::err::ConnectError),
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum NetlinkError {
|
||||
#[error(transparent)]
|
||||
SetDevice(#[from] wg::err::SetDeviceError),
|
||||
#[error(transparent)]
|
||||
GetDevice(#[from] wg::err::GetDeviceError),
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum SetPskError {
|
||||
#[error("The indicated wireguard interface does not exist")]
|
||||
NoSuchInterface,
|
||||
#[error("The indicated peer does not exist on the wireguard interface")]
|
||||
NoSuchPeer,
|
||||
#[error(transparent)]
|
||||
NetlinkError(#[from] NetlinkError),
|
||||
}
|
||||
|
||||
impl From<wg::err::SetDeviceError> for SetPskError {
|
||||
fn from(err: wg::err::SetDeviceError) -> Self {
|
||||
NetlinkError::from(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wg::err::GetDeviceError> for SetPskError {
|
||||
fn from(err: wg::err::GetDeviceError) -> Self {
|
||||
NetlinkError::from(err).into()
|
||||
}
|
||||
}
|
||||
|
||||
use msgs::SetPskError as SetPskMsgsError;
|
||||
use SetPskError as SetPskNetlinkError;
|
||||
impl From<SetPskNetlinkError> for SetPskMsgsError {
|
||||
fn from(err: SetPskError) -> Self {
|
||||
match err {
|
||||
SetPskNetlinkError::NoSuchPeer => SetPskMsgsError::NoSuchPeer,
|
||||
_ => SetPskMsgsError::InternalError,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NetlinkWireGuardBroker {
|
||||
sock: wg::WgSocket,
|
||||
}
|
||||
|
||||
impl NetlinkWireGuardBroker {
|
||||
pub fn new() -> Result<Self, ConnectError> {
|
||||
let sock = wg::WgSocket::connect()?;
|
||||
Ok(Self { sock })
|
||||
}
|
||||
}
|
||||
|
||||
impl WireGuardBroker for NetlinkWireGuardBroker {
|
||||
type Error = SetPskError;
|
||||
|
||||
fn set_psk(
|
||||
&mut self,
|
||||
interface: &str,
|
||||
peer_id: [u8; 32],
|
||||
psk: [u8; 32],
|
||||
) -> Result<(), Self::Error> {
|
||||
// Ensure that the peer exists by querying the device configuration
|
||||
// TODO: Use InvalidInterfaceError
|
||||
let state = self
|
||||
.sock
|
||||
.get_device(wg::DeviceInterface::from_name(interface.to_owned()))?;
|
||||
|
||||
if state
|
||||
.peers
|
||||
.iter()
|
||||
.find(|p| &p.public_key == &peer_id)
|
||||
.is_none()
|
||||
{
|
||||
return Err(SetPskError::NoSuchPeer);
|
||||
}
|
||||
|
||||
// Peer update description
|
||||
let mut set_peer = wireguard_uapi::set::Peer::from_public_key(&peer_id);
|
||||
set_peer
|
||||
.flags
|
||||
.push(wireguard_uapi::linux::set::WgPeerF::UpdateOnly);
|
||||
set_peer.preshared_key = Some(&psk);
|
||||
|
||||
// Device update description
|
||||
let mut set_dev = wireguard_uapi::set::Device::from_ifname(interface.to_owned());
|
||||
set_dev.peers.push(set_peer);
|
||||
|
||||
self.sock.set_device(set_dev)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user