2019-01-30 11:36:00 +01:00
|
|
|
// Copyright 2019 Parity Technologies (UK) Ltd.
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
|
|
// to deal in the Software without restriction, including without limitation
|
|
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
// DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
//! [Noise protocol framework][noise] support for libp2p.
|
|
|
|
//!
|
|
|
|
//! This crate provides `libp2p_core::InboundUpgrade` and `libp2p_core::OutboundUpgrade`
|
2019-03-11 13:42:53 +01:00
|
|
|
//! implementations for various noise handshake patterns (currently IK, IX, and XX)
|
|
|
|
//! over a particular choice of DH key agreement (currently only X25519).
|
2019-01-30 11:36:00 +01:00
|
|
|
//!
|
|
|
|
//! All upgrades produce as output a pair, consisting of the remote's static public key
|
|
|
|
//! and a `NoiseOutput` which represents the established cryptographic session with the
|
|
|
|
//! remote, implementing `tokio_io::AsyncRead` and `tokio_io::AsyncWrite`.
|
|
|
|
//!
|
|
|
|
//! # Usage
|
|
|
|
//!
|
|
|
|
//! Example:
|
|
|
|
//!
|
|
|
|
//! ```
|
|
|
|
//! use libp2p_core::Transport;
|
|
|
|
//! use libp2p_tcp::TcpConfig;
|
2019-03-11 13:42:53 +01:00
|
|
|
//! use libp2p_noise::{Keypair, X25519, NoiseConfig};
|
2019-01-30 11:36:00 +01:00
|
|
|
//!
|
|
|
|
//! # fn main() {
|
2019-03-11 13:42:53 +01:00
|
|
|
//! let keys = Keypair::<X25519>::new();
|
|
|
|
//! let transport = TcpConfig::new().with_upgrade(NoiseConfig::xx(keys));
|
2019-01-30 11:36:00 +01:00
|
|
|
//! // ...
|
|
|
|
//! # }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! [noise]: http://noiseprotocol.org/
|
|
|
|
|
|
|
|
mod error;
|
|
|
|
mod io;
|
2019-03-11 13:42:53 +01:00
|
|
|
mod protocol;
|
2019-01-30 11:36:00 +01:00
|
|
|
|
|
|
|
pub mod rt1;
|
|
|
|
pub mod rt15;
|
|
|
|
|
|
|
|
pub use error::NoiseError;
|
|
|
|
pub use io::NoiseOutput;
|
2019-03-11 13:42:53 +01:00
|
|
|
pub use protocol::{Keypair, PublicKey, Protocol, ProtocolParams, IX, IK, XX};
|
|
|
|
pub use protocol::x25519::X25519;
|
2019-01-30 11:36:00 +01:00
|
|
|
|
2019-03-19 17:27:30 +01:00
|
|
|
use libp2p_core::{UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::Negotiated};
|
2019-01-30 11:36:00 +01:00
|
|
|
use tokio_io::{AsyncRead, AsyncWrite};
|
2019-03-11 13:42:53 +01:00
|
|
|
use zeroize::Zeroize;
|
2019-01-30 11:36:00 +01:00
|
|
|
|
|
|
|
/// The protocol upgrade configuration.
|
|
|
|
#[derive(Clone)]
|
2019-03-11 13:42:53 +01:00
|
|
|
pub struct NoiseConfig<P, C: Zeroize, R = ()> {
|
|
|
|
keys: Keypair<C>,
|
|
|
|
params: ProtocolParams,
|
2019-01-30 11:36:00 +01:00
|
|
|
remote: R,
|
|
|
|
_marker: std::marker::PhantomData<P>
|
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<C: Protocol<C> + Zeroize> NoiseConfig<IX, C> {
|
2019-01-30 11:36:00 +01:00
|
|
|
/// Create a new `NoiseConfig` for the IX handshake pattern.
|
2019-03-11 13:42:53 +01:00
|
|
|
pub fn ix(keys: Keypair<C>) -> Self {
|
2019-01-30 11:36:00 +01:00
|
|
|
NoiseConfig {
|
2019-03-11 13:42:53 +01:00
|
|
|
keys,
|
|
|
|
params: C::params_ix(),
|
2019-01-30 11:36:00 +01:00
|
|
|
remote: (),
|
|
|
|
_marker: std::marker::PhantomData
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<C: Protocol<C> + Zeroize> NoiseConfig<XX, C> {
|
2019-01-30 11:36:00 +01:00
|
|
|
/// Create a new `NoiseConfig` for the XX handshake pattern.
|
2019-03-11 13:42:53 +01:00
|
|
|
pub fn xx(keys: Keypair<C>) -> Self {
|
2019-01-30 11:36:00 +01:00
|
|
|
NoiseConfig {
|
2019-03-11 13:42:53 +01:00
|
|
|
keys,
|
|
|
|
params: C::params_xx(),
|
2019-01-30 11:36:00 +01:00
|
|
|
remote: (),
|
|
|
|
_marker: std::marker::PhantomData
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<C: Protocol<C> + Zeroize> NoiseConfig<IK, C> {
|
2019-01-30 11:36:00 +01:00
|
|
|
/// Create a new `NoiseConfig` for the IK handshake pattern (recipient side).
|
2019-03-11 13:42:53 +01:00
|
|
|
pub fn ik_listener(keys: Keypair<C>) -> Self {
|
2019-01-30 11:36:00 +01:00
|
|
|
NoiseConfig {
|
2019-03-11 13:42:53 +01:00
|
|
|
keys,
|
|
|
|
params: C::params_ik(),
|
2019-01-30 11:36:00 +01:00
|
|
|
remote: (),
|
|
|
|
_marker: std::marker::PhantomData
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<C: Protocol<C> + Zeroize> NoiseConfig<IK, C, PublicKey<C>> {
|
2019-01-30 11:36:00 +01:00
|
|
|
/// Create a new `NoiseConfig` for the IK handshake pattern (initiator side).
|
2019-03-11 13:42:53 +01:00
|
|
|
pub fn ik_dialer(keys: Keypair<C>, remote: PublicKey<C>) -> Self {
|
2019-01-30 11:36:00 +01:00
|
|
|
NoiseConfig {
|
2019-03-11 13:42:53 +01:00
|
|
|
keys,
|
|
|
|
params: C::params_ik(),
|
2019-01-30 11:36:00 +01:00
|
|
|
remote,
|
|
|
|
_marker: std::marker::PhantomData
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handshake pattern IX /////////////////////////////////////////////////////
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<T, C> InboundUpgrade<T> for NoiseConfig<IX, C>
|
2019-01-30 11:36:00 +01:00
|
|
|
where
|
2019-03-11 13:42:53 +01:00
|
|
|
T: AsyncRead + AsyncWrite,
|
|
|
|
NoiseConfig<IX, C>: UpgradeInfo,
|
|
|
|
C: Protocol<C> + AsRef<[u8]> + Zeroize
|
2019-01-30 11:36:00 +01:00
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
type Output = (PublicKey<C>, NoiseOutput<Negotiated<T>>);
|
2019-01-30 11:36:00 +01:00
|
|
|
type Error = NoiseError;
|
2019-03-19 17:27:30 +01:00
|
|
|
type Future = rt1::NoiseInboundFuture<Negotiated<T>, C>;
|
2019-01-30 11:36:00 +01:00
|
|
|
|
2019-03-19 17:27:30 +01:00
|
|
|
fn upgrade_inbound(self, socket: Negotiated<T>, _: Self::Info) -> Self::Future {
|
2019-03-11 13:42:53 +01:00
|
|
|
let session = self.params.into_builder()
|
|
|
|
.local_private_key(self.keys.secret().as_ref())
|
2019-01-30 11:36:00 +01:00
|
|
|
.build_responder()
|
|
|
|
.map_err(NoiseError::from);
|
|
|
|
rt1::NoiseInboundFuture::new(socket, session)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<T, C> OutboundUpgrade<T> for NoiseConfig<IX, C>
|
2019-01-30 11:36:00 +01:00
|
|
|
where
|
2019-03-11 13:42:53 +01:00
|
|
|
T: AsyncRead + AsyncWrite,
|
|
|
|
NoiseConfig<IX, C>: UpgradeInfo,
|
|
|
|
C: Protocol<C> + AsRef<[u8]> + Zeroize
|
2019-01-30 11:36:00 +01:00
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
type Output = (PublicKey<C>, NoiseOutput<Negotiated<T>>);
|
2019-01-30 11:36:00 +01:00
|
|
|
type Error = NoiseError;
|
2019-03-19 17:27:30 +01:00
|
|
|
type Future = rt1::NoiseOutboundFuture<Negotiated<T>, C>;
|
2019-01-30 11:36:00 +01:00
|
|
|
|
2019-03-19 17:27:30 +01:00
|
|
|
fn upgrade_outbound(self, socket: Negotiated<T>, _: Self::Info) -> Self::Future {
|
2019-03-11 13:42:53 +01:00
|
|
|
let session = self.params.into_builder()
|
|
|
|
.local_private_key(self.keys.secret().as_ref())
|
2019-01-30 11:36:00 +01:00
|
|
|
.build_initiator()
|
|
|
|
.map_err(NoiseError::from);
|
|
|
|
rt1::NoiseOutboundFuture::new(socket, session)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handshake pattern XX /////////////////////////////////////////////////////
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<T, C> InboundUpgrade<T> for NoiseConfig<XX, C>
|
2019-01-30 11:36:00 +01:00
|
|
|
where
|
2019-03-11 13:42:53 +01:00
|
|
|
T: AsyncRead + AsyncWrite,
|
|
|
|
NoiseConfig<XX, C>: UpgradeInfo,
|
|
|
|
C: Protocol<C> + AsRef<[u8]> + Zeroize
|
2019-01-30 11:36:00 +01:00
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
type Output = (PublicKey<C>, NoiseOutput<Negotiated<T>>);
|
2019-01-30 11:36:00 +01:00
|
|
|
type Error = NoiseError;
|
2019-03-19 17:27:30 +01:00
|
|
|
type Future = rt15::NoiseInboundFuture<Negotiated<T>, C>;
|
2019-01-30 11:36:00 +01:00
|
|
|
|
2019-03-19 17:27:30 +01:00
|
|
|
fn upgrade_inbound(self, socket: Negotiated<T>, _: Self::Info) -> Self::Future {
|
2019-03-11 13:42:53 +01:00
|
|
|
let session = self.params.into_builder()
|
|
|
|
.local_private_key(self.keys.secret().as_ref())
|
2019-01-30 11:36:00 +01:00
|
|
|
.build_responder()
|
|
|
|
.map_err(NoiseError::from);
|
|
|
|
rt15::NoiseInboundFuture::new(socket, session)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<T, C> OutboundUpgrade<T> for NoiseConfig<XX, C>
|
2019-01-30 11:36:00 +01:00
|
|
|
where
|
2019-03-11 13:42:53 +01:00
|
|
|
T: AsyncRead + AsyncWrite,
|
|
|
|
NoiseConfig<XX, C>: UpgradeInfo,
|
|
|
|
C: Protocol<C> + AsRef<[u8]> + Zeroize
|
2019-01-30 11:36:00 +01:00
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
type Output = (PublicKey<C>, NoiseOutput<Negotiated<T>>);
|
2019-01-30 11:36:00 +01:00
|
|
|
type Error = NoiseError;
|
2019-03-19 17:27:30 +01:00
|
|
|
type Future = rt15::NoiseOutboundFuture<Negotiated<T>, C>;
|
2019-01-30 11:36:00 +01:00
|
|
|
|
2019-03-19 17:27:30 +01:00
|
|
|
fn upgrade_outbound(self, socket: Negotiated<T>, _: Self::Info) -> Self::Future {
|
2019-03-11 13:42:53 +01:00
|
|
|
let session = self.params.into_builder()
|
|
|
|
.local_private_key(self.keys.secret().as_ref())
|
2019-01-30 11:36:00 +01:00
|
|
|
.build_initiator()
|
|
|
|
.map_err(NoiseError::from);
|
|
|
|
rt15::NoiseOutboundFuture::new(socket, session)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handshake pattern IK /////////////////////////////////////////////////////
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<T, C> InboundUpgrade<T> for NoiseConfig<IK, C>
|
2019-01-30 11:36:00 +01:00
|
|
|
where
|
2019-03-11 13:42:53 +01:00
|
|
|
T: AsyncRead + AsyncWrite,
|
|
|
|
NoiseConfig<IK, C>: UpgradeInfo,
|
|
|
|
C: Protocol<C> + AsRef<[u8]> + Zeroize
|
2019-01-30 11:36:00 +01:00
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
type Output = (PublicKey<C>, NoiseOutput<Negotiated<T>>);
|
2019-01-30 11:36:00 +01:00
|
|
|
type Error = NoiseError;
|
2019-03-19 17:27:30 +01:00
|
|
|
type Future = rt1::NoiseInboundFuture<Negotiated<T>, C>;
|
2019-01-30 11:36:00 +01:00
|
|
|
|
2019-03-19 17:27:30 +01:00
|
|
|
fn upgrade_inbound(self, socket: Negotiated<T>, _: Self::Info) -> Self::Future {
|
2019-03-11 13:42:53 +01:00
|
|
|
let session = self.params.into_builder()
|
|
|
|
.local_private_key(self.keys.secret().as_ref())
|
2019-01-30 11:36:00 +01:00
|
|
|
.build_responder()
|
|
|
|
.map_err(NoiseError::from);
|
|
|
|
rt1::NoiseInboundFuture::new(socket, session)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-11 13:42:53 +01:00
|
|
|
impl<T, C> OutboundUpgrade<T> for NoiseConfig<IK, C, PublicKey<C>>
|
2019-01-30 11:36:00 +01:00
|
|
|
where
|
2019-03-11 13:42:53 +01:00
|
|
|
T: AsyncRead + AsyncWrite,
|
|
|
|
NoiseConfig<IK, C, PublicKey<C>>: UpgradeInfo,
|
|
|
|
C: Protocol<C> + AsRef<[u8]> + Zeroize
|
2019-01-30 11:36:00 +01:00
|
|
|
{
|
2019-03-19 17:27:30 +01:00
|
|
|
type Output = (PublicKey<C>, NoiseOutput<Negotiated<T>>);
|
2019-01-30 11:36:00 +01:00
|
|
|
type Error = NoiseError;
|
2019-03-19 17:27:30 +01:00
|
|
|
type Future = rt1::NoiseOutboundFuture<Negotiated<T>, C>;
|
2019-01-30 11:36:00 +01:00
|
|
|
|
2019-03-19 17:27:30 +01:00
|
|
|
fn upgrade_outbound(self, socket: Negotiated<T>, _: Self::Info) -> Self::Future {
|
2019-03-11 13:42:53 +01:00
|
|
|
let session = self.params.into_builder()
|
|
|
|
.local_private_key(self.keys.secret().as_ref())
|
2019-01-30 11:36:00 +01:00
|
|
|
.remote_public_key(self.remote.as_ref())
|
|
|
|
.build_initiator()
|
|
|
|
.map_err(NoiseError::from);
|
|
|
|
rt1::NoiseOutboundFuture::new(socket, session)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|