mirror of
https://github.com/rosenpass/rosenpass.git
synced 2026-02-28 14:33:37 -08:00
Compare commits
1 Commits
regression
...
dev/karo/h
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64c2cf60fe |
@@ -1,33 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
iterations=$1
|
|
||||||
sleep_time=$2
|
|
||||||
|
|
||||||
PWD=$(pwd)
|
|
||||||
EXEC=$PWD/target/release/rosenpass
|
|
||||||
LOGS=$PWD/output/logs
|
|
||||||
|
|
||||||
mkdir -p output/logs
|
|
||||||
|
|
||||||
run_command() {
|
|
||||||
local file=$1
|
|
||||||
local log_file="$2"
|
|
||||||
($EXEC exchange-config $file 2>&1 | sed "s/^/[$2] /" | tee -a $log_file) &
|
|
||||||
echo $!
|
|
||||||
}
|
|
||||||
|
|
||||||
pids=()
|
|
||||||
|
|
||||||
(cd output/dut && run_command "configs/dut-$iterations.toml" "dut.log") & piddut=$!
|
|
||||||
for (( x=0; x<$iterations; x++ )); do
|
|
||||||
(cd output/ate && run_command "configs/ate-$x.toml" "ate-$x.log") & pids+=($!)
|
|
||||||
done
|
|
||||||
|
|
||||||
sleep $sleep_time
|
|
||||||
|
|
||||||
lsof -i :9999 | awk 'NR!=1 {print $2}' | xargs kill
|
|
||||||
|
|
||||||
for (( x=0; x<$iterations; x++ )); do
|
|
||||||
port=$((x + 50000))
|
|
||||||
lsof -i :$port | awk 'NR!=1 {print $2}' | xargs kill
|
|
||||||
done
|
|
||||||
8
.github/workflows/qc.yaml
vendored
8
.github/workflows/qc.yaml
vendored
@@ -176,12 +176,8 @@ jobs:
|
|||||||
cargo fuzz run fuzz_handle_msg -- -max_total_time=5
|
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
|
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_mceliece_encaps -- -max_total_time=5
|
||||||
cargo fuzz run fuzz_box_secret_alloc_malloc -- -max_total_time=5
|
cargo fuzz run fuzz_box_secret_alloc -- -max_total_time=5
|
||||||
cargo fuzz run fuzz_box_secret_alloc_memfdsec -- -max_total_time=5
|
cargo fuzz run fuzz_vec_secret_alloc -- -max_total_time=5
|
||||||
cargo fuzz run fuzz_box_secret_alloc_memfdsec_mallocfb -- -max_total_time=5
|
|
||||||
cargo fuzz run fuzz_vec_secret_alloc_malloc -- -max_total_time=5
|
|
||||||
cargo fuzz run fuzz_vec_secret_alloc_memfdsec -- -max_total_time=5
|
|
||||||
cargo fuzz run fuzz_vec_secret_alloc_memfdsec_mallocfb -- -max_total_time=5
|
|
||||||
|
|
||||||
codecov:
|
codecov:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
19
.github/workflows/regressions.yml
vendored
19
.github/workflows/regressions.yml
vendored
@@ -1,19 +0,0 @@
|
|||||||
name: QC
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
checks: write
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
multi-peer:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- run: cargo build --bin rosenpass --release
|
|
||||||
- run: python misc/generate_configs.py
|
|
||||||
- run: chmod +x .ci/run-regression.sh
|
|
||||||
- run: .ci/run-regression.sh 100 20
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -20,5 +20,3 @@ _markdown_*
|
|||||||
**/result
|
**/result
|
||||||
**/result-*
|
**/result-*
|
||||||
.direnv
|
.direnv
|
||||||
|
|
||||||
/output
|
|
||||||
487
Cargo.lock
generated
487
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
24
Cargo.toml
24
Cargo.toml
@@ -12,10 +12,14 @@ members = [
|
|||||||
"fuzz",
|
"fuzz",
|
||||||
"secret-memory",
|
"secret-memory",
|
||||||
"rp",
|
"rp",
|
||||||
"wireguard-broker",
|
"wireguard-broker"
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = ["rosenpass", "rp", "wireguard-broker"]
|
default-members = [
|
||||||
|
"rosenpass",
|
||||||
|
"rp",
|
||||||
|
"wireguard-broker",
|
||||||
|
]
|
||||||
|
|
||||||
[workspace.metadata.release]
|
[workspace.metadata.release]
|
||||||
# ensure that adding `--package` as argument to `cargo release` still creates version tags in the form of `vx.y.z`
|
# ensure that adding `--package` as argument to `cargo release` still creates version tags in the form of `vx.y.z`
|
||||||
@@ -41,24 +45,18 @@ env_logger = "0.10.2"
|
|||||||
toml = "0.7.8"
|
toml = "0.7.8"
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
allocator-api2 = "0.2.14"
|
allocator-api2 = "0.2.14"
|
||||||
memsec = { git="https://github.com/rosenpass/memsec.git" ,rev="aceb9baee8aec6844125bd6612f92e9a281373df", features = [ "alloc_ext", ] }
|
memsec = "0.6.3"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
typenum = "1.17.0"
|
typenum = "1.17.0"
|
||||||
log = { version = "0.4.21" }
|
log = { version = "0.4.21" }
|
||||||
clap = { version = "4.5.7", features = ["derive"] }
|
clap = { version = "4.5.6", features = ["derive"] }
|
||||||
serde = { version = "1.0.203", features = ["derive"] }
|
serde = { version = "1.0.203", features = ["derive"] }
|
||||||
arbitrary = { version = "1.3.2", features = ["derive"] }
|
arbitrary = { version = "1.3.2", features = ["derive"] }
|
||||||
anyhow = { version = "1.0.86", features = ["backtrace", "std"] }
|
anyhow = { version = "1.0.86", features = ["backtrace", "std"] }
|
||||||
mio = { version = "0.8.11", features = ["net", "os-poll"] }
|
mio = { version = "0.8.11", features = ["net", "os-poll"] }
|
||||||
oqs-sys = { version = "0.9.1", default-features = false, features = [
|
oqs-sys = { version = "0.9.1", default-features = false, features = ['classic_mceliece', 'kyber'] }
|
||||||
'classic_mceliece',
|
|
||||||
'kyber',
|
|
||||||
] }
|
|
||||||
blake2 = "0.10.6"
|
blake2 = "0.10.6"
|
||||||
chacha20poly1305 = { version = "0.10.1", default-features = false, features = [
|
chacha20poly1305 = { version = "0.10.1", default-features = false, features = [ "std", "heapless" ] }
|
||||||
"std",
|
|
||||||
"heapless",
|
|
||||||
] }
|
|
||||||
zerocopy = { version = "0.7.34", features = ["derive"] }
|
zerocopy = { version = "0.7.34", features = ["derive"] }
|
||||||
home = "0.5.9"
|
home = "0.5.9"
|
||||||
derive_builder = "0.20.0"
|
derive_builder = "0.20.0"
|
||||||
@@ -73,8 +71,6 @@ libfuzzer-sys = "0.4"
|
|||||||
test_bin = "0.4.0"
|
test_bin = "0.4.0"
|
||||||
criterion = "0.4.0"
|
criterion = "0.4.0"
|
||||||
allocator-api2-tests = "0.2.15"
|
allocator-api2-tests = "0.2.15"
|
||||||
procspawn = {version = "1.0.0", features= ["test-support"]}
|
|
||||||
|
|
||||||
|
|
||||||
#Broker dependencies (might need cleanup or changes)
|
#Broker dependencies (might need cleanup or changes)
|
||||||
wireguard-uapi = "3.0.0"
|
wireguard-uapi = "3.0.0"
|
||||||
|
|||||||
@@ -3,12 +3,33 @@
|
|||||||
#define SESSION_START_EVENTS 0
|
#define SESSION_START_EVENTS 0
|
||||||
#define RANDOMIZED_CALL_IDS 0
|
#define RANDOMIZED_CALL_IDS 0
|
||||||
|
|
||||||
|
|
||||||
#include "config.mpv"
|
#include "config.mpv"
|
||||||
#include "prelude/basic.mpv"
|
#include "prelude/basic.mpv"
|
||||||
#include "crypto/key.mpv"
|
#include "crypto/key.mpv"
|
||||||
#include "crypto/kem.mpv"
|
#include "crypto/kem.mpv"
|
||||||
|
|
||||||
#include "rosenpass/oracles.mpv"
|
#include "rosenpass/oracles.mpv"
|
||||||
|
|
||||||
|
nounif v:seed_prec; attacker(prepare_seed(trusted_seed( v )))/6217[hypothesis].
|
||||||
|
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
|
||||||
|
nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
|
||||||
|
nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
|
||||||
|
nounif v:key_prec; attacker(prepare_key(trusted_key( v )))/6213[hypothesis].
|
||||||
|
nounif v:kem_sk_prec; attacker(prepare_kem_sk(trusted_kem_sk( v )))/6212[hypothesis].
|
||||||
|
nounif v:key; attacker(prepare_key( v ))/6211[hypothesis].
|
||||||
|
nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].
|
||||||
|
nounif Spk:kem_sk_tmpl;
|
||||||
|
attacker(Creveal_kem_pk(Spk))/6110[conclusion].
|
||||||
|
nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
|
||||||
|
attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr ))/6109[conclusion].
|
||||||
|
nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
|
||||||
|
attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/6108[conclusion].
|
||||||
|
nounif rh:RespHello_t;
|
||||||
|
attacker(Cresp_hello( *rh ))/6107[conclusion].
|
||||||
|
nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
|
||||||
|
attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/6106[conclusion].
|
||||||
|
|
||||||
let main = rosenpass_main.
|
let main = rosenpass_main.
|
||||||
|
|
||||||
@lemma "state coherence, initiator: Initiator accepting a RespHello message implies they also generated the associated InitHello message"
|
@lemma "state coherence, initiator: Initiator accepting a RespHello message implies they also generated the associated InitHello message"
|
||||||
|
|||||||
@@ -10,6 +10,26 @@
|
|||||||
|
|
||||||
let main = rosenpass_main.
|
let main = rosenpass_main.
|
||||||
|
|
||||||
|
nounif v:seed_prec; attacker(prepare_seed(trusted_seed( v )))/6217[hypothesis].
|
||||||
|
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
|
||||||
|
nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
|
||||||
|
nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
|
||||||
|
nounif v:key_prec; attacker(prepare_key(trusted_key( v )))/6213[hypothesis].
|
||||||
|
nounif v:kem_sk_prec; attacker(prepare_kem_sk(trusted_kem_sk( v )))/6212[hypothesis].
|
||||||
|
nounif v:key; attacker(prepare_key( v ))/6211[hypothesis].
|
||||||
|
nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].
|
||||||
|
nounif Spk:kem_sk_tmpl;
|
||||||
|
attacker(Creveal_kem_pk(Spk))/6110[conclusion].
|
||||||
|
nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
|
||||||
|
attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr ))/6109[conclusion].
|
||||||
|
nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
|
||||||
|
attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/6108[conclusion].
|
||||||
|
nounif rh:RespHello_t;
|
||||||
|
attacker(Cresp_hello( *rh ))/6107[conclusion].
|
||||||
|
nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
|
||||||
|
attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/6106[conclusion].
|
||||||
|
|
||||||
|
|
||||||
@lemma "non-interruptability: Adv cannot prevent a genuine InitHello message from being accepted"
|
@lemma "non-interruptability: Adv cannot prevent a genuine InitHello message from being accepted"
|
||||||
lemma ih:InitHello_t, psk:key, sski:kem_sk, sskr:kem_sk;
|
lemma ih:InitHello_t, psk:key, sski:kem_sk, sskr:kem_sk;
|
||||||
event(IHRjct(ih, psk, sskr, kem_pub(sski)))
|
event(IHRjct(ih, psk, sskr, kem_pub(sski)))
|
||||||
|
|||||||
@@ -88,6 +88,18 @@ set verboseCompleted=VERBOSE.
|
|||||||
#define SES_EV(...)
|
#define SES_EV(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if COOKIE_EVENTS
|
||||||
|
#define COOKIE_EV(...) __VA_ARGS__
|
||||||
|
#else
|
||||||
|
#define COOKIE_EV(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KEM_EVENTS
|
||||||
|
#define KEM_EV(...) __VA_ARGS__
|
||||||
|
#else
|
||||||
|
#define KEM_EV(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
(* TODO: Authentication timing properties *)
|
(* TODO: Authentication timing properties *)
|
||||||
(* TODO: Proof that every adversary submitted package is equivalent to one generated by the proper algorithm using different coins. This probably requires introducing an oracle that extracts the coins used and explicitly adding the notion of coins used for Packet->Packet steps and an inductive RNG notion. *)
|
(* TODO: Proof that every adversary submitted package is equivalent to one generated by the proper algorithm using different coins. This probably requires introducing an oracle that extracts the coins used and explicitly adding the notion of coins used for Packet->Packet steps and an inductive RNG notion. *)
|
||||||
|
|||||||
@@ -41,23 +41,32 @@ restriction s:seed, p1:Atom, p2:Atom, ad1:Atom, ad2:Atom;
|
|||||||
event(ConsumeSeed(p1, s, ad1)) && event(ConsumeSeed(p2, s, ad2))
|
event(ConsumeSeed(p1, s, ad1)) && event(ConsumeSeed(p2, s, ad2))
|
||||||
==> p1 = p2 && ad1 = ad2.
|
==> p1 = p2 && ad1 = ad2.
|
||||||
|
|
||||||
|
letfun create_mac2(k:key, msg:bits) = prf(k,msg).
|
||||||
|
|
||||||
#include "rosenpass/responder.macro"
|
#include "rosenpass/responder.macro"
|
||||||
fun Cinit_conf(kem_sk_tmpl, key_tmpl, kem_pk_tmpl, InitConf_t) : Atom [data].
|
fun Cinit_conf(kem_sk_tmpl, key_tmpl, kem_pk_tmpl, InitConf_t) : Atom [data].
|
||||||
CK_EV( event OskOinit_conf(key, key). )
|
CK_EV( event OskOinit_conf(key, key). )
|
||||||
MTX_EV( event ICRjct(InitConf_t, key, kem_sk, kem_pk). )
|
MTX_EV( event ICRjct(InitConf_t, key, kem_sk, kem_pk). )
|
||||||
SES_EV( event ResponderSession(InitConf_t, key). )
|
SES_EV( event ResponderSession(InitConf_t, key). )
|
||||||
event ConsumeBiscuit(Atom, kem_sk, kem_pk, Atom).
|
KEM_EV(event Oinit_conf_KemUse(SessionId, SessionId, Atom).)
|
||||||
let Oinit_conf() =
|
#ifdef KEM_EVENTS
|
||||||
in(C, Cinit_conf(Ssskm, Spsk, Sspkt, ic));
|
restriction sidi:SessionId, sidr:SessionId, ad1:Atom, ad2:Atom;
|
||||||
#if RANDOMIZED_CALL_IDS
|
event(Oinit_conf_KemUse(sidi, sidr, ad1)) && event(Oinit_conf_KemUse(sidi, sidr, ad2))
|
||||||
new call:Atom;
|
==> ad1 = ad2.
|
||||||
#else
|
|
||||||
call <- Cinit_conf(Ssskm, Spsk, Sspkt, ic);
|
|
||||||
#endif
|
#endif
|
||||||
|
event ConsumeBiscuit(Atom, kem_sk, kem_pk, Atom).
|
||||||
|
|
||||||
|
fun Ccookie(key, bits) : Atom[data].
|
||||||
|
|
||||||
|
let Oinit_conf_inner(Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t, call:Atom) =
|
||||||
|
|
||||||
SETUP_HANDSHAKE_STATE()
|
SETUP_HANDSHAKE_STATE()
|
||||||
|
|
||||||
eski <- kem_sk0;
|
eski <- kem_sk0;
|
||||||
epki <- kem_pk0;
|
epki <- kem_pk0;
|
||||||
let try_ = (
|
let try_ = (
|
||||||
|
let InitConf(sidi, sidr, biscuit, auth) = ic in
|
||||||
|
KEM_EV(event Oinit_conf_KemUse(sidi, sidr, call);)
|
||||||
INITCONF_CONSUME()
|
INITCONF_CONSUME()
|
||||||
event ConsumeBiscuit(biscuit_no, sskm, spkt, call);
|
event ConsumeBiscuit(biscuit_no, sskm, spkt, call);
|
||||||
CK_EV( event OskOinit_conf(ck_rh, osk); )
|
CK_EV( event OskOinit_conf(ck_rh, osk); )
|
||||||
@@ -73,10 +82,20 @@ let Oinit_conf() =
|
|||||||
#endif
|
#endif
|
||||||
).
|
).
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
Oinit_conf_inner(Ssskm, Spsk, Sspkt, ic, call).
|
||||||
|
|
||||||
restriction biscuit_no:Atom, sskm:kem_sk, spkr:kem_pk, ad1:Atom, ad2:Atom;
|
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))
|
event(ConsumeBiscuit(biscuit_no, sskm, spkr, ad1)) && event(ConsumeBiscuit(biscuit_no, sskm, spkr, ad2))
|
||||||
==> ad1 = ad2.
|
==> ad1 = ad2.
|
||||||
|
|
||||||
// TODO: Restriction biscuit no invalidation
|
// TODO: Restriction biscuit no invalidation
|
||||||
|
|
||||||
#include "rosenpass/initiator.macro"
|
#include "rosenpass/initiator.macro"
|
||||||
@@ -85,11 +104,29 @@ CK_EV( event OskOresp_hello(key, key, key). )
|
|||||||
MTX_EV( event RHRjct(RespHello_t, key, kem_sk, kem_pk). )
|
MTX_EV( event RHRjct(RespHello_t, key, kem_sk, kem_pk). )
|
||||||
MTX_EV( event ICSent(RespHello_t, InitConf_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). )
|
SES_EV( event InitiatorSession(RespHello_t, key). )
|
||||||
let Oresp_hello(HS_DECL_ARGS) =
|
|
||||||
in(C, Cresp_hello(RespHello(sidr, =sidi, ecti, scti, biscuit, auth)));
|
KEM_EV(event Oresp_hello_KemUse(SessionId, SessionId, Atom).)
|
||||||
|
#ifdef KEM_EVENTS
|
||||||
|
restriction sidi:SessionId, sidr:SessionId, ad1:Atom, ad2:Atom;
|
||||||
|
event(Oresp_hello_KemUse(sidi, sidr, ad1)) && event(Oresp_hello_KemUse(sidi, sidr, ad2))
|
||||||
|
==> ad1 = ad2.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef COOKIE_EVENTS
|
||||||
|
COOKIE_EVENTS(Oresp_hello)
|
||||||
|
#endif
|
||||||
|
let Oresp_hello(HS_DECL_ARGS, C_in:channel, call:Atom) =
|
||||||
|
in(C_in, Cresp_hello(RespHello(sidr, =sidi, ecti, scti, biscuit, auth)));
|
||||||
|
in(C_in, mac2_key:key);
|
||||||
rh <- RespHello(sidr, sidi, ecti, scti, biscuit, auth);
|
rh <- RespHello(sidr, sidi, ecti, scti, biscuit, auth);
|
||||||
|
#ifdef COOKIE_EVENTS
|
||||||
|
msg <- RH2b(rh);
|
||||||
|
|
||||||
|
COOKIE_PROCESS(Oresp_hello,
|
||||||
|
#endif
|
||||||
/* try */ let ic = (
|
/* try */ let ic = (
|
||||||
ck_ini <- ck;
|
ck_ini <- ck;
|
||||||
|
KEM_EV(event Oresp_hello_KemUse(sidi, sidr, call);)
|
||||||
RESPHELLO_CONSUME()
|
RESPHELLO_CONSUME()
|
||||||
ck_ih <- ck;
|
ck_ih <- ck;
|
||||||
INITCONF_PRODUCE()
|
INITCONF_PRODUCE()
|
||||||
@@ -98,14 +135,25 @@ let Oresp_hello(HS_DECL_ARGS) =
|
|||||||
SES_EV( event InitiatorSession(rh, osk); )
|
SES_EV( event InitiatorSession(rh, osk); )
|
||||||
ic
|
ic
|
||||||
/* success */ ) in (
|
/* success */ ) in (
|
||||||
out(C, ic)
|
icbits <- IC2b(ic);
|
||||||
|
mac <- create_mac(spkt, icbits);
|
||||||
|
mac2 <- create_mac2(mac2_key, mac_envelope2b(mac));
|
||||||
|
out(C_in, ic);
|
||||||
|
out(C_in, mac);
|
||||||
|
out(C_in, mac2)
|
||||||
|
|
||||||
/* fail */ ) else (
|
/* fail */ ) else (
|
||||||
#if MESSAGE_TRANSMISSION_EVENTS
|
#if MESSAGE_TRANSMISSION_EVENTS
|
||||||
event RHRjct(rh, psk, sski, spkr)
|
event RHRjct(rh, psk, sski, spkr)
|
||||||
#else
|
#else
|
||||||
0
|
0
|
||||||
#endif
|
#endif
|
||||||
).
|
)
|
||||||
|
#ifdef COOKIE_EVENTS
|
||||||
|
)
|
||||||
|
#else
|
||||||
|
.
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO: Restriction: Biscuit no invalidation
|
// TODO: Restriction: Biscuit no invalidation
|
||||||
|
|
||||||
@@ -116,24 +164,33 @@ MTX_EV( event IHRjct(InitHello_t, key, kem_sk, kem_pk). )
|
|||||||
MTX_EV( event RHSent(InitHello_t, RespHello_t, key, kem_sk, kem_pk). )
|
MTX_EV( event RHSent(InitHello_t, RespHello_t, key, kem_sk, kem_pk). )
|
||||||
event ConsumeSidr(SessionId, Atom).
|
event ConsumeSidr(SessionId, Atom).
|
||||||
event ConsumeBn(Atom, kem_sk, kem_pk, Atom).
|
event ConsumeBn(Atom, kem_sk, kem_pk, Atom).
|
||||||
let Oinit_hello() =
|
KEM_EV(event Oinit_hello_KemUse(SessionId, SessionId, Atom).)
|
||||||
in(C, Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih));
|
|
||||||
#if RANDOMIZED_CALL_IDS
|
#ifdef KEM_EVENTS
|
||||||
new call:Atom;
|
restriction sidi:SessionId, sidr:SessionId, ad1:Atom, ad2:Atom;
|
||||||
#else
|
event(Oinit_hello_KemUse(sidi, sidr, ad1)) && event(Oinit_hello_KemUse(sidi, sidr, ad2))
|
||||||
call <- Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih);
|
==> ad1 = ad2.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
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, mac2_key:key, C_out:channel, call:Atom) =
|
||||||
// TODO: This is ugly
|
// TODO: This is ugly
|
||||||
let InitHello(sidi, epki, sctr, pidiC, auth) = ih in
|
let InitHello(sidi, epki, sctr, pidiC, auth) = ih in
|
||||||
|
|
||||||
SETUP_HANDSHAKE_STATE()
|
SETUP_HANDSHAKE_STATE()
|
||||||
|
|
||||||
eski <- kem_sk0;
|
eski <- kem_sk0;
|
||||||
epti <- rng_key(setup_seed(Septi)); // RHR4
|
|
||||||
spti <- rng_key(setup_seed(Sspti)); // RHR5
|
|
||||||
event ConsumeBn(biscuit_no, sskm, spkt, call);
|
event ConsumeBn(biscuit_no, sskm, spkt, call);
|
||||||
event ConsumeSidr(sidr, call);
|
event ConsumeSidr(sidr, call);
|
||||||
|
|
||||||
|
epti <- rng_key(setup_seed(Septi)); // RHR4
|
||||||
|
spti <- rng_key(setup_seed(Sspti)); // RHR5
|
||||||
event ConsumeSeed(Epti, setup_seed(Septi), call);
|
event ConsumeSeed(Epti, setup_seed(Septi), call);
|
||||||
event ConsumeSeed(Spti, setup_seed(Sspti), call);
|
event ConsumeSeed(Spti, setup_seed(Sspti), call);
|
||||||
|
// out(C_out, spkt);
|
||||||
|
|
||||||
let rh = (
|
let rh = (
|
||||||
|
KEM_EV(event Oinit_hello_KemUse(sidi, sidr, call);)
|
||||||
INITHELLO_CONSUME()
|
INITHELLO_CONSUME()
|
||||||
ck_ini <- ck;
|
ck_ini <- ck;
|
||||||
RESPHELLO_PRODUCE()
|
RESPHELLO_PRODUCE()
|
||||||
@@ -141,7 +198,14 @@ let Oinit_hello() =
|
|||||||
MTX_EV( event RHSent(ih, rh, psk, sskr, spki); )
|
MTX_EV( event RHSent(ih, rh, psk, sskr, spki); )
|
||||||
rh
|
rh
|
||||||
/* success */ ) in (
|
/* success */ ) in (
|
||||||
out(C, rh)
|
rhbits <- RH2b(rh);
|
||||||
|
mac <- create_mac(spkt, rhbits);
|
||||||
|
|
||||||
|
out(C_out, rh);
|
||||||
|
out(C_out, mac);
|
||||||
|
mac2 <- create_mac2(mac2_key, mac_envelope2b(mac));
|
||||||
|
out(C_out, mac2)
|
||||||
|
|
||||||
/* fail */ ) else (
|
/* fail */ ) else (
|
||||||
#if MESSAGE_TRANSMISSION_EVENTS
|
#if MESSAGE_TRANSMISSION_EVENTS
|
||||||
event IHRjct(ih, psk, sskr, spki)
|
event IHRjct(ih, psk, sskr, spki)
|
||||||
@@ -150,6 +214,18 @@ let Oinit_hello() =
|
|||||||
#endif
|
#endif
|
||||||
).
|
).
|
||||||
|
|
||||||
|
let Oinit_hello() =
|
||||||
|
in(C, Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih));
|
||||||
|
in(C, mac2_key:key);
|
||||||
|
|
||||||
|
#if RANDOMIZED_CALL_IDS
|
||||||
|
new call:Atom;
|
||||||
|
#else
|
||||||
|
call <- Cinit_hello(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Oinit_hello_inner(sidr, biscuit_no, Ssskm, Spsk, Sspkt, Septi, Sspti, ih, mac2_key, C, call).
|
||||||
|
|
||||||
restriction sid:SessionId, ad1:Atom, ad2:Atom;
|
restriction sid:SessionId, ad1:Atom, ad2:Atom;
|
||||||
event(ConsumeSidr(sid, ad1)) && event(ConsumeSidr(sid, ad2))
|
event(ConsumeSidr(sid, ad1)) && event(ConsumeSidr(sid, ad2))
|
||||||
==> ad1 = ad2.
|
==> ad1 = ad2.
|
||||||
@@ -166,27 +242,55 @@ fun Cinitiator(SessionId, kem_sk_tmpl, key_tmpl, kem_pk_tmpl, seed_tmpl, seed_tm
|
|||||||
CK_EV( event OskOinitiator_ck(key). )
|
CK_EV( event OskOinitiator_ck(key). )
|
||||||
CK_EV( event OskOinitiator(key, key, kem_sk, kem_pk, key). )
|
CK_EV( event OskOinitiator(key, key, kem_sk, kem_pk, key). )
|
||||||
MTX_EV( event IHSent(InitHello_t, key, kem_sk, kem_pk). )
|
MTX_EV( event IHSent(InitHello_t, key, kem_sk, kem_pk). )
|
||||||
|
KEM_EV(event Oinitiator_inner_KemUse(SessionId, SessionId, Atom).)
|
||||||
|
|
||||||
|
#ifdef KEM_EVENTS
|
||||||
|
restriction sidi:SessionId, sidr:SessionId, ad1:Atom, ad2:Atom;
|
||||||
|
event(Oinitiator_inner_KemUse(sidi, sidr, ad1)) && event(Oinitiator_inner_KemUse(sidi, sidr, ad2))
|
||||||
|
==> ad1 = ad2.
|
||||||
|
#endif
|
||||||
event ConsumeSidi(SessionId, Atom).
|
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, last_cookie:key, C_out:channel, call:Atom) =
|
||||||
|
|
||||||
|
SETUP_HANDSHAKE_STATE()
|
||||||
|
sidr <- sid0;
|
||||||
|
|
||||||
|
KEM_EV(event Oinitiator_inner_KemUse(sidi, sidr, call);)
|
||||||
|
|
||||||
|
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, ih);
|
||||||
|
ihbits <- IH2b(ih);
|
||||||
|
mac <- create_mac(spkt, ihbits);
|
||||||
|
out(C_out, mac);
|
||||||
|
mac2 <- create_mac2(last_cookie, mac_envelope2b(mac));
|
||||||
|
out(C_out, mac2);
|
||||||
|
|
||||||
|
Oresp_hello(HS_PASS_ARGS, C_out, call).
|
||||||
|
|
||||||
let Oinitiator() =
|
let Oinitiator() =
|
||||||
|
|
||||||
in(C, Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr));
|
in(C, Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr));
|
||||||
|
|
||||||
#if RANDOMIZED_CALL_IDS
|
#if RANDOMIZED_CALL_IDS
|
||||||
new call:Atom;
|
new call:Atom;
|
||||||
#else
|
#else
|
||||||
call <- Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr);
|
call <- Cinitiator(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr);
|
||||||
#endif
|
#endif
|
||||||
SETUP_HANDSHAKE_STATE()
|
|
||||||
RNG_KEM_PAIR(eski, epki, Seski) // IHI3
|
in(C, last_cookie:key);
|
||||||
sidr <- sid0;
|
Oinitiator_inner(sidi, Ssskm, Spsk, Sspkt, Seski, Ssptr, last_cookie, C, call).
|
||||||
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;
|
restriction sid:SessionId, ad1:Atom, ad2:Atom;
|
||||||
event(ConsumeSidi(sid, ad1)) && event(ConsumeSidi(sid, ad2))
|
event(ConsumeSidi(sid, ad1)) && event(ConsumeSidi(sid, ad2))
|
||||||
@@ -207,21 +311,3 @@ let rosenpass_main() = 0
|
|||||||
| REP(RESPONDER_BOUND, Oinit_hello)
|
| REP(RESPONDER_BOUND, Oinit_hello)
|
||||||
| REP(RESPONDER_BOUND, Oinit_conf).
|
| REP(RESPONDER_BOUND, Oinit_conf).
|
||||||
|
|
||||||
nounif v:seed_prec; attacker(prepare_seed(trusted_seed( v )))/6217[hypothesis].
|
|
||||||
nounif v:seed; attacker(prepare_seed( v ))/6216[hypothesis].
|
|
||||||
nounif v:seed; attacker(rng_kem_sk( v ))/6215[hypothesis].
|
|
||||||
nounif v:seed; attacker(rng_key( v ))/6214[hypothesis].
|
|
||||||
nounif v:key_prec; attacker(prepare_key(trusted_key( v )))/6213[hypothesis].
|
|
||||||
nounif v:kem_sk_prec; attacker(prepare_kem_sk(trusted_kem_sk( v )))/6212[hypothesis].
|
|
||||||
nounif v:key; attacker(prepare_key( v ))/6211[hypothesis].
|
|
||||||
nounif v:kem_sk; attacker(prepare_kem_sk( v ))/6210[hypothesis].
|
|
||||||
nounif Spk:kem_sk_tmpl;
|
|
||||||
attacker(Creveal_kem_pk(Spk))/6110[conclusion].
|
|
||||||
nounif sid:SessionId, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Seski:seed_tmpl, Ssptr:seed_tmpl;
|
|
||||||
attacker(Cinitiator( *sid, *Ssskm, *Spsk, *Sspkt, *Seski, *Ssptr ))/6109[conclusion].
|
|
||||||
nounif sid:SessionId, biscuit_no:Atom, Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, Septi:seed_tmpl, Sspti:seed_tmpl, ih:InitHello_t;
|
|
||||||
attacker(Cinit_hello( *sid, *biscuit_no, *Ssskm, *Spsk, *Sspkt, *Septi, *Sspti, *ih ))/6108[conclusion].
|
|
||||||
nounif rh:RespHello_t;
|
|
||||||
attacker(Cresp_hello( *rh ))/6107[conclusion].
|
|
||||||
nounif Ssskm:kem_sk_tmpl, Spsk:key_tmpl, Sspkt:kem_sk_tmpl, ic:InitConf_t;
|
|
||||||
attacker(Cinit_conf( *Ssskm, *Spsk, *Sspkt, *ic ))/6106[conclusion].
|
|
||||||
|
|||||||
@@ -2,6 +2,26 @@
|
|||||||
#include "crypto/kem.mpv"
|
#include "crypto/kem.mpv"
|
||||||
#include "rosenpass/handshake_state.mpv"
|
#include "rosenpass/handshake_state.mpv"
|
||||||
|
|
||||||
|
fun Envelope(
|
||||||
|
key,
|
||||||
|
bits
|
||||||
|
): bits [data].
|
||||||
|
|
||||||
|
type mac_envelope_t.
|
||||||
|
fun mac_envelope(
|
||||||
|
key,
|
||||||
|
bits
|
||||||
|
) : mac_envelope_t.
|
||||||
|
|
||||||
|
fun mac_envelope2b(mac_envelope_t) : bits [typeConverter].
|
||||||
|
|
||||||
|
letfun create_mac(pk:kem_pk, payload:bits) = mac_envelope(lprf2(MAC, kem_pk2b(pk), payload), payload).
|
||||||
|
|
||||||
|
fun mac_envelope_pk_test(mac_envelope_t, kem_pk) : bool
|
||||||
|
reduc forall pk:kem_pk, b:bits;
|
||||||
|
mac_envelope_pk_test(mac_envelope(prf(prf(prf(prf(key0,PROTOCOL),MAC),kem_pk2b(pk)),
|
||||||
|
b), b), pk) = true.
|
||||||
|
|
||||||
type InitHello_t.
|
type InitHello_t.
|
||||||
fun InitHello(
|
fun InitHello(
|
||||||
SessionId, // sidi
|
SessionId, // sidi
|
||||||
@@ -11,6 +31,8 @@ fun InitHello(
|
|||||||
bits // auth
|
bits // auth
|
||||||
) : InitHello_t [data].
|
) : InitHello_t [data].
|
||||||
|
|
||||||
|
fun IH2b(InitHello_t) : bitstring [typeConverter].
|
||||||
|
|
||||||
#define INITHELLO_PRODUCE() \
|
#define INITHELLO_PRODUCE() \
|
||||||
ck <- lprf1(CK_INIT, kem_pk2b(spkr)); /* IHI1 */ \
|
ck <- lprf1(CK_INIT, kem_pk2b(spkr)); /* IHI1 */ \
|
||||||
/* not handled here */ /* IHI2 */ \
|
/* not handled here */ /* IHI2 */ \
|
||||||
@@ -41,6 +63,8 @@ fun RespHello(
|
|||||||
bits // auth
|
bits // auth
|
||||||
) : RespHello_t [data].
|
) : RespHello_t [data].
|
||||||
|
|
||||||
|
fun RH2b(RespHello_t) : bitstring [typeConverter].
|
||||||
|
|
||||||
#define RESPHELLO_PRODUCE() \
|
#define RESPHELLO_PRODUCE() \
|
||||||
/* not handled here */ /* RHR1 */ \
|
/* not handled here */ /* RHR1 */ \
|
||||||
MIX2(sid2b(sidr), sid2b(sidi)) /* RHR3 */ \
|
MIX2(sid2b(sidr), sid2b(sidi)) /* RHR3 */ \
|
||||||
@@ -67,13 +91,14 @@ fun InitConf(
|
|||||||
bits // auth
|
bits // auth
|
||||||
) : InitConf_t [data].
|
) : InitConf_t [data].
|
||||||
|
|
||||||
|
fun IC2b(InitConf_t) : bitstring [typeConverter].
|
||||||
|
|
||||||
#define INITCONF_PRODUCE() \
|
#define INITCONF_PRODUCE() \
|
||||||
MIX2(sid2b(sidi), sid2b(sidr)) /* ICI3 */ \
|
MIX2(sid2b(sidi), sid2b(sidr)) /* ICI3 */ \
|
||||||
ENCRYPT_AND_MIX(auth, empty) /* ICI4 */ \
|
ENCRYPT_AND_MIX(auth, empty) /* ICI4 */ \
|
||||||
ic <- InitConf(sidi, sidr, biscuit, auth);
|
ic <- InitConf(sidi, sidr, biscuit, auth);
|
||||||
|
|
||||||
#define INITCONF_CONSUME() \
|
#define INITCONF_CONSUME() \
|
||||||
let InitConf(sidi, sidr, biscuit, auth) = ic in \
|
|
||||||
LOAD_BISCUIT(biscuit_no, biscuit) /* ICR1 */ \
|
LOAD_BISCUIT(biscuit_no, biscuit) /* ICR1 */ \
|
||||||
ENCRYPT_AND_MIX(rh_auth, empty) /* ICIR */ \
|
ENCRYPT_AND_MIX(rh_auth, empty) /* ICIR */ \
|
||||||
ck_rh <- ck; /* ---- */ /* TODO: Move into oracles.mpv */ \
|
ck_rh <- ck; /* ---- */ /* TODO: Move into oracles.mpv */ \
|
||||||
|
|||||||
@@ -48,37 +48,13 @@ test = false
|
|||||||
doc = false
|
doc = false
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "fuzz_box_secret_alloc_malloc"
|
name = "fuzz_box_secret_alloc"
|
||||||
path = "fuzz_targets/box_secret_alloc_malloc.rs"
|
path = "fuzz_targets/box_secret_alloc.rs"
|
||||||
test = false
|
test = false
|
||||||
doc = false
|
doc = false
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "fuzz_vec_secret_alloc_malloc"
|
name = "fuzz_vec_secret_alloc"
|
||||||
path = "fuzz_targets/vec_secret_alloc_malloc.rs"
|
path = "fuzz_targets/vec_secret_alloc.rs"
|
||||||
test = false
|
|
||||||
doc = false
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "fuzz_box_secret_alloc_memfdsec"
|
|
||||||
path = "fuzz_targets/box_secret_alloc_memfdsec.rs"
|
|
||||||
test = false
|
|
||||||
doc = false
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "fuzz_vec_secret_alloc_memfdsec"
|
|
||||||
path = "fuzz_targets/vec_secret_alloc_memfdsec.rs"
|
|
||||||
test = false
|
|
||||||
doc = false
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "fuzz_box_secret_alloc_memfdsec_mallocfb"
|
|
||||||
path = "fuzz_targets/box_secret_alloc_memfdsec_mallocfb.rs"
|
|
||||||
test = false
|
|
||||||
doc = false
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "fuzz_vec_secret_alloc_memfdsec_mallocfb"
|
|
||||||
path = "fuzz_targets/vec_secret_alloc_memfdsec_mallocfb.rs"
|
|
||||||
test = false
|
test = false
|
||||||
doc = false
|
doc = false
|
||||||
@@ -2,12 +2,7 @@
|
|||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
use rosenpass_secret_memory::alloc::secret_box;
|
use rosenpass_secret_memory::alloc::secret_box;
|
||||||
use rosenpass_secret_memory::policy::*;
|
|
||||||
use std::sync::Once;
|
|
||||||
|
|
||||||
static ONCE: Once = Once::new();
|
|
||||||
|
|
||||||
fuzz_target!(|data: &[u8]| {
|
fuzz_target!(|data: &[u8]| {
|
||||||
ONCE.call_once(secret_policy_try_use_memfd_secrets);
|
|
||||||
let _ = secret_box(data);
|
let _ = secret_box(data);
|
||||||
});
|
});
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#![no_main]
|
|
||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
|
||||||
use rosenpass_secret_memory::alloc::secret_box;
|
|
||||||
use rosenpass_secret_memory::policy::*;
|
|
||||||
use std::sync::Once;
|
|
||||||
static ONCE: Once = Once::new();
|
|
||||||
|
|
||||||
fuzz_target!(|data: &[u8]| {
|
|
||||||
ONCE.call_once(secret_policy_use_only_malloc_secrets);
|
|
||||||
let _ = secret_box(data);
|
|
||||||
});
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#![no_main]
|
|
||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
|
||||||
use rosenpass_secret_memory::alloc::secret_box;
|
|
||||||
use rosenpass_secret_memory::policy::*;
|
|
||||||
use std::sync::Once;
|
|
||||||
|
|
||||||
static ONCE: Once = Once::new();
|
|
||||||
|
|
||||||
fuzz_target!(|data: &[u8]| {
|
|
||||||
ONCE.call_once(secret_policy_use_only_memfd_secrets);
|
|
||||||
let _ = secret_box(data);
|
|
||||||
});
|
|
||||||
@@ -6,13 +6,9 @@ use libfuzzer_sys::fuzz_target;
|
|||||||
use rosenpass::protocol::CryptoServer;
|
use rosenpass::protocol::CryptoServer;
|
||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
use rosenpass_secret_memory::policy::*;
|
|
||||||
use rosenpass_secret_memory::Secret;
|
use rosenpass_secret_memory::Secret;
|
||||||
use std::sync::Once;
|
|
||||||
|
|
||||||
static ONCE: Once = Once::new();
|
|
||||||
fuzz_target!(|rx_buf: &[u8]| {
|
fuzz_target!(|rx_buf: &[u8]| {
|
||||||
ONCE.call_once(secret_policy_use_only_malloc_secrets);
|
|
||||||
let sk = Secret::from_slice(&[0; StaticKem::SK_LEN]);
|
let sk = Secret::from_slice(&[0; StaticKem::SK_LEN]);
|
||||||
let pk = Secret::from_slice(&[0; StaticKem::PK_LEN]);
|
let pk = Secret::from_slice(&[0; StaticKem::PK_LEN]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use std::sync::Once;
|
|
||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
use rosenpass_secret_memory::alloc::secret_vec;
|
use rosenpass_secret_memory::alloc::secret_vec;
|
||||||
use rosenpass_secret_memory::policy::*;
|
|
||||||
|
|
||||||
static ONCE: Once = Once::new();
|
|
||||||
|
|
||||||
fuzz_target!(|data: &[u8]| {
|
fuzz_target!(|data: &[u8]| {
|
||||||
ONCE.call_once(secret_policy_try_use_memfd_secrets);
|
|
||||||
let mut vec = secret_vec();
|
let mut vec = secret_vec();
|
||||||
vec.extend_from_slice(data);
|
vec.extend_from_slice(data);
|
||||||
});
|
});
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#![no_main]
|
|
||||||
|
|
||||||
use std::sync::Once;
|
|
||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
|
||||||
use rosenpass_secret_memory::alloc::secret_vec;
|
|
||||||
use rosenpass_secret_memory::policy::*;
|
|
||||||
|
|
||||||
static ONCE: Once = Once::new();
|
|
||||||
|
|
||||||
fuzz_target!(|data: &[u8]| {
|
|
||||||
ONCE.call_once(secret_policy_use_only_malloc_secrets);
|
|
||||||
let mut vec = secret_vec();
|
|
||||||
vec.extend_from_slice(data);
|
|
||||||
});
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#![no_main]
|
|
||||||
|
|
||||||
use std::sync::Once;
|
|
||||||
|
|
||||||
use libfuzzer_sys::fuzz_target;
|
|
||||||
use rosenpass_secret_memory::alloc::secret_vec;
|
|
||||||
use rosenpass_secret_memory::policy::*;
|
|
||||||
|
|
||||||
static ONCE: Once = Once::new();
|
|
||||||
|
|
||||||
fuzz_target!(|data: &[u8]| {
|
|
||||||
ONCE.call_once(secret_policy_use_only_memfd_secrets);
|
|
||||||
let mut vec = secret_vec();
|
|
||||||
vec.extend_from_slice(data);
|
|
||||||
});
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# Additional files
|
|
||||||
|
|
||||||
This folder contains additional files that are used in the project.
|
|
||||||
|
|
||||||
## `generate_configs.py`
|
|
||||||
|
|
||||||
The script is used to generate configuration files for a benchmark setup
|
|
||||||
consisting of a device under testing (DUT) and automatic test equipment (ATE),
|
|
||||||
basically a strong machine capable of running multiple Rosenpass instances at
|
|
||||||
once.
|
|
||||||
|
|
||||||
At the top of the script multiple variables can be set to configure the DUT IP
|
|
||||||
address and more. Once configured you may run `python3 generate_configs.py` to
|
|
||||||
create the configuration files.
|
|
||||||
|
|
||||||
A new folder called `output/` is created containing the subfolder `dut/` and
|
|
||||||
`ate/`. The former has to be copied on the DUT, ideally reproducible hardware
|
|
||||||
like a Raspberry Pi, while the latter is copied to the ATE, i.e. a laptop.
|
|
||||||
|
|
||||||
### Running a benchmark
|
|
||||||
|
|
||||||
On the ATE a run script is required since multiple instances of `rosenpass` are
|
|
||||||
started with different configurations in parallel. The scripts are named after
|
|
||||||
the number of instances they start, e.g. `run-50.sh` starts 50 instances.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# on the ATE aka laptop
|
|
||||||
cd output/ate
|
|
||||||
./run-10.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
On the DUT you start a single Rosenpass instance with the configuration matching
|
|
||||||
the ATE number of peers.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# on the DUT aka Raspberry Pi
|
|
||||||
rosenpass exchange-config configs/dut-10.toml
|
|
||||||
```
|
|
||||||
|
|
||||||
Use whatever measurement tool you like to monitor the DUT and ATE.
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
from subprocess import run
|
|
||||||
import os
|
|
||||||
|
|
||||||
config = dict(
|
|
||||||
peer_counts=[1, 5, 10, 50, 100, 500],
|
|
||||||
peer_count_max=100,
|
|
||||||
ate_ip="127.0.0.1",
|
|
||||||
dut_ip="127.0.0.1",
|
|
||||||
dut_port=9999,
|
|
||||||
path_to_rosenpass_bin=os.getcwd() + "/target/release/rosenpass",
|
|
||||||
)
|
|
||||||
|
|
||||||
print(config)
|
|
||||||
|
|
||||||
output_dir = Path("output")
|
|
||||||
output_dir.mkdir(exist_ok=True)
|
|
||||||
|
|
||||||
template_dut = """
|
|
||||||
public_key = "keys/dut-public-key"
|
|
||||||
secret_key = "keys/dut-secret-key"
|
|
||||||
listen = ["{dut_ip}:{dut_port}"]
|
|
||||||
verbosity = "Quiet"
|
|
||||||
"""
|
|
||||||
template_dut_peer = """
|
|
||||||
[[peers]] # ATE-{i}
|
|
||||||
public_key = "keys/ate-{i}-public-key"
|
|
||||||
endpoint = "{ate_ip}:{ate_port}"
|
|
||||||
key_out = "out/key_out_{i}"
|
|
||||||
"""
|
|
||||||
|
|
||||||
template_ate = """
|
|
||||||
public_key = "keys/ate-{i}-public-key"
|
|
||||||
secret_key = "keys/ate-{i}-secret-key"
|
|
||||||
listen = ["{ate_ip}:{ate_port}"]
|
|
||||||
verbosity = "Quiet"
|
|
||||||
|
|
||||||
[[peers]] # DUT
|
|
||||||
public_key = "keys/dut-public-key"
|
|
||||||
endpoint = "{dut_ip}:{dut_port}"
|
|
||||||
key_out = "out/key_out_{i}"
|
|
||||||
"""
|
|
||||||
|
|
||||||
(output_dir / "dut" / "keys").mkdir(exist_ok=True, parents=True)
|
|
||||||
(output_dir / "dut" / "out").mkdir(exist_ok=True, parents=True)
|
|
||||||
(output_dir / "dut" / "configs").mkdir(exist_ok=True, parents=True)
|
|
||||||
(output_dir / "ate" / "keys").mkdir(exist_ok=True, parents=True)
|
|
||||||
(output_dir / "ate" / "out").mkdir(exist_ok=True, parents=True)
|
|
||||||
(output_dir / "ate" / "configs").mkdir(exist_ok=True, parents=True)
|
|
||||||
|
|
||||||
for peer_count in config["peer_counts"]:
|
|
||||||
dut_config = template_dut.format(**config)
|
|
||||||
for i in range(peer_count):
|
|
||||||
dut_config += template_dut_peer.format(**config, i=i, ate_port=50000 + i)
|
|
||||||
|
|
||||||
(output_dir / "dut" / "configs" / f"dut-{peer_count}.toml").write_text(dut_config)
|
|
||||||
|
|
||||||
if not (output_dir / "dut" / "keys" / "dut-public-key").exists():
|
|
||||||
print("Generate DUT keys")
|
|
||||||
run(
|
|
||||||
[
|
|
||||||
config["path_to_rosenpass_bin"],
|
|
||||||
"gen-keys",
|
|
||||||
f"configs/dut-{peer_count}.toml",
|
|
||||||
],
|
|
||||||
cwd=output_dir / "dut",
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
print("DUT keys already exist")
|
|
||||||
|
|
||||||
# copy the DUT public key to the ATE
|
|
||||||
(output_dir / "ate" / "keys" / "dut-public-key").write_bytes(
|
|
||||||
(output_dir / "dut" / "keys" / "dut-public-key").read_bytes()
|
|
||||||
)
|
|
||||||
|
|
||||||
ate_script = "(trap 'kill 0' SIGINT; \\\n"
|
|
||||||
|
|
||||||
for i in range(config["peer_count_max"]):
|
|
||||||
(output_dir / "ate" / "configs" / f"ate-{i}.toml").write_text(
|
|
||||||
template_ate.format(**config, i=i, ate_port=50000 + i)
|
|
||||||
)
|
|
||||||
|
|
||||||
if not (output_dir / "ate" / "keys" / f"ate-{i}-public-key").exists():
|
|
||||||
# generate ATE keys
|
|
||||||
run(
|
|
||||||
[config["path_to_rosenpass_bin"], "gen-keys", f"configs/ate-{i}.toml"],
|
|
||||||
cwd=output_dir / "ate",
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
print(f"ATE-{i} keys already exist")
|
|
||||||
|
|
||||||
# copy the ATE public keys to the DUT
|
|
||||||
(output_dir / "dut" / "keys" / f"ate-{i}-public-key").write_bytes(
|
|
||||||
(output_dir / "ate" / "keys" / f"ate-{i}-public-key").read_bytes()
|
|
||||||
)
|
|
||||||
|
|
||||||
ate_script += (
|
|
||||||
f"{config['path_to_rosenpass_bin']} exchange-config configs/ate-{i}.toml & \\\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
if (i + 1) in config["peer_counts"]:
|
|
||||||
write_script = ate_script
|
|
||||||
write_script += "wait)"
|
|
||||||
|
|
||||||
(output_dir / "ate" / f"run-{i+1}.sh").write_text(write_script)
|
|
||||||
@@ -49,8 +49,6 @@ criterion = { workspace = true }
|
|||||||
test_bin = { workspace = true }
|
test_bin = { workspace = true }
|
||||||
stacker = { workspace = true }
|
stacker = { workspace = true }
|
||||||
serial_test = {workspace = true}
|
serial_test = {workspace = true}
|
||||||
procspawn = {workspace = true}
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
enable_broker_api = ["rosenpass-wireguard-broker/enable_broker_api"]
|
enable_broker_api = ["rosenpass-wireguard-broker/enable_broker_api"]
|
||||||
enable_memfd_alloc = []
|
|
||||||
@@ -5,7 +5,6 @@ use rosenpass_cipher_traits::Kem;
|
|||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
|
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets;
|
|
||||||
|
|
||||||
fn handle(
|
fn handle(
|
||||||
tx: &mut CryptoServer,
|
tx: &mut CryptoServer,
|
||||||
@@ -57,7 +56,6 @@ fn make_server_pair() -> Result<(CryptoServer, CryptoServer)> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn criterion_benchmark(c: &mut Criterion) {
|
fn criterion_benchmark(c: &mut Criterion) {
|
||||||
secret_policy_try_use_memfd_secrets();
|
|
||||||
let (mut a, mut b) = make_server_pair().unwrap();
|
let (mut a, mut b) = make_server_pair().unwrap();
|
||||||
c.bench_function("cca_secret_alloc", |bench| {
|
c.bench_function("cca_secret_alloc", |bench| {
|
||||||
bench.iter(|| {
|
bench.iter(|| {
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ use clap::{Parser, Subcommand};
|
|||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::Kem;
|
||||||
use rosenpass_ciphers::kem::StaticKem;
|
use rosenpass_ciphers::kem::StaticKem;
|
||||||
use rosenpass_secret_memory::file::StoreSecret;
|
use rosenpass_secret_memory::file::StoreSecret;
|
||||||
use rosenpass_secret_memory::{
|
|
||||||
secret_policy_try_use_memfd_secrets, secret_policy_use_only_malloc_secrets,
|
|
||||||
};
|
|
||||||
use rosenpass_util::file::{LoadValue, LoadValueB64};
|
use rosenpass_util::file::{LoadValue, LoadValueB64};
|
||||||
use rosenpass_wireguard_broker::brokers::native_unix::{
|
use rosenpass_wireguard_broker::brokers::native_unix::{
|
||||||
NativeUnixBroker, NativeUnixBrokerConfigBaseBuilder, NativeUnixBrokerConfigBaseBuilderError,
|
NativeUnixBroker, NativeUnixBrokerConfigBaseBuilder, NativeUnixBrokerConfigBaseBuilderError,
|
||||||
@@ -157,13 +154,6 @@ impl CliCommand {
|
|||||||
/// ## TODO
|
/// ## TODO
|
||||||
/// - This method consumes the [`CliCommand`] value. It might be wise to use a reference...
|
/// - This method consumes the [`CliCommand`] value. It might be wise to use a reference...
|
||||||
pub fn run(self, test_helpers: Option<AppServerTest>) -> anyhow::Result<()> {
|
pub fn run(self, test_helpers: Option<AppServerTest>) -> anyhow::Result<()> {
|
||||||
//Specify secret policy
|
|
||||||
|
|
||||||
#[cfg(feature = "enable_memfd_alloc")]
|
|
||||||
secret_policy_try_use_memfd_secrets();
|
|
||||||
#[cfg(not(feature = "enable_memfd_alloc"))]
|
|
||||||
secret_policy_use_only_malloc_secrets();
|
|
||||||
|
|
||||||
use CliCommand::*;
|
use CliCommand::*;
|
||||||
match self {
|
match self {
|
||||||
Man => {
|
Man => {
|
||||||
|
|||||||
@@ -19,16 +19,12 @@
|
|||||||
//! [CryptoServer].
|
//! [CryptoServer].
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use rosenpass_secret_memory::policy::*;
|
|
||||||
//! use rosenpass_cipher_traits::Kem;
|
//! use rosenpass_cipher_traits::Kem;
|
||||||
//! use rosenpass_ciphers::kem::StaticKem;
|
//! use rosenpass_ciphers::kem::StaticKem;
|
||||||
//! use rosenpass::{
|
//! use rosenpass::{
|
||||||
//! protocol::{SSk, SPk, MsgBuf, PeerPtr, CryptoServer, SymKey},
|
//! protocol::{SSk, SPk, MsgBuf, PeerPtr, CryptoServer, SymKey},
|
||||||
//! };
|
//! };
|
||||||
//! # fn main() -> anyhow::Result<()> {
|
//! # fn main() -> anyhow::Result<()> {
|
||||||
//! // Set security policy for storing secrets
|
|
||||||
//!
|
|
||||||
//! secret_policy_try_use_memfd_secrets();
|
|
||||||
//!
|
//!
|
||||||
//! // initialize secret and public key for peer a ...
|
//! // initialize secret and public key for peer a ...
|
||||||
//! let (mut peer_a_sk, mut peer_a_pk) = (SSk::zero(), SPk::zero());
|
//! let (mut peer_a_sk, mut peer_a_pk) = (SSk::zero(), SPk::zero());
|
||||||
@@ -2149,7 +2145,6 @@ mod test {
|
|||||||
use std::{net::SocketAddrV4, thread::sleep, time::Duration};
|
use std::{net::SocketAddrV4, thread::sleep, time::Duration};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use serial_test::serial;
|
|
||||||
|
|
||||||
struct VecHostIdentifier(Vec<u8>);
|
struct VecHostIdentifier(Vec<u8>);
|
||||||
|
|
||||||
@@ -2171,21 +2166,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_logging() {
|
|
||||||
use std::io::Write;
|
|
||||||
let mut log_builder = env_logger::Builder::from_default_env(); // sets log level filter from environment (or defaults)
|
|
||||||
log_builder.filter_level(log::LevelFilter::Info);
|
|
||||||
log_builder.format_timestamp_nanos();
|
|
||||||
log_builder.format(|buf, record| {
|
|
||||||
let ts_format = buf.timestamp_nanos().to_string();
|
|
||||||
writeln!(buf, "{}: {}", &ts_format[14..], record.args())
|
|
||||||
});
|
|
||||||
|
|
||||||
let _ = log_builder.try_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
/// Ensure that the protocol implementation can deal with truncated
|
/// Ensure that the protocol implementation can deal with truncated
|
||||||
/// messages and with overlong messages.
|
/// messages and with overlong messages.
|
||||||
///
|
///
|
||||||
@@ -2201,8 +2182,6 @@ mod test {
|
|||||||
/// Through all this, the handshake should still successfully terminate;
|
/// Through all this, the handshake should still successfully terminate;
|
||||||
/// i.e. an exchanged key must be produced in both servers.
|
/// i.e. an exchanged key must be produced in both servers.
|
||||||
fn handles_incorrect_size_messages() {
|
fn handles_incorrect_size_messages() {
|
||||||
setup_logging();
|
|
||||||
rosenpass_secret_memory::secret_policy_try_use_memfd_secrets();
|
|
||||||
stacker::grow(8 * 1024 * 1024, || {
|
stacker::grow(8 * 1024 * 1024, || {
|
||||||
const OVERSIZED_MESSAGE: usize = ((MAX_MESSAGE_LEN as f32) * 1.2) as usize;
|
const OVERSIZED_MESSAGE: usize = ((MAX_MESSAGE_LEN as f32) * 1.2) as usize;
|
||||||
type MsgBufPlus = Public<OVERSIZED_MESSAGE>;
|
type MsgBufPlus = Public<OVERSIZED_MESSAGE>;
|
||||||
@@ -2273,10 +2252,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_regular_exchange() {
|
fn test_regular_exchange() {
|
||||||
setup_logging();
|
|
||||||
rosenpass_secret_memory::secret_policy_try_use_memfd_secrets();
|
|
||||||
stacker::grow(8 * 1024 * 1024, || {
|
stacker::grow(8 * 1024 * 1024, || {
|
||||||
type MsgBufPlus = Public<MAX_MESSAGE_LEN>;
|
type MsgBufPlus = Public<MAX_MESSAGE_LEN>;
|
||||||
let (mut a, mut b) = make_server_pair().unwrap();
|
let (mut a, mut b) = make_server_pair().unwrap();
|
||||||
@@ -2320,7 +2296,7 @@ mod test {
|
|||||||
|
|
||||||
//B handles InitConf, sends EmptyData
|
//B handles InitConf, sends EmptyData
|
||||||
let HandleMsgResult {
|
let HandleMsgResult {
|
||||||
resp: _,
|
resp,
|
||||||
exchanged_with,
|
exchanged_with,
|
||||||
} = b
|
} = b
|
||||||
.handle_msg(&a_to_b_buf.as_slice()[..init_conf_len], &mut *b_to_a_buf)
|
.handle_msg(&a_to_b_buf.as_slice()[..init_conf_len], &mut *b_to_a_buf)
|
||||||
@@ -2334,10 +2310,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn test_regular_init_conf_retransmit() {
|
fn test_regular_init_conf_retransmit() {
|
||||||
setup_logging();
|
|
||||||
rosenpass_secret_memory::secret_policy_try_use_memfd_secrets();
|
|
||||||
stacker::grow(8 * 1024 * 1024, || {
|
stacker::grow(8 * 1024 * 1024, || {
|
||||||
type MsgBufPlus = Public<MAX_MESSAGE_LEN>;
|
type MsgBufPlus = Public<MAX_MESSAGE_LEN>;
|
||||||
let (mut a, mut b) = make_server_pair().unwrap();
|
let (mut a, mut b) = make_server_pair().unwrap();
|
||||||
@@ -2382,7 +2355,7 @@ mod test {
|
|||||||
|
|
||||||
//B handles InitConf, sends EmptyData
|
//B handles InitConf, sends EmptyData
|
||||||
let HandleMsgResult {
|
let HandleMsgResult {
|
||||||
resp: _,
|
resp,
|
||||||
exchanged_with,
|
exchanged_with,
|
||||||
} = b
|
} = b
|
||||||
.handle_msg(&a_to_b_buf.as_slice()[..init_conf_len], &mut *b_to_a_buf)
|
.handle_msg(&a_to_b_buf.as_slice()[..init_conf_len], &mut *b_to_a_buf)
|
||||||
@@ -2395,7 +2368,7 @@ mod test {
|
|||||||
|
|
||||||
//B handles InitConf again, sends EmptyData
|
//B handles InitConf again, sends EmptyData
|
||||||
let HandleMsgResult {
|
let HandleMsgResult {
|
||||||
resp: _,
|
resp,
|
||||||
exchanged_with,
|
exchanged_with,
|
||||||
} = b
|
} = b
|
||||||
.handle_msg(&a_to_b_buf.as_slice()[..init_conf_len], &mut *b_to_a_buf)
|
.handle_msg(&a_to_b_buf.as_slice()[..init_conf_len], &mut *b_to_a_buf)
|
||||||
@@ -2409,10 +2382,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn cookie_reply_mechanism_responder_under_load() {
|
fn cookie_reply_mechanism_responder_under_load() {
|
||||||
setup_logging();
|
|
||||||
rosenpass_secret_memory::secret_policy_try_use_memfd_secrets();
|
|
||||||
stacker::grow(8 * 1024 * 1024, || {
|
stacker::grow(8 * 1024 * 1024, || {
|
||||||
type MsgBufPlus = Public<MAX_MESSAGE_LEN>;
|
type MsgBufPlus = Public<MAX_MESSAGE_LEN>;
|
||||||
let (mut a, mut b) = make_server_pair().unwrap();
|
let (mut a, mut b) = make_server_pair().unwrap();
|
||||||
@@ -2506,10 +2476,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
|
||||||
fn cookie_reply_mechanism_initiator_bails_on_message_under_load() {
|
fn cookie_reply_mechanism_initiator_bails_on_message_under_load() {
|
||||||
setup_logging();
|
|
||||||
rosenpass_secret_memory::secret_policy_try_use_memfd_secrets();
|
|
||||||
stacker::grow(8 * 1024 * 1024, || {
|
stacker::grow(8 * 1024 * 1024, || {
|
||||||
type MsgBufPlus = Public<MAX_MESSAGE_LEN>;
|
type MsgBufPlus = Public<MAX_MESSAGE_LEN>;
|
||||||
let (mut a, mut b) = make_server_pair().unwrap();
|
let (mut a, mut b) = make_server_pair().unwrap();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::{builder::Str, Parser};
|
||||||
use rosenpass::{app_server::AppServerTestBuilder, cli::CliArgs};
|
use rosenpass::{app_server::AppServerTestBuilder, cli::CliArgs};
|
||||||
use rosenpass_secret_memory::{Public, Secret};
|
use rosenpass_secret_memory::{Public, Secret};
|
||||||
use rosenpass_wireguard_broker::{WireguardBrokerMio, WG_KEY_LEN, WG_PEER_LEN};
|
use rosenpass_wireguard_broker::{WireguardBrokerMio, WG_KEY_LEN, WG_PEER_LEN};
|
||||||
@@ -275,7 +275,6 @@ fn check_exchange_under_dos() {
|
|||||||
fs::remove_dir_all(&tmpdir).unwrap();
|
fs::remove_dir_all(&tmpdir).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct MockBrokerInner {
|
struct MockBrokerInner {
|
||||||
psk: Option<Secret<WG_KEY_LEN>>,
|
psk: Option<Secret<WG_KEY_LEN>>,
|
||||||
|
|||||||
@@ -37,6 +37,3 @@ netlink-packet-wireguard = "0.2"
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = {workspace = true}
|
tempfile = {workspace = true}
|
||||||
stacker = {workspace = true}
|
stacker = {workspace = true}
|
||||||
|
|
||||||
[features]
|
|
||||||
enable_memfd_alloc = []
|
|
||||||
|
|||||||
@@ -102,7 +102,6 @@ mod tests {
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use rosenpass::protocol::{SPk, SSk};
|
use rosenpass::protocol::{SPk, SSk};
|
||||||
use rosenpass_secret_memory::secret_policy_try_use_memfd_secrets;
|
|
||||||
use rosenpass_secret_memory::Secret;
|
use rosenpass_secret_memory::Secret;
|
||||||
use rosenpass_util::file::LoadValue;
|
use rosenpass_util::file::LoadValue;
|
||||||
use rosenpass_util::file::LoadValueB64;
|
use rosenpass_util::file::LoadValueB64;
|
||||||
@@ -111,8 +110,7 @@ mod tests {
|
|||||||
use crate::key::{genkey, pubkey, WG_B64_LEN};
|
use crate::key::{genkey, pubkey, WG_B64_LEN};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_key_loopback() {
|
fn it_works() {
|
||||||
secret_policy_try_use_memfd_secrets();
|
|
||||||
let private_keys_dir = tempdir().unwrap();
|
let private_keys_dir = tempdir().unwrap();
|
||||||
fs::remove_dir(private_keys_dir.path()).unwrap();
|
fs::remove_dir(private_keys_dir.path()).unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ use std::process::exit;
|
|||||||
use cli::{Cli, Command};
|
use cli::{Cli, Command};
|
||||||
use exchange::exchange;
|
use exchange::exchange;
|
||||||
use key::{genkey, pubkey};
|
use key::{genkey, pubkey};
|
||||||
use rosenpass_secret_memory::policy;
|
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
mod exchange;
|
mod exchange;
|
||||||
@@ -11,11 +10,6 @@ mod key;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
#[cfg(feature = "enable_memfd_alloc")]
|
|
||||||
policy::secret_policy_try_use_memfd_secrets();
|
|
||||||
#[cfg(not(feature = "enable_memfd_alloc"))]
|
|
||||||
policy::secret_policy_use_only_malloc_secrets();
|
|
||||||
|
|
||||||
let cli = match Cli::parse(std::env::args().peekable()) {
|
let cli = match Cli::parse(std::env::args().peekable()) {
|
||||||
Ok(cli) => cli,
|
Ok(cli) => cli,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|||||||
@@ -23,4 +23,3 @@ log = { workspace = true }
|
|||||||
allocator-api2-tests = { workspace = true }
|
allocator-api2-tests = { workspace = true }
|
||||||
tempfile = {workspace = true}
|
tempfile = {workspace = true}
|
||||||
base64ct = {workspace = true}
|
base64ct = {workspace = true}
|
||||||
procspawn = {workspace = true}
|
|
||||||
@@ -4,41 +4,37 @@ use std::ptr::NonNull;
|
|||||||
use allocator_api2::alloc::{AllocError, Allocator, Layout};
|
use allocator_api2::alloc::{AllocError, Allocator, Layout};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
struct MallocAllocatorContents;
|
struct MemsecAllocatorContents;
|
||||||
|
|
||||||
/// Memory allocation using using the memsec crate
|
/// Memory allocation using using the memsec crate
|
||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
pub struct MallocAllocator {
|
pub struct MemsecAllocator {
|
||||||
_dummy_private_data: MallocAllocatorContents,
|
_dummy_private_data: MemsecAllocatorContents,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A box backed by the memsec allocator
|
/// A box backed by the memsec allocator
|
||||||
pub type MallocBox<T> = allocator_api2::boxed::Box<T, MallocAllocator>;
|
pub type MemsecBox<T> = allocator_api2::boxed::Box<T, MemsecAllocator>;
|
||||||
|
|
||||||
/// A vector backed by the memsec allocator
|
/// A vector backed by the memsec allocator
|
||||||
pub type MallocVec<T> = allocator_api2::vec::Vec<T, MallocAllocator>;
|
pub type MemsecVec<T> = allocator_api2::vec::Vec<T, MemsecAllocator>;
|
||||||
|
|
||||||
pub fn malloc_box_try<T>(x: T) -> Result<MallocBox<T>, AllocError> {
|
pub fn memsec_box<T>(x: T) -> MemsecBox<T> {
|
||||||
MallocBox::<T>::try_new_in(x, MallocAllocator::new())
|
MemsecBox::<T>::new_in(x, MemsecAllocator::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn malloc_box<T>(x: T) -> MallocBox<T> {
|
pub fn memsec_vec<T>() -> MemsecVec<T> {
|
||||||
MallocBox::<T>::new_in(x, MallocAllocator::new())
|
MemsecVec::<T>::new_in(MemsecAllocator::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn malloc_vec<T>() -> MallocVec<T> {
|
impl MemsecAllocator {
|
||||||
MallocVec::<T>::new_in(MallocAllocator::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MallocAllocator {
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
_dummy_private_data: MallocAllocatorContents,
|
_dummy_private_data: MemsecAllocatorContents,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Allocator for MallocAllocator {
|
unsafe impl Allocator for MemsecAllocator {
|
||||||
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||||
// Call memsec allocator
|
// Call memsec allocator
|
||||||
let mem: Option<NonNull<[u8]>> = unsafe { memsec::malloc_sized(layout.size()) };
|
let mem: Option<NonNull<[u8]>> = unsafe { memsec::malloc_sized(layout.size()) };
|
||||||
@@ -52,8 +48,8 @@ unsafe impl Allocator for MallocAllocator {
|
|||||||
// Ensure the right alignment is used
|
// Ensure the right alignment is used
|
||||||
let off = (mem.as_ptr() as *const u8).align_offset(layout.align());
|
let off = (mem.as_ptr() as *const u8).align_offset(layout.align());
|
||||||
if off != 0 {
|
if off != 0 {
|
||||||
log::error!("Allocation {layout:?} was requested but malloc-based memsec returned allocation \
|
log::error!("Allocation {layout:?} was requested but memsec returned allocation \
|
||||||
with offset {off} from the requested alignment. Malloc always allocates values \
|
with offset {off} from the requested alignment. Memsec always allocates values \
|
||||||
at the end of a memory page for security reasons, custom alignments are not supported. \
|
at the end of a memory page for security reasons, custom alignments are not supported. \
|
||||||
You could try allocating an oversized value.");
|
You could try allocating an oversized value.");
|
||||||
unsafe { memsec::free(mem) };
|
unsafe { memsec::free(mem) };
|
||||||
@@ -70,7 +66,7 @@ unsafe impl Allocator for MallocAllocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for MallocAllocator {
|
impl fmt::Debug for MemsecAllocator {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt.write_str("<memsec based Rust allocator>")
|
fmt.write_str("<memsec based Rust allocator>")
|
||||||
}
|
}
|
||||||
@@ -82,21 +78,21 @@ mod test {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
make_test! { test_sizes(MallocAllocator::new()) }
|
make_test! { test_sizes(MemsecAllocator::new()) }
|
||||||
make_test! { test_vec(MallocAllocator::new()) }
|
make_test! { test_vec(MemsecAllocator::new()) }
|
||||||
make_test! { test_many_boxes(MallocAllocator::new()) }
|
make_test! { test_many_boxes(MemsecAllocator::new()) }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn malloc_allocation() {
|
fn memsec_allocation() {
|
||||||
let alloc = MallocAllocator::new();
|
let alloc = MemsecAllocator::new();
|
||||||
malloc_allocation_impl::<0>(&alloc);
|
memsec_allocation_impl::<0>(&alloc);
|
||||||
malloc_allocation_impl::<7>(&alloc);
|
memsec_allocation_impl::<7>(&alloc);
|
||||||
malloc_allocation_impl::<8>(&alloc);
|
memsec_allocation_impl::<8>(&alloc);
|
||||||
malloc_allocation_impl::<64>(&alloc);
|
memsec_allocation_impl::<64>(&alloc);
|
||||||
malloc_allocation_impl::<999>(&alloc);
|
memsec_allocation_impl::<999>(&alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn malloc_allocation_impl<const N: usize>(alloc: &MallocAllocator) {
|
fn memsec_allocation_impl<const N: usize>(alloc: &MemsecAllocator) {
|
||||||
let layout = Layout::new::<[u8; N]>();
|
let layout = Layout::new::<[u8; N]>();
|
||||||
let mem = alloc.allocate(layout).unwrap();
|
let mem = alloc.allocate(layout).unwrap();
|
||||||
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
#![cfg(target_os = "linux")]
|
|
||||||
use std::fmt;
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
use allocator_api2::alloc::{AllocError, Allocator, Layout};
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default)]
|
|
||||||
struct MemfdSecAllocatorContents;
|
|
||||||
|
|
||||||
/// Memory allocation using using the memsec crate
|
|
||||||
#[derive(Copy, Clone, Default)]
|
|
||||||
pub struct MemfdSecAllocator {
|
|
||||||
_dummy_private_data: MemfdSecAllocatorContents,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A box backed by the memsec allocator
|
|
||||||
pub type MemfdSecBox<T> = allocator_api2::boxed::Box<T, MemfdSecAllocator>;
|
|
||||||
|
|
||||||
/// A vector backed by the memsec allocator
|
|
||||||
pub type MemfdSecVec<T> = allocator_api2::vec::Vec<T, MemfdSecAllocator>;
|
|
||||||
|
|
||||||
pub fn memfdsec_box_try<T>(x: T) -> Result<MemfdSecBox<T>, AllocError> {
|
|
||||||
MemfdSecBox::<T>::try_new_in(x, MemfdSecAllocator::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn memfdsec_box<T>(x: T) -> MemfdSecBox<T> {
|
|
||||||
MemfdSecBox::<T>::new_in(x, MemfdSecAllocator::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn memfdsec_vec<T>() -> MemfdSecVec<T> {
|
|
||||||
MemfdSecVec::<T>::new_in(MemfdSecAllocator::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MemfdSecAllocator {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
_dummy_private_data: MemfdSecAllocatorContents,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Allocator for MemfdSecAllocator {
|
|
||||||
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
|
||||||
// Call memsec allocator
|
|
||||||
let mem: Option<NonNull<[u8]>> = unsafe { memsec::memfd_secret_sized(layout.size()) };
|
|
||||||
|
|
||||||
// Unwrap the option
|
|
||||||
let Some(mem) = mem else {
|
|
||||||
log::error!("Allocation {layout:?} was requested but memfd-based memsec returned a null pointer");
|
|
||||||
return Err(AllocError);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ensure the right alignment is used
|
|
||||||
let off = (mem.as_ptr() as *const u8).align_offset(layout.align());
|
|
||||||
if off != 0 {
|
|
||||||
log::error!("Allocation {layout:?} was requested but memfd-based memsec returned allocation \
|
|
||||||
with offset {off} from the requested alignment. Memfd always allocates values \
|
|
||||||
at the end of a memory page for security reasons, custom alignments are not supported. \
|
|
||||||
You could try allocating an oversized value.");
|
|
||||||
unsafe { memsec::free_memfd_secret(mem) };
|
|
||||||
return Err(AllocError);
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(mem)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
|
|
||||||
unsafe {
|
|
||||||
memsec::free_memfd_secret(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for MemfdSecAllocator {
|
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
fmt.write_str("<memsec based Rust allocator>")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use allocator_api2_tests::make_test;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
make_test! { test_sizes(MemfdSecAllocator::new()) }
|
|
||||||
make_test! { test_vec(MemfdSecAllocator::new()) }
|
|
||||||
make_test! { test_many_boxes(MemfdSecAllocator::new()) }
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn memfdsec_allocation() {
|
|
||||||
let alloc = MemfdSecAllocator::new();
|
|
||||||
memfdsec_allocation_impl::<0>(&alloc);
|
|
||||||
memfdsec_allocation_impl::<7>(&alloc);
|
|
||||||
memfdsec_allocation_impl::<8>(&alloc);
|
|
||||||
memfdsec_allocation_impl::<64>(&alloc);
|
|
||||||
memfdsec_allocation_impl::<999>(&alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn memfdsec_allocation_impl<const N: usize>(alloc: &MemfdSecAllocator) {
|
|
||||||
let layout = Layout::new::<[u8; N]>();
|
|
||||||
let mem = alloc.allocate(layout).unwrap();
|
|
||||||
|
|
||||||
// https://libsodium.gitbook.io/doc/memory_management#guarded-heap-allocations
|
|
||||||
// promises us that allocated memory is initialized with the magic byte 0xDB
|
|
||||||
// and memsec promises to provide a reimplementation of the libsodium mechanism;
|
|
||||||
// it uses the magic value 0xD0 though
|
|
||||||
assert_eq!(unsafe { mem.as_ref() }, &[0xD0u8; N]);
|
|
||||||
let mem = NonNull::new(mem.as_ptr() as *mut u8).unwrap();
|
|
||||||
unsafe { alloc.deallocate(mem, layout) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
pub mod malloc;
|
|
||||||
pub mod memfdsec;
|
|
||||||
@@ -1,86 +1,6 @@
|
|||||||
pub mod memsec;
|
pub mod memsec;
|
||||||
|
|
||||||
use std::sync::OnceLock;
|
pub use crate::alloc::memsec::{
|
||||||
|
memsec_box as secret_box, memsec_vec as secret_vec, MemsecAllocator as SecretAllocator,
|
||||||
use allocator_api2::alloc::{AllocError, Allocator};
|
MemsecBox as SecretBox, MemsecVec as SecretVec,
|
||||||
use memsec::malloc::MallocAllocator;
|
};
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
use memsec::memfdsec::MemfdSecAllocator;
|
|
||||||
|
|
||||||
static ALLOC_TYPE: OnceLock<SecretAllocType> = OnceLock::new();
|
|
||||||
|
|
||||||
/// Sets the secret allocation type to use.
|
|
||||||
/// Intended usage at startup before secret allocation
|
|
||||||
/// takes place
|
|
||||||
pub fn set_secret_alloc_type(alloc_type: SecretAllocType) {
|
|
||||||
ALLOC_TYPE.set(alloc_type).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_or_init_secret_alloc_type(alloc_type: SecretAllocType) -> SecretAllocType {
|
|
||||||
*ALLOC_TYPE.get_or_init(|| alloc_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum SecretAllocType {
|
|
||||||
MemsecMalloc,
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
MemsecMemfdSec,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SecretAlloc {
|
|
||||||
alloc_type: SecretAllocType,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for SecretAlloc {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
alloc_type: *ALLOC_TYPE.get().expect(
|
|
||||||
"Secret security policy not specified. \
|
|
||||||
Run the specifying policy function in \
|
|
||||||
rosenpass_secret_memory::policy or set a \
|
|
||||||
custom policy by initializing \
|
|
||||||
rosenpass_secret_memory::alloc::ALLOC_TYPE \
|
|
||||||
before using secrets",
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Allocator for SecretAlloc {
|
|
||||||
fn allocate(
|
|
||||||
&self,
|
|
||||||
layout: std::alloc::Layout,
|
|
||||||
) -> Result<std::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
|
|
||||||
match self.alloc_type {
|
|
||||||
SecretAllocType::MemsecMalloc => MallocAllocator::default().allocate(layout),
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
SecretAllocType::MemsecMemfdSec => MemfdSecAllocator::default().allocate(layout),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn deallocate(&self, ptr: std::ptr::NonNull<u8>, layout: std::alloc::Layout) {
|
|
||||||
match self.alloc_type {
|
|
||||||
SecretAllocType::MemsecMalloc => MallocAllocator::default().deallocate(ptr, layout),
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
SecretAllocType::MemsecMemfdSec => MemfdSecAllocator::default().deallocate(ptr, layout),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type SecretBox<T> = allocator_api2::boxed::Box<T, SecretAlloc>;
|
|
||||||
|
|
||||||
/// A vector backed by the memsec allocator
|
|
||||||
pub type SecretVec<T> = allocator_api2::vec::Vec<T, SecretAlloc>;
|
|
||||||
|
|
||||||
pub fn secret_box_try<T>(x: T) -> Result<SecretBox<T>, AllocError> {
|
|
||||||
SecretBox::<T>::try_new_in(x, SecretAlloc::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn secret_box<T>(x: T) -> SecretBox<T> {
|
|
||||||
SecretBox::<T>::new_in(x, SecretAlloc::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn secret_vec<T>() -> SecretVec<T> {
|
|
||||||
SecretVec::<T>::new_in(SecretAlloc::default())
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,6 +9,3 @@ pub use crate::public::Public;
|
|||||||
|
|
||||||
mod secret;
|
mod secret;
|
||||||
pub use crate::secret::Secret;
|
pub use crate::secret::Secret;
|
||||||
|
|
||||||
pub mod policy;
|
|
||||||
pub use crate::policy::*;
|
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
pub fn secret_policy_try_use_memfd_secrets() {
|
|
||||||
let alloc_type = {
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
{
|
|
||||||
if crate::alloc::memsec::memfdsec::memfdsec_box_try(0u8).is_ok() {
|
|
||||||
crate::alloc::SecretAllocType::MemsecMemfdSec
|
|
||||||
} else {
|
|
||||||
crate::alloc::SecretAllocType::MemsecMalloc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "linux"))]
|
|
||||||
{
|
|
||||||
crate::alloc::SecretAllocType::MemsecMalloc
|
|
||||||
}
|
|
||||||
};
|
|
||||||
assert_eq!(
|
|
||||||
alloc_type,
|
|
||||||
crate::alloc::get_or_init_secret_alloc_type(alloc_type)
|
|
||||||
);
|
|
||||||
|
|
||||||
log::info!("Secrets will be allocated using {:?}", alloc_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
pub fn secret_policy_use_only_memfd_secrets() {
|
|
||||||
let alloc_type = crate::alloc::SecretAllocType::MemsecMemfdSec;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
alloc_type,
|
|
||||||
crate::alloc::get_or_init_secret_alloc_type(alloc_type)
|
|
||||||
);
|
|
||||||
|
|
||||||
log::info!("Secrets will be allocated using {:?}", alloc_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn secret_policy_use_only_malloc_secrets() {
|
|
||||||
let alloc_type = crate::alloc::SecretAllocType::MemsecMalloc;
|
|
||||||
assert_eq!(
|
|
||||||
alloc_type,
|
|
||||||
crate::alloc::get_or_init_secret_alloc_type(alloc_type)
|
|
||||||
);
|
|
||||||
|
|
||||||
log::info!("Secrets will be allocated using {:?}", alloc_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod test {
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! test_spawn_process_with_policies {
|
|
||||||
($body:block, $($f: expr),*) => {
|
|
||||||
$(
|
|
||||||
let handle = procspawn::spawn((), |_| {
|
|
||||||
|
|
||||||
$f();
|
|
||||||
|
|
||||||
$body
|
|
||||||
|
|
||||||
});
|
|
||||||
handle.join().unwrap();
|
|
||||||
)*
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! test_spawn_process_provided_policies {
|
|
||||||
($body: block) => {
|
|
||||||
$crate::test_spawn_process_with_policies!(
|
|
||||||
$body,
|
|
||||||
$crate::policy::secret_policy_try_use_memfd_secrets,
|
|
||||||
$crate::secret_policy_use_only_malloc_secrets
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
{
|
|
||||||
$crate::test_spawn_process_with_policies!(
|
|
||||||
$body,
|
|
||||||
$crate::policy::secret_policy_use_only_memfd_secrets
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -321,41 +321,32 @@ impl<const N: usize> StoreSecret for Secret<N> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::test_spawn_process_provided_policies;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::{fs, os::unix::fs::PermissionsExt};
|
use std::{fs, os::unix::fs::PermissionsExt};
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
procspawn::enable_test_support!();
|
|
||||||
|
|
||||||
/// check that we can alloc using the magic pool
|
/// check that we can alloc using the magic pool
|
||||||
#[test]
|
#[test]
|
||||||
fn secret_memory_pool_take() {
|
fn secret_memory_pool_take() {
|
||||||
test_spawn_process_provided_policies!({
|
|
||||||
const N: usize = 0x100;
|
const N: usize = 0x100;
|
||||||
let mut pool = SecretMemoryPool::new();
|
let mut pool = SecretMemoryPool::new();
|
||||||
let secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
let secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
||||||
assert_eq!(secret.as_ref(), &[0; N]);
|
assert_eq!(secret.as_ref(), &[0; N]);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// check that a secret lives, even if its [SecretMemoryPool] is deleted
|
/// check that a secret lives, even if its [SecretMemoryPool] is deleted
|
||||||
#[test]
|
#[test]
|
||||||
fn secret_memory_pool_drop() {
|
fn secret_memory_pool_drop() {
|
||||||
test_spawn_process_provided_policies!({
|
|
||||||
const N: usize = 0x100;
|
const N: usize = 0x100;
|
||||||
let mut pool = SecretMemoryPool::new();
|
let mut pool = SecretMemoryPool::new();
|
||||||
let secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
let secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
||||||
std::mem::drop(pool);
|
std::mem::drop(pool);
|
||||||
assert_eq!(secret.as_ref(), &[0; N]);
|
assert_eq!(secret.as_ref(), &[0; N]);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// check that a secret can be reborn, freshly initialized with zero
|
/// check that a secret can be reborn, freshly initialized with zero
|
||||||
#[test]
|
#[test]
|
||||||
fn secret_memory_pool_release() {
|
fn secret_memory_pool_release() {
|
||||||
test_spawn_process_provided_policies!({
|
|
||||||
const N: usize = 1;
|
const N: usize = 1;
|
||||||
let mut pool = SecretMemoryPool::new();
|
let mut pool = SecretMemoryPool::new();
|
||||||
let mut secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
let mut secret: ZeroizingSecretBox<[u8; N]> = pool.take();
|
||||||
@@ -370,13 +361,11 @@ mod test {
|
|||||||
|
|
||||||
// and that the secret was zeroized
|
// and that the secret was zeroized
|
||||||
assert_eq!(new_secret.as_ref(), &[0; N]);
|
assert_eq!(new_secret.as_ref(), &[0; N]);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// test loading a secret from an example file, and then storing it again in a different file
|
/// test loading a secret from an example file, and then storing it again in a different file
|
||||||
#[test]
|
#[test]
|
||||||
fn test_secret_load_store() {
|
fn test_secret_load_store() {
|
||||||
test_spawn_process_provided_policies!({
|
|
||||||
const N: usize = 100;
|
const N: usize = 100;
|
||||||
|
|
||||||
// Generate original random bytes
|
// Generate original random bytes
|
||||||
@@ -407,13 +396,11 @@ mod test {
|
|||||||
|
|
||||||
// Check that the contents of the new file match the original file
|
// Check that the contents of the new file match the original file
|
||||||
assert_eq!(new_file_contents, original_file_contents);
|
assert_eq!(new_file_contents, original_file_contents);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// test loading a base64 encoded secret from an example file, and then storing it again in a different file
|
/// test loading a base64 encoded secret from an example file, and then storing it again in a different file
|
||||||
#[test]
|
#[test]
|
||||||
fn test_secret_load_store_base64() {
|
fn test_secret_load_store_base64() {
|
||||||
test_spawn_process_provided_policies!({
|
|
||||||
const N: usize = 100;
|
const N: usize = 100;
|
||||||
// Generate original random bytes
|
// Generate original random bytes
|
||||||
let original_bytes: [u8; N] = [rand::random(); N];
|
let original_bytes: [u8; N] = [rand::random(); N];
|
||||||
@@ -462,6 +449,5 @@ mod test {
|
|||||||
//Check new file permissions are secret
|
//Check new file permissions are secret
|
||||||
let metadata = fs::metadata(&new_file).unwrap();
|
let metadata = fs::metadata(&new_file).unwrap();
|
||||||
assert_eq!(metadata.permissions().mode() & 0o000777, 0o600);
|
assert_eq!(metadata.permissions().mode() & 0o000777, 0o600);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ rosenpass-util = { workspace = true }
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = {workspace = true}
|
rand = {workspace = true}
|
||||||
procspawn = {workspace = true}
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
enable_broker_api=[]
|
enable_broker_api=[]
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ impl WireGuardBroker for NetlinkWireGuardBroker {
|
|||||||
fn set_psk(&mut self, config: SerializedBrokerConfig) -> Result<(), Self::Error> {
|
fn set_psk(&mut self, config: SerializedBrokerConfig) -> Result<(), Self::Error> {
|
||||||
let config: NetworkBrokerConfig = config
|
let config: NetworkBrokerConfig = config
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_e| SetPskError::NoSuchInterface)?;
|
.map_err(|e| SetPskError::NoSuchInterface)?;
|
||||||
// Ensure that the peer exists by querying the device configuration
|
// Ensure that the peer exists by querying the device configuration
|
||||||
// TODO: Use InvalidInterfaceError
|
// TODO: Use InvalidInterfaceError
|
||||||
|
|
||||||
|
|||||||
@@ -53,15 +53,10 @@ mod integration_tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
procspawn::enable_test_support!();
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_psk_exchanges() {
|
fn test_psk_exchanges() {
|
||||||
const TEST_RUNS: usize = 100;
|
const TEST_RUNS: usize = 100;
|
||||||
|
|
||||||
use rosenpass_secret_memory::test_spawn_process_provided_policies;
|
|
||||||
|
|
||||||
test_spawn_process_provided_policies!({
|
|
||||||
let server_broker_inner = Arc::new(Mutex::new(MockServerBrokerInner::default()));
|
let server_broker_inner = Arc::new(Mutex::new(MockServerBrokerInner::default()));
|
||||||
// Create a mock BrokerServer
|
// Create a mock BrokerServer
|
||||||
let server_broker = MockServerBroker::new(server_broker_inner.clone());
|
let server_broker = MockServerBroker::new(server_broker_inner.clone());
|
||||||
@@ -135,6 +130,5 @@ mod integration_tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
handle.join().unwrap().unwrap();
|
handle.join().unwrap().unwrap();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user