diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..5bcbefd --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + println!("cargo:rustc-link-search=/home/rixxc/Work/Jasmin/libjade/src/"); +} diff --git a/default.nix b/default.nix index 992e52c..00e6b01 100644 --- a/default.nix +++ b/default.nix @@ -6,21 +6,46 @@ }: with pkgs; let + jasmin-src = fetchFromGitHub { + owner = "Rixxc"; + repo = "jasmin"; + rev = "783aea97836f5ddf7b62de24ab94768cb606adf8"; + hash = "sha256-5XXZ2IYXCixJHaswdYkG8ivh3fIftaibOgkpz2TKGMI="; + }; + + jasmin-drv = callPackage "${jasmin-src}/default.nix" { inherit pkgs; }; + jasminc = jasmin-drv.overrideAttrs { + name = "jasmin with syscalls"; + buildPhase = '' + make -C compiler/ CIL + make -C compiler/ + ''; + }; + agent = callPackage "${fetchgit { url = "https://gitea.rixxc.de/rixxc/agent_harness.git"; rev = "d2154ade95b88fe90709cdb12a35da50e0ddb5ee"; hash = "sha256-low2S2z5vaFSS6ZdDVaxJdwBZk+mjXaG2zhConCWQPQ="; }}/default.nix" { inherit pkgs; }; + + libjade = callPackage "${fetchFromGitHub { + owner = "formosa-crypto"; + repo = "libjade"; + rev = "b0940068243f01dc3c185d166f1450936eec3eed"; + hash = "sha256-w71QmJn5TG1cJ+SGXJyjh86uge177uRGSvwgnJXpKYg="; + }}/default.nix" + { inherit pkgs jasminc; }; in rustPlatform.buildRustPackage { name = "wireguard-agent"; src = nix-gitignore.gitignoreSource [ ] ./.; - nativeBuildInputs = [ - (rust-bin.fromRustupToolchainFile ./rust-toolchain.toml) + nativeBuildInputs = [ + (rust-bin.fromRustupToolchainFile ./rust-toolchain.toml) agent + libjade ]; cargoLock = { diff --git a/src/wireguard/handshake/noise.rs b/src/wireguard/handshake/noise.rs index 92c8c5f..c082c8c 100644 --- a/src/wireguard/handshake/noise.rs +++ b/src/wireguard/handshake/noise.rs @@ -212,19 +212,31 @@ mod tests { } } +#[link(name = "jade")] +extern "C" { + fn jade_scalarmult_curve25519_amd64_mulx( + out: *mut [u8; 32], + sk: *const [u8; 32], + pk: *const [u8; 32], + ); +} + // Computes an X25519 shared secret. // // This function wraps dalek to add a zero-check. // This is not recommended by the Noise specification, // but implemented in the kernel with which we strive for absolute equivalent behavior. #[inline(always)] -fn shared_secret(sk: &StaticSecret, pk: &PublicKey) -> Result { - let ss = sk.diffie_hellman(pk); - if ss.as_bytes().ct_eq(&[0u8; 32]).into() { - Err(HandshakeError::InvalidSharedSecret) - } else { - Ok(ss) +fn shared_secret(sk: &StaticSecret, pk: &PublicKey) -> Result<[u8; 32], HandshakeError> { + let mut ss = [0u8; 32]; + unsafe { + jade_scalarmult_curve25519_amd64_mulx( + ss.as_mut_ptr() as *mut [u8; 32], + sk.to_bytes().as_ptr() as *const [u8; 32], + pk.to_bytes().as_ptr() as *const [u8; 32], + ); } + Ok(ss) } pub(super) fn create_initiation( @@ -271,7 +283,7 @@ pub(super) fn create_initiation( // (C, k) := Kdf2(C, DH(E_priv, S_pub)) - let (ck, key) = KDF2!(&ck, shared_secret(&eph_sk, &pk)?.as_bytes()); + let (ck, key) = KDF2!(&ck, &shared_secret(&eph_sk, &pk)?); // msg.static := Aead(k, 0, S_pub, H) @@ -341,7 +353,7 @@ pub(super) fn consume_initiation<'a, O>( // (C, k) := Kdf2(C, DH(E_priv, S_pub)) let eph_r_pk = PublicKey::from(msg.f_ephemeral); - let (ck, key) = KDF2!(&ck, shared_secret(&keyst.sk, &eph_r_pk)?.as_bytes()); + let (ck, key) = KDF2!(&ck, &shared_secret(&keyst.sk, &eph_r_pk)?); // msg.static := Aead(k, 0, S_pub, H) @@ -387,7 +399,7 @@ pub(super) fn consume_initiation<'a, O>( // check and update timestamp - peer.check_replay_flood(device, &ts)?; + // peer.check_replay_flood(device, &ts)?; // H := Hash(H || msg.timestamp) @@ -440,11 +452,11 @@ pub(super) fn create_response( // C := Kdf1(C, DH(E_priv, E_pub)) - let ck = KDF1!(&ck, shared_secret(&eph_sk, &eph_r_pk)?.as_bytes()); + let ck = KDF1!(&ck, &shared_secret(&eph_sk, &eph_r_pk)?); // C := Kdf1(C, DH(E_priv, S_pub)) - let ck = KDF1!(&ck, shared_secret(&eph_sk, &pk)?.as_bytes()); + let ck = KDF1!(&ck, &shared_secret(&eph_sk, &pk)?); // (C, tau, k) := Kdf3(C, Q) @@ -522,11 +534,11 @@ pub(super) fn consume_response<'a, O>( // C := Kdf1(C, DH(E_priv, E_pub)) let eph_r_pk = PublicKey::from(msg.f_ephemeral); - let ck = KDF1!(&ck, shared_secret(&eph_sk, &eph_r_pk)?.as_bytes()); + let ck = KDF1!(&ck, &shared_secret(&eph_sk, &eph_r_pk)?); // C := Kdf1(C, DH(E_priv, S_pub)) - let ck = KDF1!(&ck, shared_secret(&keyst.sk, &eph_r_pk)?.as_bytes()); + let ck = KDF1!(&ck, &shared_secret(&keyst.sk, &eph_r_pk)?); // (C, tau, k) := Kdf3(C, Q)