proto: API to expose the `CircuitBinding` type.

Closes #993
This commit is contained in:
Nick Mathewson 2023-08-04 08:51:26 -04:00
parent 61513de6d0
commit 65a0ac5512
4 changed files with 40 additions and 5 deletions

View File

@ -14,3 +14,6 @@ ADDED: `ClientCirc::start_conversation()` to eventually replace
BREAKING: `ClientCirc::allow_stream_requests` is now async BREAKING: `ClientCirc::allow_stream_requests` is now async
BREAKING: `IncomingStream::discard` now takes `mut self` instead of `self` and BREAKING: `IncomingStream::discard` now takes `mut self` instead of `self` and
returns a `Result<(), Bug>` returns a `Result<(), Bug>`
ADDED: `ClientCirc::binding_key`

View File

@ -57,12 +57,14 @@ use crate::circuit::reactor::{
CircuitHandshake, CtrlMsg, Reactor, RECV_WINDOW_INIT, STREAM_READER_BUFFER, CircuitHandshake, CtrlMsg, Reactor, RECV_WINDOW_INIT, STREAM_READER_BUFFER,
}; };
pub use crate::circuit::unique_id::UniqId; pub use crate::circuit::unique_id::UniqId;
pub use crate::crypto::binding::CircuitBinding;
use crate::crypto::cell::HopNum; use crate::crypto::cell::HopNum;
use crate::stream::{ use crate::stream::{
AnyCmdChecker, DataCmdChecker, DataStream, ResolveCmdChecker, ResolveStream, StreamParameters, AnyCmdChecker, DataCmdChecker, DataStream, ResolveCmdChecker, ResolveStream, StreamParameters,
StreamReader, StreamReader,
}; };
use crate::{Error, ResolveError, Result}; use crate::{Error, ResolveError, Result};
use educe::Educe;
use tor_cell::{ use tor_cell::{
chancell::{self, msg::AnyChanMsg, CircId}, chancell::{self, msg::AnyChanMsg, CircId},
relaycell::msg::{AnyRelayMsg, Begin, Resolve, Resolved, ResolvedVal}, relaycell::msg::{AnyRelayMsg, Begin, Resolve, Resolved, ResolvedVal},
@ -171,7 +173,8 @@ pub struct ClientCirc {
} }
/// Mutable state shared by [`ClientCirc`] and [`Reactor`]. /// Mutable state shared by [`ClientCirc`] and [`Reactor`].
#[derive(Debug)] #[derive(Educe)]
#[educe(Debug)]
struct MutableState { struct MutableState {
/// Information about this circuit's path. /// Information about this circuit's path.
/// ///
@ -179,6 +182,16 @@ struct MutableState {
/// client code; when we need to add a hop (which is less frequent) we use /// client code; when we need to add a hop (which is less frequent) we use
/// [`Arc::make_mut()`]. /// [`Arc::make_mut()`].
path: Arc<path::Path>, path: Arc<path::Path>,
/// Circuit binding keys [q.v.][`CircuitBinding`] information for each hop
/// in the circuit's path.
///
/// NOTE: Right now, there is a `CircuitBinding` for every hop. There's a
/// fair chance that this will change in the future, and I don't want other
/// code to assume that a `CircuitBinding` _must_ exist, so I'm making this
/// an `Option`.
#[educe(Debug(ignore))]
binding: Vec<Option<CircuitBinding>>,
} }
/// A ClientCirc that needs to send a create cell and receive a created* cell. /// A ClientCirc that needs to send a create cell and receive a created* cell.
@ -342,6 +355,25 @@ impl ClientCirc {
&self.channel &self.channel
} }
/// Return the cryptographic material used to prove knowledge of a shared
/// secret with with `hop`.
///
/// See [`CircuitBinding`] for more information on how this is used.
///
/// Return None if we have no circuit binding information for the hop, or if
/// the hop does not exist.
pub fn binding_key(&self, hop: HopNum) -> Option<CircuitBinding> {
self.mutable
.lock()
.expect("poisoned lock")
.binding
.get::<usize>(hop.into())
.cloned()
.flatten()
// NOTE: I'm not thrilled to have to copy this information, but we use
// it very rarely, so it's not _that_ bad IMO.
}
/// Start an ad-hoc protocol exchange to the specified hop on this circuit /// Start an ad-hoc protocol exchange to the specified hop on this circuit
/// ///
/// To use this: /// To use this:

View File

@ -643,7 +643,8 @@ impl Reactor {
let crypto_out = OutboundClientCrypt::new(); let crypto_out = OutboundClientCrypt::new();
let (control_tx, control_rx) = mpsc::unbounded(); let (control_tx, control_rx) = mpsc::unbounded();
let path = Arc::new(path::Path::default()); let path = Arc::new(path::Path::default());
let mutable = Arc::new(Mutex::new(MutableState { path })); let binding = Vec::new();
let mutable = Arc::new(Mutex::new(MutableState { path, binding }));
let (reactor_closed_tx, reactor_closed_rx) = oneshot::channel(); let (reactor_closed_tx, reactor_closed_rx) = oneshot::channel();
@ -1080,9 +1081,9 @@ impl Reactor {
self.hops.push(hop); self.hops.push(hop);
self.crypto_in.add_layer(rev); self.crypto_in.add_layer(rev);
self.crypto_out.add_layer(fwd); self.crypto_out.add_layer(fwd);
drop(binding); // XXXX
let mut mutable = self.mutable.lock().expect("poisoned lock"); let mut mutable = self.mutable.lock().expect("poisoned lock");
Arc::make_mut(&mut mutable.path).push_hop(peer_id); Arc::make_mut(&mut mutable.path).push_hop(peer_id);
mutable.binding.push(binding);
} }
/// Handle a RELAY cell on this circuit with stream ID 0. /// Handle a RELAY cell on this circuit with stream ID 0.

View File

@ -1,7 +1,6 @@
//! Types related to binding messages to specific circuits //! Types related to binding messages to specific circuits
#![allow(dead_code, unreachable_pub)] // XXXX remove. #[cfg(feature = "hs-service")]
use tor_hscrypto::ops::HsMacKey; use tor_hscrypto::ops::HsMacKey;
use zeroize::Zeroizing; use zeroize::Zeroizing;