mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-05-29 02:31:20 +00:00
This reverts commit 73996885cb2d645ee91361204c33e7039290aabc.
This commit is contained in:
parent
e45dce2d9a
commit
0a3d4cdfad
@ -13,11 +13,7 @@ log = "0.4.1"
|
||||
protobuf = "2.0.2"
|
||||
rand = "0.3.17"
|
||||
ring = { version = "0.12", features = ["rsa_signing"] }
|
||||
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 }
|
||||
rust-crypto = "^0.2"
|
||||
rw-stream-sink = { path = "../../misc/rw-stream-sink" }
|
||||
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", optional = true }
|
||||
tokio-io = "0.1.0"
|
||||
@ -26,7 +22,6 @@ untrusted = "0.5"
|
||||
[features]
|
||||
default = ["secp256k1"]
|
||||
secp256k1 = ["eth-secp256k1"]
|
||||
aes-all = ["aesni","lazy_static"]
|
||||
|
||||
[dev-dependencies]
|
||||
libp2p-tcp-transport = { path = "../../transports/tcp" }
|
||||
|
@ -85,11 +85,8 @@ supported_impl!(
|
||||
|
||||
// TODO: the Go & JS implementations advertise Blowfish ; however doing so in Rust leads to
|
||||
// runtime errors
|
||||
// TODO: the AES library we're using seems to have a bug causing data corruption from time to time,
|
||||
// which is why we prioritize TwoFish
|
||||
supported_impl!(
|
||||
ciphers: Cipher,
|
||||
"TwofishCTR" => Cipher::Twofish,
|
||||
"AES-128" => Cipher::Aes128,
|
||||
"AES-256" => Cipher::Aes256,
|
||||
);
|
||||
|
@ -21,8 +21,7 @@
|
||||
//! Individual messages decoding.
|
||||
|
||||
use bytes::BytesMut;
|
||||
use super::StreamCipher;
|
||||
|
||||
use codec::StreamCipher;
|
||||
use error::SecioError;
|
||||
use futures::sink::Sink;
|
||||
use futures::stream::Stream;
|
||||
@ -88,24 +87,21 @@ 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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
let mut data_buf = frame.to_vec();
|
||||
data_buf.truncate(content_length);
|
||||
// Note that there is no way to decipher in place with rust-crypto right now.
|
||||
let mut decrypted_data = crypted_data.to_vec();
|
||||
self.cipher_state
|
||||
.try_apply_keystream(&mut data_buf)
|
||||
.map_err::<SecioError,_>(|e|e.into())?;
|
||||
.process(&crypted_data, &mut decrypted_data);
|
||||
|
||||
Ok(Async::Ready(Some(data_buf)))
|
||||
Ok(Async::Ready(Some(decrypted_data)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
//! Individual messages encoding.
|
||||
|
||||
use bytes::BytesMut;
|
||||
use super::StreamCipher;
|
||||
use codec::StreamCipher;
|
||||
use futures::sink::Sink;
|
||||
use futures::stream::Stream;
|
||||
use futures::Poll;
|
||||
@ -62,15 +62,22 @@ where
|
||||
type SinkItem = BytesMut;
|
||||
type SinkError = S::SinkError;
|
||||
|
||||
fn start_send(&mut self, mut data_buf: Self::SinkItem) -> StartSend<Self::SinkItem, Self::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;
|
||||
|
||||
// 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)
|
||||
// Apparently this is the fastest way of doing.
|
||||
// See https://gist.github.com/kirushik/e0d93759b0cd102f814408595c20a9d0
|
||||
let mut out_buffer = BytesMut::from(vec![0; capacity]);
|
||||
|
||||
{
|
||||
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]
|
||||
|
@ -24,7 +24,7 @@
|
||||
use self::decode::DecoderMiddleware;
|
||||
use self::encode::EncoderMiddleware;
|
||||
|
||||
use aes_ctr::stream_cipher::StreamCipherCore;
|
||||
use crypto::symmetriccipher::SynchronousStreamCipher;
|
||||
use ring::hmac;
|
||||
use tokio_io::codec::length_delimited;
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
@ -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 StreamCipherCore + Send>;
|
||||
pub type StreamCipher = Box<dyn SynchronousStreamCipher + Send>;
|
||||
|
||||
|
||||
/// Takes control of `socket`. Returns an object that implements `future::Sink` and
|
||||
@ -90,7 +90,6 @@ 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[..]),
|
||||
@ -111,7 +110,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) {
|
||||
@ -179,9 +178,4 @@ mod tests {
|
||||
fn full_codec_encode_then_decode_aes256() {
|
||||
full_codec_encode_then_decode(Cipher::Aes256);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full_codec_encode_then_decode_twofish() {
|
||||
full_codec_encode_then_decode(Cipher::Twofish);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
//! Defines the `SecioError` enum that groups all possible errors in SECIO.
|
||||
|
||||
use aes_ctr::stream_cipher::LoopError;
|
||||
use crypto::symmetriccipher::SymmetricCipherError;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::io::Error as IoError;
|
||||
@ -55,8 +55,8 @@ pub enum SecioError {
|
||||
/// The final check of the handshake failed.
|
||||
NonceVerificationFailed,
|
||||
|
||||
/// Error with block cipher.
|
||||
CipherError(LoopError),
|
||||
/// Error while decoding/encoding data.
|
||||
CipherError(SymmetricCipherError),
|
||||
|
||||
/// The received frame was of invalid length.
|
||||
FrameTooShort,
|
||||
@ -111,9 +111,9 @@ impl fmt::Display for SecioError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LoopError> for SecioError {
|
||||
impl From<SymmetricCipherError> for SecioError {
|
||||
#[inline]
|
||||
fn from(err: LoopError) -> SecioError {
|
||||
fn from(err: SymmetricCipherError) -> SecioError {
|
||||
SecioError::CipherError(err)
|
||||
}
|
||||
}
|
||||
|
@ -484,8 +484,8 @@ where
|
||||
(cipher, hmac)
|
||||
};
|
||||
|
||||
Ok(full_codec(socket, encoding_cipher, encoding_hmac,
|
||||
decoding_cipher, decoding_hmac))
|
||||
Ok(full_codec(socket, encoding_cipher, encoding_hmac, decoding_cipher,
|
||||
decoding_hmac))
|
||||
});
|
||||
|
||||
match codec {
|
||||
|
@ -78,11 +78,10 @@
|
||||
//! `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 ctr;
|
||||
extern crate crypto;
|
||||
extern crate futures;
|
||||
extern crate libp2p_core;
|
||||
#[macro_use]
|
||||
@ -94,12 +93,8 @@ 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")]
|
||||
@ -122,8 +117,8 @@ mod algo_support;
|
||||
mod codec;
|
||||
mod error;
|
||||
mod handshake;
|
||||
mod structs_proto;
|
||||
mod stream_cipher;
|
||||
mod structs_proto;
|
||||
|
||||
/// Implementation of the `ConnectionUpgrade` trait of `libp2p_core`. Automatically applies
|
||||
/// secio on any connection.
|
||||
|
@ -19,17 +19,12 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use super::codec::StreamCipher;
|
||||
use aes_ctr::stream_cipher::generic_array::GenericArray;
|
||||
use aes_ctr::stream_cipher::NewFixStreamCipher;
|
||||
use aes_ctr::{Aes128Ctr, Aes256Ctr};
|
||||
use ctr::Ctr128;
|
||||
use twofish::Twofish;
|
||||
use crypto::{aessafe, blockmodes::CtrModeX8};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Cipher {
|
||||
Aes128,
|
||||
Aes256,
|
||||
Twofish,
|
||||
}
|
||||
|
||||
impl Cipher {
|
||||
@ -38,7 +33,6 @@ impl Cipher {
|
||||
match *self {
|
||||
Cipher::Aes128 => 16,
|
||||
Cipher::Aes256 => 32,
|
||||
Cipher::Twofish => 32,
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,114 +44,16 @@ impl Cipher {
|
||||
}
|
||||
|
||||
/// Returns your stream cipher depending on `Cipher`.
|
||||
#[cfg(not(all(feature = "aes-all", any(target_arch = "x86_64", target_arch = "x86"))))]
|
||||
pub fn ctr(key_size: Cipher, key: &[u8], iv: &[u8]) -> StreamCipher {
|
||||
ctr_int(key_size, key, iv)
|
||||
}
|
||||
|
||||
/// Returns your stream cipher depending on `Cipher`.
|
||||
#[cfg(all(feature = "aes-all", any(target_arch = "x86_64", target_arch = "x86")))]
|
||||
pub fn ctr(key_size: Cipher, key: &[u8], iv: &[u8]) -> StreamCipher {
|
||||
if *aes_alt::AES_NI {
|
||||
aes_alt::ctr_alt(key_size, key, iv)
|
||||
} else {
|
||||
ctr_int(key_size, key, iv)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(all(feature = "aes-all", any(target_arch = "x86_64", target_arch = "x86")))]
|
||||
mod aes_alt {
|
||||
extern crate aesni;
|
||||
use ::codec::StreamCipher;
|
||||
use ctr::Ctr128;
|
||||
use self::aesni::{Aes128, Aes256};
|
||||
use ctr::stream_cipher::NewFixStreamCipher;
|
||||
use ctr::stream_cipher::generic_array::GenericArray;
|
||||
use twofish::Twofish;
|
||||
use super::Cipher;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref AES_NI: bool = is_x86_feature_detected!("aes")
|
||||
&& is_x86_feature_detected!("sse2")
|
||||
&& is_x86_feature_detected!("sse3");
|
||||
|
||||
}
|
||||
|
||||
/// AES-128 in CTR mode
|
||||
pub type Aes128Ctr = Ctr128<Aes128>;
|
||||
/// AES-256 in CTR mode
|
||||
pub type Aes256Ctr = Ctr128<Aes256>;
|
||||
/// Returns alternate stream cipher if target functionalities does not allow standard one.
|
||||
/// Eg : aes without sse
|
||||
pub fn ctr_alt(key_size: Cipher, key: &[u8], iv: &[u8]) -> StreamCipher {
|
||||
match key_size {
|
||||
Cipher::Aes128 => Box::new(Aes128Ctr::new(
|
||||
GenericArray::from_slice(key),
|
||||
GenericArray::from_slice(iv),
|
||||
)),
|
||||
Cipher::Aes256 => Box::new(Aes256Ctr::new(
|
||||
GenericArray::from_slice(key),
|
||||
GenericArray::from_slice(iv),
|
||||
)),
|
||||
Cipher::Twofish => Box::new(Ctr128::<Twofish>::new(
|
||||
GenericArray::from_slice(key),
|
||||
GenericArray::from_slice(iv),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ctr_int(key_size: Cipher, key: &[u8], iv: &[u8]) -> StreamCipher {
|
||||
pub fn ctr(key_size: Cipher, key: &[u8], iv: &[u8]) -> StreamCipher {
|
||||
match key_size {
|
||||
Cipher::Aes128 => Box::new(Aes128Ctr::new(
|
||||
GenericArray::from_slice(key),
|
||||
GenericArray::from_slice(iv),
|
||||
)),
|
||||
Cipher::Aes256 => Box::new(Aes256Ctr::new(
|
||||
GenericArray::from_slice(key),
|
||||
GenericArray::from_slice(iv),
|
||||
)),
|
||||
Cipher::Twofish => Box::new(Ctr128::<Twofish>::new(
|
||||
GenericArray::from_slice(key),
|
||||
GenericArray::from_slice(iv),
|
||||
)),
|
||||
Cipher::Aes128 => {
|
||||
let aes_dec = aessafe::AesSafe128EncryptorX8::new(key);
|
||||
Box::new(CtrModeX8::new(aes_dec, iv))
|
||||
},
|
||||
Cipher::Aes256 => {
|
||||
let aes_dec = aessafe::AesSafe256EncryptorX8::new(key);
|
||||
Box::new(CtrModeX8::new(aes_dec, iv))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "aes-all",
|
||||
any(target_arch = "x86_64", target_arch = "x86"),
|
||||
))]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Cipher, ctr};
|
||||
|
||||
#[test]
|
||||
fn assert_non_native_run() {
|
||||
// this test is for asserting aes unsuported opcode does not break on old cpu
|
||||
let key = [0;16];
|
||||
let iv = [0;16];
|
||||
|
||||
let mut aes = ctr(Cipher::Aes128, &key, &iv);
|
||||
let mut content = [0;16];
|
||||
assert!(aes
|
||||
.try_apply_keystream(&mut content).is_ok());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// aesni compile check for aes-all (aes-all import aesni through aes_ctr only if those checks pass)
|
||||
#[cfg(all(
|
||||
feature = "aes-all",
|
||||
any(target_arch = "x86_64", target_arch = "x86"),
|
||||
any(target_feature = "aes", target_feature = "ssse3"),
|
||||
))]
|
||||
compile_error!(
|
||||
"aes-all must be compile without aes and sse3 flags : currently \
|
||||
is_x86_feature_detected macro will not detect feature correctly otherwhise. \
|
||||
RUSTFLAGS=\"-C target-feature=+aes,+ssse3\" enviromental variable. \
|
||||
For x86 target arch additionally enable sse2 target feature."
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user