diff --git a/Cargo.toml b/Cargo.toml index ec96c0a..af65514 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,5 @@ authors = ["klutzytheklutzy@gmail.com"] log = "*" rand = "*" +num = "*" +enum_primitive = "*" diff --git a/examples/google.rs b/examples/google.rs index 8dcef56..7ead7c1 100644 --- a/examples/google.rs +++ b/examples/google.rs @@ -1,5 +1,3 @@ -#![feature(net)] - extern crate suruga; use std::io::prelude::*; diff --git a/src/cipher/chacha20_poly1305.rs b/src/cipher/chacha20_poly1305.rs index 6b539ff..ae6dd07 100644 --- a/src/cipher/chacha20_poly1305.rs +++ b/src/cipher/chacha20_poly1305.rs @@ -118,18 +118,18 @@ impl Aead for ChaCha20Poly1305 { } #[inline(always)] - fn new_encryptor(&self, key: Vec) -> Box { + fn new_encryptor(&self, key: Vec) -> Box { let encryptor = ChaCha20Poly1305Encryptor { key: key, }; - Box::new(encryptor) as Box + Box::new(encryptor) as Box } #[inline(always)] - fn new_decryptor(&self, key: Vec) -> Box { + fn new_decryptor(&self, key: Vec) -> Box { let decryptor = ChaCha20Poly1305Decryptor { key: key, }; - Box::new(decryptor) as Box + Box::new(decryptor) as Box } } diff --git a/src/cipher/mod.rs b/src/cipher/mod.rs index 2f09ca1..b27930f 100644 --- a/src/cipher/mod.rs +++ b/src/cipher/mod.rs @@ -15,8 +15,8 @@ pub trait Aead { fn key_size(&self) -> usize; fn fixed_iv_len(&self) -> usize; fn mac_len(&self) -> usize; - fn new_encryptor(&self, key: Vec) -> Box; - fn new_decryptor(&self, key: Vec) -> Box; + fn new_encryptor(&self, key: Vec) -> Box; + fn new_decryptor(&self, key: Vec) -> Box; } pub trait Encryptor { @@ -41,7 +41,7 @@ macro_rules! cipher_suite { $id:ident = $kex:ident, $cipher:ident, $mac:ident, $v1:expr, $v2:expr; )+) => ( #[allow(non_camel_case_types)] - #[derive(Copy, PartialEq, Debug)] + #[derive(Copy, Clone, PartialEq, Debug)] pub enum CipherSuite { $( $id, diff --git a/src/client.rs b/src/client.rs index 279e094..d4693f2 100644 --- a/src/client.rs +++ b/src/client.rs @@ -7,7 +7,7 @@ use rand::{Rng, OsRng}; use tls_result::TlsResult; use tls_result::TlsErrorKind::{UnexpectedMessage, InternalError, DecryptError, IllegalParameter}; -use util::crypto_compare; +use util::{SurugaError, crypto_compare}; use cipher::{self, Aead}; use cipher::prf::Prf; use crypto::sha2::sha256; @@ -255,7 +255,10 @@ impl Write for TlsClient { Err(err) => { let err = self.tls.send_tls_alert(err); // FIXME more verbose io error - Err(io::Error::new(io::ErrorKind::Other, "TLS write error", Some(err.desc))) + Err(io::Error::new(io::ErrorKind::Other, SurugaError { + desc: "TLS write error", + cause: Some(Box::new(err)), + })) } } } @@ -280,7 +283,7 @@ impl Read for TlsClient { let selflen = self.buf.len(); let necessary = cmp::min(remaining, selflen); - copy_memory(&mut buf[pos .. pos + necessary], &self.buf[.. necessary]); + copy_memory(&self.buf[.. necessary], &mut buf[pos .. pos + necessary]); pos += necessary; self.buf = self.buf[necessary..].to_vec(); diff --git a/src/crypto/wrapping.rs b/src/crypto/wrapping.rs index 388e69d..0d7276c 100644 --- a/src/crypto/wrapping.rs +++ b/src/crypto/wrapping.rs @@ -3,7 +3,7 @@ // NOTE: since there is no const fn (yet), you can't use `w32(100)` function // for consts and statics. (workaround: use `Wrapping(100)`.) -pub use std::num::wrapping::{Wrapping, WrappingOps}; +pub use std::num::Wrapping; pub trait ToWrapping { fn to_w64(self) -> w64; diff --git a/src/lib.rs b/src/lib.rs index b0bbeab..e4a8896 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,11 +3,15 @@ #![allow(missing_copy_implementations)] -#![feature(io, core, collections, net)] +#![feature(core, collections)] #[macro_use] extern crate log; extern crate rand; +extern crate num; + +#[macro_use] +extern crate enum_primitive; pub use tls::Tls; pub use client::TlsClient; diff --git a/src/record.rs b/src/record.rs index 8ed5137..9bba1e4 100644 --- a/src/record.rs +++ b/src/record.rs @@ -1,5 +1,5 @@ use std::io::prelude::*; -use std::num::FromPrimitive; +use num::traits::FromPrimitive; use tls_result::TlsResult; use tls_result::TlsErrorKind::{UnexpectedMessage, RecordOverflow, BadRecordMac, AlertReceived}; @@ -15,14 +15,16 @@ use self::ContentType::{ChangeCipherSpecTy, AlertTy, HandshakeTy, ApplicationDat use self::Message::{HandshakeMessage, ChangeCipherSpecMessage, AlertMessage, ApplicationDataMessage}; -#[repr(u8)] -#[derive(Copy, PartialEq, FromPrimitive, Debug)] -pub enum ContentType { - ChangeCipherSpecTy = 20, - AlertTy = 21, - HandshakeTy = 22, - ApplicationDataTy = 23, - // HeartBeat = 24, RFC 6520 extension :-) +enum_from_primitive! { + #[repr(u8)] + #[derive(Copy, Clone, PartialEq, Debug)] + pub enum ContentType { + ChangeCipherSpecTy = 20, + AlertTy = 21, + HandshakeTy = 22, + ApplicationDataTy = 23, + // HeartBeat = 24, RFC 6520 extension :-) + } } /// maximum length of Record (excluding content_type, version, length fields) @@ -84,7 +86,7 @@ impl EncryptedRecord { pub struct RecordWriter { writer: W, // if encryptor is None, handshake is not done yet. - encryptor: Option>, + encryptor: Option>, write_count: u64, } @@ -97,7 +99,7 @@ impl RecordWriter { } } - pub fn set_encryptor(&mut self, encryptor: Box) { + pub fn set_encryptor(&mut self, encryptor: Box) { self.encryptor = Some(encryptor); self.write_count = 0; } @@ -191,7 +193,7 @@ pub enum Message { pub struct RecordReader { reader: R, // if decryptor is none, handshake is not done yet. - decryptor: Option>, + decryptor: Option>, read_count: u64, handshake_buffer: HandshakeBuffer, } @@ -206,7 +208,7 @@ impl RecordReader { } } - pub fn set_decryptor(&mut self, decryptor: Box) { + pub fn set_decryptor(&mut self, decryptor: Box) { self.decryptor = Some(decryptor); self.read_count = 0; } diff --git a/src/test.rs b/src/test.rs index e42fcfa..5e6462f 100644 --- a/src/test.rs +++ b/src/test.rs @@ -30,9 +30,9 @@ impl Decryptor for NullDecryptor { fn null_tls(reader: R, writer: W) -> Tls { let mut tls = Tls::new(reader, writer, OsRng::new().unwrap()); - let null_encryptor = Box::new(NullEncryptor) as Box; + let null_encryptor = Box::new(NullEncryptor) as Box; tls.writer.set_encryptor(null_encryptor); - let null_decryptor = Box::new(NullDecryptor) as Box; + let null_decryptor = Box::new(NullDecryptor) as Box; tls.reader.set_decryptor(null_decryptor); tls diff --git a/src/tls_item.rs b/src/tls_item.rs index 7ac3ecc..841e7ca 100644 --- a/src/tls_item.rs +++ b/src/tls_item.rs @@ -89,13 +89,15 @@ macro_rules! tls_enum { ),+ } ) => ( - #[allow(non_camel_case_types)] - #[derive(Copy, PartialEq, FromPrimitive)] - $(#[$a])* - pub enum $name { - $( - $item = $n, - )+ + enum_from_primitive! { + #[allow(non_camel_case_types)] + #[derive(Copy, Clone, PartialEq)] + $(#[$a])* + pub enum $name { + $( + $item = $n, + )+ + } } impl TlsItem for $name { @@ -106,7 +108,7 @@ macro_rules! tls_enum { fn tls_read(reader: &mut R) -> ::tls_result::TlsResult<$name> { let num = stry_read_num!($repr_ty, reader) as u64; - let n: Option<$name> = ::std::num::FromPrimitive::from_u64(num); + let n: Option<$name> = ::num::traits::FromPrimitive::from_u64(num); match n { Some(n) => Ok(n), None => tls_err!(::tls_result::TlsErrorKind::DecodeError, diff --git a/src/tls_result.rs b/src/tls_result.rs index cae0f31..1b53292 100644 --- a/src/tls_result.rs +++ b/src/tls_result.rs @@ -1,8 +1,8 @@ -use std::error::{Error, FromError}; +use std::error::Error; use std::io; use std::fmt; -#[derive(Copy, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum TlsErrorKind { // corresponds to alert messages @@ -54,8 +54,8 @@ impl Error for TlsError { } } -impl FromError for TlsError { - fn from_error(err: io::Error) -> TlsError { +impl From for TlsError { + fn from(err: io::Error) -> TlsError { TlsError { kind: TlsErrorKind::IoFailure, desc: format!("io error: {}", err), diff --git a/src/util.rs b/src/util.rs index 24a87f8..3a6eeb0 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,28 @@ -use std::mem; -use std::num::Int; +use std::{mem, fmt}; +use std::error::Error; use std::io::{self, Read, Write}; +#[derive(Debug)] +pub struct SurugaError { + pub desc: &'static str, + pub cause: Option>, +} + +impl fmt::Display for SurugaError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + ::fmt(self, fmt) + } +} + +impl Error for SurugaError { + fn description(&self) -> &str { + self.desc + } + + // FIXME: implement fn cause(&self) -> Option<&Error> + // This runs into difficulties with differing trait bounds. +} + /// constant-time compare function. /// `a` and `b` may be SECRET, but the length is known. /// precondition: `a.len() == b.len()` @@ -62,7 +83,10 @@ pub trait ReadExt: Read { while pos < len { let num_bytes = try!(self.read(&mut buf[pos..])); if num_bytes == 0 { - return Err(io::Error::new(io::ErrorKind::Other, "EOF during `fill_exact`", None)); + return Err(io::Error::new(io::ErrorKind::Other, SurugaError { + desc: "EOF during `fill_exact`", + cause: None + })); } pos += num_bytes; }