diff --git a/flake.nix b/flake.nix index dc288ee..139dc5f 100644 --- a/flake.nix +++ b/flake.nix @@ -62,6 +62,7 @@ gawk wireguard-tools ]; + # a function to generate a nix derivation for rosenpass against any # given set of nixpkgs rpDerivation = p: @@ -89,6 +90,11 @@ # otherwise pkg-config tries to link non-existent dynamic libs PKG_CONFIG_ALL_STATIC = true; + # 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_ + RUST_MIN_STACK = 8 * 1024 * 1024; # 8 MiB + # nix defaults to building for aarch64 _without_ the armv8-a # crypto extensions, but liboqs depens on these preBuild = @@ -241,6 +247,7 @@ # devShells.default = pkgs.mkShell { inherit (packages.proof-proverif) CRYPTOVERIF_LIB; + inherit (packages.rosenpass) RUST_MIN_STACK; inputsFrom = [ packages.default ]; nativeBuildInputs = with pkgs; [ cargo-release @@ -252,6 +259,7 @@ }; devShells.coverage = pkgs.mkShell { inputsFrom = [ packages.default ]; + inherit (packages.rosenpass) RUST_MIN_STACK; nativeBuildInputs = with pkgs; [ inputs.fenix.packages.${system}.complete.toolchain cargo-llvm-cov ]; }; diff --git a/src/protocol.rs b/src/protocol.rs index b013ea6..9753517 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -775,6 +775,8 @@ impl CryptoServer { let mut len = 0; let mut exchanged = false; + ensure!(!rx_buf.is_empty(), "received empty message, ignoring it"); + let peer = match rx_buf[0].try_into() { Ok(MsgType::InitHello) => { let msg_in = rx_buf.envelope::>()?; @@ -1693,3 +1695,32 @@ impl CryptoServer { Ok(hs.peer()) } } + +#[cfg(test)] +mod test { + use super::*; + + fn init_crypto_server() -> CryptoServer { + // always init libsodium before anything + crate::sodium::sodium_init().unwrap(); + + // initialize public and private key for the crypto server + let (mut sk, mut pk) = (SSk::zero(), SPk::zero()); + StaticKEM::keygen(sk.secret_mut(), pk.secret_mut()).expect("unable to generate keys"); + + CryptoServer::new(sk, pk) + } + + /// The determination of the message type relies on reading the first byte of the message. Only + /// after that the length of the message is checked against the specified message type. This + /// test ensures that nothing breaks in the case of an empty message. + #[test] + #[should_panic = "called `Result::unwrap()` on an `Err` value: received empty message, ignoring it"] + fn handle_empty_message() { + let mut crypt = init_crypto_server(); + let empty_rx_buf = [0u8; 0]; + let mut tx_buf = [0u8; 0]; + + crypt.handle_msg(&empty_rx_buf, &mut tx_buf).unwrap(); + } +}