diff --git a/Cargo.lock b/Cargo.lock index 4d18b7725d34d9cfdb48a180ea50c44258638546..68471a45ab6cd3484a2fa44925ce5a08ffd3a34f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -669,15 +669,6 @@ dependencies = [ "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ctor" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "derive_more" version = "0.14.1" @@ -1495,11 +1486,6 @@ dependencies = [ "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "half" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "hashbrown" version = "0.6.3" @@ -2011,14 +1997,6 @@ dependencies = [ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "output_vt100" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot" version = "0.9.0" @@ -2117,23 +2095,6 @@ name = "pkg-config" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "pkstl" -version = "0.1.0" -dependencies = [ - "bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "chacha20-poly1305-aead 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ppv-lite86" version = "0.2.6" @@ -2174,17 +2135,6 @@ dependencies = [ "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "pretty_assertions" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "proc-macro-error" version = "0.2.6" @@ -2614,16 +2564,6 @@ dependencies = [ "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "serde_cbor" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "serde_derive" version = "1.0.103" @@ -3433,7 +3373,6 @@ dependencies = [ "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -"checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" "checksum derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6d944ac6003ed268757ef1ee686753b57efc5fcf0ebe7b64c9fc81e7e32ff839" "checksum derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" @@ -3462,7 +3401,6 @@ dependencies = [ "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum graphql-parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a5613c31f18676f164112732202124f373bb2103ff017b3b85ca954ea6a66ada" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" -"checksum half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ff54597ea139063f4225f1ec47011b03c9de4a486957ff3fc506881dac951d0" "checksum hashbrown 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e6073d0ca812575946eb5f35ff68dbe519907b25c42530389ff946dc84c6ead" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" @@ -3521,7 +3459,6 @@ dependencies = [ "checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f" "checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" "checksum os_type 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7edc011af0ae98b7f88cf7e4a83b70a54a75d2b8cb013d6efd02e5956207e9eb" -"checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" @@ -3538,7 +3475,6 @@ dependencies = [ "checksum predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178" "checksum predicates-tree 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" -"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" @@ -3586,7 +3522,6 @@ dependencies = [ "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" -"checksum serde_cbor 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7081ed758ec726a6ed8ee7e92f5d3f6e6f8c3901b1f972e3a4a2f2599fad14f" "checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" "checksum serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" "checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" diff --git a/Cargo.toml b/Cargo.toml index 078c9139021e40696bfac6f6d08688d6cce9bf72..43874c823dedd5fd6c3ff3fc1626aa77e8b69bb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,6 @@ members = [ "lib/tools/common-tools", "lib/tools/dbs-tools", "lib/tools/json-pest-parser", - "lib/tools/pkstl", "lib/tools/rules-engine", ] diff --git a/lib/tools/pkstl/Cargo.toml b/lib/tools/pkstl/Cargo.toml deleted file mode 100644 index 85a5fdcb75f984de89d794975b7f7401d45885dc..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "pkstl" -version = "0.1.0" -authors = ["elois <elois@duniter.org>"] -description = "Public Key Secure Transport Layer." -repository = "https://git.duniter.org/nodes/rust/duniter-rs" -readme = "README.md" -keywords = ["security", "transport", "cryptography"] -license = "AGPL-3.0" -edition = "2018" - -[lib] -path = "src/lib.rs" - -[dependencies] -bincode = { version = "1.2.0", optional = true } -chacha20-poly1305-aead = "0.1.2" -clear_on_drop = "0.2.3" -failure = "0.1.5" -flate2 = { version = "1.0.11", optional = true } -ring = "0.16.9" -serde = { version = "1.0.*", features = ["derive"], optional = true } -serde_cbor = { version = "0.10.2", optional = true } -serde_json = { version = "1.0.40", optional = true } -log = "0.4.*" - -[dev-dependencies] -pretty_assertions = "0.6.1" - -[features] -default = ["zip-sign"] -zip-sign = ["flate2"] -ser = ["zip-sign", "serde"] -bin = ["bincode", "ser"] -cbor = ["serde_cbor", "ser"] -json = ["serde_json", "ser"] diff --git a/lib/tools/pkstl/src/agreement.rs b/lib/tools/pkstl/src/agreement.rs deleted file mode 100644 index f9f176c67f845006d8f823b29a37fe2a9861263a..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/agreement.rs +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage cryptographic agreement operations. - -use crate::seeds::{Seed32, Seed48, Seed64}; -use crate::{Error, Result}; -use ring::{agreement, pbkdf2, rand}; -use std::num::NonZeroU32; - -const ITERATIONS: u32 = 3; - -#[derive(Clone, Copy, Debug)] -pub enum SharedSecretLen { - B32, - B48, - B64, -} - -impl SharedSecretLen { - fn algo(self) -> pbkdf2::Algorithm { - match self { - Self::B32 => pbkdf2::PBKDF2_HMAC_SHA256, - Self::B48 => pbkdf2::PBKDF2_HMAC_SHA384, - Self::B64 => pbkdf2::PBKDF2_HMAC_SHA512, - } - } -} - -pub enum SharedSecret { - B32(Seed32), - B48(Seed48), - B64(Seed64), -} - -impl AsMut<[u8]> for SharedSecret { - fn as_mut(&mut self) -> &mut [u8] { - match self { - Self::B32(seed) => seed.as_mut(), - Self::B48(seed) => seed.as_mut(), - Self::B64(seed) => seed.as_mut(), - } - } -} - -impl SharedSecret { - fn new(len: SharedSecretLen) -> Self { - match len { - SharedSecretLen::B32 => SharedSecret::B32(Seed32::default()), - SharedSecretLen::B48 => SharedSecret::B48(Seed48::default()), - SharedSecretLen::B64 => SharedSecret::B64(Seed64::default()), - } - } -} - -#[derive(Clone, Debug)] -/// Ephemeral public key used once to generate shared secret -pub struct EphemeralPublicKey(agreement::PublicKey); - -impl AsRef<[u8]> for EphemeralPublicKey { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -/// Ephemeral key pair used once to generate shared secret -#[derive(Debug)] -pub struct EphemeralKeyPair { - privkey: agreement::EphemeralPrivateKey, - pubkey: EphemeralPublicKey, -} - -impl EphemeralKeyPair { - /// Generate ephemeral key pair - pub fn generate() -> Result<Self> { - let rng = rand::SystemRandom::new(); - let privkey = agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng) - .map_err(|_| Error::FailToGenEphemerKeyPair)?; - let pubkey = EphemeralPublicKey( - privkey - .compute_public_key() - .map_err(|_| Error::FailToGenEphemerPubKey)?, - ); - - Ok(EphemeralKeyPair { privkey, pubkey }) - } - /// Get ephemeral public key - pub fn public_key(&self) -> &EphemeralPublicKey { - &self.pubkey - } - /// Compute shared secret - pub fn compute_shared_secret( - self, - other_ephemeral_public_key: &[u8], - shared_secret_len: SharedSecretLen, - ) -> Result<SharedSecret> { - let salt = if self.pubkey.as_ref() > other_ephemeral_public_key { - self.pubkey.as_ref() - } else { - other_ephemeral_public_key - }; - - agreement::agree_ephemeral( - self.privkey, - &agreement::UnparsedPublicKey::new(&agreement::X25519, other_ephemeral_public_key), - Error::FailToComputeAgreement, - |key_material| Ok(derive(key_material, salt, shared_secret_len)), - ) - } -} - -fn derive(seed: &[u8], salt: &[u8], shared_secret_len: SharedSecretLen) -> SharedSecret { - let mut shared_secret = SharedSecret::new(shared_secret_len); - pbkdf2::derive( - shared_secret_len.algo(), - NonZeroU32::new(ITERATIONS).expect("ITERATIONS must be > 0"), - salt, - seed, - shared_secret.as_mut(), - ); - shared_secret -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn test_exchange_dh_shared_secret_48b() -> Result<()> { - let ephemeral_kp_server = EphemeralKeyPair::generate()?; - let ephemeral_kp_client = EphemeralKeyPair::generate()?; - - let ephemeral_pk_server = ephemeral_kp_server.public_key().clone(); - let ephemeral_pk_client = ephemeral_kp_client.public_key().clone(); - - // Sharer secret of 48 bytes - let mut shared_secret_server_48b = ephemeral_kp_server.compute_shared_secret( - ephemeral_kp_client.public_key().as_ref(), - SharedSecretLen::B48, - )?; - - let mut shared_secret_client_48b = ephemeral_kp_client - .compute_shared_secret(ephemeral_pk_server.as_ref(), SharedSecretLen::B48)?; - - assert_eq!( - shared_secret_server_48b.as_mut().to_vec(), - shared_secret_client_48b.as_mut().to_vec() - ); - - println!("ephemeral_pk_server={:?}", ephemeral_pk_server.as_ref()); - println!("ephemeral_pk_client={:?}", ephemeral_pk_client.as_ref()); - println!( - "shared_secret_server={:?}", - shared_secret_server_48b.as_mut() - ); - println!( - "shared_secret_client={:?}", - shared_secret_client_48b.as_mut() - ); - - Ok(()) - } - - #[test] - fn test_exchange_dh_shared_secret_64b() -> Result<()> { - let ephemeral_kp_server = EphemeralKeyPair::generate()?; - let ephemeral_kp_client = EphemeralKeyPair::generate()?; - - let ephemeral_pk_server = ephemeral_kp_server.public_key().clone(); - let ephemeral_pk_client = ephemeral_kp_client.public_key().clone(); - - // Sharer secret of 64 bytes - let mut shared_secret_server_64b = ephemeral_kp_server.compute_shared_secret( - ephemeral_kp_client.public_key().as_ref(), - SharedSecretLen::B64, - )?; - - let mut shared_secret_client_64b = ephemeral_kp_client - .compute_shared_secret(ephemeral_pk_server.as_ref(), SharedSecretLen::B64)?; - - assert_eq!( - shared_secret_server_64b.as_mut().to_vec(), - shared_secret_client_64b.as_mut().to_vec() - ); - - println!("ephemeral_pk_server={:?}", ephemeral_pk_server.as_ref()); - println!("ephemeral_pk_client={:?}", ephemeral_pk_client.as_ref()); - println!( - "shared_secret_server={:?}", - shared_secret_server_64b.as_mut() - ); - println!( - "shared_secret_client={:?}", - shared_secret_client_64b.as_mut() - ); - - Ok(()) - } -} diff --git a/lib/tools/pkstl/src/complete.rs b/lib/tools/pkstl/src/complete.rs deleted file mode 100644 index ee8ebb7ff67f5914dbae69423822be1feb1d4cf6..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/complete.rs +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage complete secure and decentralized transport layer. - -pub mod message; -#[cfg(feature = "ser")] -pub mod serde; -pub mod writer; - -#[cfg(feature = "ser")] -pub use self::serde::IncomingMessage; - -use crate::{Error, Message, MinimalSecureLayer, Result, SecureLayerConfig, Seed32}; -use flate2::write::{DeflateDecoder, DeflateEncoder}; -use message::IncomingBinaryMessage; -use ring::signature::Ed25519KeyPair; -use std::io::{BufWriter, Write}; - -#[cfg(feature = "ser")] -use ::serde::de::DeserializeOwned; -#[cfg(feature = "ser")] -use ::serde::Serialize; -#[cfg(feature = "ser")] -use std::fmt::Debug; - -/// Secure layer -#[derive(Debug)] -pub struct SecureLayer { - minimal_secure_layer: MinimalSecureLayer, - sig_key_pair: Option<Ed25519KeyPair>, -} - -impl SecureLayer { - /// Try to clone, The negotiation must have been successful - pub fn try_clone(&mut self) -> Result<Self> { - let msl_clone = self.minimal_secure_layer.try_clone()?; - - Ok(SecureLayer { - minimal_secure_layer: msl_clone, - sig_key_pair: None, - }) - } - /// Change configuration - #[inline] - pub fn change_config(&mut self, new_config: SecureLayerConfig) -> Result<()> { - self.minimal_secure_layer.change_config(new_config)?; - Ok(()) - } - fn compress(&self, bin_message: &[u8]) -> Result<Vec<u8>> { - // Create buffer - let buffer = BufWriter::new(Vec::with_capacity(bin_message.len())); - - // Determine compression level - let compression_level = - if bin_message.len() < self.minimal_secure_layer.config.compression_min_size { - flate2::Compression::none() - } else { - self.minimal_secure_layer.config.compression - }; - - // Create compressor - let mut deflate_encoder = DeflateEncoder::new(buffer, compression_level); - - // Write message in compressor buffer - deflate_encoder - .write_all(&bin_message[..]) - .map_err(Error::ZipError)?; - - // Finalize compression - let bin_msg_compressed: BufWriter<Vec<u8>> = - deflate_encoder.finish().map_err(Error::ZipError)?; - - // Flush buffer - let bin_msg_compressed = bin_msg_compressed - .into_inner() - .map_err(|_| Error::BufferFlushError)?; - - Ok(bin_msg_compressed) - } - /// Create secure layer - #[inline] - pub fn create( - config: SecureLayerConfig, - sig_key_pair_seed: Option<Seed32>, - expected_remote_sig_pubkey: Option<Vec<u8>>, - ) -> Result<Self> { - let seed = sig_key_pair_seed.unwrap_or_else(Seed32::random); - - let secure_layer = SecureLayer { - minimal_secure_layer: MinimalSecureLayer::create(config, expected_remote_sig_pubkey)?, - sig_key_pair: Some( - Ed25519KeyPair::from_seed_unchecked(seed.as_ref()) - .map_err(|_| Error::FailtoGenSigKeyPair)?, - ), - }; - - Ok(secure_layer) - } - /// Read binary incoming datas - pub fn read_bin(&mut self, incoming_datas: &[u8]) -> Result<Vec<IncomingBinaryMessage>> { - let mut messages = Vec::new(); - - let message_opt = self.minimal_secure_layer.read(incoming_datas)?; - - if let Some(message) = message_opt { - match message { - Message::Connect { - custom_datas, - sig_pubkey, - .. - } => { - messages.push(IncomingBinaryMessage::Connect { - custom_datas: if let Some(custom_datas) = custom_datas { - Some(Self::uncompress(&custom_datas)?) - } else { - None - }, - peer_sig_public_key: sig_pubkey, - }); - if let Some(Message::Ack { custom_datas }) = - self.minimal_secure_layer.take_ack_msg_recv_too_early()? - { - messages.push(IncomingBinaryMessage::Ack { - custom_datas: if let Some(custom_datas) = custom_datas { - Some(Self::uncompress(&custom_datas)?) - } else { - None - }, - }); - } - } - Message::Ack { custom_datas } => { - messages.push(IncomingBinaryMessage::Ack { - custom_datas: if let Some(custom_datas) = custom_datas { - Some(Self::uncompress(&custom_datas)?) - } else { - None - }, - }); - for msg in self.minimal_secure_layer.drain_tmp_stack_user_msgs()? { - if let Message::Message { custom_datas } = msg { - messages.push(IncomingBinaryMessage::Message { - datas: if let Some(custom_datas) = custom_datas { - Some(Self::uncompress(&custom_datas)?) - } else { - None - }, - }); - } - } - } - Message::Message { custom_datas } => { - messages.push(IncomingBinaryMessage::Message { - datas: if let Some(custom_datas) = custom_datas { - Some(Self::uncompress(&custom_datas)?) - } else { - None - }, - }) - } - }; - } - Ok(messages) - } - /// Read incoming datas - #[cfg(feature = "ser")] - #[inline] - pub fn read<M>(&mut self, incoming_datas: &[u8]) -> Result<Vec<IncomingMessage<M>>> - where - M: Debug + DeserializeOwned, - { - self::serde::deserializer::read::<M>(self, incoming_datas) - } - fn uncompress(bin_zip_msg: &[u8]) -> Result<Vec<u8>> { - let mut deflate_decoder = DeflateDecoder::new(Vec::with_capacity(bin_zip_msg.len() * 5)); - deflate_decoder - .write_all(&bin_zip_msg) - .map_err(Error::ZipError)?; - deflate_decoder.finish().map_err(Error::ZipError) - } - /// Write ack message with optional binary custom datas - pub fn write_ack_msg_bin<W>( - &mut self, - custom_datas: Option<&[u8]>, - writer: &mut BufWriter<W>, - ) -> Result<()> - where - W: Write, - { - // Serialize and compress custom datas - let custom_datas = if let Some(custom_datas) = custom_datas { - Some(self.compress(custom_datas)?) - } else { - None - }; - - writer::write_ack_msg::<W>(self, custom_datas, writer) - } - /// Write ack message with optional custom datas - #[cfg(feature = "ser")] - #[inline] - pub fn write_ack_msg<M, W>( - &mut self, - custom_datas: Option<&M>, - writer: &mut BufWriter<W>, - ) -> Result<()> - where - M: Serialize, - W: Write, - { - self::serde::serializer::write_ack_msg::<M, W>(self, custom_datas, writer) - } - /// Write connect message with optional binary custom datas - pub fn write_connect_msg_bin<W>( - &mut self, - custom_datas: Option<&[u8]>, - writer: &mut BufWriter<W>, - ) -> Result<()> - where - W: Write, - { - // Compress custom datas - let custom_datas = if let Some(custom_datas) = custom_datas { - Some(self.compress(custom_datas)?) - } else { - None - }; - - writer::write_connect_msg(self, custom_datas, writer) - } - /// Write connect message with optional custom datas - #[cfg(feature = "ser")] - #[inline] - pub fn write_connect_msg<M, W>( - &mut self, - custom_datas: Option<&M>, - writer: &mut BufWriter<W>, - ) -> Result<()> - where - M: Serialize, - W: Write, - { - self::serde::serializer::write_connect_msg::<M, W>(self, custom_datas, writer) - } - /*/// Split secure layer in writer and reader - pub fn split(self) -> Result<(SecureWriter, SecureReader)> { - unimplemented!() - }*/ - /// Write message on a writer - #[cfg(feature = "ser")] - #[inline] - pub fn write<M, W>(&mut self, message: &M, writer: &mut BufWriter<W>) -> Result<()> - where - M: Serialize, - W: Write, - { - self::serde::serializer::write_message::<M, W>(self, message, writer) - } - /// Write binary message on a writer - pub fn write_bin<W>(&mut self, binary_message: &[u8], writer: &mut BufWriter<W>) -> Result<()> - where - W: Write, - { - // Compress message - let bin_zip_msg = self.compress(&binary_message[..])?; - - writer::write_bin_message::<W>(self, &bin_zip_msg, writer) - } -} - -#[cfg(test)] -mod tests { - - use super::*; - #[cfg(feature = "ser")] - use crate::MessageFormat; - use crate::{EncryptAlgo, SecureLayerConfig}; - - #[test] - fn test_change_config() -> Result<()> { - let mut msl = SecureLayer::create(SecureLayerConfig::default(), None, None)?; - msl.change_config(SecureLayerConfig { - compression: flate2::Compression::fast(), - compression_min_size: 8_192, - #[cfg(feature = "ser")] - message_format: MessageFormat::RawBinary, - encrypt_algo: EncryptAlgo::default(), - }) - .expect("change config must be success"); - Ok(()) - } -} diff --git a/lib/tools/pkstl/src/complete/message.rs b/lib/tools/pkstl/src/complete/message.rs deleted file mode 100644 index 768d232e97960828d012264050c5c91ec50cfb8b..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/complete/message.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage complete Public Key Secure Transport Layer. -//! Sub-module define incoming messages format. - -/// Incoming binary Message -#[derive(Debug, PartialEq)] -pub enum IncomingBinaryMessage { - /// Connect message - Connect { - /// Your custom datas - custom_datas: Option<Vec<u8>>, - /// Peer public key of signature algorithm - peer_sig_public_key: Vec<u8>, - }, - /// Ack message - Ack { - /// Your custom datas - custom_datas: Option<Vec<u8>>, - }, - /// Message - Message { - /// Message datas (This is an option because it's possible to receive an empty message) - datas: Option<Vec<u8>>, - }, -} diff --git a/lib/tools/pkstl/src/complete/serde.rs b/lib/tools/pkstl/src/complete/serde.rs deleted file mode 100644 index d2723fda9446330d872e081a2155bfae8301bd22..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/complete/serde.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage complete secure and decentralized transport layer with serialization/deserialization. - -use serde::de::DeserializeOwned; -use std::fmt::Debug; - -pub mod deserializer; -pub mod serializer; - -const HEADER_FORMAT_LEN: usize = 4; - -/// Incoming Message -#[derive(Debug)] -pub enum IncomingMessage<M: Debug + DeserializeOwned> { - /// Connect message - Connect { - /// Your custom datas - custom_datas: Option<M>, - /// Peer public key of signature algorithm - peer_sig_public_key: Vec<u8>, - }, - /// Ack message - Ack { - /// Your custom datas - custom_datas: Option<M>, - }, - /// Message - Message { - /// Message datas (This is an option because it's possible to receive an empty message) - datas: Option<M>, - }, -} - -#[derive(Debug)] -pub enum SerdeError { - #[cfg(feature = "bin")] - /// Bincode error - BincodeError(String), - #[cfg(feature = "cbor")] - /// Cbor error - CborError(serde_cbor::error::Error), - #[cfg(feature = "json")] - /// Json error - JsonError(serde_json::Error), - /// For the "raw binary" format, use the functions suffixed by _bin - UseSuffixedBinFunctions, - /// Not copyable error for linter - _IoError(std::io::Error), -} diff --git a/lib/tools/pkstl/src/complete/serde/deserializer.rs b/lib/tools/pkstl/src/complete/serde/deserializer.rs deleted file mode 100644 index c3fcc9036bdbf267b70cee3010631d41c1bb88a1..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/complete/serde/deserializer.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Define PKSTL deserializer. - -use super::SerdeError; -use super::{IncomingMessage, HEADER_FORMAT_LEN}; -use crate::format::MessageFormat; -use crate::{Error, IncomingBinaryMessage, Result, SecureLayer}; -use serde::de::DeserializeOwned; -use std::convert::TryFrom; -use std::fmt::Debug; - -pub(crate) fn read<M>( - sl: &mut SecureLayer, - incoming_datas: &[u8], -) -> Result<Vec<IncomingMessage<M>>> -where - M: Debug + DeserializeOwned, -{ - let bin_msgs = sl.read_bin(incoming_datas)?; - - let mut msgs = Vec::new(); - - for bin_msg in bin_msgs { - match bin_msg { - IncomingBinaryMessage::Connect { - custom_datas, - peer_sig_public_key, - } => msgs.push(IncomingMessage::Connect { - custom_datas: if let Some(custom_datas) = custom_datas { - Some(deserialize(&custom_datas)?) - } else { - None - }, - peer_sig_public_key, - }), - IncomingBinaryMessage::Ack { custom_datas } => msgs.push(IncomingMessage::Ack { - custom_datas: if let Some(custom_datas) = custom_datas { - Some(deserialize(&custom_datas)?) - } else { - None - }, - }), - IncomingBinaryMessage::Message { datas } => msgs.push(IncomingMessage::Message { - datas: if let Some(datas) = datas { - Some(deserialize(&datas)?) - } else { - None - }, - }), - }; - } - Ok(msgs) -} - -#[inline] -fn deserialize<M: Debug + DeserializeOwned>(binary_message: &[u8]) -> Result<M> { - if binary_message.len() < HEADER_FORMAT_LEN { - return Err(Error::RecvInvalidMsg( - crate::errors::IncomingMsgErr::MessageTooShort, - )); - } - - // Read format - let message_format = MessageFormat::try_from(&binary_message[..HEADER_FORMAT_LEN])?; - - deserialize_inner(&binary_message[HEADER_FORMAT_LEN..], message_format) - .map_err(Error::SerdeError) -} - -pub fn deserialize_inner<M>( - binary_message: &[u8], - message_format: MessageFormat, -) -> std::result::Result<M, SerdeError> -where - M: Debug + DeserializeOwned, -{ - match message_format { - MessageFormat::RawBinary => Err(SerdeError::UseSuffixedBinFunctions), - #[cfg(feature = "bin")] - MessageFormat::Bincode => Ok(bincode::deserialize::<M>(binary_message) - .map_err(|e| SerdeError::BincodeError(format!("{}", e)))?), - #[cfg(feature = "cbor")] - MessageFormat::Cbor => { - Ok(serde_cbor::from_slice::<M>(binary_message).map_err(SerdeError::CborError)?) - } - #[cfg(feature = "json")] - MessageFormat::Utf8Json => { - Ok(serde_json::from_slice::<M>(binary_message).map_err(SerdeError::JsonError)?) - } - _ => unimplemented!(), - } -} diff --git a/lib/tools/pkstl/src/complete/serde/serializer.rs b/lib/tools/pkstl/src/complete/serde/serializer.rs deleted file mode 100644 index 70450be6a956879b4ef3f82a9850aa2c43a4f017..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/complete/serde/serializer.rs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Define PKSTL serializer. - -use super::SerdeError; -use crate::format::MessageFormat; -use crate::{Error, Result, SecureLayer}; -use serde::Serialize; -use std::io::{BufWriter, Write}; - -pub(crate) fn write_connect_msg<M, W>( - sl: &mut SecureLayer, - custom_datas: Option<&M>, - writer: &mut BufWriter<W>, -) -> Result<()> -where - M: Serialize, - W: Write, -{ - // Serialize and compress custom datas - let custom_datas = if let Some(custom_datas) = custom_datas { - let bin_msg = serialize(custom_datas, sl.minimal_secure_layer.config.message_format)?; - Some(sl.compress(&bin_msg[..])?) - } else { - None - }; - - // Write binary message on a writer - crate::complete::writer::write_connect_msg::<W>(sl, custom_datas, writer) -} - -pub(crate) fn write_ack_msg<M, W>( - sl: &mut SecureLayer, - custom_datas: Option<&M>, - writer: &mut BufWriter<W>, -) -> Result<()> -where - M: Serialize, - W: Write, -{ - // Serialize and compress custom datas - let custom_datas = if let Some(custom_datas) = custom_datas { - let bin_msg = serialize(custom_datas, sl.minimal_secure_layer.config.message_format)?; - Some(sl.compress(&bin_msg[..])?) - } else { - None - }; - - // Write binary message on a writer - crate::complete::writer::write_ack_msg::<W>(sl, custom_datas, writer) -} - -pub(crate) fn write_message<M, W>( - sl: &mut SecureLayer, - message: &M, - writer: &mut BufWriter<W>, -) -> Result<()> -where - M: Serialize, - W: Write, -{ - // Serialize message - let bin_msg = serialize(message, sl.minimal_secure_layer.config.message_format)?; - - // Compress message - let bin_zip_msg = sl.compress(&bin_msg[..])?; - - // Write binary message on a writer - crate::complete::writer::write_bin_message::<W>(sl, &bin_zip_msg, writer) -} - -pub fn serialize<M>(message: &M, message_format: MessageFormat) -> Result<Vec<u8>> -where - M: Serialize, -{ - let mut writer = BufWriter::new(Vec::with_capacity(1_024)); - writer - .write(message_format.as_ref()) - .map_err(Error::WriteError)?; - serialize_inner(message, message_format, &mut writer).map_err(Error::SerdeError)?; - writer.into_inner().map_err(|_| Error::BufferFlushError) -} - -pub fn serialize_inner<M, W>( - message: &M, - message_format: MessageFormat, - writer: &mut W, -) -> std::result::Result<(), SerdeError> -where - M: Serialize, - W: Write, -{ - match message_format { - MessageFormat::RawBinary => Err(SerdeError::UseSuffixedBinFunctions), - #[cfg(feature = "bin")] - MessageFormat::Bincode => Ok(bincode::serialize_into(writer, message) - .map_err(|e| SerdeError::BincodeError(format!("{}", e)))?), - #[cfg(feature = "cbor")] - MessageFormat::Cbor => { - Ok(serde_cbor::to_writer(writer, message).map_err(SerdeError::CborError)?) - } - #[cfg(feature = "json")] - MessageFormat::Utf8Json => { - Ok(serde_json::to_writer(writer, message).map_err(SerdeError::JsonError)?) - } - _ => unimplemented!(), - } -} diff --git a/lib/tools/pkstl/src/complete/writer.rs b/lib/tools/pkstl/src/complete/writer.rs deleted file mode 100644 index c69276ebc03d22060cc9e71488296da84aa50d2d..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/complete/writer.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage complete Public Key Secure Transport Layer. -//! Sub-module define write operations. - -use super::SecureLayer; -use crate::{Error, Result}; -use ring::signature::{Ed25519KeyPair, KeyPair}; -use std::io::{BufWriter, Write}; - -#[inline] -pub fn write_connect_msg<W>( - sl: &mut SecureLayer, - custom_datas: Option<Vec<u8>>, - writer: &mut BufWriter<W>, -) -> Result<()> -where - W: Write, -{ - if let Some(ref sig_key_pair) = sl.sig_key_pair { - // Create connect message - let bin_connect_msg = sl.minimal_secure_layer.create_connect_message( - sig_key_pair.public_key().as_ref(), - match custom_datas { - Some(ref d) => Some(&d[..]), - None => None, - }, - )?; - - // Write connect message - writer - .write(&bin_connect_msg) - .map_err(|_| Error::BufferFlushError)?; - - // Sign message and write signature - sign_bin_msg_and_write_sig(sig_key_pair, &bin_connect_msg, writer) - } else { - Err(Error::ConnectMsgAlreadyWritten) - } -} - -#[inline] -pub fn write_ack_msg<W>( - sl: &mut SecureLayer, - custom_datas: Option<Vec<u8>>, - writer: &mut BufWriter<W>, -) -> Result<()> -where - W: Write, -{ - if let Some(ref sig_key_pair) = sl.sig_key_pair { - // Create ack message - let bin_connect_msg = sl - .minimal_secure_layer - .create_ack_message(match custom_datas { - Some(ref d) => Some(&d[..]), - None => None, - })?; - - // Write ack message - writer - .write(&bin_connect_msg) - .map_err(|_| Error::BufferFlushError)?; - - // Sign message and write signature - sign_bin_msg_and_write_sig(sig_key_pair, &bin_connect_msg, writer) - } else { - Err(Error::ConnectMsgAlreadyWritten) - } -} - -#[inline] -fn sign_bin_msg_and_write_sig<W>( - sig_key_pair: &Ed25519KeyPair, - bin_msg: &[u8], - writer: &mut BufWriter<W>, -) -> Result<()> -where - W: Write, -{ - writer - .write(sig_key_pair.sign(bin_msg).as_ref()) - .map(|_| ()) - .map_err(|_| Error::BufferFlushError) -} - -#[inline] -pub fn write_bin_message<W>( - sl: &mut SecureLayer, - message: &[u8], - writer: &mut BufWriter<W>, -) -> Result<()> -where - W: Write, -{ - sl.minimal_secure_layer.write_message(message, writer) -} diff --git a/lib/tools/pkstl/src/config.rs b/lib/tools/pkstl/src/config.rs deleted file mode 100644 index b883b2318dc1b9e06bce310bc64f178067fdda67..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/config.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage PKSTL configuration. - -use crate::encryption::EncryptAlgo; - -#[cfg(feature = "zip-sign")] -const DEFAULT_COMPRESSION_MIN_SIZE: usize = 8_192; - -#[cfg(feature = "ser")] -use crate::format::MessageFormat; - -#[cfg(feature = "zip-sign")] -#[derive(Clone, Copy, Debug, PartialEq)] -/// PKSTL Configuration -pub struct SecureLayerConfig { - #[cfg(feature = "zip-sign")] - /// Compression level - pub compression: flate2::Compression, - #[cfg(feature = "zip-sign")] - /// Compression minimal size in bytes - pub compression_min_size: usize, - #[cfg(feature = "ser")] - /// Message format - pub message_format: MessageFormat, - /// Encryption algorithm - pub encrypt_algo: EncryptAlgo, -} - -impl Default for SecureLayerConfig { - fn default() -> Self { - SecureLayerConfig { - #[cfg(feature = "zip-sign")] - compression: flate2::Compression::fast(), - #[cfg(feature = "zip-sign")] - compression_min_size: DEFAULT_COMPRESSION_MIN_SIZE, - #[cfg(feature = "ser")] - message_format: MessageFormat::default(), - encrypt_algo: EncryptAlgo::default(), - } - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn test_default_config() { - assert_eq!( - SecureLayerConfig { - compression: flate2::Compression::fast(), - compression_min_size: DEFAULT_COMPRESSION_MIN_SIZE, - #[cfg(feature = "ser")] - message_format: MessageFormat::default(), - encrypt_algo: EncryptAlgo::default(), - }, - SecureLayerConfig::default() - ) - } -} diff --git a/lib/tools/pkstl/src/constants.rs b/lib/tools/pkstl/src/constants.rs deleted file mode 100644 index be53fe190f33e9ed9d8b491c1135b2a5ff71b899..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/constants.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Declare PKSTL constants. - -/// Sig algo length -pub const SIG_ALGO_LEN: usize = 4; - -/// Current version -pub(crate) const CURRENT_VERSION: [u8; 4] = [0, 0, 0, 1]; - -/// Challenge size -pub(crate) const CHALLENGE_SIZE: usize = 32; - -/// Hash size -pub(crate) const HASH_SIZE: usize = 32; - -/// Ephemeral public key size -pub(crate) const EPK_SIZE: usize = 32; - -/// Magic value (at the beginning of all messages) -pub(crate) const MAGIC_VALUE: [u8; 4] = [0xE2, 0xC2, 0xE2, 0xD2]; - -/// Message type length -pub(crate) const MSG_TYPE_LEN: usize = 2; - -/// User message type -pub(crate) const USER_MSG_TYPE: &[u8] = &[0, 0]; - -/// Connect message type -pub(crate) const CONNECT_MSG_TYPE: &[u8] = &[0, 1]; - -/// Ack message type -pub(crate) const ACK_MSG_TYPE: &[u8] = &[0, 2]; - -/// Sig pubkey begin -pub(crate) const SIG_PUBKEY_BEGIN: usize = MSG_TYPE_LEN + EPK_SIZE + SIG_ALGO_LEN; diff --git a/lib/tools/pkstl/src/digest.rs b/lib/tools/pkstl/src/digest.rs deleted file mode 100644 index 39b7955023bc0ae1982d24d1855b0420235ae7f4..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/digest.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage cryptographic digest operations. - -pub(crate) fn sha256(datas: &[u8]) -> impl AsRef<[u8]> { - ring::digest::digest(&ring::digest::SHA256, datas) -} diff --git a/lib/tools/pkstl/src/encryption.rs b/lib/tools/pkstl/src/encryption.rs deleted file mode 100644 index 7e0519da89c68cbf0f2a6bb0e10c9f87938ef9c7..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/encryption.rs +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage cryptographic encryption operations. - -mod chacha20_poly1305_aead; - -use crate::agreement::{SharedSecret, SharedSecretLen}; -use crate::Result; -use std::io::{BufWriter, Read, Write}; - -/// Encryption algorithm -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum EncryptAlgo { - /// ChaCha20 stream cipher use the Poly1305 authenticator with Associated Data (AEAD) algorithm (see https://tools.ietf.org/html/rfc7539). - Chacha20Poly1305Aead, -} - -impl Default for EncryptAlgo { - fn default() -> Self { - Self::Chacha20Poly1305Aead - } -} - -impl EncryptAlgo { - pub(crate) fn shared_secret_len(self) -> SharedSecretLen { - match self { - Self::Chacha20Poly1305Aead => SharedSecretLen::B48, - } - } -} - -#[derive(Clone, Debug)] -pub enum EncryptAlgoWithSecretKey { - Chacha20Poly1305Aead(chacha20_poly1305_aead::SecretKey), -} - -impl EncryptAlgoWithSecretKey { - pub fn build(encrypt_algo: EncryptAlgo, shared_secret: SharedSecret) -> Self { - match encrypt_algo { - EncryptAlgo::Chacha20Poly1305Aead => { - if let SharedSecret::B48(seed) = shared_secret { - Self::Chacha20Poly1305Aead(chacha20_poly1305_aead::SecretKey::new(&seed)) - } else { - panic!("dev error: EncryptAlgo::Chacha20Poly1305Aead must request shared secret of 48 bytes !") - } - } - } - } -} - -#[inline] -pub(crate) fn decrypt<W: Write>( - encrypted_datas: &[u8], - algo_with_secret_key: &EncryptAlgoWithSecretKey, - writer: &mut BufWriter<W>, -) -> Result<()> { - match algo_with_secret_key { - EncryptAlgoWithSecretKey::Chacha20Poly1305Aead(secret_key) => { - chacha20_poly1305_aead::decrypt(encrypted_datas, secret_key, writer) - } - } -} - -/// Encrypt datas -#[inline] -pub(crate) fn encrypt<R: Read, W: Write>( - reader: &mut R, - algo_with_secret_key: &EncryptAlgoWithSecretKey, - writer: &mut BufWriter<W>, -) -> Result<()> { - match algo_with_secret_key { - EncryptAlgoWithSecretKey::Chacha20Poly1305Aead(secret_key) => { - chacha20_poly1305_aead::encrypt(reader, secret_key, writer) - } - } -} - -#[cfg(test)] -pub mod tests { - - use super::*; - use crate::seeds::{tests::random_seed_48, Seed32, Seed48}; - - pub fn gen_random_encrypt_algo_with_secret() -> EncryptAlgoWithSecretKey { - let random_shared_secret = SharedSecret::B48(random_seed_48()); - EncryptAlgoWithSecretKey::build(EncryptAlgo::Chacha20Poly1305Aead, random_shared_secret) - } - - #[test] - fn test_default() { - assert_eq!(EncryptAlgo::Chacha20Poly1305Aead, EncryptAlgo::default()); - } - - #[test] - #[should_panic( - expected = "dev error: EncryptAlgo::Chacha20Poly1305Aead must request shared secret of 48 bytes !" - )] - fn test_encryption_with_wrong_shared_secret_len() { - let shared_secret = SharedSecret::B32(Seed32::new([ - 0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - ])); - EncryptAlgoWithSecretKey::build(EncryptAlgo::Chacha20Poly1305Aead, shared_secret); - } - - #[test] - fn test_encryption_ok() -> Result<()> { - let datas = b"My secret datas".to_vec(); - - let shared_secret = SharedSecret::B48(Seed48::new([ - 0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, - ])); - let encrypt_algo_with_secret_key = - EncryptAlgoWithSecretKey::build(EncryptAlgo::Chacha20Poly1305Aead, shared_secret); - - let mut encrypted_datas = BufWriter::new(Vec::with_capacity(datas.len())); - - encrypt( - &mut &datas[..], - &encrypt_algo_with_secret_key, - &mut encrypted_datas, - )?; - let encrypted_datas = encrypted_datas - .into_inner() - .expect("fail to flush encrypt buffer"); - - let mut decrypted_datas = BufWriter::new(Vec::with_capacity(datas.len())); - decrypt( - &encrypted_datas, - &encrypt_algo_with_secret_key, - &mut decrypted_datas, - )?; - let decrypted_datas = decrypted_datas - .into_inner() - .expect("fail to flush decrypt buffer"); - - println!("encrypted_datas={:?}", encrypted_datas); - println!("decrypted_datas={:?}", decrypted_datas); - - assert_eq!(datas, decrypted_datas); - - Ok(()) - } -} diff --git a/lib/tools/pkstl/src/encryption/chacha20_poly1305_aead.rs b/lib/tools/pkstl/src/encryption/chacha20_poly1305_aead.rs deleted file mode 100644 index acea90c39ca7865bce1d552f6c03caaf01f2983a..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/encryption/chacha20_poly1305_aead.rs +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage cryptographic encryption operations with Chacha20Poly1305Aead algorithm. - -use crate::seeds::Seed48; -use crate::{Error, Result}; -use clear_on_drop::clear::Clear; -use std::io::{BufWriter, Read, Write}; - -const CHACHA20_TAG_SIZE: usize = 16; - -#[derive(Clone, Debug, Default)] -/// Secret key used for encryption algo -pub struct SecretKey { - key: [u8; 32], - nonce: [u8; 12], - aad: [u8; 4], -} - -impl Drop for SecretKey { - #[inline] - fn drop(&mut self) { - <[u8; 32] as Clear>::clear(&mut self.key); - <[u8; 12] as Clear>::clear(&mut self.nonce); - <[u8; 4] as Clear>::clear(&mut self.aad); - } -} - -impl SecretKey { - /// Create new secret key - pub fn new(seed: &Seed48) -> SecretKey { - let mut secret_key = SecretKey::default(); - - secret_key.key.copy_from_slice(&seed.as_ref()[0..32]); - secret_key.nonce.copy_from_slice(&seed.as_ref()[32..44]); - secret_key.aad.copy_from_slice(&seed.as_ref()[44..48]); - - secret_key - } -} - -/// Decrypt datas -pub fn decrypt<W: Write>( - encrypted_datas: &[u8], - secret_key: &SecretKey, - writer: &mut BufWriter<W>, -) -> Result<()> { - let payload_len = encrypted_datas.len() - CHACHA20_TAG_SIZE; - - chacha20_poly1305_aead::decrypt( - &secret_key.key, - &secret_key.nonce, - &secret_key.aad, - &encrypted_datas[0..payload_len], - &encrypted_datas[payload_len..], - writer, - ) - .map_err(Error::FailToDecryptDatas)?; - - Ok(()) -} - -/// Encrypt datas -pub fn encrypt<R: Read, W: Write>( - reader: &mut R, - secret_key: &SecretKey, - writer: &mut BufWriter<W>, -) -> Result<()> { - let tag = chacha20_poly1305_aead::encrypt_read( - &secret_key.key, - &secret_key.nonce, - &secret_key.aad, - reader, - writer, - ) - .map_err(Error::FailToEncryptDatas)?; - - writer - .write(&tag.to_vec()) - .map_err(Error::FailToEncryptDatas)?; - - Ok(()) -} - -#[cfg(test)] -mod tests { - - use super::*; - use crate::seeds::Seed48; - - #[test] - fn test_encryption() -> Result<()> { - let datas = b"My secret datas".to_vec(); - - let secret_key = SecretKey::new(&Seed48::new([ - 0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, - ])); - - let mut encrypted_datas = BufWriter::new(Vec::with_capacity(datas.len())); - - encrypt(&mut &datas[..], &secret_key, &mut encrypted_datas)?; - let encrypted_datas = encrypted_datas - .into_inner() - .expect("fail to flush encrypt buffer"); - - let mut decrypted_datas = BufWriter::new(Vec::with_capacity(datas.len())); - decrypt(&encrypted_datas, &secret_key, &mut decrypted_datas)?; - let decrypted_datas = decrypted_datas - .into_inner() - .expect("fail to flush decrypt buffer"); - - println!("encrypted_datas={:?}", encrypted_datas); - println!("decrypted_datas={:?}", decrypted_datas); - - assert_eq!(datas, decrypted_datas); - - Ok(()) - } -} diff --git a/lib/tools/pkstl/src/errors.rs b/lib/tools/pkstl/src/errors.rs deleted file mode 100644 index 5eb4e3b5745dc187c52be13fbd937e6bc760d936..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/errors.rs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage Secure and decentralized transport layer errors. - -/// PKSTL Error -#[derive(Debug)] -pub enum Error { - /// Error when flush writer buffer - BufferFlushError, - /// The connection had already failed earlier - ConnectionHadFail, - /// Connect msg already written - ConnectMsgAlreadyWritten, - /// Fail to compute agreement - FailToComputeAgreement, - /// Fail to decrypt datas - FailToDecryptDatas(chacha20_poly1305_aead::DecryptError), - /// Fail to encrypt datas - FailToEncryptDatas(std::io::Error), - /// Fail to generate ephemeral key pair - FailToGenEphemerKeyPair, - /// Fail to generate ephemeral public key - FailToGenEphemerPubKey, - /// Fail to generate signature key pair - FailtoGenSigKeyPair, - /// Forbidden to change the configuration after the security layer has been cloned - ForbidChangeConfAfterClone, - /// Forbidden to write the ACK message now - ForbidWriteAckMsgNow, - /// Message must be signed - MessageMustBeSigned, - /// The negotiation must have been successful - NegoMustHaveBeenSuccessful, - #[cfg(feature = "ser")] - /// Error in serialization/deserialization - SerdeError(crate::complete::serde::SerdeError), - /// Serialization error - SerializationError(std::io::Error), - /// Tru to generate connect message too late - TryToGenConnectMsgTooLate, - /// Trying to write a message when the negotiation is not successful - TryToWriteMsgWhenNegoNotSuccessful, - /// Receive invalid message - RecvInvalidMsg(IncomingMsgErr), - /// Unexpected remote signature public key - UnexpectedRemoteSigPubKey, - /// Error on writer - WriteError(std::io::Error), - /// Written length error - WrittenLenError { - /// Expected - expected: usize, - /// Found - found: usize, - }, - #[cfg(feature = "zip-sign")] - /// Compression or decompression error - ZipError(std::io::Error), -} - -impl From<IncomingMsgErr> for Error { - fn from(e: IncomingMsgErr) -> Self { - Self::RecvInvalidMsg(e) - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -/// Incoming message error -pub enum IncomingMsgErr { - /// Invalid challenge - InvalidChallenge, - /// Invalid hash or signature - InvalidHashOrSig, - /// Invalid magic value - InvalidMagicValue, - /// Message too short - MessageTooShort, - /// Unexpected a cck message - UnexpectedAckMsg, - /// Unexpected connect message - UnexpectedConnectMsg, - /// Unexpected user message - UnexpectedMessage, - /// Unexpected encryption state - /// It may be that the message is in clear when we expect it to be encrypted. - UnexpectedEncryptionState, - /// Unknown message format - UnknownMessageFormat, - /// Unknown message type - UnknownMessageType, - /// Unsupported signature algorithm - UnsupportedSigAlgo, - /// Unsupported version - UnsupportedVersion, -} diff --git a/lib/tools/pkstl/src/format.rs b/lib/tools/pkstl/src/format.rs deleted file mode 100644 index cb85a4590ac8992ba6065eae739daa1b8a7d7ad0..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/format.rs +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage PKSTL messages format. - -use crate::errors::IncomingMsgErr; -use std::convert::TryFrom; - -const RAW_BINARY: &[u8] = &[0, 0, 0, 0]; -const UTF8_PLAIN_TEXT: &[u8] = &[0, 0, 0, 1]; - -#[cfg(feature = "bin")] -const BINCODE: &[u8] = &[0, 0, 0, 4]; - -#[cfg(feature = "cbor")] -const CBOR: &[u8] = &[0, 0, 0, 3]; - -#[cfg(feature = "json")] -const UTF8_JSON: &[u8] = &[0, 0, 0, 2]; - -/// Message format -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum MessageFormat { - /// raw binary - RawBinary, - /// UTF-8 plain text - Utf8PlainText, - #[cfg(feature = "json")] - /// UTF-8 JSON - Utf8Json, - #[cfg(feature = "cbor")] - /// CBOR (Binary JSON) - Cbor, - #[cfg(feature = "bin")] - /// Bincode - Bincode, -} - -impl Default for MessageFormat { - fn default() -> Self { - Self::RawBinary - } -} - -impl TryFrom<&[u8]> for MessageFormat { - type Error = IncomingMsgErr; - - fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> { - match bytes { - #[cfg(feature = "bin")] - BINCODE => Ok(Self::Bincode), - #[cfg(feature = "cbor")] - CBOR => Ok(Self::Cbor), - RAW_BINARY => Ok(Self::RawBinary), - #[cfg(feature = "json")] - UTF8_JSON => Ok(Self::Utf8Json), - UTF8_PLAIN_TEXT => Ok(Self::Utf8PlainText), - _ => Err(IncomingMsgErr::UnknownMessageFormat), - } - } -} - -impl AsRef<[u8]> for MessageFormat { - fn as_ref(&self) -> &[u8] { - match self { - #[cfg(feature = "bin")] - Self::Bincode => BINCODE, - #[cfg(feature = "cbor")] - Self::Cbor => CBOR, - Self::RawBinary => RAW_BINARY, - #[cfg(feature = "json")] - Self::Utf8Json => UTF8_JSON, - Self::Utf8PlainText => UTF8_PLAIN_TEXT, - } - } -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn test_default() { - assert_eq!(MessageFormat::RawBinary, MessageFormat::default()); - } - - #[test] - fn test_messafe_format_as_ref() { - // RawBinary - assert_eq!(RAW_BINARY, MessageFormat::RawBinary.as_ref()); - - // Utf8PlainText - assert_eq!(UTF8_PLAIN_TEXT, MessageFormat::Utf8PlainText.as_ref()); - - // Utf8Json - #[cfg(feature = "json")] - assert_eq!(UTF8_JSON, MessageFormat::Utf8Json.as_ref()); - - // Cbor - #[cfg(feature = "cbor")] - assert_eq!(CBOR, MessageFormat::Cbor.as_ref()); - - // Bincode - #[cfg(feature = "bin")] - assert_eq!(BINCODE, MessageFormat::Bincode.as_ref()); - } - - #[test] - fn test_message_format_try_from() -> Result<(), IncomingMsgErr> { - // RawBinary - assert_eq!( - MessageFormat::RawBinary, - MessageFormat::try_from(RAW_BINARY)? - ); - - // Utf8PlainText - assert_eq!( - MessageFormat::Utf8PlainText, - MessageFormat::try_from(UTF8_PLAIN_TEXT)? - ); - - // Utf8Json - #[cfg(feature = "json")] - assert_eq!(MessageFormat::Utf8Json, MessageFormat::try_from(UTF8_JSON)?); - - // Cbor - #[cfg(feature = "cbor")] - assert_eq!(MessageFormat::Cbor, MessageFormat::try_from(CBOR)?); - - // Bincode - #[cfg(feature = "bin")] - assert_eq!(MessageFormat::Bincode, MessageFormat::try_from(BINCODE)?); - - // UnknownMessageFormat - let bytes = vec![0, 0, 0, 5]; - assert_eq!( - Err(IncomingMsgErr::UnknownMessageFormat), - MessageFormat::try_from(&bytes[..]), - ); - - Ok(()) - } -} diff --git a/lib/tools/pkstl/src/lib.rs b/lib/tools/pkstl/src/lib.rs deleted file mode 100644 index 41d97e7b79493a02279a1f2aca331b5e8a39c526..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/lib.rs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Public Key Secure Transport Layer. - -#![deny( - clippy::option_unwrap_used, - clippy::result_unwrap_used, - missing_docs, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unsafe_code, - unstable_features, - unused_import_braces, - unused_qualifications -)] - -mod agreement; -#[cfg(feature = "zip-sign")] -mod complete; -mod config; -mod constants; -mod digest; -mod encryption; -mod errors; -#[cfg(feature = "ser")] -mod format; -mod message; -mod minimal; -mod reader; -mod seeds; -mod signature; -mod status; - -pub use agreement::EphemeralPublicKey; -pub use config::SecureLayerConfig; -pub use encryption::EncryptAlgo; -pub use errors::Error; -pub use message::{EncapsuledMessage, Message}; -pub use minimal::MinimalSecureLayer; -pub use seeds::Seed32; -pub use signature::{SIG_ALGO_ED25519, SIG_ALGO_ED25519_ARRAY}; - -#[cfg(feature = "ser")] -pub use complete::IncomingMessage; -#[cfg(feature = "ser")] -pub use format::MessageFormat; - -#[cfg(feature = "zip-sign")] -pub use complete::message::IncomingBinaryMessage; -#[cfg(feature = "zip-sign")] -pub use complete::SecureLayer; - -/// PKSTL Result -pub type Result<T> = std::result::Result<T, Error>; - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub(crate) enum LocalNegoThread { - Created, - ConnectMsgSent, - ValidAckMsgReceived, -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub(crate) enum RemoteNegoThread { - WaitConnectMsg, - ValidConnectMsgReceived, - AckMsgSent, -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum MsgType { - Connect, - Ack, - UserMsg, -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum Action { - Create(MsgType), - Receive(MsgType), -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum ActionSideEffects { - PushUserMsgIntoTmpStack, -} diff --git a/lib/tools/pkstl/src/message.rs b/lib/tools/pkstl/src/message.rs deleted file mode 100644 index 0ecf9f4d7ab08f2933c246832b36cac102f05b5d..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/message.rs +++ /dev/null @@ -1,494 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage PKSTL messages. - -use crate::constants::*; -use crate::digest::sha256; -use crate::{Error, Result}; -use std::io::{BufWriter, Write}; - -const CONNECT_MSG_TYPE_HEADERS_SIZE: usize = 70; -const ACK_MSG_TYPE_HEADERS_SIZE: usize = 34; - -const HEADERS_AND_FOOTERS_MAX_SIZE: usize = 136; - -/// Message -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum Message { - /// Connect message - Connect { - /// Signature algorithm - sig_algo: [u8; SIG_ALGO_LEN], - /// Signature public key - sig_pubkey: Vec<u8>, - /// Custom datas - custom_datas: Option<Vec<u8>>, - }, - /// Ack Message - Ack { - /// Custom datas - custom_datas: Option<Vec<u8>>, - }, - /// Message - Message { - /// Custom datas - custom_datas: Option<Vec<u8>>, - }, -} - -/// Message that referencing datas -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum MessageRef<'a> { - /// Connect message - Connect { - /// Signature algorithm - sig_algo: [u8; SIG_ALGO_LEN], - /// Signature public key - sig_pubkey: Vec<u8>, - /// Custom datas - custom_datas: Option<&'a [u8]>, - }, - /// Ack Message - Ack { - /// Custom datas - custom_datas: Option<&'a [u8]>, - }, - /// Message - Message { - /// Custom datas - custom_datas: Option<&'a [u8]>, - }, -} - -/// Encapsuled message -#[derive(Debug, PartialEq)] -pub struct EncapsuledMessage { - pub(crate) datas: Vec<u8>, -} - -impl AsRef<[u8]> for EncapsuledMessage { - fn as_ref(&self) -> &[u8] { - &self.datas[..] - } -} - -#[derive(Debug, Eq, PartialEq)] -pub(crate) enum MsgTypeHeaders { - Connect { - peer_ephemeral_pk: [u8; EPK_SIZE], - sig_algo: [u8; SIG_ALGO_LEN], - sig_pubkey: Vec<u8>, - }, - Ack { - challenge: [u8; CHALLENGE_SIZE], - }, - UserMsg, -} - -impl MsgTypeHeaders { - pub(crate) fn must_be_encrypted(&self) -> bool { - if let MsgTypeHeaders::UserMsg = self { - true - } else { - false - } - } -} - -struct InnerPreparedMsg<'a> { - bin_user_msg: Option<&'a [u8]>, - type_msg_headers: Vec<u8>, -} - -impl Message { - pub(crate) fn from_bytes(msg_bytes: Vec<u8>, msg_type_headers: MsgTypeHeaders) -> Result<Self> { - // Read custom datas - let custom_datas = if !msg_bytes.is_empty() { - Some(msg_bytes) - } else { - None - }; - - // Build message according to it's type - match msg_type_headers { - MsgTypeHeaders::UserMsg => Ok(Message::Message { custom_datas }), - MsgTypeHeaders::Connect { - sig_algo, - sig_pubkey, - .. - } => Ok(Message::Connect { - sig_algo, - sig_pubkey, - custom_datas, - }), - MsgTypeHeaders::Ack { .. } => Ok(Message::Ack { custom_datas }), - } - } -} - -impl<'a> MessageRef<'a> { - #[inline] - fn prepare_message( - &self, - self_epk: &[u8], - peer_epk: Option<&Vec<u8>>, - ) -> Result<InnerPreparedMsg<'a>> { - match self { - Self::Connect { - sig_algo, - sig_pubkey, - custom_datas, - } => { - // type message headers - let mut type_msg_headers = Vec::with_capacity(CONNECT_MSG_TYPE_HEADERS_SIZE); - type_msg_headers - .write(CONNECT_MSG_TYPE) - .map_err(Error::WriteError)?; - type_msg_headers - .write(self_epk) - .map_err(Error::WriteError)?; - type_msg_headers - .write(&sig_algo[..]) - .map_err(Error::WriteError)?; - type_msg_headers - .write(sig_pubkey) - .map_err(Error::WriteError)?; - - Ok(InnerPreparedMsg { - bin_user_msg: *custom_datas, - type_msg_headers, - }) - } - Self::Ack { custom_datas } => { - // type message headers - let mut type_msg_headers = Vec::with_capacity(ACK_MSG_TYPE_HEADERS_SIZE); - type_msg_headers - .write(ACK_MSG_TYPE) - .map_err(Error::WriteError)?; - // write challenge - if let Some(peer_epk) = peer_epk { - Self::write_challenge(peer_epk, &mut type_msg_headers)?; - } else { - panic!("Dev error: try to write ack message before known peer epk."); - } - - Ok(InnerPreparedMsg { - bin_user_msg: *custom_datas, - type_msg_headers, - }) - } - Self::Message { custom_datas } => Ok(InnerPreparedMsg { - bin_user_msg: *custom_datas, - type_msg_headers: USER_MSG_TYPE.to_vec(), - }), - } - } - /// Convert message to bytes - pub(crate) fn to_bytes( - &self, - self_epk: &[u8], - peer_epk: Option<&Vec<u8>>, - ) -> Result<EncapsuledMessage> { - let InnerPreparedMsg { - bin_user_msg, - type_msg_headers, - } = self.prepare_message(self_epk, peer_epk)?; - - let bin_user_msg_len = bin_user_msg.unwrap_or(&[]).len(); - - // Create temporary write buffer for datas that will then be signed or hashed - let mut bytes_will_signed_or_hashed = BufWriter::new(Vec::with_capacity( - bin_user_msg_len + HEADERS_AND_FOOTERS_MAX_SIZE, - )); - - // Write MAGIC_VALUE - bytes_will_signed_or_hashed - .write(&MAGIC_VALUE) - .map_err(Error::WriteError)?; - - // Write VERSION - bytes_will_signed_or_hashed - .write(&CURRENT_VERSION) - .map_err(Error::WriteError)?; - - // Write ENCAPSULED_MSG_SIZE - let encapsuled_msg_size = type_msg_headers.len() + bin_user_msg.unwrap_or(&[]).len(); - bytes_will_signed_or_hashed - .write(&(encapsuled_msg_size as u64).to_be_bytes()) - .map_err(Error::WriteError)?; - - // Write type message headers - bytes_will_signed_or_hashed - .write(&type_msg_headers) - .map_err(Error::WriteError)?; - - // Write user message - if let Some(bin_user_msg) = bin_user_msg { - bytes_will_signed_or_hashed - .write(bin_user_msg) - .map_err(Error::WriteError)?; - } - - // Flush bytes_will_signed buffer - let bytes_will_signed_or_hashed = bytes_will_signed_or_hashed - .into_inner() - .map_err(|_| Error::BufferFlushError)?; - - // Return the bytes will signed - Ok(EncapsuledMessage { - datas: bytes_will_signed_or_hashed, - }) - } - #[inline] - fn write_challenge<W: Write>(ephem_pk: &[u8], writer: &mut W) -> Result<()> { - writer - .write(sha256(ephem_pk).as_ref()) - .map_err(Error::WriteError)?; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - - use super::*; - use pretty_assertions::assert_eq; - - #[test] - fn test_encapsuled_message() { - let encapsuled_msg = EncapsuledMessage { - datas: vec![1, 2, 3], - }; - - assert_eq!(&[1, 2, 3], encapsuled_msg.as_ref()); - } - - #[test] - fn test_connect_message_to_bytes() -> Result<()> { - let fake_epk = &[0u8; 32]; - - // Test connect message with custom datas - let message = MessageRef::Connect { - custom_datas: Some(&[5, 4, 4, 5]), - sig_algo: [0u8; SIG_ALGO_LEN], - sig_pubkey: vec![ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, - ], - }; - assert_eq!( - EncapsuledMessage { - datas: vec![ - 226, 194, 226, 210, // MAGIC_VALUE - 0, 0, 0, 1, // VERSION - 0, 0, 0, 0, 0, 0, 0, 74, // ENCAPSULED_MSG_LEN - 0, 1, // CONNECT_MSG_TYPE - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, // fake EPK (32 bytes) - 0, 0, 0, 0, // SIG_ALGO - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, // fake SIG_PK (32 bytes) - 5, 4, 4, 5 // custom datas - ], - }, - message.to_bytes(fake_epk, None)? - ); - - // Test connect message without custom datas - let message = MessageRef::Connect { - custom_datas: None, - sig_algo: [0u8; SIG_ALGO_LEN], - sig_pubkey: vec![ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, - ], - }; - - assert_eq!( - EncapsuledMessage { - datas: vec![ - 226, 194, 226, 210, // MAGIC_VALUE - 0, 0, 0, 1, // VERSION - 0, 0, 0, 0, 0, 0, 0, 70, // ENCAPSULED_MSG_LEN - 0, 1, // CONNECT_MSG_TYPE - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, // fake EPK (32 bytes) - 0, 0, 0, 0, // SIG_ALGO - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, // fake SIG_PK (32 bytes) - ], - }, - message.to_bytes(fake_epk, None,)? - ); - - Ok(()) - } - - #[test] - fn test_ack_message_to_bytes() -> Result<()> { - let fake_epk = &[0u8; 32]; - - // Test ack message with custom datas - let message = MessageRef::Ack { - custom_datas: Some(&[5, 4, 4, 5]), - }; - assert_eq!( - EncapsuledMessage { - datas: vec![ - 226, 194, 226, 210, // MAGIC_VALUE - 0, 0, 0, 1, // VERSION - 0, 0, 0, 0, 0, 0, 0, 38, // ENCAPSULED_MSG_LEN - 0, 2, // ACK_MSG_TYPE - 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142, 159, 142, 32, - 8, 151, 20, 133, 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, 41, - 37, // CHALLENGE (hash sha256) - 5, 4, 4, 5 // custom datas - ], - }, - message.to_bytes(fake_epk, Some(&fake_epk.to_vec()),)? - ); - - // Test ack message without custom datas - let message = MessageRef::Ack { custom_datas: None }; - assert_eq!( - EncapsuledMessage { - datas: vec![ - 226, 194, 226, 210, // MAGIC_VALUE - 0, 0, 0, 1, // VERSION - 0, 0, 0, 0, 0, 0, 0, 34, // ENCAPSULED_MSG_LEN - 0, 2, // ACK_MSG_TYPE - 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142, 159, 142, 32, - 8, 151, 20, 133, 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, 41, - 37, // CHALLENGE (hash sha256) - ], - }, - message.to_bytes(fake_epk, Some(&fake_epk.to_vec()),)? - ); - - Ok(()) - } - - #[test] - #[should_panic(expected = "Dev error: try to write ack message before known peer epk.")] - fn test_ack_message_to_bytes_before_recv_connect_msg() { - let fake_epk = &[0u8; 32]; - - // Test ack message without custom datas - let message = MessageRef::Ack { custom_datas: None }; - let _ = message.to_bytes(fake_epk, None); - } - - #[test] - fn test_user_message_to_bytes() -> Result<()> { - let fake_epk = &[0u8; 32]; - - // Test user message - let empty_user_message = MessageRef::Message { - custom_datas: Some(&[5, 4, 4, 5]), - }; - assert_eq!( - EncapsuledMessage { - datas: vec![ - 226, 194, 226, 210, // MAGIC_VALUE - 0, 0, 0, 1, // VERSION - 0, 0, 0, 0, 0, 0, 0, 6, // ENCAPSULED_MSG_LEN - 0, 0, // USER_MSG_TYPE - 5, 4, 4, 5 // custom datas - ], - }, - empty_user_message.to_bytes(fake_epk, None)? - ); - - // Test empty user message - let empty_user_message = MessageRef::Message { custom_datas: None }; - assert_eq!( - EncapsuledMessage { - datas: vec![ - 226, 194, 226, 210, // MAGIC_VALUE - 0, 0, 0, 1, // VERSION - 0, 0, 0, 0, 0, 0, 0, 2, // ENCAPSULED_MSG_LEN - 0, 0, // USER_MSG_TYPE - ], - }, - empty_user_message.to_bytes(fake_epk, None)? - ); - - Ok(()) - } - - #[test] - fn test_message_from_bytes() -> Result<()> { - // Define message - let mut msg_bytes = vec![ - 3, 3, 3, 3, // user message - ]; - - // User message - assert_eq!( - Message::Message { - custom_datas: Some(vec![3, 3, 3, 3]), - }, - Message::from_bytes(msg_bytes.clone(), MsgTypeHeaders::UserMsg)? - ); - - // Ack message - assert_eq!( - Message::Ack { - custom_datas: Some(vec![3, 3, 3, 3]), - }, - Message::from_bytes( - msg_bytes.clone(), - MsgTypeHeaders::Ack { - challenge: [0u8; CHALLENGE_SIZE] - } - )? - ); - - // Connect message - assert_eq!( - Message::Connect { - sig_pubkey: (0..31).collect(), - sig_algo: [0u8; SIG_ALGO_LEN], - custom_datas: Some(vec![3, 3, 3, 3]), - }, - Message::from_bytes( - msg_bytes.clone(), - MsgTypeHeaders::Connect { - peer_ephemeral_pk: [0u8; EPK_SIZE], - sig_algo: [0u8; SIG_ALGO_LEN], - sig_pubkey: (0..31).collect(), - } - )? - ); - - // Truncate user message content, msut be not panic - assert_eq!( - Message::Message { - custom_datas: Some(vec![3, 3]) - }, - Message::from_bytes(msg_bytes.drain(..2).collect(), MsgTypeHeaders::UserMsg)?, - ); - - // Empty message - let empty_msg_bytes = vec![]; - assert_eq!( - Message::Message { custom_datas: None }, - Message::from_bytes(empty_msg_bytes, MsgTypeHeaders::UserMsg)? - ); - - Ok(()) - } -} diff --git a/lib/tools/pkstl/src/minimal.rs b/lib/tools/pkstl/src/minimal.rs deleted file mode 100644 index 996493aba0deb93354d85bb3203ccb7f5499cd33..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/minimal.rs +++ /dev/null @@ -1,633 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Manage minimal secure and decentralized transport layer. - -use crate::agreement::{EphemeralKeyPair, EphemeralPublicKey}; -use crate::config::SecureLayerConfig; -use crate::constants::*; -use crate::digest::sha256; -use crate::encryption::{encrypt, EncryptAlgoWithSecretKey}; -use crate::errors::IncomingMsgErr; -use crate::message::{EncapsuledMessage, Message, MessageRef, MsgTypeHeaders}; -use crate::reader::{self, DecryptedIncomingDatas}; -use crate::signature::{self, SIG_ALGO_ED25519_ARRAY}; -use crate::status::SecureLayerStatus; -use crate::{Action, ActionSideEffects, Error, MsgType, Result}; -use std::io::{BufReader, BufWriter, Write}; - -/// Minimal secure layer -#[derive(Debug)] -pub struct MinimalSecureLayer { - ack_msg_recv_too_early: Option<Vec<u8>>, - cloned: bool, - pub(crate) config: SecureLayerConfig, - pub(crate) encrypt_algo_with_secret: Option<EncryptAlgoWithSecretKey>, - ephemeral_kp: Option<EphemeralKeyPair>, - pub(crate) ephemeral_pubkey: EphemeralPublicKey, - peer_epk: Option<Vec<u8>>, - peer_sig_pubkey: Option<Vec<u8>>, - pub(crate) status: SecureLayerStatus, - tmp_stack_user_msgs: Vec<Vec<u8>>, -} - -impl MinimalSecureLayer { - /// Try to clone, The negotiation must have been successful - pub fn try_clone(&mut self) -> Result<Self> { - if self.status == SecureLayerStatus::NegotiationSuccessful { - self.cloned = true; - Ok(MinimalSecureLayer { - ack_msg_recv_too_early: None, - cloned: true, - config: self.config, - encrypt_algo_with_secret: self.encrypt_algo_with_secret.clone(), - ephemeral_kp: None, - ephemeral_pubkey: self.ephemeral_pubkey.clone(), - peer_epk: None, - peer_sig_pubkey: None, - status: SecureLayerStatus::NegotiationSuccessful, - tmp_stack_user_msgs: self.tmp_stack_user_msgs.clone(), - }) - } else { - Err(Error::NegoMustHaveBeenSuccessful) - } - } - /// Change configuration - pub fn change_config(&mut self, new_config: SecureLayerConfig) -> Result<()> { - if !self.cloned { - self.config = new_config; - Ok(()) - } else { - Err(Error::ForbidChangeConfAfterClone) - } - } - /// Create minimal secure layer - pub fn create( - config: SecureLayerConfig, - expected_remote_sig_public_key: Option<Vec<u8>>, - ) -> Result<Self> { - let ephemeral_kp = EphemeralKeyPair::generate()?; - let ephemeral_pubkey = ephemeral_kp.public_key().clone(); - - let secure_layer = MinimalSecureLayer { - ack_msg_recv_too_early: None, - cloned: false, - config, - encrypt_algo_with_secret: None, - ephemeral_pubkey, - ephemeral_kp: Some(ephemeral_kp), - peer_epk: None, - peer_sig_pubkey: expected_remote_sig_public_key, - status: SecureLayerStatus::init(), - tmp_stack_user_msgs: Vec::new(), - }; - - Ok(secure_layer) - } - pub(crate) fn compute_shared_secret(&mut self, peer_ephemeral_public_key: &[u8]) -> Result<()> { - let encrypt_algo = self.config.encrypt_algo; - let ephemeral_kp = self.ephemeral_kp.take(); - if let Some(ephemeral_kp) = ephemeral_kp { - let shared_secret = ephemeral_kp.compute_shared_secret( - peer_ephemeral_public_key, - encrypt_algo.shared_secret_len(), - )?; - - self.encrypt_algo_with_secret = - Some(EncryptAlgoWithSecretKey::build(encrypt_algo, shared_secret)); - - Ok(()) - } else if self.encrypt_algo_with_secret.is_some() { - // Shared secret already computed, do nothing - Ok(()) - } else { - unreachable!("dev error: fisrt call of compute_shared_secret() without ephemeral_kp !") - } - } - /// Drain temporary stack of remote messages - pub fn drain_tmp_stack_user_msgs(&mut self) -> Result<Vec<Message>> { - let bin_msgs: Vec<Vec<u8>> = self.tmp_stack_user_msgs.drain(..).collect(); - let mut msgs = Vec::with_capacity(bin_msgs.len()); - for bin_msg in bin_msgs { - if let Some(msg) = self.read_inner(&bin_msg, false)? { - msgs.push(msg); - } - } - Ok(msgs) - } - #[inline] - /// Encapsulate message - fn encapsulate_message(&mut self, message: &MessageRef) -> Result<EncapsuledMessage> { - message.to_bytes(&self.ephemeral_pubkey.as_ref(), self.peer_epk.as_ref()) - } - /// Take ACK message received too early - #[inline] - pub fn take_ack_msg_recv_too_early(&mut self) -> Result<Option<Message>> { - if let Some(bin_ack_msg) = self.ack_msg_recv_too_early.take() { - self.read(&bin_ack_msg) - } else { - Ok(None) - } - } - #[inline] - /// Read incoming datas - pub fn read(&mut self, incoming_datas: &[u8]) -> Result<Option<Message>> { - self.read_inner(incoming_datas, true) - } - fn read_inner( - &mut self, - incoming_datas: &[u8], - check_encrypt_state: bool, - ) -> Result<Option<Message>> { - // Decrypt incoming messsage and parse headers - let DecryptedIncomingDatas { - mut datas, - user_msg_begin, - user_msg_end, - msg_type_headers, - } = match reader::read( - self.encrypt_algo_with_secret.as_ref(), - incoming_datas, - check_encrypt_state, - ) { - Ok(decrypted_incoming_datas) => decrypted_incoming_datas, - Err(e) => { - self.status = SecureLayerStatus::Fail; - return Err(e); - } - }; - - //println!("DEBUG TMP: msg_type_headers={:#?}", msg_type_headers); - match msg_type_headers { - MsgTypeHeaders::Connect { - peer_ephemeral_pk, - ref sig_pubkey, - .. - } => { - // Verify (or get) peer sig pubkey - if let Some(ref peer_sig_pubkey) = self.peer_sig_pubkey { - if sig_pubkey != peer_sig_pubkey { - return Err(Error::UnexpectedRemoteSigPubKey); - } - } else { - self.peer_sig_pubkey = Some(sig_pubkey.to_vec()); - } - - // Verify sig - // The reader has already made sure that the signature algorithm is supported, - // as we only support the Ed25519 algorithm, we know that it is necessarily this one. - if !self.verify_sig(&datas, sig_pubkey, user_msg_end) { - return Err(IncomingMsgErr::InvalidHashOrSig.into()); - } - - // Update status - self.status - .apply_action(Action::Receive(MsgType::Connect))?; - - // Get peeer EPK and compute shared secret - self.peer_epk = Some(peer_ephemeral_pk.to_vec()); - self.compute_shared_secret(&peer_ephemeral_pk[..])?; - } - MsgTypeHeaders::Ack { challenge } => { - // Verify challenge - if challenge != sha256(self.ephemeral_pubkey.as_ref()).as_ref() { - return Err(IncomingMsgErr::InvalidChallenge.into()); - } - - let peer_sig_pubkey = if let Some(ref peer_sig_pubkey) = self.peer_sig_pubkey { - peer_sig_pubkey - } else if self.ack_msg_recv_too_early.is_none() { - self.ack_msg_recv_too_early = Some(incoming_datas.to_vec()); - return Ok(None); - } else { - self.status = SecureLayerStatus::Fail; - return Err(IncomingMsgErr::UnexpectedAckMsg.into()); - }; - - // Verify sig - // The reader has already made sure that the signature algorithm is supported, - // as we only support the Ed25519 algorithm, we know that it is necessarily this one. - if !self.verify_sig(&datas, peer_sig_pubkey, user_msg_end) { - return Err(IncomingMsgErr::InvalidHashOrSig.into()); - } - - // Update status - self.status.apply_action(Action::Receive(MsgType::Ack))?; - } - MsgTypeHeaders::UserMsg => { - // Verify status - if let Some(ActionSideEffects::PushUserMsgIntoTmpStack) = self - .status - .apply_action(Action::Receive(MsgType::UserMsg))? - { - self.tmp_stack_user_msgs.push(datas); - return Ok(None); - } - - // Verify hash - let datas_hashed = &datas[..user_msg_end]; - let hash = &datas[user_msg_end..]; - if hash != sha256(datas_hashed).as_ref() { - return Err(IncomingMsgErr::InvalidHashOrSig.into()); - } - } - } - - // Get message - let message = Message::from_bytes( - datas.drain(user_msg_begin..user_msg_end).collect(), - msg_type_headers, - )?; - - Ok(Some(message)) - } - /// Encrypt and write message on a writer - #[inline] - fn encrypt_and_write<W: Write>( - &mut self, - encapsuled_message: &EncapsuledMessage, - writer: &mut BufWriter<W>, - ) -> Result<()> { - let encrypt_algo_with_secret = - if let Some(ref encrypt_algo_with_secret) = self.encrypt_algo_with_secret { - encrypt_algo_with_secret - } else { - panic!("Dev error: try to get encrypt_algo_with_secret before it's computed !") - }; - - let mut datas_will_encrypted = BufWriter::new(Vec::with_capacity( - encapsuled_message.as_ref().len() + HASH_SIZE, - )); - - // Write encapsuled message - datas_will_encrypted - .write(encapsuled_message.as_ref()) - .map_err(Error::WriteError)?; - // Write encapsuled message hash - datas_will_encrypted - .write(sha256(encapsuled_message.as_ref()).as_ref()) - .map_err(Error::WriteError)?; - - // Flush datas_will_encrypted buffer - let datas_will_encrypted = datas_will_encrypted - .into_inner() - .map_err(|_| Error::BufferFlushError)?; - - // Encrypt - encrypt( - &mut BufReader::new(&datas_will_encrypted[..]), - encrypt_algo_with_secret, - writer, - )?; - - Ok(()) - } - #[inline] - /// Create connect message - pub fn create_connect_message( - &mut self, - public_key: &[u8], - custom_datas: Option<&[u8]>, - ) -> Result<Vec<u8>> { - // Update status - self.status.apply_action(Action::Create(MsgType::Connect))?; - - // Create message and update status - match self.encapsulate_message(&MessageRef::Connect { - sig_algo: SIG_ALGO_ED25519_ARRAY, - sig_pubkey: public_key.to_vec(), - custom_datas, - }) { - Ok(encapsuled_msg) => Ok(encapsuled_msg.datas), - Err(e) => { - self.status = SecureLayerStatus::Fail; - Err(e) - } - } - } - #[inline] - /// Create ack message - pub fn create_ack_message(&mut self, custom_datas: Option<&[u8]>) -> Result<Vec<u8>> { - // Update status - self.status.apply_action(Action::Create(MsgType::Ack))?; - - // Create message and update status - match self.encapsulate_message(&MessageRef::Ack { custom_datas }) { - Ok(encapsuled_msg) => Ok(encapsuled_msg.datas), - Err(e) => { - self.status = SecureLayerStatus::Fail; - Err(e) - } - } - } - #[inline] - /// Write message - pub fn write_message<W: Write>( - &mut self, - datas: &[u8], - writer: &mut BufWriter<W>, - ) -> Result<()> { - // Update status - self.status.apply_action(Action::Create(MsgType::UserMsg))?; - - match self.encapsuled_and_encrypt_and_write_message(datas, writer) { - Ok(()) => { - self.status = SecureLayerStatus::NegotiationSuccessful; - Ok(()) - } - Err(e) => { - self.status = SecureLayerStatus::Fail; - Err(e) - } - } - } - #[inline] - fn encapsuled_and_encrypt_and_write_message<W: Write>( - &mut self, - datas: &[u8], - writer: &mut BufWriter<W>, - ) -> Result<()> { - let encapsuled_msg = self.encapsulate_message(&MessageRef::Message { - custom_datas: Some(datas), - })?; - self.encrypt_and_write(&encapsuled_msg, writer) - } - #[inline] - fn verify_sig(&self, datas: &[u8], sig_pubkey: &[u8], user_msg_end: usize) -> bool { - let datas_signed = &datas[..user_msg_end]; - let sig = &datas[user_msg_end..]; - signature::verify_sig(sig_pubkey, datas_signed, sig) - } -} - -#[cfg(test)] -mod tests { - - use super::*; - use crate::encryption::EncryptAlgo; - use crate::signature::SIG_ALGO_ED25519; - use crate::Seed32; - use ring::signature::{Ed25519KeyPair, KeyPair}; - - fn create_connect_msg_bytes(mut epk: Vec<u8>, sig_kp: &Ed25519KeyPair) -> Result<Vec<u8>> { - let mut incoming_datas = Vec::with_capacity(100); - incoming_datas.append(&mut MAGIC_VALUE.to_vec()); - incoming_datas.append(&mut CURRENT_VERSION.to_vec()); - incoming_datas.append(&mut 74u64.to_be_bytes().to_vec()); // Encapsuled message length - incoming_datas.append(&mut vec![0, 1]); // CONNECT type - incoming_datas.append(&mut epk); // EPK - incoming_datas.append(&mut SIG_ALGO_ED25519.to_vec()); // SIG_ALGO - incoming_datas.append(&mut sig_kp.public_key().as_ref().to_vec()); // SIG_PK - incoming_datas.append(&mut vec![5, 4, 4, 5]); // User custom datas - let sig = sig_kp.sign(&incoming_datas); - incoming_datas.append(&mut sig.as_ref().to_vec()); // SIG - Ok(incoming_datas) - } - - fn create_ack_msg_bytes(remote_epk: Vec<u8>, sig_kp: &Ed25519KeyPair) -> Result<Vec<u8>> { - let mut incoming_datas = Vec::with_capacity(100); - incoming_datas.append(&mut MAGIC_VALUE.to_vec()); - incoming_datas.append(&mut CURRENT_VERSION.to_vec()); - incoming_datas.append(&mut 34u64.to_be_bytes().to_vec()); // Encapsuled message length - incoming_datas.append(&mut vec![0, 2]); // ACK type - incoming_datas.append(&mut sha256(&remote_epk).as_ref().to_vec()); // Challenge - let sig = sig_kp.sign(&incoming_datas); - incoming_datas.append(&mut sig.as_ref().to_vec()); // SIG - Ok(incoming_datas) - } - - #[test] - fn test_change_config() -> Result<()> { - let mut msl = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - msl.change_config(SecureLayerConfig { - encrypt_algo: EncryptAlgo::Chacha20Poly1305Aead, - ..SecureLayerConfig::default() - }) - .expect("change config must be success"); - Ok(()) - } - - #[test] - fn test_compute_shared_secret_twice() -> Result<()> { - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - let msl2 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - msl1.compute_shared_secret(msl2.ephemeral_pubkey.as_ref())?; - msl1.compute_shared_secret(msl2.ephemeral_pubkey.as_ref())?; - Ok(()) - } - - #[test] - fn test_status_update_to_fail() -> Result<()> { - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - let fake_encrypted_incoming_datas = &[0, 0, 0, 0]; - let result = msl1.read(fake_encrypted_incoming_datas); - - assert_eq!(SecureLayerStatus::Fail, msl1.status); - - if let Err(Error::RecvInvalidMsg(e)) = result { - assert_eq!(IncomingMsgErr::UnexpectedMessage, e); - } else { - panic!("unexpected result") - } - Ok(()) - } - - #[test] - fn test_ack_msg_with_wrong_challenge() -> Result<()> { - // Create ack message - let mut incoming_datas = Vec::with_capacity(100); - incoming_datas.append(&mut MAGIC_VALUE.to_vec()); - incoming_datas.append(&mut CURRENT_VERSION.to_vec()); - incoming_datas.append(&mut 34u64.to_be_bytes().to_vec()); // Encapsuled message length - incoming_datas.append(&mut vec![0, 2]); // ACK type - incoming_datas.append(&mut [0u8; 32].to_vec()); // fake challenge - incoming_datas.append(&mut [0u8; 32].to_vec()); // fake sig - - // Create secure layer - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - // Read ack msg - let result = msl1.read(&incoming_datas[..]); - if let Err(Error::RecvInvalidMsg(e)) = result { - assert_eq!(IncomingMsgErr::InvalidChallenge, e); - Ok(()) - } else { - println!("unexpected result={:?}", result); - panic!(); - } - } - - #[test] - fn test_write_user_msg_before_nego() -> Result<()> { - // Create secure layer - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - // Try to create ack message before connect message - let result = msl1.write_message(&[], &mut BufWriter::new(Vec::new())); - if let Err(Error::NegoMustHaveBeenSuccessful) = result { - Ok(()) - } else { - println!("unexpected result={:?}", result); - panic!(); - } - } - - #[test] - fn test_create_ack_msg_before_connect() -> Result<()> { - // Create secure layer - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - // Try to create ack message before connect message - let result = msl1.create_ack_message(None); - if let Err(Error::ForbidWriteAckMsgNow) = result { - Ok(()) - } else { - println!("unexpected result={:?}", result); - panic!(); - } - } - - #[test] - fn test_connect_msg_twice() -> Result<()> { - // Create sig keypair - let sig_kp = Ed25519KeyPair::from_seed_unchecked(Seed32::random().as_ref()) - .map_err(|_| Error::FailtoGenSigKeyPair)?; - - // Create secure layer - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - let _ = msl1.create_connect_message(sig_kp.public_key().as_ref(), None)?; - - // Try to create connect message twice - let result = msl1.create_connect_message(sig_kp.public_key().as_ref(), None); - if let Err(Error::ConnectMsgAlreadyWritten) = result { - Ok(()) - } else { - println!("unexpected result={:?}", result); - panic!(); - } - } - - #[test] - fn test_connect_msg_with_wrong_sig() -> Result<()> { - // Crate fake keys - let fake_ephem_pk = &[0u8; 32][..]; - let fake_sig_pk = [0u8; 32].to_vec(); - let _fake_signature_opt = Some(&[0u8; 32][..]); - - // Create connect msg bytes - let mut incoming_datas = Vec::with_capacity(100); - incoming_datas.append(&mut MAGIC_VALUE.to_vec()); - incoming_datas.append(&mut CURRENT_VERSION.to_vec()); - incoming_datas.append(&mut 74u64.to_be_bytes().to_vec()); // Encapsuled message length - incoming_datas.append(&mut vec![0, 1]); // CONNECT type - incoming_datas.append(&mut fake_ephem_pk.to_vec()); // EPK - incoming_datas.append(&mut SIG_ALGO_ED25519.to_vec()); // SIG_ALGO - incoming_datas.append(&mut fake_sig_pk.clone()); // SIG_PK - incoming_datas.append(&mut vec![5, 4, 4, 5]); // User custom datas - incoming_datas.append(&mut [0u8; 32].to_vec()); // fake sig - - // Create secure layer - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - // Read connect msg - let result = msl1.read(&incoming_datas[..]); - if let Err(Error::RecvInvalidMsg(e)) = result { - assert_eq!(IncomingMsgErr::InvalidHashOrSig, e); - Ok(()) - } else { - println!("unexpected result={:?}", result); - panic!(); - } - } - - #[test] - fn test_recv_connect_msg_twice() -> Result<()> { - // Create sig keypair - let sig_kp = Ed25519KeyPair::from_seed_unchecked(Seed32::random().as_ref()) - .map_err(|_| Error::FailtoGenSigKeyPair)?; - - // Create EKP - let ephemeral_kp = EphemeralKeyPair::generate()?; - - // Create connect msg bytes - let incoming_datas = - create_connect_msg_bytes(ephemeral_kp.public_key().as_ref().to_vec(), &sig_kp)?; - - // Create secure layer - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - // Read connect message - let _ = msl1.read(&incoming_datas[..])?; - - // Reread same connect message - let result = msl1.read(&incoming_datas[..]); - if let Err(Error::RecvInvalidMsg(IncomingMsgErr::UnexpectedConnectMsg)) = result { - Ok(()) - } else { - println!("unexpected result={:?}", result); - panic!(); - } - } - - #[test] - fn test_recv_ack_msg_early_twice() -> Result<()> { - // Create sig keypair - let sig_kp = Ed25519KeyPair::from_seed_unchecked(Seed32::random().as_ref()) - .map_err(|_| Error::FailtoGenSigKeyPair)?; - - // Create secure layer - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - // Create ack msg bytes - let incoming_datas = - create_ack_msg_bytes(msl1.ephemeral_pubkey.as_ref().to_vec(), &sig_kp)?; - - // Read ack message received too early - let _ = msl1.read(&incoming_datas[..]); - // Re-read ack message received too early - let result = msl1.read(&incoming_datas[..]); - if let Err(Error::RecvInvalidMsg(IncomingMsgErr::UnexpectedAckMsg)) = result { - Ok(()) - } else { - println!("unexpected result={:?}", result); - panic!(); - } - } - - #[test] - fn test_recv_user_msg_before_nego() -> Result<()> { - // Create secure layer - let mut msl1 = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - // Create empty user msg fakely encryted - let mut incoming_datas = Vec::with_capacity(100); - incoming_datas.append(&mut vec![0, 0, 0, 0]); - incoming_datas.append(&mut CURRENT_VERSION.to_vec()); - incoming_datas.append(&mut 2u64.to_be_bytes().to_vec()); // Encapsuled message length - incoming_datas.append(&mut vec![0, 0]); // USER_MSG_TYPE - incoming_datas.append(&mut sha256(&incoming_datas).as_ref().to_vec()); // Hash - - // Read user message received before_nego - let result = msl1.read(&incoming_datas[..]); - if let Err(Error::RecvInvalidMsg(IncomingMsgErr::UnexpectedMessage)) = result { - Ok(()) - } else { - println!("unexpected result={:?}", result); - panic!(); - } - } -} diff --git a/lib/tools/pkstl/src/reader.rs b/lib/tools/pkstl/src/reader.rs deleted file mode 100644 index 62dae03cba500a5a9f7e0b5d3250f3a77d3c20be..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/reader.rs +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Define PKSTL reader. - -use crate::constants::*; -use crate::encryption::{decrypt, EncryptAlgoWithSecretKey}; -use crate::errors::IncomingMsgErr; -use crate::message::MsgTypeHeaders; -use crate::signature::SIG_ALGO_ED25519; -use crate::{Error, Result}; -use std::io::{BufWriter, Write}; - -const MAGIC_VALUE_END: usize = 4; -const VERSION_END: usize = 8; -pub(crate) const ENCAPSULED_MSG_BEGIN: usize = 16; - -#[derive(Debug, PartialEq)] -pub(crate) struct DecryptedIncomingDatas { - pub(crate) datas: Vec<u8>, - pub(crate) user_msg_begin: usize, - pub(crate) user_msg_end: usize, - pub(crate) msg_type_headers: MsgTypeHeaders, -} - -/// Read incoming datas -pub(crate) fn read( - encrypt_algo_with_secret_opt: Option<&EncryptAlgoWithSecretKey>, - incoming_datas: &[u8], - check_encrypt_state: bool, -) -> std::result::Result<DecryptedIncomingDatas, Error> { - // Decrypt datas - let datas_encrypted; - let mut buffer = BufWriter::new(Vec::with_capacity(incoming_datas.len())); - if incoming_datas[..MAGIC_VALUE_END] == MAGIC_VALUE { - // Datas are not encrypted - datas_encrypted = false; - buffer.write(incoming_datas).map_err(Error::WriteError)?; - } else { - // Datas are encrypted - datas_encrypted = true; - if let Some(encrypt_algo_with_secret) = encrypt_algo_with_secret_opt { - decrypt(incoming_datas, encrypt_algo_with_secret, &mut buffer)?; - } else { - return Err(Error::RecvInvalidMsg(IncomingMsgErr::UnexpectedMessage)); - } - } - let decrypted_datas = buffer.into_inner().map_err(|_| Error::BufferFlushError)?; - - // Check magic value - if decrypted_datas[..MAGIC_VALUE_END] != MAGIC_VALUE { - return Err(IncomingMsgErr::InvalidMagicValue.into()); - } - - // Check version - if decrypted_datas[MAGIC_VALUE_END..VERSION_END] != CURRENT_VERSION { - return Err(IncomingMsgErr::UnsupportedVersion.into()); - } - - // Read ENCAPSULED_MSG_SIZE - let mut buffer_8_bytes: [u8; 8] = <[u8; 8]>::default(); - buffer_8_bytes.copy_from_slice(&decrypted_datas[VERSION_END..ENCAPSULED_MSG_BEGIN]); - let encapsuled_msg_size = u64::from_be_bytes(buffer_8_bytes) as usize; - let user_msg_end = ENCAPSULED_MSG_BEGIN + encapsuled_msg_size; - - // Read type headers - let (msg_type_headers, type_headers_len) = - read_type_headers(&decrypted_datas[ENCAPSULED_MSG_BEGIN..])?; - - if check_encrypt_state && datas_encrypted != msg_type_headers.must_be_encrypted() { - Err(Error::RecvInvalidMsg( - IncomingMsgErr::UnexpectedEncryptionState, - )) - } else { - Ok(DecryptedIncomingDatas { - datas: decrypted_datas, - user_msg_begin: ENCAPSULED_MSG_BEGIN + type_headers_len, - user_msg_end, - msg_type_headers, - }) - } -} - -fn read_type_headers(type_headers: &[u8]) -> Result<(MsgTypeHeaders, usize)> { - // Match message type - match &type_headers[..MSG_TYPE_LEN] { - USER_MSG_TYPE => Ok((MsgTypeHeaders::UserMsg, MSG_TYPE_LEN)), - CONNECT_MSG_TYPE => { - // Read PEER_EPHEMERAL_PUBKEY - let mut peer_ephemeral_pk = [0u8; EPK_SIZE]; - peer_ephemeral_pk.copy_from_slice(&type_headers[MSG_TYPE_LEN..MSG_TYPE_LEN + EPK_SIZE]); - // Read SIG_ALGO and SIG_PUBKEY - match &type_headers[(MSG_TYPE_LEN + EPK_SIZE)..(SIG_PUBKEY_BEGIN)] { - SIG_ALGO_ED25519 => { - let mut sig_algo = [0u8; SIG_ALGO_LEN]; - sig_algo.copy_from_slice( - &type_headers - [(MSG_TYPE_LEN + EPK_SIZE)..(MSG_TYPE_LEN + EPK_SIZE + SIG_ALGO_LEN)], - ); - Ok(( - MsgTypeHeaders::Connect { - peer_ephemeral_pk, - sig_algo, - sig_pubkey: type_headers[SIG_PUBKEY_BEGIN..(SIG_PUBKEY_BEGIN + 32)] - .to_vec(), - }, - SIG_PUBKEY_BEGIN + 32, - )) - } - _ => Err(IncomingMsgErr::UnsupportedSigAlgo.into()), - } - } - ACK_MSG_TYPE => { - let mut challenge = [0u8; CHALLENGE_SIZE]; - challenge - .copy_from_slice(&&type_headers[MSG_TYPE_LEN..(MSG_TYPE_LEN + CHALLENGE_SIZE)]); - Ok(( - MsgTypeHeaders::Ack { challenge }, - MSG_TYPE_LEN + CHALLENGE_SIZE, - )) - } - _ => Err(IncomingMsgErr::UnknownMessageType.into()), - } -} - -#[cfg(test)] -mod tests { - - use super::*; - use crate::digest::sha256; - use crate::encryption::{encrypt, tests::gen_random_encrypt_algo_with_secret}; - use crate::signature::{SIG_ALGO_ED25519, SIG_ALGO_ED25519_ARRAY}; - use pretty_assertions::assert_eq; - use std::io::BufReader; - - #[test] - fn test_unexpected_user_msg() { - let fake_encrypted_incoming_datas = &[0, 0, 0, 0]; - let result = read(None, fake_encrypted_incoming_datas, true); - if let Err(Error::RecvInvalidMsg(e)) = result { - assert_eq!(IncomingMsgErr::UnexpectedMessage, e); - } else { - panic!("unexpected result") - } - } - - #[test] - fn test_msg_with_unsupported_version() { - let mut fake_incoming_datas = MAGIC_VALUE.to_vec(); - fake_incoming_datas.append(&mut vec![0, 0, 0, 2]); - - let result = read(None, &fake_incoming_datas, true); - if let Err(Error::RecvInvalidMsg(e)) = result { - assert_eq!(IncomingMsgErr::UnsupportedVersion, e); - } else { - panic!("unexpected result") - } - } - - #[test] - fn test_unencrypted_usr_msg() { - let mut empty_user_msg = MAGIC_VALUE.to_vec(); - empty_user_msg.append(&mut CURRENT_VERSION.to_vec()); - empty_user_msg.append(&mut vec![0, 0, 0, 0, 0, 0, 0, 2]); // ENCAPSULED_MSG_SIZE - empty_user_msg.append(&mut USER_MSG_TYPE.to_vec()); - - let result = read(None, &empty_user_msg, true); - if let Err(Error::RecvInvalidMsg(e)) = result { - assert_eq!(IncomingMsgErr::UnexpectedEncryptionState, e); - } else { - panic!("unexpected result") - } - } - - #[test] - fn test_user_msg_with_wrong_magiv_value() -> Result<()> { - let wrong_magic_value = vec![0, 0, 0, 0]; - let encrypt_algo_with_secret = gen_random_encrypt_algo_with_secret(); - let mut encrypted_datas = BufWriter::new(Vec::new()); - - encrypt( - &mut BufReader::new(&wrong_magic_value[..]), - &encrypt_algo_with_secret, - &mut encrypted_datas, - )?; - let encrypted_incoming_datas = encrypted_datas.into_inner().expect("buffer flush error"); - - let result = read( - Some(&encrypt_algo_with_secret), - &encrypted_incoming_datas[..], - true, - ); - if let Err(Error::RecvInvalidMsg(e)) = result { - assert_eq!(IncomingMsgErr::InvalidMagicValue, e); - } else { - panic!("unexpected result") - } - Ok(()) - } - - #[test] - fn test_read() -> Result<()> { - // Crate fake keys - let fake_ephem_pk = &[0u8; 32][..]; - let fake_sig_pk = [0u8; 32].to_vec(); - let _fake_signature_opt = Some(&[0u8; 32][..]); - - // Create fake challenge - let mut fake_challenge = [0u8; 32]; - fake_challenge.copy_from_slice(sha256(fake_ephem_pk).as_ref()); - - // Create encrypt_algo_with_secret - let encrypt_algo_with_secret = gen_random_encrypt_algo_with_secret(); - - ///////////////////// - // CONNECT MSG - ///////////////////// - - let mut incoming_datas = Vec::with_capacity(100); - incoming_datas.append(&mut MAGIC_VALUE.to_vec()); - incoming_datas.append(&mut CURRENT_VERSION.to_vec()); - incoming_datas.append(&mut 74u64.to_be_bytes().to_vec()); // Encapsuled message length - incoming_datas.append(&mut vec![0, 1]); // CONNECT type - incoming_datas.append(&mut fake_ephem_pk.to_vec()); // EPK - incoming_datas.append(&mut SIG_ALGO_ED25519.to_vec()); // SIG_ALGO - incoming_datas.append(&mut fake_sig_pk.clone()); // SIG_PK - incoming_datas.append(&mut vec![5, 4, 4, 5]); // User custom datas - incoming_datas.append(&mut [0u8; 32].to_vec()); // fake sig - assert_eq!( - DecryptedIncomingDatas { - datas: incoming_datas.clone(), - user_msg_begin: 86, - user_msg_end: 90, - msg_type_headers: MsgTypeHeaders::Connect { - peer_ephemeral_pk: [0u8; EPK_SIZE], - sig_algo: SIG_ALGO_ED25519_ARRAY, - sig_pubkey: fake_sig_pk, - } - }, - read(Some(&encrypt_algo_with_secret), &incoming_datas[..], true)?, - ); - - ///////////////////// - // ACK MSG - ///////////////////// - - // Read incoming ack message without custom datas - let mut incoming_datas = Vec::with_capacity(100); - incoming_datas.append(&mut MAGIC_VALUE.to_vec()); - incoming_datas.append(&mut CURRENT_VERSION.to_vec()); - incoming_datas.append(&mut 34u64.to_be_bytes().to_vec()); // Encapsuled message length - incoming_datas.append(&mut vec![0, 2]); // ACK type - incoming_datas.append(&mut fake_challenge.to_vec()); // ACK challenge - incoming_datas.append(&mut [0u8; 32].to_vec()); // fake sig - assert_eq!( - DecryptedIncomingDatas { - datas: incoming_datas.clone(), - user_msg_begin: 50, - user_msg_end: 50, - msg_type_headers: MsgTypeHeaders::Ack { - challenge: fake_challenge, - } - }, - read(Some(&encrypt_algo_with_secret), &incoming_datas[..], true)?, - ); - - Ok(()) - } - - #[test] - fn test_read_user_type_headers() -> Result<()> { - let type_headers = vec![0, 0]; // USER_MSG_TYPE - - let expected = (MsgTypeHeaders::UserMsg, 2); - - assert_eq!(expected, read_type_headers(&type_headers[..])?); - - Ok(()) - } - - #[test] - fn test_read_unknown_type_headers() { - let type_headers = vec![1, 0]; // Unknown type - - let result = read_type_headers(&type_headers[..]); - - if let Err(Error::RecvInvalidMsg(e)) = read_type_headers(&type_headers[..]) { - assert_eq!(e, IncomingMsgErr::UnknownMessageType); - } else { - println!("{:?}", result); - panic!("Unexpected result"); - } - } - - #[test] - fn test_read_ack_type_headers() -> Result<()> { - let challenge = [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 0, 1, - ]; - let mut type_headers = vec![ - 0, 2, // ACK_MSG_TYPE - ]; - type_headers.append(&mut challenge.to_vec()); - - let expected = (MsgTypeHeaders::Ack { challenge }, 34); - - assert_eq!(expected, read_type_headers(&type_headers[..])?); - - Ok(()) - } - - #[test] - fn test_read_connect_type_headers() -> Result<()> { - let type_headers = vec![ - 0, 1, // CONNECT_MSG_TYPE - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 0, 1, // EPK (32 bytes) - 0, 0, 0, 0, // SIG_ALGO_ED25519 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 0, 1, // Sig pubkey (32 bytes) - ]; - - let expected = ( - MsgTypeHeaders::Connect { - peer_ephemeral_pk: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 0, 1, - ], - sig_algo: [0, 0, 0, 0], - sig_pubkey: type_headers[38..].to_vec(), - }, - 70, - ); - - assert_eq!(expected, read_type_headers(&type_headers[..])?); - - Ok(()) - } - - #[test] - fn test_read_connect_type_headers_with_unsupported_sig_algo() { - let type_headers = vec![ - 0, 1, // CONNECT_MSG_TYPE - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 0, 1, // EPK (32 bytes) - 0, 0, 0, 1, // Unsupported sig algo - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, - 9, 0, 1, // Sig pubkey (32 bytes) - ]; - - let result = read_type_headers(&type_headers[..]); - - if let Err(Error::RecvInvalidMsg(e)) = read_type_headers(&type_headers[..]) { - assert_eq!(e, IncomingMsgErr::UnsupportedSigAlgo); - } else { - println!("{:?}", result); - panic!("Unexpected result"); - } - } -} diff --git a/lib/tools/pkstl/src/seeds.rs b/lib/tools/pkstl/src/seeds.rs deleted file mode 100644 index f62ffed2ad23e463182dcd8ddbd22c57d7789ce6..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/seeds.rs +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (C) 2017-2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Provide wrappers around cryptographic seeds - -use clear_on_drop::clear::Clear; - -/// Store a 32 bytes seed. -#[derive(Clone, Debug, Default, PartialEq)] -pub struct Seed32([u8; 32]); - -impl AsRef<[u8]> for Seed32 { - fn as_ref(&self) -> &[u8] { - &self.0 - } -} - -impl AsMut<[u8]> for Seed32 { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0 - } -} - -impl Drop for Seed32 { - #[inline] - fn drop(&mut self) { - <[u8; 32] as Clear>::clear(&mut self.0); - } -} - -impl Seed32 { - #[inline] - /// Create new seed - pub fn new(seed_bytes: [u8; 32]) -> Seed32 { - Seed32(seed_bytes) - } - #[inline] - /// Generate random seed - pub fn random() -> Seed32 { - if let Ok(random_bytes) = ring::rand::generate::<[u8; 32]>(&ring::rand::SystemRandom::new()) - { - Seed32::new(random_bytes.expose()) - } else { - panic!("System error: fail to generate random seed !") - } - } -} - -/// Store a 48 bytes seed. -#[derive(Default)] -pub struct Seed48(InnerSeed48); - -struct InnerSeed48([u8; 48]); - -impl Default for InnerSeed48 { - fn default() -> Self { - InnerSeed48([0u8; 48]) - } -} - -impl AsRef<[u8]> for Seed48 { - fn as_ref(&self) -> &[u8] { - &(self.0).0 - } -} - -impl AsMut<[u8]> for Seed48 { - fn as_mut(&mut self) -> &mut [u8] { - &mut (self.0).0 - } -} - -impl Drop for Seed48 { - #[inline] - fn drop(&mut self) { - <InnerSeed48 as Clear>::clear(&mut self.0); - } -} - -#[cfg(test)] -impl Seed48 { - #[inline] - /// Create new seed - pub fn new(seed_bytes: [u8; 48]) -> Seed48 { - Seed48(InnerSeed48(seed_bytes)) - } -} - -/// Store a 64 bytes seed. -#[derive(Default)] -pub struct Seed64(InnerSeed64); - -struct InnerSeed64([u8; 64]); - -impl Default for InnerSeed64 { - fn default() -> Self { - InnerSeed64([0u8; 64]) - } -} - -impl AsMut<[u8]> for Seed64 { - fn as_mut(&mut self) -> &mut [u8] { - &mut (self.0).0 - } -} - -impl Drop for Seed64 { - #[inline] - fn drop(&mut self) { - <InnerSeed64 as Clear>::clear(&mut self.0); - } -} - -#[cfg(test)] -pub mod tests { - - use super::*; - - #[inline] - /// Generate random Seed48 - pub fn random_seed_48() -> Seed48 { - if let Ok(random_bytes) = ring::rand::generate::<[u8; 48]>(&ring::rand::SystemRandom::new()) - { - Seed48::new(random_bytes.expose()) - } else { - panic!("System error: fail to generate random seed !") - } - } - - #[test] - fn tests_seed32() { - assert_ne!(Seed32::random(), Seed32::random()); - - let mut seed = Seed32::new([3u8; 32]); - - assert_eq!(&[3u8; 32], seed.as_ref()); - assert_eq!(&mut [3u8; 32], seed.as_mut()); - } -} diff --git a/lib/tools/pkstl/src/signature.rs b/lib/tools/pkstl/src/signature.rs deleted file mode 100644 index 29641160be9748629f24326479f9daad2a0268be..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/signature.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Define PKSTL Signature. - -use ring::signature::UnparsedPublicKey; - -/// Signature algorithm Ed25519 -pub const SIG_ALGO_ED25519: &[u8] = &[0, 0, 0, 0]; - -/// Signature algorithm Ed25519 array -pub const SIG_ALGO_ED25519_ARRAY: [u8; 4] = [0, 0, 0, 0]; - -pub(crate) fn verify_sig(pubkey: &[u8], message: &[u8], sig: &[u8]) -> bool { - UnparsedPublicKey::new(&ring::signature::ED25519, pubkey) - .verify(message, sig) - .is_ok() -} diff --git a/lib/tools/pkstl/src/status.rs b/lib/tools/pkstl/src/status.rs deleted file mode 100644 index 200ac43e9f983b379fc4eab13ea18e7d1505f06c..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/src/status.rs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Handle KPSTL status. - -use crate::errors::IncomingMsgErr; -use crate::{Action, ActionSideEffects, Error, LocalNegoThread, MsgType, RemoteNegoThread, Result}; - -/// Secure layer status -#[derive(Clone, Copy, Debug, PartialEq)] -pub(crate) enum SecureLayerStatus { - /// An error has occurred or one peer message is wrong - Fail, - /// Negotiation in progress - OngoingNegotiation { - local: LocalNegoThread, - remote: RemoteNegoThread, - }, - /// Equivalent to "AckMsgWrittenAndPeerAckMsgOk" - NegotiationSuccessful, -} - -impl SecureLayerStatus { - pub(crate) fn init() -> Self { - SecureLayerStatus::OngoingNegotiation { - local: LocalNegoThread::Created, - remote: RemoteNegoThread::WaitConnectMsg, - } - } - pub(crate) fn apply_action(&mut self, action: Action) -> Result<Option<ActionSideEffects>> { - match self { - Self::Fail => Err(Error::ConnectionHadFail), - Self::OngoingNegotiation { local, remote } => match action { - Action::Create(msg_type) => match msg_type { - MsgType::Connect => { - if *local == LocalNegoThread::Created { - *local = LocalNegoThread::ConnectMsgSent; - Ok(None) - } else { - Err(Error::ConnectMsgAlreadyWritten) - } - } - MsgType::Ack => { - if *remote == RemoteNegoThread::ValidConnectMsgReceived { - if *local == LocalNegoThread::ValidAckMsgReceived { - *self = Self::NegotiationSuccessful; - } else { - *remote = RemoteNegoThread::AckMsgSent; - } - Ok(None) - } else { - Err(Error::ForbidWriteAckMsgNow) - } - } - MsgType::UserMsg => { - *self = Self::Fail; - Err(Error::NegoMustHaveBeenSuccessful) - } - }, - Action::Receive(msg_type) => match msg_type { - MsgType::Connect => { - if *remote == RemoteNegoThread::WaitConnectMsg { - *remote = RemoteNegoThread::ValidConnectMsgReceived; - Ok(None) - } else { - *self = Self::Fail; - Err(Error::RecvInvalidMsg(IncomingMsgErr::UnexpectedConnectMsg)) - } - } - MsgType::Ack => { - if *local == LocalNegoThread::ConnectMsgSent { - if *remote == RemoteNegoThread::AckMsgSent { - *self = Self::NegotiationSuccessful; - } else { - *local = LocalNegoThread::ValidAckMsgReceived; - } - Ok(None) - } else { - *self = Self::Fail; - Err(Error::RecvInvalidMsg(IncomingMsgErr::UnexpectedAckMsg)) - } - } - MsgType::UserMsg => { - if *remote == RemoteNegoThread::AckMsgSent - && *local == LocalNegoThread::ConnectMsgSent - { - Ok(Some(ActionSideEffects::PushUserMsgIntoTmpStack)) - } else { - *self = Self::Fail; - Err(Error::RecvInvalidMsg(IncomingMsgErr::UnexpectedMessage)) - } - } - }, - }, - Self::NegotiationSuccessful => match action { - Action::Create(msg_type) => match msg_type { - MsgType::Connect => Err(Error::ConnectMsgAlreadyWritten), - MsgType::Ack => Err(Error::ForbidWriteAckMsgNow), - MsgType::UserMsg => Ok(None), - }, - Action::Receive(msg_type) => match msg_type { - MsgType::Connect => { - *self = Self::Fail; - Err(Error::RecvInvalidMsg(IncomingMsgErr::UnexpectedConnectMsg)) - } - MsgType::Ack => { - *self = Self::Fail; - Err(Error::RecvInvalidMsg(IncomingMsgErr::UnexpectedAckMsg)) - } - MsgType::UserMsg => Ok(None), - }, - }, - } - } -} diff --git a/lib/tools/pkstl/tests/complete_mode.rs b/lib/tools/pkstl/tests/complete_mode.rs deleted file mode 100644 index 47dcecc87fdbd5fba6758f7bef35ba361d0dc689..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/tests/complete_mode.rs +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Test Public Key Secure Transport Layer in complete mode. - -#[cfg(feature = "zip-sign")] -mod tests { - use pkstl::*; - use ring::signature::{Ed25519KeyPair, KeyPair}; - use std::io::BufWriter; - - trait AsOptRef { - fn as_opt_ref(&self) -> Option<&[u8]>; - } - - impl AsOptRef for Option<Vec<u8>> { - fn as_opt_ref(&self) -> Option<&[u8]> { - match self { - Some(ref datas) => Some(&datas[..]), - None => None, - } - } - } - - fn server_infos() -> Result<(SecureLayer, Vec<u8>)> { - // Create server sig keypair seed - let seed = Seed32::random(); - - // Create server secure layer - let server_msl = - SecureLayer::create(SecureLayerConfig::default(), Some(seed.clone()), None)?; - - // Get server sig pubkey - let server_sig_pubkey = Ed25519KeyPair::from_seed_unchecked(seed.as_ref()) - .map_err(|_| Error::FailtoGenSigKeyPair)? - .public_key() - .as_ref() - .to_vec(); - - Ok((server_msl, server_sig_pubkey)) - } - - fn client_infos(expected_server_sig_pubkey: Option<Vec<u8>>) -> Result<SecureLayer> { - // Create client secure layer - let client_msl = SecureLayer::create( - SecureLayerConfig::default(), - None, - expected_server_sig_pubkey, - )?; - - Ok(client_msl) - } - - fn send_connect_msg( - sender_msl: &mut SecureLayer, - receiver_msl: &mut SecureLayer, - custom_datas: Option<Vec<u8>>, - ) -> Result<Vec<u8>> { - // Write connect message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - sender_msl.write_connect_msg_bin(custom_datas.as_opt_ref(), &mut channel)?; - - // Receiver read connect message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - let msg_received = receiver_msl.read_bin(&channel[..])?; - if let IncomingBinaryMessage::Connect { - custom_datas: custom_datas_received, - peer_sig_public_key, - } = msg_received.get(0).expect("Must be receive a message") - { - assert_eq!(&custom_datas, custom_datas_received); - Ok(peer_sig_public_key.to_owned()) - } else { - print!("Unexpected incoming message={:?}", msg_received); - panic!(); - } - } - - fn send_ack_msg( - sender_msl: &mut SecureLayer, - receiver_msl: &mut SecureLayer, - custom_datas: Option<Vec<u8>>, - ) -> Result<()> { - // Write ack message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - sender_msl.write_ack_msg_bin(custom_datas.as_opt_ref(), &mut channel)?; - - // Receiver read ack message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - let msg_received = receiver_msl.read_bin(&channel[..])?; - if let IncomingBinaryMessage::Ack { - custom_datas: custom_datas_received, - } = msg_received.get(0).expect("Must be receive a message") - { - assert_eq!(&custom_datas, custom_datas_received); - Ok(()) - } else { - print!("Unexpected incoming message={:?}", msg_received); - panic!(); - } - } - - fn send_user_msg( - sender_msl: &mut SecureLayer, - receiver_msl: &mut SecureLayer, - datas: Vec<u8>, - ) -> Result<()> { - // Write user message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - sender_msl.write_bin(&datas[..], &mut channel)?; - - // Receiver read user message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - let msg_received = receiver_msl.read_bin(&channel[..])?; - if let IncomingBinaryMessage::Message { - datas: datas_received, - } = msg_received.get(0).expect("Must be receive a message") - { - assert_eq!(&Some(datas), datas_received); - Ok(()) - } else { - print!("Unexpected incoming message={:?}", msg_received); - panic!(); - } - } - - #[test] - fn server_recv_ack_early() -> Result<()> { - ////////////////////////// - // SERVER INFOS - ////////////////////////// - - let (mut server_msl, server_sig_pk) = server_infos()?; - - ////////////////////////// - // CLIENT INFOS - ////////////////////////// - - let mut client_msl = client_infos(Some(server_sig_pk.clone()))?; - - ////////////////////////// - // SERVER CONNECT MSG - ////////////////////////// - - send_connect_msg(&mut server_msl, &mut client_msl, Some(vec![5, 1, 1, 5]))?; - - ////////////////////////// - // CLIENT ACK MSG - ////////////////////////// - - // Client write ack message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - let client_ack_custom_datas = Some(vec![7, 1, 1, 7]); - client_msl.write_ack_msg_bin(client_ack_custom_datas.as_opt_ref(), &mut channel)?; - - // Server read ack message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - let msg_receiveds = server_msl.read_bin(&channel[..])?; - - // Server must read nothing because the ack message received too early has been set aside - assert_eq!( - Vec::<IncomingBinaryMessage>::with_capacity(0), - msg_receiveds - ); - - ////////////////////////// - // CLIENT CONNECT MSG - ////////////////////////// - - // Client write connect message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - let client_connect_custom_datas = Some(vec![5, 1, 1, 5]); - client_msl.write_connect_msg_bin(client_connect_custom_datas.as_opt_ref(), &mut channel)?; - - // Server read connect message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - let msgs_received = server_msl.read_bin(&channel[..])?; - if let IncomingBinaryMessage::Connect { - custom_datas: custom_datas_received, - .. - } = msgs_received.get(0).expect("Must be receive a message") - { - assert_eq!(&client_connect_custom_datas, custom_datas_received); - } else { - print!("Unexpected incoming messages={:?}", msgs_received); - panic!(); - } - - // Server must also receive the ack message that had been set aside - if let IncomingBinaryMessage::Ack { - custom_datas: custom_datas_received, - } = msgs_received.get(1).expect("Must be receive a message") - { - assert_eq!(&client_ack_custom_datas, custom_datas_received); - } else { - print!("Unexpected incoming messages={:?}", msgs_received); - panic!(); - } - - Ok(()) - } - - #[test] - fn ordered_passing_case() -> Result<()> { - ////////////////////////// - // SERVER INFOS - ////////////////////////// - - let (mut server_msl, server_sig_pk) = server_infos()?; - - ////////////////////////// - // CLIENT INFOS - ////////////////////////// - - let mut client_msl = client_infos(Some(server_sig_pk.clone()))?; - - ////////////////////////// - // CLIENT CONNECT MSG - ////////////////////////// - - let _client_sig_pk_recv = - send_connect_msg(&mut client_msl, &mut server_msl, Some(vec![5, 4, 4, 5]))?; - - ////////////////////////// - // SERVER CONNECT MSG - ////////////////////////// - - let server_sig_pk_recv = - send_connect_msg(&mut server_msl, &mut client_msl, Some(vec![5, 3, 3, 5]))?; - assert_eq!(server_sig_pk, server_sig_pk_recv); - - ////////////////////////// - // SERVER ACK MSG - ////////////////////////// - - send_ack_msg(&mut server_msl, &mut client_msl, Some(vec![5, 9, 9, 5]))?; - - ////////////////////////// - // CLIENT ACK MSG - ////////////////////////// - - send_ack_msg(&mut client_msl, &mut server_msl, Some(vec![5, 0, 0, 5]))?; - - // Negociation must be successfull, so we can clone secure layer - client_msl.try_clone()?; - server_msl.try_clone()?; - - // After clone, we can't change config - let result = client_msl.change_config(SecureLayerConfig::default()); - if let Err(Error::ForbidChangeConfAfterClone) = result { - // OK - } else { - println!("unexpected result={:?}", result); - panic!(); - } - - ////////////////////////// - // CLIENT USER MSG - ////////////////////////// - - send_user_msg(&mut client_msl, &mut server_msl, vec![5, 5, 5, 5])?; - - ////////////////////////// - // SERVER USER MSG - ////////////////////////// - - send_user_msg(&mut server_msl, &mut client_msl, vec![9, 9, 9, 9])?; - - Ok(()) - } -} diff --git a/lib/tools/pkstl/tests/complete_serde_mode.rs b/lib/tools/pkstl/tests/complete_serde_mode.rs deleted file mode 100644 index ab7e58174c6468a90ccff515165b45b588ec11b9..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/tests/complete_serde_mode.rs +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Test Public Key Secure Transport Layer in complete mode with "ser" feature. - -#[cfg(feature = "ser")] -mod tests { - use pkstl::*; - use ring::signature::{Ed25519KeyPair, KeyPair}; - use serde::de::DeserializeOwned; - use serde::Serialize; - use std::fmt::Debug; - use std::io::BufWriter; - - fn server_infos(format: MessageFormat) -> Result<(SecureLayer, Vec<u8>)> { - // Create server sig keypair seed - let seed = Seed32::random(); - - // Create server secure layer - let mut conf = SecureLayerConfig::default(); - conf.message_format = format; - let server_msl = SecureLayer::create(conf, Some(seed.clone()), None)?; - - // Get server sig pubkey - let server_sig_pubkey = Ed25519KeyPair::from_seed_unchecked(seed.as_ref()) - .map_err(|_| Error::FailtoGenSigKeyPair)? - .public_key() - .as_ref() - .to_vec(); - - Ok((server_msl, server_sig_pubkey)) - } - - fn client_infos( - expected_server_sig_pubkey: Option<Vec<u8>>, - format: MessageFormat, - ) -> Result<SecureLayer> { - // Create client secure layer - let mut conf = SecureLayerConfig::default(); - conf.message_format = format; - let client_msl = SecureLayer::create(conf, None, expected_server_sig_pubkey)?; - - Ok(client_msl) - } - - fn send_connect_msg<D: Debug + PartialEq + Serialize + DeserializeOwned>( - sender_msl: &mut SecureLayer, - receiver_msl: &mut SecureLayer, - custom_datas: Option<D>, - ) -> Result<Vec<u8>> { - // Write connect message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - sender_msl.write_connect_msg(custom_datas.as_ref(), &mut channel)?; - - // Receiver read connect message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - let msg_received = receiver_msl.read(&channel[..])?; - if let IncomingMessage::Connect { - custom_datas: custom_datas_received, - peer_sig_public_key, - } = msg_received.get(0).expect("Must be receive a message") - { - assert_eq!(&custom_datas, custom_datas_received); - Ok(peer_sig_public_key.to_owned()) - } else { - print!("Unexpected incoming message={:?}", msg_received); - panic!(); - } - } - - fn send_ack_msg<D: Debug + PartialEq + Serialize + DeserializeOwned>( - sender_msl: &mut SecureLayer, - receiver_msl: &mut SecureLayer, - custom_datas: Option<D>, - ) -> Result<()> { - // Write ack message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - sender_msl.write_ack_msg(custom_datas.as_ref(), &mut channel)?; - - // Receiver read ack message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - let msg_received = receiver_msl.read(&channel[..])?; - if let IncomingMessage::Ack { - custom_datas: custom_datas_received, - } = msg_received.get(0).expect("Must be receive a message") - { - assert_eq!(&custom_datas, custom_datas_received); - Ok(()) - } else { - print!("Unexpected incoming message={:?}", msg_received); - panic!(); - } - } - - fn send_user_msg<D: Debug + PartialEq + Serialize + DeserializeOwned>( - sender_msl: &mut SecureLayer, - receiver_msl: &mut SecureLayer, - datas: D, - ) -> Result<()> { - // Write user message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - sender_msl.write(&datas, &mut channel)?; - - // Receiver read user message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - let msg_received = receiver_msl.read(&channel[..])?; - if let IncomingMessage::Message { - datas: datas_received, - } = msg_received.get(0).expect("Must be receive a message") - { - assert_eq!(&Some(datas), datas_received); - Ok(()) - } else { - print!("Unexpected incoming message={:?}", msg_received); - panic!(); - } - } - - #[cfg(feature = "bin")] - #[test] - fn ordered_passing_case_bincode() -> Result<()> { - test_ordered_passing_case( - MessageFormat::Bincode, - Some("abc".to_owned()), - None, - Some("blablabla".to_owned()), - ) - } - - #[cfg(feature = "cbor")] - #[test] - fn ordered_passing_case_cbor() -> Result<()> { - test_ordered_passing_case( - MessageFormat::Cbor, - None, - Some("def".to_owned()), - Some("blablabla".to_owned()), - ) - } - - #[cfg(feature = "json")] - #[test] - fn ordered_passing_case_json() -> Result<()> { - test_ordered_passing_case( - MessageFormat::Utf8Json, - Some("abc".to_owned()), - Some("def".to_owned()), - None, - ) - } - - fn test_ordered_passing_case<D: Clone + Debug + PartialEq + Serialize + DeserializeOwned>( - message_format: MessageFormat, - connect_msg_custom_datas: Option<D>, - ack_msg_custom_datas: Option<D>, - user_msg_datas: Option<D>, - ) -> Result<()> { - ////////////////////////// - // SERVER INFOS - ////////////////////////// - - let (mut server_msl, server_sig_pk) = server_infos(message_format)?; - - ////////////////////////// - // CLIENT INFOS - ////////////////////////// - - let mut client_msl = client_infos(Some(server_sig_pk.clone()), message_format)?; - - ////////////////////////// - // CLIENT CONNECT MSG - ////////////////////////// - - let _client_sig_pk_recv = send_connect_msg( - &mut client_msl, - &mut server_msl, - connect_msg_custom_datas.clone(), - )?; - - ////////////////////////// - // SERVER CONNECT MSG - ////////////////////////// - - let server_sig_pk_recv = - send_connect_msg(&mut server_msl, &mut client_msl, connect_msg_custom_datas)?; - assert_eq!(server_sig_pk, server_sig_pk_recv); - - ////////////////////////// - // SERVER ACK MSG - ////////////////////////// - - send_ack_msg( - &mut server_msl, - &mut client_msl, - ack_msg_custom_datas.clone(), - )?; - - ////////////////////////// - // CLIENT ACK MSG - ////////////////////////// - - send_ack_msg(&mut client_msl, &mut server_msl, ack_msg_custom_datas)?; - - ////////////////////////// - // CLIENT USER MSG - ////////////////////////// - - send_user_msg(&mut client_msl, &mut server_msl, user_msg_datas.clone())?; - - ////////////////////////// - // SERVER USER MSG - ////////////////////////// - - send_user_msg(&mut server_msl, &mut client_msl, user_msg_datas)?; - - Ok(()) - } -} diff --git a/lib/tools/pkstl/tests/minimal_mode.rs b/lib/tools/pkstl/tests/minimal_mode.rs deleted file mode 100644 index 6f7537202b73f68d8cc771699048f78acb1cad0e..0000000000000000000000000000000000000000 --- a/lib/tools/pkstl/tests/minimal_mode.rs +++ /dev/null @@ -1,485 +0,0 @@ -// Copyright (C) 2019 Eloïs SANCHEZ. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. - -//! Test Public Key Secure Transport Layer in minimal mode. - -use pkstl::*; -use ring::signature::{Ed25519KeyPair, KeyPair}; -use std::io::{BufWriter, Write}; - -trait AsOptRef { - fn as_opt_ref(&self) -> Option<&[u8]>; -} - -impl AsOptRef for Option<Vec<u8>> { - fn as_opt_ref(&self) -> Option<&[u8]> { - match self { - Some(ref datas) => Some(&datas[..]), - None => None, - } - } -} - -fn client_infos(server_sig_kp: &[u8]) -> Result<(MinimalSecureLayer, Ed25519KeyPair)> { - // Create client sig keypair - let client_sig_kp = Ed25519KeyPair::from_seed_unchecked(Seed32::random().as_ref()) - .map_err(|_| Error::FailtoGenSigKeyPair)?; - - // Create client secure layer - let client_msl = - MinimalSecureLayer::create(SecureLayerConfig::default(), Some(server_sig_kp.to_vec()))?; - - Ok((client_msl, client_sig_kp)) -} - -fn server_infos() -> Result<(MinimalSecureLayer, Ed25519KeyPair)> { - // Create server secure layer - let server_msl = MinimalSecureLayer::create(SecureLayerConfig::default(), None)?; - - // Create server sig keypair - let server_sig_kp = Ed25519KeyPair::from_seed_unchecked(Seed32::random().as_ref()) - .map_err(|_| Error::FailtoGenSigKeyPair)?; - - Ok((server_msl, server_sig_kp)) -} - -fn send_connect_msg_inner( - sender_msl: &mut MinimalSecureLayer, - sender_sig_kp: &Ed25519KeyPair, - receiver_msl: &mut MinimalSecureLayer, - custom_datas: Option<Vec<u8>>, -) -> Result<Option<Message>> { - // Create and sign connect message - let connect_msg = sender_msl.create_connect_message( - sender_sig_kp.public_key().as_ref(), - custom_datas.as_opt_ref(), - )?; - let sig = sender_sig_kp.sign(&connect_msg); - - // Write connect message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - channel - .write(&connect_msg) - .map_err(|_| Error::BufferFlushError)?; - channel - .write(sig.as_ref()) - .map_err(|_| Error::BufferFlushError)?; - - // Receiver read connect message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - receiver_msl.read(&channel[..]) -} - -#[inline] -fn send_connect_msg( - sender_msl: &mut MinimalSecureLayer, - sender_sig_kp: &Ed25519KeyPair, - receiver_msl: &mut MinimalSecureLayer, - custom_datas: Option<Vec<u8>>, -) -> Result<()> { - let connect_msg_received = send_connect_msg_inner( - sender_msl, - sender_sig_kp, - receiver_msl, - custom_datas.clone(), - )? - .expect("Must be receive a message"); - assert_eq!( - Message::Connect { - sig_algo: SIG_ALGO_ED25519_ARRAY, - sig_pubkey: sender_sig_kp.public_key().as_ref().to_vec(), - custom_datas, - }, - connect_msg_received, - ); - Ok(()) -} - -#[inline] -fn send_ack_msg( - sender_msl: &mut MinimalSecureLayer, - sender_sig_kp: &Ed25519KeyPair, - receiver_msl: &mut MinimalSecureLayer, - custom_datas: Option<Vec<u8>>, -) -> Result<()> { - let msg_received = send_ack_msg_inner( - sender_msl, - sender_sig_kp, - receiver_msl, - custom_datas.as_opt_ref(), - )? - .expect("Must be receive a message"); - assert_eq!(Message::Ack { custom_datas }, msg_received,); - Ok(()) -} - -fn send_ack_msg_inner<'a>( - sender_msl: &mut MinimalSecureLayer, - sender_sig_kp: &Ed25519KeyPair, - receiver_msl: &'a mut MinimalSecureLayer, - custom_datas: Option<&[u8]>, -) -> Result<Option<Message>> { - // Create and sign server ack message - let ack_msg = sender_msl.create_ack_message(custom_datas)?; - let sig = sender_sig_kp.sign(&ack_msg); - - // Write server ack message and it's sig in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - channel - .write(&ack_msg) - .map_err(|_| Error::BufferFlushError)?; - channel - .write(sig.as_ref()) - .map_err(|_| Error::BufferFlushError)?; - - // Client read server ack message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - receiver_msl.read(&channel[..]) -} - -#[inline] -fn send_user_msg( - sender_msl: &mut MinimalSecureLayer, - receiver_msl: &mut MinimalSecureLayer, - datas: Vec<u8>, -) -> Result<()> { - let msg_received = send_user_msg_inner(sender_msl, receiver_msl, datas.clone())? - .expect("Must be receive a message"); - assert_eq!( - Message::Message { - custom_datas: Some(datas), - }, - msg_received, - ); - Ok(()) -} - -fn send_user_msg_inner( - sender_msl: &mut MinimalSecureLayer, - receiver_msl: &mut MinimalSecureLayer, - datas: Vec<u8>, -) -> Result<Option<Message>> { - // Client write one message in channel - let mut channel = BufWriter::new(Vec::with_capacity(1_000)); - sender_msl.write_message(&datas, &mut channel)?; - - // Server read client message from channel - let channel = channel.into_inner().map_err(|_| Error::BufferFlushError)?; - receiver_msl.read(&channel[..]) -} - -#[test] -fn server_recv_ack_early() -> Result<()> { - ////////////////////////// - // SERVER INFOS - ////////////////////////// - - let (mut server_msl, server_sig_kp) = server_infos()?; - - ////////////////////////// - // CLIENT INFOS - ////////////////////////// - - let (mut client_msl, client_sig_kp) = client_infos(server_sig_kp.public_key().as_ref())?; - - ////////////////////////// - // SERVER CONNECT MSG - ////////////////////////// - - send_connect_msg( - &mut server_msl, - &server_sig_kp, - &mut client_msl, - Some(vec![5, 1, 1, 5]), - )?; - - ////////////////////////// - // CLIENT ACK MSG - ////////////////////////// - - assert_eq!( - None, - send_ack_msg_inner( - &mut client_msl, - &client_sig_kp, - &mut server_msl, - Some(&[7, 1, 1, 7]), - )? - ); - - ////////////////////////// - // CLIENT CONNECT MSG - ////////////////////////// - - send_connect_msg( - &mut client_msl, - &client_sig_kp, - &mut server_msl, - Some(vec![5, 4, 4, 5]), - )?; - - ////////////////////////// - // SERVER ACK MSG - ////////////////////////// - - send_ack_msg( - &mut server_msl, - &server_sig_kp, - &mut client_msl, - Some(vec![3, 1, 1, 3]), - )?; - - ///////////////////////////////////////// - // RECEIVE CLIENT USER MSG TOO EARLY - ///////////////////////////////////////// - - assert_eq!( - None, - send_user_msg_inner(&mut client_msl, &mut server_msl, vec![5, 2, 2, 5],)? - ); - - ////////////////////////////////////////// - // GET CLIENT ACK MSG RECEIVED TOO EARLY - ////////////////////////////////////////// - - assert_eq!( - Some(Message::Ack { - custom_datas: Some(vec![7, 1, 1, 7]), - }), - server_msl.take_ack_msg_recv_too_early()? - ); - - assert_eq!(None, server_msl.take_ack_msg_recv_too_early()?); - - ////////////////////////////////////////// - // GET CLIENT USER MSG RECEIVED TOO EARLY - ////////////////////////////////////////// - - assert_eq!( - vec![Message::Message { - custom_datas: Some(vec![5, 2, 2, 5]), - }], - server_msl.drain_tmp_stack_user_msgs()? - ); - - assert_eq!( - Vec::<Message>::with_capacity(0), - server_msl.drain_tmp_stack_user_msgs()? - ); - - Ok(()) -} - -#[test] -fn disordered_passing_case() -> Result<()> { - ////////////////////////// - // SERVER INFOS - ////////////////////////// - - let (mut server_msl, server_sig_kp) = server_infos()?; - - ////////////////////////// - // CLIENT INFOS - ////////////////////////// - - let (mut client_msl, client_sig_kp) = client_infos(server_sig_kp.public_key().as_ref())?; - - ////////////////////////// - // CLIENT CONNECT MSG - ////////////////////////// - - send_connect_msg( - &mut client_msl, - &client_sig_kp, - &mut server_msl, - Some(vec![5, 4, 4, 5]), - )?; - - ////////////////////////// - // SERVER ACK MSG - ////////////////////////// - - send_ack_msg( - &mut server_msl, - &server_sig_kp, - &mut client_msl, - Some(vec![5, 8, 8, 5]), - )?; - - ////////////////////////// - // SERVER CONNECT MSG - ////////////////////////// - - send_connect_msg( - &mut server_msl, - &server_sig_kp, - &mut client_msl, - Some(vec![5, 1, 1, 5]), - )?; - - ////////////////////////// - // CLIENT ACK MSG - ////////////////////////// - - send_ack_msg( - &mut client_msl, - &client_sig_kp, - &mut server_msl, - Some(vec![7, 4, 4, 7]), - )?; - - ////////////////////////// - // SERVER USER MSG - ////////////////////////// - - send_user_msg(&mut server_msl, &mut client_msl, vec![1, 5, 5, 1])?; - - Ok(()) -} - -#[test] -fn test_middle_man_detection() -> Result<()> { - ////////////////////////// - // SERVER INFOS - ////////////////////////// - - let (_server_msl, server_sig_kp) = server_infos()?; - - ////////////////////////// - // MIDDLE MAN INFOS - ////////////////////////// - - let (mut middle_msl, middle_sig_kp) = server_infos()?; - - ////////////////////////// - // CLIENT INFOS - ////////////////////////// - - let (mut client_msl, client_sig_kp) = client_infos(server_sig_kp.public_key().as_ref())?; - - ////////////////////////// - // CLIENT CONNECT MSG - ////////////////////////// - - send_connect_msg( - &mut client_msl, - &client_sig_kp, - &mut middle_msl, - Some(vec![7, 6, 5, 4]), - )?; - - ////////////////////////// - // MIDDLE MAN CONNECT MSG - ////////////////////////// - - let result = send_connect_msg( - &mut middle_msl, - &middle_sig_kp, - &mut client_msl, - Some(vec![7, 5, 6, 4]), - ); - if let Err(Error::UnexpectedRemoteSigPubKey) = result { - Ok(()) - } else { - println!("unexpected result={:?}", result); - panic!(); - } -} - -#[test] -fn ordered_passing_case() -> Result<()> { - ////////////////////////// - // SERVER INFOS - ////////////////////////// - - let (mut server_msl, server_sig_kp) = server_infos()?; - - ////////////////////////// - // CLIENT INFOS - ////////////////////////// - - let (mut client_msl, client_sig_kp) = client_infos(server_sig_kp.public_key().as_ref())?; - - ////////////////////////// - // CLIENT CONNECT MSG - ////////////////////////// - - send_connect_msg( - &mut client_msl, - &client_sig_kp, - &mut server_msl, - Some(vec![5, 4, 4, 5]), - )?; - - ////////////////////////// - // SERVER CONNECT MSG - ////////////////////////// - - send_connect_msg( - &mut server_msl, - &server_sig_kp, - &mut client_msl, - Some(vec![5, 6, 6, 5]), - )?; - - ////////////////////////// - // SERVER ACK MSG - ////////////////////////// - - send_ack_msg( - &mut server_msl, - &server_sig_kp, - &mut client_msl, - Some(vec![5, 8, 8, 5]), - )?; - - ////////////////////////// - // CLIENT ACK MSG - ////////////////////////// - - send_ack_msg( - &mut client_msl, - &client_sig_kp, - &mut server_msl, - Some(vec![5, 9, 9, 5]), - )?; - - // Negociation must be successfull, so we can clone secure layer - client_msl.try_clone()?; - server_msl.try_clone()?; - - // After clone, we can't change config - let result = client_msl.change_config(SecureLayerConfig::default()); - if let Err(Error::ForbidChangeConfAfterClone) = result { - // OK - } else { - println!("unexpected result={:?}", result); - panic!(); - } - - ////////////////////////// - // CLIENT USER MSG - ////////////////////////// - - send_user_msg(&mut client_msl, &mut server_msl, vec![5, 7, 7, 5])?; - - ////////////////////////// - // SERVER USER MSG - ////////////////////////// - - send_user_msg(&mut server_msl, &mut client_msl, vec![7, 4, 4, 7])?; - - Ok(()) -}