2016-02-05 13:40:41 +01:00
|
|
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
|
|
|
// This file is part of Parity.
|
|
|
|
|
|
|
|
// Parity is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
|
|
|
// Parity is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2016-01-24 18:53:54 +01:00
|
|
|
use std::sync::Arc;
|
2015-11-30 16:38:55 +01:00
|
|
|
use mio::*;
|
|
|
|
use mio::tcp::*;
|
|
|
|
use hash::*;
|
2016-01-09 10:27:41 +01:00
|
|
|
use sha3::Hashable;
|
2015-12-02 12:07:46 +01:00
|
|
|
use bytes::Bytes;
|
2015-11-30 16:38:55 +01:00
|
|
|
use crypto::*;
|
|
|
|
use crypto;
|
2015-12-17 11:42:30 +01:00
|
|
|
use network::connection::{Connection};
|
2016-01-13 11:31:37 +01:00
|
|
|
use network::host::{HostInfo};
|
2016-02-14 01:03:48 +01:00
|
|
|
use network::node_table::NodeId;
|
2016-01-10 12:53:55 +01:00
|
|
|
use error::*;
|
2016-01-13 11:31:37 +01:00
|
|
|
use network::error::NetworkError;
|
2016-01-24 18:53:54 +01:00
|
|
|
use network::stats::NetworkStats;
|
2016-01-21 16:48:37 +01:00
|
|
|
use io::{IoContext, StreamToken};
|
2015-11-30 16:38:55 +01:00
|
|
|
|
2015-12-17 11:42:30 +01:00
|
|
|
#[derive(PartialEq, Eq, Debug)]
|
2015-11-30 16:38:55 +01:00
|
|
|
enum HandshakeState {
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Just created
|
2015-11-30 16:38:55 +01:00
|
|
|
New,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Waiting for auth packet
|
2015-11-30 16:38:55 +01:00
|
|
|
ReadingAuth,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Waiting for ack packet
|
2015-11-30 16:38:55 +01:00
|
|
|
ReadingAck,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Ready to start a session
|
2015-11-30 16:38:55 +01:00
|
|
|
StartSession,
|
|
|
|
}
|
|
|
|
|
2016-01-10 22:42:27 +01:00
|
|
|
/// RLPx protocol handhake. See https://github.com/ethereum/devp2p/blob/master/rlpx.md#encrypted-handshake
|
2015-11-30 16:38:55 +01:00
|
|
|
pub struct Handshake {
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Remote node public key
|
2015-11-30 16:38:55 +01:00
|
|
|
pub id: NodeId,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Underlying connection
|
2015-11-30 16:38:55 +01:00
|
|
|
pub connection: Connection,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Handshake state
|
2015-11-30 16:38:55 +01:00
|
|
|
state: HandshakeState,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Outgoing or incoming connection
|
2015-12-02 12:07:46 +01:00
|
|
|
pub originated: bool,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// ECDH ephemeral
|
2015-12-02 12:07:46 +01:00
|
|
|
pub ecdhe: KeyPair,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Connection nonce
|
2015-12-02 12:07:46 +01:00
|
|
|
pub nonce: H256,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Handshake public key
|
2015-12-02 12:07:46 +01:00
|
|
|
pub remote_public: Public,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Remote connection nonce.
|
2015-12-02 12:07:46 +01:00
|
|
|
pub remote_nonce: H256,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// A copy of received encryped auth packet
|
2015-12-02 12:07:46 +01:00
|
|
|
pub auth_cipher: Bytes,
|
2016-01-10 22:42:27 +01:00
|
|
|
/// A copy of received encryped ack packet
|
2016-02-20 01:10:27 +01:00
|
|
|
pub ack_cipher: Bytes,
|
|
|
|
/// This Handshake is marked for deleteion flag
|
|
|
|
pub expired: bool,
|
2015-11-30 16:38:55 +01:00
|
|
|
}
|
|
|
|
|
2016-01-08 13:49:00 +01:00
|
|
|
const AUTH_PACKET_SIZE: usize = 307;
|
|
|
|
const ACK_PACKET_SIZE: usize = 210;
|
2016-02-17 14:07:11 +01:00
|
|
|
const HANDSHAKE_TIMEOUT: u64 = 5000;
|
2015-12-02 12:07:46 +01:00
|
|
|
|
2015-11-30 16:38:55 +01:00
|
|
|
impl Handshake {
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Create a new handshake object
|
2016-01-24 18:53:54 +01:00
|
|
|
pub fn new(token: StreamToken, id: Option<&NodeId>, socket: TcpStream, nonce: &H256, stats: Arc<NetworkStats>) -> Result<Handshake, UtilError> {
|
2015-11-30 16:38:55 +01:00
|
|
|
Ok(Handshake {
|
2016-01-24 18:53:54 +01:00
|
|
|
id: if let Some(id) = id { id.clone()} else { NodeId::new() },
|
|
|
|
connection: Connection::new(token, socket, stats),
|
2015-12-02 12:07:46 +01:00
|
|
|
originated: false,
|
2015-11-30 16:38:55 +01:00
|
|
|
state: HandshakeState::New,
|
|
|
|
ecdhe: try!(KeyPair::create()),
|
|
|
|
nonce: nonce.clone(),
|
|
|
|
remote_public: Public::new(),
|
2015-12-02 12:07:46 +01:00
|
|
|
remote_nonce: H256::new(),
|
|
|
|
auth_cipher: Bytes::new(),
|
|
|
|
ack_cipher: Bytes::new(),
|
2016-02-20 01:10:27 +01:00
|
|
|
expired: false,
|
2015-11-30 16:38:55 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-02-12 09:52:32 +01:00
|
|
|
/// Get id of the remote node if known
|
|
|
|
pub fn id(&self) -> &NodeId {
|
|
|
|
&self.id
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get stream token id
|
|
|
|
pub fn token(&self) -> StreamToken {
|
|
|
|
self.connection.token()
|
|
|
|
}
|
|
|
|
|
2016-02-20 01:10:27 +01:00
|
|
|
/// Mark this handshake as inactive to be deleted lated.
|
|
|
|
pub fn set_expired(&mut self) {
|
|
|
|
self.expired = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Check if this handshake is expired.
|
|
|
|
pub fn expired(&self) -> bool {
|
|
|
|
self.expired
|
|
|
|
}
|
|
|
|
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Start a handhsake
|
2016-01-21 16:48:37 +01:00
|
|
|
pub fn start<Message>(&mut self, io: &IoContext<Message>, host: &HostInfo, originated: bool) -> Result<(), UtilError> where Message: Send + Clone{
|
2015-12-02 12:07:46 +01:00
|
|
|
self.originated = originated;
|
2016-01-21 16:48:37 +01:00
|
|
|
io.register_timer(self.connection.token, HANDSHAKE_TIMEOUT).ok();
|
2015-11-30 16:38:55 +01:00
|
|
|
if originated {
|
2015-12-02 12:07:46 +01:00
|
|
|
try!(self.write_auth(host));
|
2015-12-03 15:11:40 +01:00
|
|
|
}
|
2015-11-30 16:38:55 +01:00
|
|
|
else {
|
2015-12-02 12:07:46 +01:00
|
|
|
self.state = HandshakeState::ReadingAuth;
|
|
|
|
self.connection.expect(AUTH_PACKET_SIZE);
|
2015-11-30 16:38:55 +01:00
|
|
|
};
|
2015-12-02 12:07:46 +01:00
|
|
|
Ok(())
|
2015-11-30 16:38:55 +01:00
|
|
|
}
|
|
|
|
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Check if handshake is complete
|
2015-11-30 16:38:55 +01:00
|
|
|
pub fn done(&self) -> bool {
|
|
|
|
self.state == HandshakeState::StartSession
|
|
|
|
}
|
|
|
|
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Readable IO handler. Drives the state change.
|
2016-01-21 16:48:37 +01:00
|
|
|
pub fn readable<Message>(&mut self, io: &IoContext<Message>, host: &HostInfo) -> Result<(), UtilError> where Message: Send + Clone {
|
2016-02-20 01:10:27 +01:00
|
|
|
if !self.expired() {
|
|
|
|
io.clear_timer(self.connection.token).unwrap();
|
|
|
|
match self.state {
|
|
|
|
HandshakeState::ReadingAuth => {
|
|
|
|
if let Some(data) = try!(self.connection.readable()) {
|
|
|
|
try!(self.read_auth(host, &data));
|
|
|
|
try!(self.write_ack());
|
|
|
|
};
|
|
|
|
},
|
|
|
|
HandshakeState::ReadingAck => {
|
|
|
|
if let Some(data) = try!(self.connection.readable()) {
|
|
|
|
try!(self.read_ack(host, &data));
|
|
|
|
self.state = HandshakeState::StartSession;
|
|
|
|
};
|
|
|
|
},
|
|
|
|
HandshakeState::StartSession => {},
|
|
|
|
_ => { panic!("Unexpected state"); }
|
|
|
|
}
|
|
|
|
if self.state != HandshakeState::StartSession {
|
|
|
|
try!(io.update_registration(self.connection.token));
|
|
|
|
}
|
2015-12-03 15:11:40 +01:00
|
|
|
}
|
2015-11-30 16:38:55 +01:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Writabe IO handler.
|
2016-01-21 16:48:37 +01:00
|
|
|
pub fn writable<Message>(&mut self, io: &IoContext<Message>, _host: &HostInfo) -> Result<(), UtilError> where Message: Send + Clone {
|
2016-02-20 01:10:27 +01:00
|
|
|
if !self.expired() {
|
|
|
|
io.clear_timer(self.connection.token).unwrap();
|
|
|
|
try!(self.connection.writable());
|
|
|
|
if self.state != HandshakeState::StartSession {
|
|
|
|
io.update_registration(self.connection.token).unwrap();
|
|
|
|
}
|
2015-12-03 15:11:40 +01:00
|
|
|
}
|
2015-11-30 16:38:55 +01:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2016-01-21 16:48:37 +01:00
|
|
|
/// Register the socket with the event loop
|
|
|
|
pub fn register_socket<Host:Handler<Timeout=Token>>(&self, reg: Token, event_loop: &mut EventLoop<Host>) -> Result<(), UtilError> {
|
2016-02-20 01:10:27 +01:00
|
|
|
if !self.expired() {
|
|
|
|
try!(self.connection.register_socket(reg, event_loop));
|
|
|
|
}
|
2016-01-21 16:48:37 +01:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2016-02-21 16:52:25 +01:00
|
|
|
/// Update socket registration with the event loop.
|
2016-01-21 16:48:37 +01:00
|
|
|
pub fn update_socket<Host:Handler<Timeout=Token>>(&self, reg: Token, event_loop: &mut EventLoop<Host>) -> Result<(), UtilError> {
|
2016-02-20 01:10:27 +01:00
|
|
|
if !self.expired() {
|
|
|
|
try!(self.connection.update_socket(reg, event_loop));
|
|
|
|
}
|
2015-11-30 16:38:55 +01:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2016-01-22 18:13:59 +01:00
|
|
|
/// Delete registration
|
|
|
|
pub fn deregister_socket<Host:Handler>(&self, event_loop: &mut EventLoop<Host>) -> Result<(), UtilError> {
|
|
|
|
try!(self.connection.deregister_socket(event_loop));
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Parse, validate and confirm auth message
|
2016-01-10 12:53:55 +01:00
|
|
|
fn read_auth(&mut self, host: &HostInfo, data: &[u8]) -> Result<(), UtilError> {
|
2015-12-02 12:07:46 +01:00
|
|
|
trace!(target:"net", "Received handshake auth to {:?}", self.connection.socket.peer_addr());
|
2016-01-24 18:53:54 +01:00
|
|
|
if data.len() != AUTH_PACKET_SIZE {
|
|
|
|
debug!(target:"net", "Wrong auth packet size");
|
|
|
|
return Err(From::from(NetworkError::BadProtocol));
|
|
|
|
}
|
2015-12-02 12:07:46 +01:00
|
|
|
self.auth_cipher = data.to_vec();
|
|
|
|
let auth = try!(ecies::decrypt(host.secret(), data));
|
|
|
|
let (sig, rest) = auth.split_at(65);
|
|
|
|
let (hepubk, rest) = rest.split_at(32);
|
|
|
|
let (pubk, rest) = rest.split_at(64);
|
|
|
|
let (nonce, _) = rest.split_at(32);
|
2016-01-24 18:53:54 +01:00
|
|
|
self.id.clone_from_slice(pubk);
|
2015-12-02 12:07:46 +01:00
|
|
|
self.remote_nonce.clone_from_slice(nonce);
|
2016-01-24 18:53:54 +01:00
|
|
|
let shared = try!(ecdh::agree(host.secret(), &self.id));
|
2016-01-08 13:32:52 +01:00
|
|
|
let signature = Signature::from_slice(sig);
|
2015-12-02 12:07:46 +01:00
|
|
|
let spub = try!(ec::recover(&signature, &(&shared ^ &self.remote_nonce)));
|
2016-01-24 18:53:54 +01:00
|
|
|
self.remote_public = spub.clone();
|
2015-12-02 12:07:46 +01:00
|
|
|
if &spub.sha3()[..] != hepubk {
|
|
|
|
trace!(target:"net", "Handshake hash mismath with {:?}", self.connection.socket.peer_addr());
|
2016-01-10 12:53:55 +01:00
|
|
|
return Err(From::from(NetworkError::Auth));
|
2015-12-02 12:07:46 +01:00
|
|
|
};
|
2016-01-24 18:53:54 +01:00
|
|
|
Ok(())
|
2015-11-30 16:38:55 +01:00
|
|
|
}
|
|
|
|
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Parse and validate ack message
|
2016-01-10 12:53:55 +01:00
|
|
|
fn read_ack(&mut self, host: &HostInfo, data: &[u8]) -> Result<(), UtilError> {
|
2015-12-02 12:07:46 +01:00
|
|
|
trace!(target:"net", "Received handshake auth to {:?}", self.connection.socket.peer_addr());
|
2016-01-24 18:53:54 +01:00
|
|
|
if data.len() != ACK_PACKET_SIZE {
|
|
|
|
debug!(target:"net", "Wrong ack packet size");
|
|
|
|
return Err(From::from(NetworkError::BadProtocol));
|
|
|
|
}
|
2015-12-02 12:07:46 +01:00
|
|
|
self.ack_cipher = data.to_vec();
|
|
|
|
let ack = try!(ecies::decrypt(host.secret(), data));
|
2015-12-03 15:11:40 +01:00
|
|
|
self.remote_public.clone_from_slice(&ack[0..64]);
|
|
|
|
self.remote_nonce.clone_from_slice(&ack[64..(64+32)]);
|
2015-11-30 16:38:55 +01:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Sends auth message
|
2016-01-10 12:53:55 +01:00
|
|
|
fn write_auth(&mut self, host: &HostInfo) -> Result<(), UtilError> {
|
2015-12-02 12:07:46 +01:00
|
|
|
trace!(target:"net", "Sending handshake auth to {:?}", self.connection.socket.peer_addr());
|
2015-11-30 16:38:55 +01:00
|
|
|
let mut data = [0u8; /*Signature::SIZE*/ 65 + /*H256::SIZE*/ 32 + /*Public::SIZE*/ 64 + /*H256::SIZE*/ 32 + 1]; //TODO: use associated constants
|
|
|
|
let len = data.len();
|
|
|
|
{
|
|
|
|
data[len - 1] = 0x0;
|
|
|
|
let (sig, rest) = data.split_at_mut(65);
|
|
|
|
let (hepubk, rest) = rest.split_at_mut(32);
|
2015-12-02 12:07:46 +01:00
|
|
|
let (pubk, rest) = rest.split_at_mut(64);
|
|
|
|
let (nonce, _) = rest.split_at_mut(32);
|
2015-12-03 15:11:40 +01:00
|
|
|
|
2015-11-30 16:38:55 +01:00
|
|
|
// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
|
|
|
|
let shared = try!(crypto::ecdh::agree(host.secret(), &self.id));
|
2015-12-02 12:07:46 +01:00
|
|
|
try!(crypto::ec::sign(self.ecdhe.secret(), &(&shared ^ &self.nonce))).copy_to(sig);
|
2015-11-30 16:38:55 +01:00
|
|
|
self.ecdhe.public().sha3_into(hepubk);
|
2015-12-02 12:07:46 +01:00
|
|
|
host.id().copy_to(pubk);
|
2015-11-30 16:38:55 +01:00
|
|
|
self.nonce.copy_to(nonce);
|
|
|
|
}
|
|
|
|
let message = try!(crypto::ecies::encrypt(&self.id, &data));
|
2015-12-02 20:11:13 +01:00
|
|
|
self.auth_cipher = message.clone();
|
|
|
|
self.connection.send(message);
|
2015-12-17 11:42:30 +01:00
|
|
|
self.connection.expect(ACK_PACKET_SIZE);
|
|
|
|
self.state = HandshakeState::ReadingAck;
|
2015-11-30 16:38:55 +01:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2016-01-10 22:42:27 +01:00
|
|
|
/// Sends ack message
|
2016-01-10 12:53:55 +01:00
|
|
|
fn write_ack(&mut self) -> Result<(), UtilError> {
|
2015-12-02 12:07:46 +01:00
|
|
|
trace!(target:"net", "Sending handshake ack to {:?}", self.connection.socket.peer_addr());
|
|
|
|
let mut data = [0u8; 1 + /*Public::SIZE*/ 64 + /*H256::SIZE*/ 32]; //TODO: use associated constants
|
|
|
|
let len = data.len();
|
|
|
|
{
|
|
|
|
data[len - 1] = 0x0;
|
|
|
|
let (epubk, rest) = data.split_at_mut(64);
|
|
|
|
let (nonce, _) = rest.split_at_mut(32);
|
|
|
|
self.ecdhe.public().copy_to(epubk);
|
|
|
|
self.nonce.copy_to(nonce);
|
|
|
|
}
|
|
|
|
let message = try!(crypto::ecies::encrypt(&self.id, &data));
|
2015-12-02 20:11:13 +01:00
|
|
|
self.ack_cipher = message.clone();
|
|
|
|
self.connection.send(message);
|
2015-12-17 11:42:30 +01:00
|
|
|
self.state = HandshakeState::StartSession;
|
2015-11-30 16:38:55 +01:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|