Skip to content

Commit

Permalink
Revert "Revert "remove rustc-serialize (libp2p#359) (libp2p#386)" (li…
Browse files Browse the repository at this point in the history
…bp2p#466)"

This reverts commit 0a3d4cd.
  • Loading branch information
tomaka committed Sep 13, 2018
1 parent 5980a45 commit 4cc6452
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 57 deletions.
7 changes: 6 additions & 1 deletion protocols/secio/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ log = "0.4.1"
protobuf = "2.0.2"
rand = "0.3.17"
ring = { version = "0.12", features = ["rsa_signing"] }
rust-crypto = "^0.2"
aes-ctr = "0.1.0"
aesni = { version = "0.4.1", features = ["nocheck"], optional = true }
twofish = "0.1.0"
ctr = "0.1"
lazy_static = { version = "0.2.11", optional = true }
rw-stream-sink = { path = "../../misc/rw-stream-sink" }
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", optional = true }
tokio-io = "0.1.0"
Expand All @@ -22,6 +26,7 @@ untrusted = "0.5"
[features]
default = ["secp256k1"]
secp256k1 = ["eth-secp256k1"]
aes-all = ["aesni","lazy_static"]

[dev-dependencies]
libp2p-tcp-transport = { path = "../../transports/tcp" }
Expand Down
8 changes: 7 additions & 1 deletion protocols/secio/src/algo_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ const ECDH_P384: &str = "P-384";

const AES_128: &str = "AES-128";
const AES_256: &str = "AES-256";
const TWOFISH_CTR: &str = "TwofishCTR";
const NULL: &str = "NULL";

const SHA_256: &str = "SHA256";
const SHA_512: &str = "SHA512";

pub(crate) const DEFAULT_AGREEMENTS_PROPOSITION: &str = "P-256,P-384";
pub(crate) const DEFAULT_CIPHERS_PROPOSITION: &str = "AES-128,AES-256";
pub(crate) const DEFAULT_CIPHERS_PROPOSITION: &str = "AES-128,AES-256,TwofishCTR";
pub(crate) const DEFAULT_DIGESTS_PROPOSITION: &str = "SHA256,SHA512";


Expand Down Expand Up @@ -110,6 +111,10 @@ where
s.push_str(AES_256);
s.push(',')
}
Cipher::TwofishCtr => {
s.push_str(TWOFISH_CTR);
s.push(',')
}
Cipher::Null => {
s.push_str(NULL);
s.push(',')
Expand All @@ -134,6 +139,7 @@ pub fn select_cipher(r: Ordering, ours: &str, theirs: &str) -> Result<Cipher, Se
match x {
AES_128 => return Ok(Cipher::Aes128),
AES_256 => return Ok(Cipher::Aes256),
TWOFISH_CTR => return Ok(Cipher::TwofishCtr),
NULL => return Ok(Cipher::Null),
_ => continue
}
Expand Down
26 changes: 15 additions & 11 deletions protocols/secio/src/codec/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
//! Individual messages decoding.

use bytes::BytesMut;
use codec::StreamCipher;
use super::StreamCipher;

use error::SecioError;
use futures::sink::Sink;
use futures::stream::Stream;
Expand Down Expand Up @@ -87,21 +88,24 @@ where
debug!("frame too short when decoding secio frame");
return Err(SecioError::FrameTooShort);
}
let content_length = frame.len() - hmac_num_bytes;
{
let (crypted_data, expected_hash) = frame.split_at(content_length);
debug_assert_eq!(expected_hash.len(), hmac_num_bytes);

let (crypted_data, expected_hash) = frame.split_at(frame.len() - hmac_num_bytes);
debug_assert_eq!(expected_hash.len(), hmac_num_bytes);

if hmac::verify(&self.hmac_key, crypted_data, expected_hash).is_err() {
debug!("hmac mismatch when decoding secio frame");
return Err(SecioError::HmacNotMatching);
if hmac::verify(&self.hmac_key, crypted_data, expected_hash).is_err() {
debug!("hmac mismatch when decoding secio frame");
return Err(SecioError::HmacNotMatching);
}
}

// Note that there is no way to decipher in place with rust-crypto right now.
let mut decrypted_data = crypted_data.to_vec();
let mut data_buf = frame.to_vec();
data_buf.truncate(content_length);
self.cipher_state
.process(&crypted_data, &mut decrypted_data);
.try_apply_keystream(&mut data_buf)
.map_err::<SecioError,_>(|e|e.into())?;

Ok(Async::Ready(Some(decrypted_data)))
Ok(Async::Ready(Some(data_buf)))
}
}

Expand Down
23 changes: 8 additions & 15 deletions protocols/secio/src/codec/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
//! Individual messages encoding.

use bytes::BytesMut;
use codec::StreamCipher;
use super::StreamCipher;
use futures::sink::Sink;
use futures::stream::Stream;
use futures::Poll;
Expand Down Expand Up @@ -62,22 +62,15 @@ where
type SinkItem = BytesMut;
type SinkError = S::SinkError;

