diff --git a/Cargo.lock b/Cargo.lock index 462fcaebd1..9ad4e872af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8668,6 +8668,7 @@ dependencies = [ "serde", "thiserror 2.0.12", "x25519-dalek", + "zeroize", ] [[package]] diff --git a/common/registration/src/lib.rs b/common/registration/src/lib.rs index 8e271ab1ea..0ea47e3d74 100644 --- a/common/registration/src/lib.rs +++ b/common/registration/src/lib.rs @@ -7,6 +7,7 @@ use nym_crypto::asymmetric::{ed25519, x25519}; use nym_ip_packet_requests::IpPair; use nym_kkt_ciphersuite::{Ciphersuite, KEM, KEMKeyDigests}; use nym_sphinx::addressing::Recipient; +use nym_wireguard_types::PresharedKey; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; @@ -44,11 +45,11 @@ pub struct WireguardRegistrationData { pub private_ipv6: Ipv6Addr, } -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct WireguardConfiguration { #[serde(with = "bs58_x25519_pubkey")] pub public_key: x25519::PublicKey, - pub psk: Option<[u8; 32]>, + pub psk: Option, pub endpoint: SocketAddr, pub private_ipv4: Ipv4Addr, pub private_ipv6: Ipv6Addr, diff --git a/common/wireguard-types/Cargo.toml b/common/wireguard-types/Cargo.toml index 35af9c2341..8d271feb0e 100644 --- a/common/wireguard-types/Cargo.toml +++ b/common/wireguard-types/Cargo.toml @@ -15,6 +15,7 @@ description = "Wireguard public key and config definitions" base64 = { workspace = true } serde = { workspace = true, features = ["derive"] } thiserror = { workspace = true } +zeroize.workspace = true x25519-dalek = { workspace = true, features = ["static_secrets"] } nym-crypto = { workspace = true, features = ["asymmetric"] } diff --git a/common/wireguard-types/src/lib.rs b/common/wireguard-types/src/lib.rs index 455eea38dd..9acf72189f 100644 --- a/common/wireguard-types/src/lib.rs +++ b/common/wireguard-types/src/lib.rs @@ -3,12 +3,14 @@ pub mod config; pub mod error; +pub mod preshared_key; pub mod public_key; use std::time::Duration; pub use config::Config; pub use error::Error; +pub use preshared_key::PresharedKey; pub use public_key::PeerPublicKey; pub const DEFAULT_PEER_TIMEOUT_CHECK: Duration = Duration::from_secs(5); // 5 seconds diff --git a/common/wireguard-types/src/preshared_key.rs b/common/wireguard-types/src/preshared_key.rs new file mode 100644 index 0000000000..7dd13ac6c2 --- /dev/null +++ b/common/wireguard-types/src/preshared_key.rs @@ -0,0 +1,26 @@ +// Copyright 2026 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use serde::{Deserialize, Serialize}; +use zeroize::{Zeroize, ZeroizeOnDrop}; + +#[derive(Debug, PartialEq, Serialize, Deserialize, Zeroize, ZeroizeOnDrop)] +pub struct PresharedKey([u8; 32]); + +impl PresharedKey { + pub fn as_bytes(&self) -> &[u8; 32] { + &self.0 + } +} + +impl From<[u8; 32]> for PresharedKey { + fn from(key: [u8; 32]) -> PresharedKey { + PresharedKey(key) + } +} + +impl From for [u8; 32] { + fn from(key: PresharedKey) -> [u8; 32] { + key.0 + } +} diff --git a/nym-gateway-probe/src/common/probe_tests.rs b/nym-gateway-probe/src/common/probe_tests.rs index e52b30fc1b..a0ee3262d9 100644 --- a/nym-gateway-probe/src/common/probe_tests.rs +++ b/nym-gateway-probe/src/common/probe_tests.rs @@ -234,7 +234,7 @@ pub async fn lp_registration_probe( " - PSK: {:?}", gateway_data .psk - .map(|k| general_purpose::STANDARD.encode(k)) + .map(|k| general_purpose::STANDARD.encode(k.as_bytes())) ); info!(" - Private IPv4: {}", gateway_data.private_ipv4); info!(" - Private IPv6: {}", gateway_data.private_ipv6); diff --git a/nym-registration-client/src/clients/lp.rs b/nym-registration-client/src/clients/lp.rs index 651d813445..b924a8456f 100644 --- a/nym-registration-client/src/clients/lp.rs +++ b/nym-registration-client/src/clients/lp.rs @@ -7,7 +7,7 @@ use crate::config::RegistrationMode; use crate::error::RegistrationClientError; use crate::lp_client::helpers::to_lp_remote_peer; use crate::lp_client::{LpRegistrationClient, NestedLpSession}; -use crate::types::{LpRegistrationResult, RegistrationResult}; +use crate::types::{RegistrationResult, WireguardRegistrationResult}; use nym_bandwidth_controller::BandwidthTicketProvider; use nym_credentials_interface::TicketType; @@ -147,13 +147,13 @@ impl LpBasedRegistrationClient { // All data flows through WireGuard after this point. // Each LP packet used its own TCP connection which was closed after the exchange. // Exit registration was completed via forwarding through entry gateway. - Ok(RegistrationResult::Lp(Box::new(LpRegistrationResult { + Ok(RegistrationResult::wireguard_lp( entry_gateway_data, exit_gateway_data, entry_lp_keypair, exit_lp_keypair, - bw_controller: self.bandwidth_controller, - }))) + self.bandwidth_controller, + )) } async fn register_wg(self) -> Result { diff --git a/nym-registration-client/src/clients/mixnet.rs b/nym-registration-client/src/clients/mixnet.rs index 859eee94ea..184111951e 100644 --- a/nym-registration-client/src/clients/mixnet.rs +++ b/nym-registration-client/src/clients/mixnet.rs @@ -1,6 +1,7 @@ // Copyright 2025 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use crate::AuthenticatorRegistrationResult; use crate::config::RegistrationClientConfig; use crate::config::RegistrationMode; use crate::error::RegistrationClientError; @@ -84,19 +85,17 @@ impl MixnetBasedRegistrationClient { } }; - Ok(RegistrationResult::Mixnet(Box::new( - MixnetRegistrationResult { - mixnet_client: ipr_client.into_mixnet_client(), - assigned_addresses: AssignedAddresses { - interface_addresses, - exit_mix_address: ipr_address, - mixnet_client_address: self.mixnet_client_address, - entry_mixnet_gateway_ip, - exit_mixnet_gateway_ip, - }, - event_rx: self.event_rx, + Ok(RegistrationResult::mixnet( + ipr_client.into_mixnet_client(), + AssignedAddresses { + interface_addresses, + exit_mix_address: ipr_address, + mixnet_client_address: self.mixnet_client_address, + entry_mixnet_gateway_ip, + exit_mixnet_gateway_ip, }, - ))) + self.event_rx, + )) } async fn register_wg(self) -> Result { @@ -199,16 +198,14 @@ impl MixnetBasedRegistrationClient { } }; - Ok(RegistrationResult::Wireguard(Box::new( - WireguardRegistrationResult { - entry_gateway_client: entry_auth_client, - exit_gateway_client: exit_auth_client, - entry_gateway_data: entry, - exit_gateway_data: exit, - authenticator_listener_handle: mixnet_listener, - bw_controller: self.bandwidth_controller, - }, - ))) + Ok(RegistrationResult::wireguard_legacy( + entry_auth_client, + exit_auth_client, + entry, + exit, + mixnet_listener, + self.bandwidth_controller, + )) } pub(crate) async fn register(self) -> Result { diff --git a/nym-registration-client/src/lib.rs b/nym-registration-client/src/lib.rs index ca00e270a0..01efc5a543 100644 --- a/nym-registration-client/src/lib.rs +++ b/nym-registration-client/src/lib.rs @@ -12,7 +12,8 @@ pub use lp_client::{ LpRegistrationClient, LpRegistrationConfig, NestedLpSession, error::LpClientError, }; pub use types::{ - LpRegistrationResult, MixnetRegistrationResult, RegistrationResult, WireguardRegistrationResult, + AuthenticatorRegistrationResult, LpRegistrationResult, MixnetRegistrationResult, + RegistrationResult, WireguardRegistrationResult, }; mod builder; diff --git a/nym-registration-client/src/lp_client/client.rs b/nym-registration-client/src/lp_client/client.rs index ab182154bd..45527b4bb7 100644 --- a/nym-registration-client/src/lp_client/client.rs +++ b/nym-registration-client/src/lp_client/client.rs @@ -597,7 +597,7 @@ where Ok(WireguardConfiguration { public_key: final_response.public_key, - psk: Some(psk), + psk: Some(psk.into()), endpoint: SocketAddr::new(self.gateway_lp_address.ip(), final_response.port), private_ipv4: final_response.private_ipv4, private_ipv6: final_response.private_ipv6, diff --git a/nym-registration-client/src/lp_client/nested_session/mod.rs b/nym-registration-client/src/lp_client/nested_session/mod.rs index b6705c9147..08ba26ee4d 100644 --- a/nym-registration-client/src/lp_client/nested_session/mod.rs +++ b/nym-registration-client/src/lp_client/nested_session/mod.rs @@ -401,10 +401,9 @@ impl NestedLpSession { } }; - // JS/SW TODO Adapt this to new gateway response Ok(WireguardConfiguration { public_key: final_response.public_key, - psk: Some(psk), + psk: Some(psk.into()), endpoint: SocketAddr::new(self.exit_address.ip(), final_response.port), private_ipv4: final_response.private_ipv4, private_ipv6: final_response.private_ipv6, diff --git a/nym-registration-client/src/types.rs b/nym-registration-client/src/types.rs index 77f07060b2..e54c2e7f75 100644 --- a/nym-registration-client/src/types.rs +++ b/nym-registration-client/src/types.rs @@ -11,7 +11,58 @@ use std::sync::Arc; pub enum RegistrationResult { Mixnet(Box), Wireguard(Box), - Lp(Box), +} + +impl RegistrationResult { + pub fn mixnet( + mixnet_client: MixnetClient, + assigned_addresses: AssignedAddresses, + event_rx: EventReceiver, + ) -> Self { + RegistrationResult::Mixnet(Box::new(MixnetRegistrationResult { + assigned_addresses, + mixnet_client, + event_rx, + })) + } + + pub fn wireguard_legacy( + entry_gateway_client: AuthenticatorClient, + exit_gateway_client: AuthenticatorClient, + entry_gateway_data: WireguardConfiguration, + exit_gateway_data: WireguardConfiguration, + authenticator_listener_handle: AuthClientMixnetListenerHandle, + bw_controller: Box, + ) -> Self { + RegistrationResult::Wireguard(Box::new(WireguardRegistrationResult::Legacy(Box::new( + AuthenticatorRegistrationResult { + entry_gateway_client, + exit_gateway_client, + entry_gateway_data, + exit_gateway_data, + authenticator_listener_handle, + bw_controller, + }, + )))) + } + + pub fn wireguard_lp( + entry_gateway_data: WireguardConfiguration, + exit_gateway_data: WireguardConfiguration, + entry_lp_keypair: Arc, + exit_lp_keypair: Arc, + bw_controller: Box, + ) -> Self { + RegistrationResult::Wireguard(Box::new(WireguardRegistrationResult::LewesProtocol( + Box::new(LpRegistrationResult { + entry_gateway_data, + exit_gateway_data, + entry_lp_keypair, + exit_lp_keypair, + bw_controller, + }), + ))) + } } pub struct MixnetRegistrationResult { @@ -20,7 +71,28 @@ pub struct MixnetRegistrationResult { pub event_rx: EventReceiver, } -pub struct WireguardRegistrationResult { +pub enum WireguardRegistrationResult { + Legacy(Box), + LewesProtocol(Box), +} + +impl WireguardRegistrationResult { + pub fn entry_gateway_data(&self) -> &WireguardConfiguration { + match self { + Self::Legacy(res) => &res.entry_gateway_data, + Self::LewesProtocol(res) => &res.entry_gateway_data, + } + } + + pub fn exit_gateway_data(&self) -> &WireguardConfiguration { + match self { + Self::Legacy(res) => &res.exit_gateway_data, + Self::LewesProtocol(res) => &res.exit_gateway_data, + } + } +} + +pub struct AuthenticatorRegistrationResult { pub entry_gateway_client: AuthenticatorClient, pub exit_gateway_client: AuthenticatorClient, pub entry_gateway_data: WireguardConfiguration,