further propagation of key rotation information

This commit is contained in:
Jędrzej Stuczyński
2025-04-24 14:17:34 +01:00
parent 85b51f21e5
commit b95afd11af
18 changed files with 272 additions and 171 deletions
-1
View File
@@ -16,7 +16,6 @@ use nym_node_requests::api::v1::mixnode::models::Mixnode;
use nym_node_requests::api::v1::network_requester::exit_policy::models::UsedExitPolicy;
use nym_node_requests::api::v1::network_requester::models::NetworkRequester;
use nym_node_requests::api::v1::node::models::{AuxiliaryDetails, HostSystem, NodeDescription};
use nym_node_requests::api::SignedHostInformation;
use nym_node_requests::routes;
use std::net::SocketAddr;
use std::path::Path;
+25 -8
View File
@@ -28,33 +28,33 @@ impl ActiveSphinxKeys {
}
}
pub(crate) fn even(&self) -> Option<impl Deref<Target = SphinxPrivateKey>> {
pub(crate) fn even(&self) -> Option<SphinxKeyGuard> {
let primary = self.inner.primary_key.load();
if primary.is_even_rotation() {
return Some(primary);
return Some(SphinxKeyGuard::Primary(primary));
}
self.secondary()
}
pub(crate) fn odd(&self) -> Option<impl Deref<Target = SphinxPrivateKey>> {
pub(crate) fn odd(&self) -> Option<SphinxKeyGuard> {
let primary = self.inner.primary_key.load();
if !primary.is_even_rotation() {
return Some(primary);
return Some(SphinxKeyGuard::Primary(primary));
}
self.secondary()
}
pub(crate) fn primary(&self) -> impl Deref<Target = SphinxPrivateKey> {
self.inner.primary_key.map(|k: &SphinxPrivateKey| k).load()
pub(crate) fn primary(&self) -> SphinxKeyGuard {
SphinxKeyGuard::Primary(self.inner.primary_key.load())
}
pub(crate) fn secondary(&self) -> Option<impl Deref<Target = SphinxPrivateKey>> {
pub(crate) fn secondary(&self) -> Option<SphinxKeyGuard> {
let guard = self.inner.secondary_key.load();
if guard.is_none() {
return None;
}
Some(SecondaryKeyGuard { guard })
Some(SphinxKeyGuard::Secondary(SecondaryKeyGuard { guard }))
}
// 1. generate new key
@@ -87,6 +87,23 @@ impl ActiveSphinxKeys {
}
}
pub(crate) enum SphinxKeyGuard {
// Primary(Guard<Arc<SphinxPrivateKey>>),
Primary(Guard<Arc<SphinxPrivateKey>>),
Secondary(SecondaryKeyGuard),
}
impl Deref for SphinxKeyGuard {
type Target = SphinxPrivateKey;
fn deref(&self) -> &Self::Target {
match self {
SphinxKeyGuard::Primary(g) => g.deref(),
SphinxKeyGuard::Secondary(g) => g.deref(),
}
}
}
pub(crate) struct SecondaryKeyGuard {
guard: Guard<Option<Arc<SphinxPrivateKey>>>,
}
+4
View File
@@ -32,6 +32,10 @@ impl SphinxPrivateKey {
self.inner.public_key()
}
pub(crate) fn inner(&self) -> &x25519::PrivateKey {
&self.inner
}
pub(crate) fn is_even_rotation(&self) -> bool {
self.rotation_id & 1 == 0
}
+13 -7
View File
@@ -223,11 +223,15 @@ impl ConnectionHandler {
SphinxKeyRotation::Unknown => {
// we have to try both keys, start with the primary as it has higher likelihood of being correct
// if let Ok(partially_unwrapped) = PartiallyUnwrappedPacket::new()
match PartiallyUnwrappedPacket::new(packet, self.shared.sphinx_keys.primary()) {
match PartiallyUnwrappedPacket::new(
packet,
self.shared.sphinx_keys.primary().inner().as_ref(),
) {
Ok(unwrapped_packet) => Ok(unwrapped_packet),
Err((packet, err)) => {
if let Some(secondary) = self.shared.sphinx_keys.secondary() {
PartiallyUnwrappedPacket::new(packet, secondary).map_err(|(_, err)| err)
PartiallyUnwrappedPacket::new(packet, secondary.inner().as_ref())
.map_err(|(_, err)| err)
} else {
Err(err)
}
@@ -238,13 +242,15 @@ impl ConnectionHandler {
let Some(odd_key) = self.shared.sphinx_keys.odd() else {
return Err(PacketProcessingError::ExpiredKey);
};
PartiallyUnwrappedPacket::new(packet, odd_key).map_err(|(_, err)| err)
PartiallyUnwrappedPacket::new(packet, odd_key.inner().as_ref())
.map_err(|(_, err)| err)
}
SphinxKeyRotation::EvenRotation => {
let Some(even_key) = self.shared.sphinx_keys.even() else {
return Err(PacketProcessingError::ExpiredKey);
};
PartiallyUnwrappedPacket::new(packet, even_key).map_err(|(_, err)| err)
PartiallyUnwrappedPacket::new(packet, even_key.inner().as_ref())
.map_err(|(_, err)| err)
}
}
}
@@ -385,19 +391,19 @@ impl ConnectionHandler {
// and by the time we need it, the rotation info should be present)
match packet.header().key_rotation {
SphinxKeyRotation::Unknown => {
process_framed_packet(packet, self.shared.sphinx_keys.primary())
process_framed_packet(packet, self.shared.sphinx_keys.primary().inner().as_ref())
}
SphinxKeyRotation::OddRotation => {
let Some(odd_key) = self.shared.sphinx_keys.odd() else {
return Err(PacketProcessingError::ExpiredKey);
};
process_framed_packet(packet, odd_key)
process_framed_packet(packet, odd_key.inner().as_ref())
}
SphinxKeyRotation::EvenRotation => {
let Some(even_key) = self.shared.sphinx_keys.even() else {
return Err(PacketProcessingError::ExpiredKey);
};
process_framed_packet(packet, even_key)
process_framed_packet(packet, even_key.inner().as_ref())
}
}
}
@@ -58,32 +58,20 @@ impl<C, F> PacketForwarder<C, F> {
C: SendWithoutResponse,
F: RoutingFilter,
{
let next_hop = packet.next_hop();
let next_hop = packet.next_hop_address();
let packet_type = packet.packet_type();
let packet = packet.into_packet();
if let Err(err) = self
.mixnet_client
.send_without_response(next_hop, packet, packet_type)
{
if let Err(err) = self.mixnet_client.send_without_response(packet) {
if err.kind() == io::ErrorKind::WouldBlock {
// we only know for sure if we dropped a packet if our sending queue was full
// in any other case the connection might still be re-established (or created for the first time)
// and the packet might get sent, but we won't know about it
self.metrics
.mixnet
.egress_dropped_forward_packet(next_hop.into())
self.metrics.mixnet.egress_dropped_forward_packet(next_hop)
} else if err.kind() == io::ErrorKind::NotConnected {
// let's give the benefit of the doubt and assume we manage to establish connection
self.metrics
.mixnet
.egress_sent_forward_packet(next_hop.into())
self.metrics.mixnet.egress_sent_forward_packet(next_hop)
}
} else {
self.metrics
.mixnet
.egress_sent_forward_packet(next_hop.into())
self.metrics.mixnet.egress_sent_forward_packet(next_hop)
}
}