From 9154c997fa8b9ffc04c5924c572283723795b011 Mon Sep 17 00:00:00 2001 From: Mathias Hall-Andersen Date: Wed, 10 Jul 2019 18:22:48 +0200 Subject: Encoding / decoding of messages --- .gitignore | 2 + Cargo.lock | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 11 +++ src/lib.rs | 11 +++ src/machine.rs | 54 +++++++++++++++ src/messages.rs | 111 ++++++++++++++++++++++++++++++ 6 files changed, 398 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/lib.rs create mode 100644 src/machine.rs create mode 100644 src/messages.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..53eaa21 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +**/*.rs.bk diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..76201a3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,209 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "byteorder" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clear_on_drop" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curve25519-dalek" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gcc" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "generic-array" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "subtle" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wg-handshake" +version = "0.1.0" +dependencies = [ + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "x25519-dalek" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ad0daef304fa0b4238f5f7ed7178774b43b06f6a9b6509f6642bef4ff1f7b9b2" +"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" +"checksum curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1f8a6fc0376eb52dc18af94915cc04dfdf8353746c0e8c550ae683a0815e5c1" +"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum x25519-dalek 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4aca1ba6bec2719576bd20dfe5b24d9359552e616d10bff257e50cd85f745d17" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b4363ca --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "wg-handshake" +version = "0.1.0" +authors = ["Mathias Hall-Andersen "] +edition = "2018" + +[dependencies] +rust-crypto = "0.2.36" + +[dependencies.x25519-dalek] +version = "^0.5" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a1aa18a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,11 @@ +mod messages; +mod machine; + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} + diff --git a/src/machine.rs b/src/machine.rs new file mode 100644 index 0000000..a9a3904 --- /dev/null +++ b/src/machine.rs @@ -0,0 +1,54 @@ +use x25519_dalek::PublicKey; +use x25519_dalek::StaticSecret; +use x25519_dalek::SharedSecret; + +/* Mutable part of handshake state */ +enum StateMutable { + Reset, + InitiationSent, + InitiationProcessed, + ReponseSent +} + +/* Immutable part of the handshake state */ +struct StateFixed { + sk : StaticSecret, + pk : PublicKey, + ss : SharedSecret +} + +struct State { + m : StateMutable, + f : StateFixed, +} + +struct KeyPair { + send : [u8; 32], + recv : [u8; 32] +} + +impl State { + /* Initialize a new handshake state machine + */ + fn new(sk : StaticSecret, pk : PublicKey) -> State { + let ss = sk.diffie_hellman(&pk); + State { + m : StateMutable::Reset, + f : StateFixed{sk, pk, ss} + } + } + + /* Begin a new handshake, returns the initial handshake message + */ + fn begin(&self) -> Vec { + vec![] + } + + /* Process a handshake message. + * + * Result is either a new state (and optionally a new key pair) or an error + */ + fn process(&self, msg : &[u8]) -> Result<(State, Option), ()> { + Err(()) + } +} diff --git a/src/messages.rs b/src/messages.rs new file mode 100644 index 0000000..c9c4239 --- /dev/null +++ b/src/messages.rs @@ -0,0 +1,111 @@ +use std::mem; + +const SIZE_TAG : usize = 16; +const SIZE_X25519_POINT : usize = 32; +const SIZE_TIMESTAMP : usize = 12; + +pub const SIZE_MESSAGE_INITIATE : usize = 116; +pub const SIZE_MESSAGE_RESPONSE : usize = 116; + +pub const TYPE_INITIATE : u8 = 1; +pub const TYPE_RESPONSE : u8 = 2; + +/* Wireguard handshake initiation message + * initator -> responder + */ +#[repr(C)] +#[derive(Copy, Clone)] +struct MessageInitiate { + f_type : u32, + f_sender : u32, + f_ephemeral : [u8; SIZE_X25519_POINT], + f_static : [u8; SIZE_X25519_POINT + SIZE_TAG], + f_timestamp : [u8; SIZE_TIMESTAMP + SIZE_TAG], +} + +impl From<&[u8]> for MessageInitiate { + fn from(b: &[u8]) -> Self { + // create owned copy + let mut owned = [0u8; mem::size_of::()]; + let mut msg : Self; + owned.copy_from_slice(b); + + // cast to MessageInitiate + unsafe { + msg = mem::transmute::<[u8; mem::size_of::()], Self>(owned); + }; + + // correct endianness + msg.f_type = msg.f_type.to_le(); + msg.f_sender = msg.f_sender.to_le(); + msg + } +} + +impl Into> for MessageInitiate { + fn into(self) -> Vec { + // correct endianness + let mut msg = self; + msg.f_type = msg.f_type.to_le(); + msg.f_sender = msg.f_sender.to_le(); + + // cast to array + let array : [u8; mem::size_of::()]; + unsafe { + array = mem::transmute::()]>(msg) + }; + + array.to_vec() + } +} + +/* Wireguard handshake responder message + * responder -> initator + */ +#[repr(C)] +#[derive(Copy, Clone)] +struct MessageResponse { + f_type : u32, + f_sender : u32, + f_receiver : u32, + f_ephemeral : [u8; SIZE_X25519_POINT], + f_empty : [u8; SIZE_TAG], +} + +impl From<&[u8]> for MessageResponse { + fn from(b: &[u8]) -> Self { + // create owned copy + let mut owned = [0u8; mem::size_of::()]; + let mut msg : Self; + owned.copy_from_slice(b); + + // cast to MessageInitiate + unsafe { + msg = mem::transmute::<[u8; mem::size_of::()], Self>(owned); + }; + + // correct endianness + msg.f_type = msg.f_type.to_le(); + msg.f_sender = msg.f_sender.to_le(); + msg.f_receiver = msg.f_receiver.to_le(); + msg + } +} + +impl Into> for MessageResponse { + fn into(self) -> Vec { + // correct endianness + let mut msg = self; + msg.f_type = msg.f_type.to_le(); + msg.f_sender = msg.f_sender.to_le(); + msg.f_receiver = msg.f_receiver.to_le(); + + // cast to array + let array : [u8; mem::size_of::()]; + unsafe { + array = mem::transmute::()]>(msg) + }; + + array.to_vec() + } +} -- cgit v1.2.3-59-g8ed1b