Skip to content

Commit

Permalink
[refactor]: Improve p2p errors.
Browse files Browse the repository at this point in the history
Signed-off-by: Aleksandr Petrosyan <[email protected]>
  • Loading branch information
appetrosyan committed Jun 8, 2022
1 parent eeff852 commit 06f0083
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 44 deletions.
39 changes: 13 additions & 26 deletions p2p/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

use std::{io, net::AddrParseError};

use iroha_crypto::ursa::{encryption::symm::prelude::ChaCha20Poly1305, kex::x25519::X25519Sha256};
use iroha_crypto::ursa::{
encryption::symm::prelude::ChaCha20Poly1305, kex::x25519::X25519Sha256,
};
pub use network::{ConnectPeer, DisconnectPeer, NetworkBase, Post};
use parity_scale_codec::{Decode, Encode};
use thiserror::Error;
Expand All @@ -18,23 +20,26 @@ pub mod peer;
pub type Network<T> = NetworkBase<T, X25519Sha256, ChaCha20Poly1305>;

/// Errors used in [`crate`].
#[derive(Clone, Debug, iroha_macro::FromVariant, Error, iroha_actor::Message)]
#[derive(Clone, Debug, Error, iroha_actor::Message)]
pub enum Error {
/// Failed to read or write
#[error("Failed IO operation.")]
Io(#[source] std::sync::Arc<io::Error>),
Io(#[from] std::sync::Arc<io::Error>),
/// Failed to read or write
#[error("{0}: Failed handshake")]
Handshake(u32),
#[error("Failed handshake")]
Handshake(#[from] HandshakeError),
/// Failed to read or write
#[error("Message improperly formatted")]
Format,
/// Failed to create keys
#[error("Failed to create session key")]
/// Failed to create keys.
#[error("Failed to create session key, or generate new key-pair.")]
Keys,
/// Failed to decode
#[error("Failed to decode object using parity scale codec")]
Decode(#[from] parity_scale_codec::Error),
/// Failed to parse address
#[error("Failed to parse socket address.")]
Addr(#[source] AddrParseError),
Addr(#[from] AddrParseError),
}

/// Error which occurs in the handshake process specifically.
Expand Down Expand Up @@ -66,24 +71,6 @@ impl From<io::Error> for Error {
}
}

impl From<parity_scale_codec::Error> for Error {
fn from(_: parity_scale_codec::Error) -> Self {
Self::Keys
}
}

impl From<CryptoError> for Error {
fn from(_: CryptoError) -> Self {
Self::Keys
}
}

impl From<aead::Error> for Error {
fn from(_: aead::Error) -> Self {
Self::Keys
}
}

/// Result shorthand.
pub type Result<T, E = Error> = std::result::Result<T, E>;

Expand Down
44 changes: 26 additions & 18 deletions p2p/src/peer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(clippy::map_err_ignore)]
use std::{
fmt::{Debug, Formatter},
marker::PhantomData,
Expand Down Expand Up @@ -29,7 +30,7 @@ use tokio::{

use crate::{
network::{ConnectionId, PeerMessage, Post, Start, StopSelf},
Error, Message, MessageResult,
Error, HandshakeError, Message, MessageResult,
};

/// Max message length in bytes.
Expand Down Expand Up @@ -119,7 +120,7 @@ where
/// If key exchange fails to produce keypair (extremely rare)
fn default_or_err() -> Result<Self, Error> {
let key_exchange = K::new();
let (public_key, secret_key) = key_exchange.keypair(None)?;
let (public_key, secret_key) = key_exchange.keypair(None).map_err(|_| Error::Keys)?;
Ok(Self {
secret_key,
public_key,
Expand All @@ -133,28 +134,35 @@ where
fn decrypt(&self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
match &self.cipher {
None => Ok(data),
Some(cipher) => Ok(cipher.decrypt_easy(DEFAULT_AAD.as_ref(), data.as_slice())?),
Some(cipher) => cipher
.decrypt_easy(DEFAULT_AAD.as_ref(), data.as_slice())
.map_err(|_| Error::Keys),
}
}

/// Encrypt bytes. If no cipher is set, the bytes are returned as is.
fn encrypt(&self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
match &self.cipher {
None => Ok(data),
Some(cipher) => Ok(cipher.encrypt_easy(DEFAULT_AAD.as_ref(), data.as_slice())?),
Some(cipher) => cipher
.encrypt_easy(DEFAULT_AAD.as_ref(), data.as_slice())
.map_err(|_| Error::Keys),
}
}

/// Creates a shared key from two public keys - local and external,
/// then instantiates an encryptor from that key.
fn derive_shared_key(&mut self, public_key: &PublicKey) -> Result<&Self, Error> {
let dh = K::new();
let shared = dh.compute_shared_secret(&self.secret_key, public_key)?;
let shared = dh
.compute_shared_secret(&self.secret_key, public_key)
.map_err(|_| Error::Keys)?;
debug!(key = ?shared.0, "Derived shared key");
let encryptor = {
let key: &[u8] = shared.0.as_slice();
SymmetricEncryptor::<E>::new_with_key(key)
}?;
}
.map_err(|_| Error::Keys)?;
self.cipher = Some(encryptor);
Ok(self)
}
Expand Down Expand Up @@ -212,14 +220,14 @@ where
/// If peer is either `Connecting`, `Disconnected`, or `Error`-ed
pub fn connection_id(&self) -> Result<ConnectionId, Error> {
match self {
Peer::Connecting(_, _) => Err(Error::Handshake(std::line!())),
Peer::Connecting(_, _) => Err(HandshakeError::WrongState.into()),
Peer::ConnectedTo(_, _, connection)
| Peer::ConnectedFrom(_, _, connection)
| Peer::SendKey(_, _, connection, _)
| Peer::GetKey(_, _, connection, _)
| Peer::Ready(_, _, connection, _) => Ok(connection.id),
Peer::Disconnected(_) => Err(Error::Handshake(std::line!())),
Peer::Error(_, _) => Err(Error::Handshake(std::line!())),
Peer::Disconnected(_) => Err(HandshakeError::Disconnected.into()),
Peer::Error(_, _) => Err(HandshakeError::BrokenPeer.into()),
}
}

Expand Down Expand Up @@ -312,7 +320,7 @@ where
Ok(Self::SendKey(id, broker, connection, crypto))
} else {
error!(peer = ?self, "Incorrect state.");
Err(Error::Handshake(std::line!()))
Err(HandshakeError::ReadHello.into())
}
}

Expand All @@ -339,7 +347,7 @@ where
Ok(Self::SendKey(id, broker, connection, crypto))
} else {
error!(peer = ?self, "Incorrect state.");
Err(Error::Handshake(std::line!()))
Err(HandshakeError::SendHello.into())
}
}

Expand Down Expand Up @@ -369,7 +377,7 @@ where
Ok(Self::GetKey(id, broker, connection, crypto))
} else {
error!(peer = ?self, "Incorrect state.");
Err(Error::Handshake(std::line!()))
Err(HandshakeError::WrongState.into())
}
}

Expand All @@ -381,7 +389,7 @@ where
let read_half = connection.read.as_mut().unwrap();
let size = read_half.read_u8().await? as usize;
if size >= MAX_HANDSHAKE_LENGTH {
return Err(Error::Handshake(std::line!()));
return Err(HandshakeError::TooLong(size, MAX_HANDSHAKE_LENGTH).into());
}
// Reading public key
read_half.as_ref().readable().await?;
Expand All @@ -396,7 +404,7 @@ where
Ok(Self::Ready(id, broker, connection, crypto))
} else {
error!(peer = ?self, "Incorrect state.");
Err(Error::Handshake(std::line!()))
Err(HandshakeError::WrongState.into())
}
}