fn start_send(&mut self, item: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {
let capacity = item.len() + self.hmac_key.digest_algorithm().output_len;
fn start_send(&mut self, mut data_buf: Self::SinkItem) -> StartSend<Self::SinkItem, Self::SinkError> {

// Apparently this is the fastest way of doing.
// See https://gist.github.com/kirushik/e0d93759b0cd102f814408595c20a9d0
let mut out_buffer = BytesMut::from(vec![0; capacity]);
// TODO if SinkError gets refactor to SecioError,
// then use try_apply_keystream
self.cipher_state.apply_keystream(&mut data_buf[..]);
let signature = hmac::sign(&self.hmac_key, &data_buf[..]);
data_buf.extend_from_slice(signature.as_ref());
self.raw_sink.start_send(data_buf)

{
let (out_data, out_sign) = out_buffer.split_at_mut(item.len());
self.cipher_state.process(&item, out_data);

let signature = hmac::sign(&self.hmac_key, out_data);
out_sign.copy_from_slice(signature.as_ref());
}

self.raw_sink.start_send(out_buffer)
}

#[inline]
Expand Down
14 changes: 10 additions & 4 deletions protocols/secio/src/codec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
use self::decode::DecoderMiddleware;
use self::encode::EncoderMiddleware;

use crypto::symmetriccipher::SynchronousStreamCipher;
use aes_ctr::stream_cipher::StreamCipherCore;
use ring::hmac;
use tokio_io::codec::length_delimited;
use tokio_io::{AsyncRead, AsyncWrite};
Expand All @@ -35,7 +35,7 @@ mod encode;
/// Type returned by `full_codec`.
pub type FullCodec<S> = DecoderMiddleware<EncoderMiddleware<length_delimited::Framed<S>>>;

pub type StreamCipher = Box<dyn SynchronousStreamCipher + Send>;
pub type StreamCipher = Box<dyn StreamCipherCore + Send>;


/// Takes control of `socket`. Returns an object that implements `future::Sink` and
Expand Down Expand Up @@ -79,7 +79,7 @@ mod tests {
use std::io::Error as IoError;
use tokio_io::codec::length_delimited::Framed;

const NULL_IV : [u8; 16] = [0; 16];
const NULL_IV : [u8; 16] = [0;16];

#[test]
fn raw_encode_then_decode() {
Expand All @@ -90,6 +90,7 @@ mod tests {
let cipher_key: [u8; 32] = rand::random();
let hmac_key: [u8; 32] = rand::random();


let encoder = EncoderMiddleware::new(
data_tx,
ctr(Cipher::Aes256, &cipher_key, &NULL_IV[..]),
Expand All @@ -110,7 +111,7 @@ mod tests {
let (_, decoded) = tokio_current_thread::block_on_all(data_sent.join(data_received))
.map_err(|_| ())
.unwrap();
assert_eq!(decoded.unwrap(), data);
assert_eq!(&decoded.unwrap()[..], &data[..]);
}

fn full_codec_encode_then_decode(cipher: Cipher) {
Expand Down Expand Up @@ -179,6 +180,11 @@ mod tests {
full_codec_encode_then_decode(Cipher::Aes256);
}

#[test]
fn full_codec_encode_then_decode_twofish() {
full_codec_encode_then_decode(Cipher::TwofishCtr);
}

#[test]
fn full_codec_encode_then_decode_null() {
full_codec_encode_then_decode(Cipher::Null);
Expand Down
10 changes: 5 additions & 5 deletions protocols/secio/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

//! Defines the `SecioError` enum that groups all possible errors in SECIO.

use crypto::symmetriccipher::SymmetricCipherError;
use aes_ctr::stream_cipher::LoopError;
use std::error;
use std::fmt;
use std::io::Error as IoError;
Expand Down Expand Up @@ -55,8 +55,8 @@ pub enum SecioError {
/// The final check of the handshake failed.
NonceVerificationFailed,

/// Error while decoding/encoding data.
CipherError(SymmetricCipherError),
/// Error with block cipher.
CipherError(LoopError),

/// The received frame was of invalid length.
FrameTooShort,
Expand Down Expand Up @@ -111,9 +111,9 @@ impl fmt::Display for SecioError {
}
}

impl From<SymmetricCipherError> for SecioError {
impl From<LoopError> for SecioError {
#[inline]
fn from(err: SymmetricCipherError) -> SecioError {
fn from(err: LoopError) -> SecioError {
SecioError::CipherError(err)
}
}
Expand Down
9 changes: 7 additions & 2 deletions protocols/secio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,11 @@
//! `SecioMiddleware` that implements `Sink` and `Stream` and can be used to send packets of data.
//!

extern crate aes_ctr;
#[cfg(feature = "secp256k1")]
extern crate asn1_der;
extern crate bytes;
extern crate crypto;
extern crate ctr;
extern crate futures;
extern crate libp2p_core;
#[macro_use]
Expand All @@ -92,8 +93,12 @@ extern crate rw_stream_sink;
#[cfg(feature = "secp256k1")]
extern crate secp256k1;
extern crate tokio_io;
extern crate twofish;
extern crate untrusted;

#[cfg(feature = "aes-all")]
#[macro_use]
extern crate lazy_static;
pub use self::error::SecioError;

#[cfg(feature = "secp256k1")]
Expand All @@ -116,8 +121,8 @@ mod algo_support;
mod codec;
mod error;
mod handshake;
mod stream_cipher;
mod structs_proto;
mod stream_cipher;

pub use algo_support::{Digest, KeyAgreement};
pub use stream_cipher::Cipher;
Expand Down

0 comments on commit 4cc6452

Please sign in to comment.