diff --git a/quicktap/src/drivers/mod.rs b/quicktap/src/drivers/mod.rs index 2b3d588..93e0349 100644 --- a/quicktap/src/drivers/mod.rs +++ b/quicktap/src/drivers/mod.rs @@ -3,7 +3,5 @@ #[cfg(unix)] #[path = "linux.rs"] pub mod tun; // Tun/tap drivers for Linux -#[cfg(unix)] -pub mod linux; pub mod tungeneric; \ No newline at end of file diff --git a/quicktap/src/lib.rs b/quicktap/src/lib.rs index 35c9dbc..8e6fbb5 100644 --- a/quicktap/src/lib.rs +++ b/quicktap/src/lib.rs @@ -1,17 +1,18 @@ //! A simple, almost pure-rust, cross-platform `WireGuard` implementation. -//! Designed to function similarly to boringtun, this crate has modules for cross-platform device drivers, the Noise_IKpsk2 handshake, and cryptography constructs required for the above. +//! Designed to function similarly to boringtun, this crate has modules for cross-platform device drivers, the `Noise_IKpsk2` handshake, and cryptography constructs required for the above. + +#![deny(missing_docs)] #![warn(clippy::pedantic)] #![warn(clippy::nursery)] -#![deny(missing_docs)] #![deny(clippy::unwrap_used)] #![deny(clippy::expect_used)] // This is an annoyance #![allow(clippy::must_use_candidate)] +pub use cidr; + pub mod drivers; pub mod qcrypto; -pub mod noise; - -pub use cidr; \ No newline at end of file +pub mod noise; \ No newline at end of file diff --git a/quicktap/src/noise/handshake/initiator.rs b/quicktap/src/noise/handshake/initiator.rs index 267fe15..8197304 100644 --- a/quicktap/src/noise/handshake/initiator.rs +++ b/quicktap/src/noise/handshake/initiator.rs @@ -1,14 +1,15 @@ //! `Noise_IKpsk2` handshake initiator packets use rand::{Rng, thread_rng}; -use x25519_dalek::{PublicKey}; +use x25519_dalek::PublicKey; + use crate::noise::error::NoiseError; use crate::noise::handshake::{HANDSHAKE_INITIATOR_CHAIN_KEY, HANDSHAKE_INITIATOR_CHAIN_KEY_HASH, HandshakeState, needs_cookie}; +use crate::qcrypto::{LABEL_MAC1, timestamp}; use crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt}; use crate::qcrypto::hashes::{qcrypto_hash_twice, qcrypto_mac}; use crate::qcrypto::hkdf::qcrypto_hkdf; use crate::qcrypto::pki::{qcrypto_dh_generate_longterm, qcrypto_dh_longterm}; -use crate::qcrypto::{LABEL_MAC1, timestamp}; /// Generate a handshake initiator packet and encrypt it using the given session state, starting a new handshake state /// # Errors @@ -16,6 +17,7 @@ use crate::qcrypto::{LABEL_MAC1, timestamp}; /// # Panics /// While containing unwraps, this function will never panic. #[allow(clippy::module_name_repetitions)] +#[allow(clippy::unwrap_used)] // Safe because it is only used for type conversions in known safe ways pub fn handshake_init_to(session: &mut HandshakeState) -> Result<[u8; 148], NoiseError> { session.s_pub_i = PublicKey::from(session.s_priv_me); session.s_pub_r = session.s_pub_them; @@ -57,7 +59,7 @@ pub fn handshake_init_to(session: &mut HandshakeState) -> Result<[u8; 148], Nois session.h = qcrypto_hash_twice(&session.h, &msg.static_pub); - let ci_k_pair = qcrypto_hkdf::<2>(&session.ck, qcrypto_dh_longterm(&session.s_priv_me, &session.s_pub_r).as_bytes()); + let ci_k_pair = qcrypto_hkdf::<2>(&session.ck, qcrypto_dh_longterm(session.s_priv_me, &session.s_pub_r).as_bytes()); session.ck = ci_k_pair[0]; let k = ci_k_pair[1]; @@ -102,6 +104,7 @@ impl HandshakeInitiatorRaw { output } + #[allow(clippy::unwrap_used)] // Only used for type conversions in known safe ways fn from_bytes(bytes: [u8; 148]) -> Self { Self { sender: bytes[4..8].try_into().unwrap(), @@ -120,6 +123,7 @@ impl HandshakeInitiatorRaw { /// # Panics /// While containing unwraps, this function will never panic. #[allow(clippy::module_name_repetitions)] +#[allow(clippy::unwrap_used)] // Only used for type conversions in known safe ways pub fn handshake_init_from(session: &mut HandshakeState, packet: [u8; 148]) -> Result<(), NoiseError> { let s_pub_i = session.s_pub_them; let s_pub_r = PublicKey::from(session.s_priv_me); @@ -140,7 +144,7 @@ pub fn handshake_init_from(session: &mut HandshakeState, packet: [u8; 148]) -> R let h = qcrypto_hash_twice(&h, &msg.ephemeral); - let ci_k_pair = qcrypto_hkdf::<2>(&ck, qcrypto_dh_longterm(&session.s_priv_me, &eph_pub).as_bytes()); + let ci_k_pair = qcrypto_hkdf::<2>(&ck, qcrypto_dh_longterm(session.s_priv_me, &eph_pub).as_bytes()); let ck = ci_k_pair[0]; let k = ci_k_pair[1]; @@ -154,7 +158,7 @@ pub fn handshake_init_from(session: &mut HandshakeState, packet: [u8; 148]) -> R let h = qcrypto_hash_twice(&h, &msg.static_pub); - let ci_k_pair = qcrypto_hkdf::<2>(&ck, qcrypto_dh_longterm(&session.s_priv_me, &session.s_pub_i).as_bytes()); + let ci_k_pair = qcrypto_hkdf::<2>(&ck, qcrypto_dh_longterm(session.s_priv_me, &session.s_pub_i).as_bytes()); let ck = ci_k_pair[0]; let k = ci_k_pair[1]; diff --git a/quicktap/src/noise/handshake/mod.rs b/quicktap/src/noise/handshake/mod.rs index e646eea..a62d2ad 100644 --- a/quicktap/src/noise/handshake/mod.rs +++ b/quicktap/src/noise/handshake/mod.rs @@ -1,8 +1,10 @@ -//! `Noise_IKpsk2` handshake, specifically the way WireGuard defines it +//! `Noise_IKpsk2` handshake, specifically the way `WireGuard` defines it use std::fmt::{Debug, Formatter}; + use rand::rngs::OsRng; use tai64::Tai64N; use x25519_dalek::{PublicKey, StaticSecret}; + use crate::qcrypto::timestamp; pub mod initiator; diff --git a/quicktap/src/noise/handshake/response.rs b/quicktap/src/noise/handshake/response.rs index 2981bb4..c3e9e6a 100644 --- a/quicktap/src/noise/handshake/response.rs +++ b/quicktap/src/noise/handshake/response.rs @@ -1,6 +1,7 @@ //! `Noise_IKpsk2` handshake response packet use x25519_dalek::PublicKey; + use crate::noise::error::NoiseError; use crate::noise::handshake::{HandshakeState, needs_cookie}; use crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt}; @@ -14,6 +15,7 @@ use crate::qcrypto::pki::{qcrypto_dh_generate_longterm, qcrypto_dh_longterm}; /// This function will error if an encryption step is unsuccessful /// # Panics /// This function, while containing unwraps, will never panic. +#[allow(clippy::unwrap_used)] // Used for known safe type conversions only pub fn handshake_response_to(session: &mut HandshakeState) -> Result<[u8; 92], NoiseError> { let eph_keypair = qcrypto_dh_generate_longterm(); @@ -67,7 +69,7 @@ pub fn handshake_response_from(session: &mut HandshakeState, packet: [u8; 92]) - let mut h = qcrypto_hash_twice(&session.h, &msg.ephemeral); ck = qcrypto_hkdf::<1>(&ck, qcrypto_dh_longterm(&session.e_priv_me, &e_pub_r).as_bytes())[0]; - ck = qcrypto_hkdf::<1>(&ck, qcrypto_dh_longterm(&session.s_priv_me, &e_pub_r).as_bytes())[0]; + ck = qcrypto_hkdf::<1>(&ck, qcrypto_dh_longterm(session.s_priv_me, &e_pub_r).as_bytes())[0]; let cr_t_k = qcrypto_hkdf::<3>(&ck, &session.q); ck = cr_t_k[0]; @@ -108,7 +110,7 @@ struct HandshakeResponseRaw { sender: [u8; 4], receiver: [u8; 4], ephemeral: [u8; 32], - empty: [u8; 0 + 16], + empty: [u8; 16], mac1: [u8; 16], mac2: [u8; 16] } @@ -133,6 +135,7 @@ impl HandshakeResponseRaw { output_array } + #[allow(clippy::unwrap_used)] // Only used for type conversions in known safe ways fn from_bytes(packet: [u8; 92]) -> Self { Self { sender: packet[4..8].try_into().unwrap(), diff --git a/quicktap/src/noise/handshake/tests.rs b/quicktap/src/noise/handshake/tests.rs index c083ee2..036f26b 100644 --- a/quicktap/src/noise/handshake/tests.rs +++ b/quicktap/src/noise/handshake/tests.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unwrap_used)] // this is a test harness, we want to panic + use crate::noise::handshake::HandshakeState; use crate::noise::handshake::initiator::{handshake_init_from, handshake_init_to}; use crate::noise::handshake::response::{handshake_response_from, handshake_response_to}; diff --git a/quicktap/src/noise/mod.rs b/quicktap/src/noise/mod.rs index e9e3167..fff7a3f 100644 --- a/quicktap/src/noise/mod.rs +++ b/quicktap/src/noise/mod.rs @@ -1,3 +1,3 @@ -//! Contains structs and functions for serializing and deserializing different packets in the Noise_IKpsk2 handshake and data frames +//! Contains structs and functions for serializing and deserializing different packets in the `Noise_IKpsk2` handshake and data frames pub mod handshake; pub mod error; \ No newline at end of file diff --git a/quicktap/src/qcrypto/aead.rs b/quicktap/src/qcrypto/aead.rs index 990840b..940d8c1 100644 --- a/quicktap/src/qcrypto/aead.rs +++ b/quicktap/src/qcrypto/aead.rs @@ -1,14 +1,15 @@ -//! Various functions for ChaCha20Poly1305 stream ciphers +//! Various functions for `ChaCha20Poly1305` stream ciphers use chacha20poly1305::{ChaCha20Poly1305, Error, KeyInit, XChaCha20Poly1305}; -use chacha20poly1305::aead::{Aead, Payload, Nonce}; +use chacha20poly1305::aead::{Aead, Nonce, Payload}; -/// Encrypt the plaintext with the given parameters using ChaCha20Poly1305 +/// Encrypt the plaintext with the given parameters using `ChaCha20Poly1305` /// # Errors /// This function will error if the encryption was unsuccessful /// # Panics /// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array. #[allow(clippy::module_name_repetitions)] +#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array pub fn qcrypto_aead(key: &[u8; 32], counter: u64, plaintext: &[u8], authtext: &[u8]) -> Result, Error> { let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap(); let mut nonce_bytes = [0u8; 12]; @@ -19,11 +20,12 @@ pub fn qcrypto_aead(key: &[u8; 32], counter: u64, plaintext: &[u8], authtext: &[ cipher.encrypt(&Nonce::::from(nonce_bytes), payload) } -/// Decrypt the ciphertext with the given parameters using ChaCha20Poly1305 +/// Decrypt the ciphertext with the given parameters using `ChaCha20Poly1305` /// # Errors /// This function will error if the decryption was unsuccessful /// # Panics /// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array. +#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array pub fn qcrypto_aead_decrypt(key: &[u8; 32], counter: u64, ciphertext: &[u8], authtext: &[u8]) -> Result, Error> { let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap(); let mut nonce_bytes = [0u8; 12]; @@ -34,11 +36,12 @@ pub fn qcrypto_aead_decrypt(key: &[u8; 32], counter: u64, ciphertext: &[u8], aut cipher.decrypt(&Nonce::::from(nonce_bytes), payload) } -/// Encrypt the ciphertext with the given parameters using XChaCha20Poly1305 +/// Encrypt the ciphertext with the given parameters using `XChaCha20Poly1305` /// # Errors /// This function will error if the decryption was unsuccessful /// # Panics /// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array. +#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array pub fn qcrypto_xaead(key: &[u8; 32], nonce: &[u8; 24], plaintext: &[u8], authtext: &[u8]) -> Result, Error> { let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap(); let mut payload = Payload::from(plaintext); @@ -47,11 +50,12 @@ pub fn qcrypto_xaead(key: &[u8; 32], nonce: &[u8; 24], plaintext: &[u8], authtex cipher.encrypt(Nonce::::from_slice(nonce), payload) } -/// Decrypt the ciphertext with the given parameters using XChaCha20Poly1305 +/// Decrypt the ciphertext with the given parameters using `XChaCha20Poly1305` /// # Errors /// This function will error if the decryption was unsuccessful /// # Panics /// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array. +#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array pub fn qcrypto_xaead_decrypt(key: &[u8; 32], nonce: &[u8; 24], ciphertext: &[u8], authtext: &[u8]) -> Result, Error> { let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap(); let mut payload = Payload::from(ciphertext); diff --git a/quicktap/src/qcrypto/hashes.rs b/quicktap/src/qcrypto/hashes.rs index 33e3289..df768ba 100644 --- a/quicktap/src/qcrypto/hashes.rs +++ b/quicktap/src/qcrypto/hashes.rs @@ -1,7 +1,7 @@ //! Various hash functions use blake2::{Blake2s256, Blake2sMac, Digest}; -use blake2::digest::{KeyInit, FixedOutput, Update}; +use blake2::digest::{FixedOutput, KeyInit, Update}; use hmac::SimpleHmac; type HmacBlake2s = SimpleHmac; @@ -24,6 +24,7 @@ pub fn qcrypto_hash_twice(input: &[u8], input2: &[u8]) -> [u8; 32] { /// Given a varied length MAC key and a varied length input, produce a 16-byte MAC digest using Blake2s /// # Panics /// This function will panic if the key is an incorrect size. +#[allow(clippy::unwrap_used)] // Safe because a panic indicates a bug in quicktap pub fn qcrypto_mac(key: &[u8], input: &[u8]) -> [u8; 16] { let mut hasher = Blake2sMac::new_from_slice(key).unwrap(); hasher.update(input); @@ -33,6 +34,7 @@ pub fn qcrypto_mac(key: &[u8], input: &[u8]) -> [u8; 16] { /// Given a varied length HMAC key and a varied length input, produce a 32-byte HMAC digest using Blake2s /// # Panics /// This function will panic if the key is an incorrect size. +#[allow(clippy::unwrap_used)] // Safe because a panic indicates a bug in quicktap pub fn qcrypto_hmac(key: &[u8], input: &[u8]) -> [u8; 32] { let mut hasher = HmacBlake2s::new_from_slice(key).unwrap(); Update::update(&mut hasher, input); @@ -43,6 +45,7 @@ pub fn qcrypto_hmac(key: &[u8], input: &[u8]) -> [u8; 32] { /// This does essentially the same thing as concatenating input2 to input and calling `qcrypto_hmac` on that. /// # Panics /// This function will panic if the key is an incorrect size. +#[allow(clippy::unwrap_used)] // Safe because a panic indicates a bug in quicktap pub fn qcrypto_hmac_twice(key: &[u8], input: &[u8], input2: &[u8]) -> [u8; 32] { let mut hasher = HmacBlake2s::new_from_slice(key).unwrap(); Update::update(&mut hasher, input); diff --git a/quicktap/src/qcrypto/mod.rs b/quicktap/src/qcrypto/mod.rs index 2e6e86a..d3e3d8d 100644 --- a/quicktap/src/qcrypto/mod.rs +++ b/quicktap/src/qcrypto/mod.rs @@ -17,7 +17,7 @@ pub fn timestamp() -> Tai64N { /// The cryptography handshake construction identifier pub const CONSTURCTION: &str = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; -/// The WireGuard protocol identifier +/// The `WireGuard` protocol identifier pub const IDENTIFIER: &str = "WireGuard v1 zx2c4 Jason@zx2c4.com"; /// The MAC1 cookie label pub const LABEL_MAC1: &str = "mac1----"; diff --git a/quicktap/src/qcrypto/tests.rs b/quicktap/src/qcrypto/tests.rs index 0ff5e02..0734c80 100644 --- a/quicktap/src/qcrypto/tests.rs +++ b/quicktap/src/qcrypto/tests.rs @@ -1,10 +1,13 @@ +#![allow(clippy::unwrap_used)] // we want to panic, this is a test file + use hex_lit::hex; -use x25519_dalek::{PublicKey}; -use crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt, qcrypto_xaead, qcrypto_xaead_decrypt}; +use x25519_dalek::PublicKey; + use crate::qcrypto::{CONSTURCTION, IDENTIFIER}; +use crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt, qcrypto_xaead, qcrypto_xaead_decrypt}; use crate::qcrypto::hashes::{qcrypto_hash, qcrypto_hash_twice, qcrypto_hmac, qcrypto_mac}; use crate::qcrypto::hkdf::qcrypto_hkdf; -use crate::qcrypto::pki::{qcrypto_dh_longterm, qcrypto_dh_generate_longterm}; +use crate::qcrypto::pki::{qcrypto_dh_generate_longterm, qcrypto_dh_longterm}; #[test] fn qcrypto_hash_test() {