Expand All @@ -416,7 +424,7 @@ where
let connection = Connection::new(rand::random(), stream);
Ok(Self::ConnectedTo(id, broker, connection))
} else {
Err(Error::Handshake(std::line!()))
Err(HandshakeError::WrongState.into())
}
}
}
Expand Down Expand Up @@ -539,7 +547,7 @@ where
Ok(data) => data,
Err(error) => {
warn!(%error, "Error decrypting message!");
let mut new_self = Self::Error(id.clone(), Error::from(error));
let mut new_self = Self::Error(id.clone(), Error::Keys);
std::mem::swap(&mut new_self, self);
return;
}
Expand Down Expand Up @@ -584,7 +592,7 @@ where
Ok(data) => data,
Err(error) => {
warn!(%error, "Error encrypting message!");
let mut new_self = Self::Error(id.clone(), Error::from(error));
let mut new_self = Self::Error(id.clone(), Error::Keys);
std::mem::swap(&mut new_self, self);
return;
}
Expand Down Expand Up @@ -794,7 +802,7 @@ impl Garbage {
pub async fn read(stream: &mut OwnedReadHalf) -> Result<Self, Error> {
let size = stream.read_u8().await? as usize;
if size >= MAX_HANDSHAKE_LENGTH {
Err(Error::Handshake(std::line!()))
Err(HandshakeError::TooLong(size, MAX_HANDSHAKE_LENGTH).into())
} else {
// Reading garbage
debug!(%size, "Reading garbage");
Expand Down

0 comments on commit 06f0083

Please sign in to comment.