diff --git a/Cargo.lock b/Cargo.lock index d07de2a..df2c030 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,12 +77,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - [[package]] name = "base64" version = "0.22.1" @@ -144,12 +138,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - [[package]] name = "core-foundation" version = "0.9.4" @@ -166,18 +154,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] - [[package]] name = "data-encoding" version = "2.6.0" @@ -216,16 +192,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "zeroize", -] - [[package]] name = "der-parser" version = "9.0.0" @@ -260,44 +226,6 @@ dependencies = [ "syn 2.0.75", ] -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "ff", - "generic-array", - "group", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core", - "subtle", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -315,17 +243,6 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - [[package]] name = "hash32" version = "0.3.1" @@ -508,16 +425,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "elliptic-curve", - "primeorder", -] - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -539,15 +446,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -586,7 +484,6 @@ name = "pterodapter" version = "0.2.0" dependencies = [ "log", - "p256", "rand", "ring", "rustls-platform-verifier", @@ -764,19 +661,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "subtle", - "zeroize", -] - [[package]] name = "security-framework" version = "2.11.1" @@ -988,12 +872,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - [[package]] name = "unicode-ident" version = "1.0.12" diff --git a/Cargo.toml b/Cargo.toml index 1a023a2..843183f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,12 +19,10 @@ smoltcp = { version = "0.11", optional = true, default-features = false, feature ring = { version = "*", optional = true, default-features = false } x509-parser = { version = "0.16", optional = true, default-features = false, features = ["validate"] } -p256 = { version = "0.13", optional = true, default-features = false, features = ["arithmetic"] } - [features] default = ["proxy", "ikev2"] proxy = ["smoltcp"] -ikev2 = ["ring", "x509-parser", "p256"] +ikev2 = ["ring", "x509-parser"] [profile.release] strip = true diff --git a/src/ikev2/crypto.rs b/src/ikev2/crypto.rs index b5e87b2..d5a887e 100644 --- a/src/ikev2/crypto.rs +++ b/src/ikev2/crypto.rs @@ -1,9 +1,6 @@ use log::debug; -use p256::{ - elliptic_curve::sec1::Tag as P256Tag, EncodedPoint, NonZeroScalar, ProjectivePoint, PublicKey, -}; -use rand::{rngs::OsRng, Rng}; -use ring::{aead, digest, hkdf, hmac}; +use rand::Rng; +use ring::{aead, agreement, digest, hkdf, hmac}; use std::{error, fmt, ops::Range}; use super::message; @@ -286,7 +283,7 @@ pub trait DHTransform { fn group_number(&self) -> u16; fn compute_shared_secret( - &self, + &mut self, other_public_key: &[u8], ) -> Result, InitError>; } @@ -295,10 +292,15 @@ impl DHTransformType { fn init(transform_type: message::TransformType) -> Result { match transform_type { message::TransformType::DH_256_ECP => { - let private_key = NonZeroScalar::random(&mut OsRng); - let public_key = PublicKey::from_secret_scalar(&private_key); + let rng = ring::rand::SystemRandom::new(); + let private_key = + agreement::EphemeralPrivateKey::generate(&agreement::ECDH_P256, &rng) + .map_err(|_| InitError::new("Failed to generate private ECDH key"))?; + let public_key = private_key + .compute_public_key() + .map_err(|_| InitError::new("Failed to compute public ECDH key"))?; Ok(DHTransformType::ECP256(DHTransformECP256 { - private_key, + private_key: Some(private_key), public_key, })) } @@ -333,25 +335,25 @@ impl DHTransform for DHTransformType { } fn compute_shared_secret( - &self, + &mut self, other_public_key: &[u8], ) -> Result, InitError> { match self { - Self::ECP256(ref dh) => dh.compute_shared_secret(other_public_key), + Self::ECP256(ref mut dh) => dh.compute_shared_secret(other_public_key), } } } pub struct DHTransformECP256 { - private_key: NonZeroScalar, - public_key: PublicKey, + private_key: Option, + public_key: agreement::PublicKey, } impl DHTransform for DHTransformECP256 { fn read_public_key(&self) -> Array { let mut res = Array::new(self.key_length_bytes()); res.as_mut_slice() - .copy_from_slice(&EncodedPoint::from(&self.public_key).as_bytes()[1..]); + .copy_from_slice(&self.public_key.as_ref()[1..]); res } @@ -368,24 +370,27 @@ impl DHTransform for DHTransformECP256 { } fn compute_shared_secret( - &self, + &mut self, other_public_key: &[u8], ) -> Result, InitError> { let mut res = Array::new(self.shared_key_length_bytes()); let mut other_public_key_sec1 = [0u8; 1 + 64]; - other_public_key_sec1[0] = P256Tag::Uncompressed.into(); + other_public_key_sec1[0] = 0x04; other_public_key_sec1[1..].copy_from_slice(other_public_key); - let other_public_key = match PublicKey::from_sec1_bytes(&other_public_key_sec1) { + let other_public_key = + agreement::UnparsedPublicKey::new(&agreement::ECDH_P256, &other_public_key_sec1); + let private_key = match self.private_key.take() { + Some(private_key) => private_key, + None => return Err("ECDH private key is already consumed".into()), + }; + match agreement::agree_ephemeral(private_key, &other_public_key, |secret_point| { + res.as_mut_slice().copy_from_slice(&secret_point) + }) { Ok(key) => key, - Err(err) => { - debug!("Failed to decode other public key {}", err); - return Err("Failed to decode other public key".into()); + Err(_) => { + return Err("Failed to compute ECDH shared secret".into()); } }; - let public_point = ProjectivePoint::from(other_public_key.as_affine()); - let secret_point = (&public_point * &self.private_key).to_affine(); - res.as_mut_slice() - .copy_from_slice(&EncodedPoint::from(secret_point).compress().as_bytes()[1..]); Ok(res) } } @@ -799,8 +804,10 @@ impl EncryptionType { } let mut salt = [0u8; 4]; salt.copy_from_slice(&key[32..]); - let key = aead::UnboundKey::new(&aead::AES_256_GCM, &key[..32]) - .map_err(|_| InitError::new("Failed to init AES GCM 256 key"))?; + let key = match aead::UnboundKey::new(&aead::AES_256_GCM, &key[..32]) { + Ok(key) => key, + Err(_) => return Err(InitError::new("Failed to init AES GCM 256 key")), + }; let key = aead::LessSafeKey::new(key); Ok(Self::AesGcm256(EncryptionAesGcm256 { key, salt, padding })) } diff --git a/src/ikev2/mod.rs b/src/ikev2/mod.rs index 36a51b2..33569c9 100644 --- a/src/ikev2/mod.rs +++ b/src/ikev2/mod.rs @@ -798,7 +798,7 @@ impl IKEv2Session { } message::PayloadType::KEY_EXCHANGE => { let kex = payload.to_key_exchange()?; - if let Some(dh) = dh_transform.as_ref() { + if let Some(ref mut dh) = dh_transform.as_mut() { let public_key = dh.read_public_key(); shared_secret = match dh.compute_shared_secret(kex.read_value()) { Ok(shared_secret) => Some(shared_secret),