Loading openssl-sys/src/lib.rs +2 −0 Original line number Diff line number Diff line Loading @@ -282,6 +282,8 @@ pub const BIO_FLAGS_SHOULD_RETRY: c_int = 0x08; pub const CRYPTO_LOCK: c_int = 1; pub const EVP_MAX_MD_SIZE: c_uint = 64; pub const MBSTRING_ASC: c_int = MBSTRING_FLAG | 1; pub const MBSTRING_BMP: c_int = MBSTRING_FLAG | 2; pub const MBSTRING_FLAG: c_int = 0x1000; Loading openssl/src/crypto/dsa.rs +7 −7 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ use libc::{c_uint, c_int, c_char, c_void}; use bn::BigNumRef; use bio::{MemBio, MemBioSlice}; use crypto::hash; use crypto::HashTypeInternals; use HashTypeInternals; use crypto::util::{CallbackState, invoke_passwd_cb}; Loading Loading @@ -249,9 +249,9 @@ mod test { let input: Vec<u8> = (0..25).cycle().take(1024).collect(); let digest = { let mut sha = Hasher::new(Type::SHA1); let mut sha = Hasher::new(Type::SHA1).unwrap(); sha.write_all(&input).unwrap(); sha.finish() sha.finish().unwrap() }; let sig = key.sign(Type::SHA1, &digest).unwrap(); Loading @@ -274,9 +274,9 @@ mod test { }; let digest = { let mut sha = Hasher::new(Type::SHA1); let mut sha = Hasher::new(Type::SHA1).unwrap(); sha.write_all(&input).unwrap(); sha.finish() sha.finish().unwrap() }; let sig = private_key.sign(Type::SHA1, &digest).unwrap(); Loading @@ -298,9 +298,9 @@ mod test { }; let digest = { let mut sha = Hasher::new(Type::SHA1); let mut sha = Hasher::new(Type::SHA1).unwrap(); sha.write_all(&input).unwrap(); sha.finish() sha.finish().unwrap() }; let mut sig = private_key.sign(Type::SHA1, &digest).unwrap(); Loading openssl/src/crypto/hash.rs +60 −90 Original line number Diff line number Diff line use libc::c_uint; use std::iter::repeat; use std::io::prelude::*; use std::io; use std::ptr; use std::cmp; use ffi; use crypto::HashTypeInternals; use HashTypeInternals; use error::ErrorStack; use nid::Nid; /// Message digest (hash) type. Loading @@ -31,26 +33,8 @@ impl HashTypeInternals for Type { Type::RIPEMD160 => Nid::RIPEMD160, } } } impl Type { /// Returns the length of the message digest. #[inline] pub fn md_len(&self) -> usize { match *self { Type::MD5 => 16, Type::SHA1 => 20, Type::SHA224 => 28, Type::SHA256 => 32, Type::SHA384 => 48, Type::SHA512 => 64, Type::RIPEMD160 => 20, } } /// Internal interface subject to removal. #[inline] pub fn evp_md(&self) -> *const ffi::EVP_MD { fn evp_md(&self) -> *const ffi::EVP_MD { unsafe { match *self { Type::MD5 => ffi::EVP_md5(), Loading Loading @@ -84,21 +68,20 @@ use self::State::*; /// use openssl::crypto::hash::{hash, Type}; /// let data = b"\x42\xF4\x97\xE0"; /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2"; /// let res = hash(Type::MD5, data); /// let res = hash(Type::MD5, data).unwrap(); /// assert_eq!(res, spec); /// ``` /// /// Use the `Write` trait to supply the input in chunks. /// /// ``` /// use std::io::prelude::*; /// use openssl::crypto::hash::{Hasher, Type}; /// let data = [b"\x42\xF4", b"\x97\xE0"]; /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2"; /// let mut h = Hasher::new(Type::MD5); /// h.write_all(data[0]); /// h.write_all(data[1]); /// let res = h.finish(); /// let mut h = Hasher::new(Type::MD5).unwrap(); /// h.update(data[0]).unwrap(); /// h.update(data[1]).unwrap(); /// let res = h.finish().unwrap(); /// assert_eq!(res, spec); /// ``` /// Loading @@ -116,14 +99,10 @@ pub struct Hasher { impl Hasher { /// Creates a new `Hasher` with the specified hash type. pub fn new(ty: Type) -> Hasher { pub fn new(ty: Type) -> Result<Hasher, ErrorStack> { ffi::init(); let ctx = unsafe { let r = ffi::EVP_MD_CTX_create(); assert!(!r.is_null()); r }; let ctx = unsafe { try_ssl_null!(ffi::EVP_MD_CTX_create()) }; let md = ty.evp_md(); let mut h = Hasher { Loading @@ -132,67 +111,60 @@ impl Hasher { type_: ty, state: Finalized, }; h.init(); h try!(h.init()); Ok(h) } #[inline] fn init(&mut self) { fn init(&mut self) -> Result<(), ErrorStack> { match self.state { Reset => return, Reset => return Ok(()), Updated => { self.finalize(); try!(self.finish()); } Finalized => (), } unsafe { let r = ffi::EVP_DigestInit_ex(self.ctx, self.md, 0 as *const _); assert_eq!(r, 1); } unsafe { try_ssl!(ffi::EVP_DigestInit_ex(self.ctx, self.md, 0 as *const _)); } self.state = Reset; Ok(()) } #[inline] fn update(&mut self, data: &[u8]) { /// Feeds data into the hasher. pub fn update(&mut self, mut data: &[u8]) -> Result<(), ErrorStack> { if self.state == Finalized { self.init(); try!(self.init()); } while !data.is_empty() { let len = cmp::min(data.len(), c_uint::max_value() as usize); unsafe { let r = ffi::EVP_DigestUpdate(self.ctx, data.as_ptr(), data.len() as c_uint); assert_eq!(r, 1); try_ssl!(ffi::EVP_DigestUpdate(self.ctx, data.as_ptr(), len as c_uint)); } data = &data[len..]; } self.state = Updated; Ok(()) } #[inline] fn finalize(&mut self) -> Vec<u8> { /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. pub fn finish(&mut self) -> Result<Vec<u8>, ErrorStack> { if self.state == Finalized { self.init(); try!(self.init()); } let md_len = self.type_.md_len(); let mut res: Vec<u8> = repeat(0).take(md_len).collect(); unsafe { let mut len = 0; let r = ffi::EVP_DigestFinal_ex(self.ctx, res.as_mut_ptr(), &mut len); let mut len = ffi::EVP_MAX_MD_SIZE; let mut res = vec![0; len as usize]; try_ssl!(ffi::EVP_DigestFinal_ex(self.ctx, res.as_mut_ptr(), &mut len)); res.truncate(len as usize); self.state = Finalized; assert_eq!(len as usize, md_len); assert_eq!(r, 1); } res Ok(res) } /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. #[inline] pub fn finish(&mut self) -> Vec<u8> { self.finalize() } } impl Write for Hasher { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.update(buf); try!(self.update(buf)); Ok(buf.len()) } Loading Loading @@ -223,9 +195,7 @@ impl Drop for Hasher { fn drop(&mut self) { unsafe { if self.state != Finalized { let mut buf: Vec<u8> = repeat(0).take(self.type_.md_len()).collect(); let mut len = 0; ffi::EVP_DigestFinal_ex(self.ctx, buf.as_mut_ptr(), &mut len); drop(self.finish()); } ffi::EVP_MD_CTX_destroy(self.ctx); } Loading @@ -233,9 +203,9 @@ impl Drop for Hasher { } /// Computes the hash of the `data` with the hash `t`. pub fn hash(t: Type, data: &[u8]) -> Vec<u8> { let mut h = Hasher::new(t); let _ = h.write_all(data); pub fn hash(t: Type, data: &[u8]) -> Result<Vec<u8>, ErrorStack> { let mut h = try!(Hasher::new(t)); try!(h.update(data)); h.finish() } Loading @@ -246,13 +216,13 @@ mod tests { use std::io::prelude::*; fn hash_test(hashtype: Type, hashtest: &(&str, &str)) { let res = hash(hashtype, &*hashtest.0.from_hex().unwrap()); let res = hash(hashtype, &*hashtest.0.from_hex().unwrap()).unwrap(); assert_eq!(res.to_hex(), hashtest.1); } fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) { let _ = h.write_all(&*hashtest.0.from_hex().unwrap()); let res = h.finish(); let _ = h.write_all(&*hashtest.0.from_hex().unwrap()).unwrap(); let res = h.finish().unwrap(); assert_eq!(res.to_hex(), hashtest.1); } Loading Loading @@ -294,7 +264,7 @@ mod tests { #[test] fn test_md5_recycle() { let mut h = Hasher::new(Type::MD5); let mut h = Hasher::new(Type::MD5).unwrap(); for test in md5_tests.iter() { hash_recycle_test(&mut h, test); } Loading @@ -302,11 +272,11 @@ mod tests { #[test] fn test_finish_twice() { let mut h = Hasher::new(Type::MD5); let _ = h.write_all(&*md5_tests[6].0.from_hex().unwrap()); let _ = h.finish(); let res = h.finish(); let null = hash(Type::MD5, &[]); let mut h = Hasher::new(Type::MD5).unwrap(); h.write_all(&*md5_tests[6].0.from_hex().unwrap()).unwrap(); h.finish().unwrap(); let res = h.finish().unwrap(); let null = hash(Type::MD5, &[]).unwrap(); assert_eq!(res, null); } Loading @@ -316,26 +286,26 @@ mod tests { let inp = md5_tests[i].0.from_hex().unwrap(); assert!(inp.len() > 2); let p = inp.len() / 2; let h0 = Hasher::new(Type::MD5); let h0 = Hasher::new(Type::MD5).unwrap(); println!("Clone a new hasher"); let mut h1 = h0.clone(); let _ = h1.write_all(&inp[..p]); h1.write_all(&inp[..p]).unwrap(); { println!("Clone an updated hasher"); let mut h2 = h1.clone(); let _ = h2.write_all(&inp[p..]); let res = h2.finish(); h2.write_all(&inp[p..]).unwrap(); let res = h2.finish().unwrap(); assert_eq!(res.to_hex(), md5_tests[i].1); } let _ = h1.write_all(&inp[p..]); let res = h1.finish(); h1.write_all(&inp[p..]).unwrap(); let res = h1.finish().unwrap(); assert_eq!(res.to_hex(), md5_tests[i].1); println!("Clone a finished hasher"); let mut h3 = h1.clone(); let _ = h3.write_all(&*md5_tests[i + 1].0.from_hex().unwrap()); let res = h3.finish(); h3.write_all(&*md5_tests[i + 1].0.from_hex().unwrap()).unwrap(); let res = h3.finish().unwrap(); assert_eq!(res.to_hex(), md5_tests[i + 1].1); } Loading openssl/src/crypto/hmac.rs +72 −80 Original line number Diff line number Diff line Loading @@ -14,14 +14,16 @@ // use libc::{c_int, c_uint}; use std::iter::repeat; use std::io; use std::io::prelude::*; use crypto::hash::Type; use std::cmp; use ffi; use ffi_extras; use HashTypeInternals; use crypto::hash::Type; use error::ErrorStack; #[derive(PartialEq, Copy, Clone)] enum State { Reset, Loading @@ -43,23 +45,22 @@ use self::State::*; /// let key = b"Jefe"; /// let data = b"what do ya want for nothing?"; /// let spec = b"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38"; /// let res = hmac(Type::MD5, key, data); /// let res = hmac(Type::MD5, key, data).unwrap(); /// assert_eq!(res, spec); /// ``` /// /// Use the `Write` trait to supply the input in chunks. /// /// ``` /// use std::io::prelude::*; /// use openssl::crypto::hash::Type; /// use openssl::crypto::hmac::HMAC; /// let key = b"Jefe"; /// let data: &[&[u8]] = &[b"what do ya ", b"want for nothing?"]; /// let spec = b"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38"; /// let mut h = HMAC::new(Type::MD5, &*key); /// h.write_all(data[0]); /// h.write_all(data[1]); /// let res = h.finish(); /// let mut h = HMAC::new(Type::MD5, &*key).unwrap(); /// h.update(data[0]).unwrap(); /// h.update(data[1]).unwrap(); /// let res = h.finish().unwrap(); /// assert_eq!(res, spec); /// ``` pub struct HMAC { Loading @@ -70,7 +71,7 @@ pub struct HMAC { impl HMAC { /// Creates a new `HMAC` with the specified hash type using the `key`. pub fn new(ty: Type, key: &[u8]) -> HMAC { pub fn new(ty: Type, key: &[u8]) -> Result<HMAC, ErrorStack> { ffi::init(); let ctx = unsafe { Loading @@ -85,86 +86,79 @@ impl HMAC { type_: ty, state: Finalized, }; h.init_once(md, key); h try!(h.init_once(md, key)); Ok(h) } #[inline] fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) { fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) -> Result<(), ErrorStack> { unsafe { let r = ffi_extras::HMAC_Init_ex(&mut self.ctx, try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, key.as_ptr(), key.len() as c_int, md, 0 as *const _); assert_eq!(r, 1); 0 as *const _)); } self.state = Reset; Ok(()) } #[inline] fn init(&mut self) { fn init(&mut self) -> Result<(), ErrorStack> { match self.state { Reset => return, Reset => return Ok(()), Updated => { self.finalize(); try!(self.finish()); } Finalized => (), } // If the key and/or md is not supplied it's reused from the last time // avoiding redundant initializations unsafe { let r = ffi_extras::HMAC_Init_ex(&mut self.ctx, try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, 0 as *const _, 0, 0 as *const _, 0 as *const _); assert_eq!(r, 1); 0 as *const _)); } self.state = Reset; Ok(()) } #[inline] fn update(&mut self, data: &[u8]) { pub fn update(&mut self, mut data: &[u8]) -> Result<(), ErrorStack> { if self.state == Finalized { self.init(); try!(self.init()); } while !data.is_empty() { let len = cmp::min(data.len(), c_uint::max_value() as usize); unsafe { let r = ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), data.len() as c_uint); assert_eq!(r, 1); try_ssl!(ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), len as c_uint)); } data = &data[len..]; } self.state = Updated; Ok(()) } #[inline] fn finalize(&mut self) -> Vec<u8> { /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. pub fn finish(&mut self) -> Result<Vec<u8>, ErrorStack> { if self.state == Finalized { self.init(); try!(self.init()); } let md_len = self.type_.md_len(); let mut res: Vec<u8> = repeat(0).take(md_len).collect(); unsafe { let mut len = 0; let r = ffi_extras::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len); let mut len = ffi::EVP_MAX_MD_SIZE; let mut res = vec![0; len as usize]; try_ssl!(ffi_extras::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len)); res.truncate(len as usize); self.state = Finalized; assert_eq!(len as usize, md_len); assert_eq!(r, 1); } res Ok(res) } /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. #[inline] pub fn finish(&mut self) -> Vec<u8> { self.finalize() } } impl Write for HMAC { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.update(buf); try!(self.update(buf)); Ok(buf.len()) } Loading Loading @@ -193,9 +187,7 @@ impl Drop for HMAC { fn drop(&mut self) { unsafe { if self.state != Finalized { let mut buf: Vec<u8> = repeat(0).take(self.type_.md_len()).collect(); let mut len = 0; ffi_extras::HMAC_Final(&mut self.ctx, buf.as_mut_ptr(), &mut len); drop(self.finish()); } ffi::HMAC_CTX_cleanup(&mut self.ctx); } Loading @@ -203,9 +195,9 @@ impl Drop for HMAC { } /// Computes the HMAC of the `data` with the hash `t` and `key`. pub fn hmac(t: Type, key: &[u8], data: &[u8]) -> Vec<u8> { let mut h = HMAC::new(t, key); let _ = h.write_all(data); pub fn hmac(t: Type, key: &[u8], data: &[u8]) -> Result<Vec<u8>, ErrorStack> { let mut h = try!(HMAC::new(t, key)); try!(h.update(data)); h.finish() } Loading @@ -220,14 +212,14 @@ mod tests { fn test_hmac(ty: Type, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) { for &(ref key, ref data, ref res) in tests.iter() { assert_eq!(hmac(ty, &**key, &**data), *res); assert_eq!(hmac(ty, &**key, &**data).unwrap(), *res); } } fn test_hmac_recycle(h: &mut HMAC, test: &(Vec<u8>, Vec<u8>, Vec<u8>)) { let &(_, ref data, ref res) = test; let _ = h.write_all(&**data); assert_eq!(h.finish(), *res); h.write_all(&**data).unwrap(); assert_eq!(h.finish().unwrap(), *res); } #[test] Loading Loading @@ -273,7 +265,7 @@ mod tests { .to_vec(), "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; let mut h = HMAC::new(MD5, &*tests[0].0); let mut h = HMAC::new(MD5, &*tests[0].0).unwrap(); for i in 0..100usize { let test = &tests[i % 2]; test_hmac_recycle(&mut h, test); Loading @@ -287,11 +279,11 @@ mod tests { b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd".from_hex().unwrap()); let mut h = HMAC::new(Type::MD5, &*test.0); let _ = h.write_all(&*test.1); let _ = h.finish(); let res = h.finish(); let null = hmac(Type::MD5, &*test.0, &[]); let mut h = HMAC::new(Type::MD5, &*test.0).unwrap(); h.write_all(&*test.1).unwrap(); h.finish().unwrap(); let res = h.finish().unwrap(); let null = hmac(Type::MD5, &*test.0, &[]).unwrap(); assert_eq!(res, null); } Loading @@ -307,26 +299,26 @@ mod tests { .to_vec(), "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; let p = tests[0].0.len() / 2; let h0 = HMAC::new(Type::MD5, &*tests[0].0); let h0 = HMAC::new(Type::MD5, &*tests[0].0).unwrap(); println!("Clone a new hmac"); let mut h1 = h0.clone(); let _ = h1.write_all(&tests[0].1[..p]); h1.write_all(&tests[0].1[..p]).unwrap(); { println!("Clone an updated hmac"); let mut h2 = h1.clone(); let _ = h2.write_all(&tests[0].1[p..]); let res = h2.finish(); h2.write_all(&tests[0].1[p..]).unwrap(); let res = h2.finish().unwrap(); assert_eq!(res, tests[0].2); } let _ = h1.write_all(&tests[0].1[p..]); let res = h1.finish(); h1.write_all(&tests[0].1[p..]).unwrap(); let res = h1.finish().unwrap(); assert_eq!(res, tests[0].2); println!("Clone a finished hmac"); let mut h3 = h1.clone(); let _ = h3.write_all(&*tests[1].1); let res = h3.finish(); h3.write_all(&*tests[1].1).unwrap(); let res = h3.finish().unwrap(); assert_eq!(res, tests[1].2); } Loading Loading @@ -373,7 +365,7 @@ mod tests { .to_vec(), "e8e99d0f45237d786d6bbaa7965c7808bbff1a91".from_hex().unwrap())]; let mut h = HMAC::new(SHA1, &*tests[0].0); let mut h = HMAC::new(SHA1, &*tests[0].0).unwrap(); for i in 0..100usize { let test = &tests[i % 2]; test_hmac_recycle(&mut h, test); Loading @@ -399,11 +391,11 @@ mod tests { .to_vec())]; for (&(ref key, ref data), res) in tests.iter().zip(results.iter()) { assert_eq!(hmac(ty, &**key, &**data), *res); assert_eq!(hmac(ty, &**key, &**data).unwrap(), *res); } // recycle test let mut h = HMAC::new(ty, &*tests[5].0); let mut h = HMAC::new(ty, &*tests[5].0).unwrap(); for i in 0..100usize { let test = &tests[4 + i % 2]; let tup = (test.0.clone(), test.1.clone(), results[4 + i % 2].clone()); Loading openssl/src/crypto/mod.rs +0 −6 Original line number Diff line number Diff line Loading @@ -14,8 +14,6 @@ // limitations under the License. // use nid::Nid; pub mod hash; pub mod hmac; pub mod pkcs5; Loading @@ -28,7 +26,3 @@ pub mod dsa; mod util; mod symm_internal; trait HashTypeInternals { fn as_nid(&self) -> Nid; } Loading
openssl-sys/src/lib.rs +2 −0 Original line number Diff line number Diff line Loading @@ -282,6 +282,8 @@ pub const BIO_FLAGS_SHOULD_RETRY: c_int = 0x08; pub const CRYPTO_LOCK: c_int = 1; pub const EVP_MAX_MD_SIZE: c_uint = 64; pub const MBSTRING_ASC: c_int = MBSTRING_FLAG | 1; pub const MBSTRING_BMP: c_int = MBSTRING_FLAG | 2; pub const MBSTRING_FLAG: c_int = 0x1000; Loading
openssl/src/crypto/dsa.rs +7 −7 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ use libc::{c_uint, c_int, c_char, c_void}; use bn::BigNumRef; use bio::{MemBio, MemBioSlice}; use crypto::hash; use crypto::HashTypeInternals; use HashTypeInternals; use crypto::util::{CallbackState, invoke_passwd_cb}; Loading Loading @@ -249,9 +249,9 @@ mod test { let input: Vec<u8> = (0..25).cycle().take(1024).collect(); let digest = { let mut sha = Hasher::new(Type::SHA1); let mut sha = Hasher::new(Type::SHA1).unwrap(); sha.write_all(&input).unwrap(); sha.finish() sha.finish().unwrap() }; let sig = key.sign(Type::SHA1, &digest).unwrap(); Loading @@ -274,9 +274,9 @@ mod test { }; let digest = { let mut sha = Hasher::new(Type::SHA1); let mut sha = Hasher::new(Type::SHA1).unwrap(); sha.write_all(&input).unwrap(); sha.finish() sha.finish().unwrap() }; let sig = private_key.sign(Type::SHA1, &digest).unwrap(); Loading @@ -298,9 +298,9 @@ mod test { }; let digest = { let mut sha = Hasher::new(Type::SHA1); let mut sha = Hasher::new(Type::SHA1).unwrap(); sha.write_all(&input).unwrap(); sha.finish() sha.finish().unwrap() }; let mut sig = private_key.sign(Type::SHA1, &digest).unwrap(); Loading
openssl/src/crypto/hash.rs +60 −90 Original line number Diff line number Diff line use libc::c_uint; use std::iter::repeat; use std::io::prelude::*; use std::io; use std::ptr; use std::cmp; use ffi; use crypto::HashTypeInternals; use HashTypeInternals; use error::ErrorStack; use nid::Nid; /// Message digest (hash) type. Loading @@ -31,26 +33,8 @@ impl HashTypeInternals for Type { Type::RIPEMD160 => Nid::RIPEMD160, } } } impl Type { /// Returns the length of the message digest. #[inline] pub fn md_len(&self) -> usize { match *self { Type::MD5 => 16, Type::SHA1 => 20, Type::SHA224 => 28, Type::SHA256 => 32, Type::SHA384 => 48, Type::SHA512 => 64, Type::RIPEMD160 => 20, } } /// Internal interface subject to removal. #[inline] pub fn evp_md(&self) -> *const ffi::EVP_MD { fn evp_md(&self) -> *const ffi::EVP_MD { unsafe { match *self { Type::MD5 => ffi::EVP_md5(), Loading Loading @@ -84,21 +68,20 @@ use self::State::*; /// use openssl::crypto::hash::{hash, Type}; /// let data = b"\x42\xF4\x97\xE0"; /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2"; /// let res = hash(Type::MD5, data); /// let res = hash(Type::MD5, data).unwrap(); /// assert_eq!(res, spec); /// ``` /// /// Use the `Write` trait to supply the input in chunks. /// /// ``` /// use std::io::prelude::*; /// use openssl::crypto::hash::{Hasher, Type}; /// let data = [b"\x42\xF4", b"\x97\xE0"]; /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2"; /// let mut h = Hasher::new(Type::MD5); /// h.write_all(data[0]); /// h.write_all(data[1]); /// let res = h.finish(); /// let mut h = Hasher::new(Type::MD5).unwrap(); /// h.update(data[0]).unwrap(); /// h.update(data[1]).unwrap(); /// let res = h.finish().unwrap(); /// assert_eq!(res, spec); /// ``` /// Loading @@ -116,14 +99,10 @@ pub struct Hasher { impl Hasher { /// Creates a new `Hasher` with the specified hash type. pub fn new(ty: Type) -> Hasher { pub fn new(ty: Type) -> Result<Hasher, ErrorStack> { ffi::init(); let ctx = unsafe { let r = ffi::EVP_MD_CTX_create(); assert!(!r.is_null()); r }; let ctx = unsafe { try_ssl_null!(ffi::EVP_MD_CTX_create()) }; let md = ty.evp_md(); let mut h = Hasher { Loading @@ -132,67 +111,60 @@ impl Hasher { type_: ty, state: Finalized, }; h.init(); h try!(h.init()); Ok(h) } #[inline] fn init(&mut self) { fn init(&mut self) -> Result<(), ErrorStack> { match self.state { Reset => return, Reset => return Ok(()), Updated => { self.finalize(); try!(self.finish()); } Finalized => (), } unsafe { let r = ffi::EVP_DigestInit_ex(self.ctx, self.md, 0 as *const _); assert_eq!(r, 1); } unsafe { try_ssl!(ffi::EVP_DigestInit_ex(self.ctx, self.md, 0 as *const _)); } self.state = Reset; Ok(()) } #[inline] fn update(&mut self, data: &[u8]) { /// Feeds data into the hasher. pub fn update(&mut self, mut data: &[u8]) -> Result<(), ErrorStack> { if self.state == Finalized { self.init(); try!(self.init()); } while !data.is_empty() { let len = cmp::min(data.len(), c_uint::max_value() as usize); unsafe { let r = ffi::EVP_DigestUpdate(self.ctx, data.as_ptr(), data.len() as c_uint); assert_eq!(r, 1); try_ssl!(ffi::EVP_DigestUpdate(self.ctx, data.as_ptr(), len as c_uint)); } data = &data[len..]; } self.state = Updated; Ok(()) } #[inline] fn finalize(&mut self) -> Vec<u8> { /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. pub fn finish(&mut self) -> Result<Vec<u8>, ErrorStack> { if self.state == Finalized { self.init(); try!(self.init()); } let md_len = self.type_.md_len(); let mut res: Vec<u8> = repeat(0).take(md_len).collect(); unsafe { let mut len = 0; let r = ffi::EVP_DigestFinal_ex(self.ctx, res.as_mut_ptr(), &mut len); let mut len = ffi::EVP_MAX_MD_SIZE; let mut res = vec![0; len as usize]; try_ssl!(ffi::EVP_DigestFinal_ex(self.ctx, res.as_mut_ptr(), &mut len)); res.truncate(len as usize); self.state = Finalized; assert_eq!(len as usize, md_len); assert_eq!(r, 1); } res Ok(res) } /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. #[inline] pub fn finish(&mut self) -> Vec<u8> { self.finalize() } } impl Write for Hasher { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.update(buf); try!(self.update(buf)); Ok(buf.len()) } Loading Loading @@ -223,9 +195,7 @@ impl Drop for Hasher { fn drop(&mut self) { unsafe { if self.state != Finalized { let mut buf: Vec<u8> = repeat(0).take(self.type_.md_len()).collect(); let mut len = 0; ffi::EVP_DigestFinal_ex(self.ctx, buf.as_mut_ptr(), &mut len); drop(self.finish()); } ffi::EVP_MD_CTX_destroy(self.ctx); } Loading @@ -233,9 +203,9 @@ impl Drop for Hasher { } /// Computes the hash of the `data` with the hash `t`. pub fn hash(t: Type, data: &[u8]) -> Vec<u8> { let mut h = Hasher::new(t); let _ = h.write_all(data); pub fn hash(t: Type, data: &[u8]) -> Result<Vec<u8>, ErrorStack> { let mut h = try!(Hasher::new(t)); try!(h.update(data)); h.finish() } Loading @@ -246,13 +216,13 @@ mod tests { use std::io::prelude::*; fn hash_test(hashtype: Type, hashtest: &(&str, &str)) { let res = hash(hashtype, &*hashtest.0.from_hex().unwrap()); let res = hash(hashtype, &*hashtest.0.from_hex().unwrap()).unwrap(); assert_eq!(res.to_hex(), hashtest.1); } fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) { let _ = h.write_all(&*hashtest.0.from_hex().unwrap()); let res = h.finish(); let _ = h.write_all(&*hashtest.0.from_hex().unwrap()).unwrap(); let res = h.finish().unwrap(); assert_eq!(res.to_hex(), hashtest.1); } Loading Loading @@ -294,7 +264,7 @@ mod tests { #[test] fn test_md5_recycle() { let mut h = Hasher::new(Type::MD5); let mut h = Hasher::new(Type::MD5).unwrap(); for test in md5_tests.iter() { hash_recycle_test(&mut h, test); } Loading @@ -302,11 +272,11 @@ mod tests { #[test] fn test_finish_twice() { let mut h = Hasher::new(Type::MD5); let _ = h.write_all(&*md5_tests[6].0.from_hex().unwrap()); let _ = h.finish(); let res = h.finish(); let null = hash(Type::MD5, &[]); let mut h = Hasher::new(Type::MD5).unwrap(); h.write_all(&*md5_tests[6].0.from_hex().unwrap()).unwrap(); h.finish().unwrap(); let res = h.finish().unwrap(); let null = hash(Type::MD5, &[]).unwrap(); assert_eq!(res, null); } Loading @@ -316,26 +286,26 @@ mod tests { let inp = md5_tests[i].0.from_hex().unwrap(); assert!(inp.len() > 2); let p = inp.len() / 2; let h0 = Hasher::new(Type::MD5); let h0 = Hasher::new(Type::MD5).unwrap(); println!("Clone a new hasher"); let mut h1 = h0.clone(); let _ = h1.write_all(&inp[..p]); h1.write_all(&inp[..p]).unwrap(); { println!("Clone an updated hasher"); let mut h2 = h1.clone(); let _ = h2.write_all(&inp[p..]); let res = h2.finish(); h2.write_all(&inp[p..]).unwrap(); let res = h2.finish().unwrap(); assert_eq!(res.to_hex(), md5_tests[i].1); } let _ = h1.write_all(&inp[p..]); let res = h1.finish(); h1.write_all(&inp[p..]).unwrap(); let res = h1.finish().unwrap(); assert_eq!(res.to_hex(), md5_tests[i].1); println!("Clone a finished hasher"); let mut h3 = h1.clone(); let _ = h3.write_all(&*md5_tests[i + 1].0.from_hex().unwrap()); let res = h3.finish(); h3.write_all(&*md5_tests[i + 1].0.from_hex().unwrap()).unwrap(); let res = h3.finish().unwrap(); assert_eq!(res.to_hex(), md5_tests[i + 1].1); } Loading
openssl/src/crypto/hmac.rs +72 −80 Original line number Diff line number Diff line Loading @@ -14,14 +14,16 @@ // use libc::{c_int, c_uint}; use std::iter::repeat; use std::io; use std::io::prelude::*; use crypto::hash::Type; use std::cmp; use ffi; use ffi_extras; use HashTypeInternals; use crypto::hash::Type; use error::ErrorStack; #[derive(PartialEq, Copy, Clone)] enum State { Reset, Loading @@ -43,23 +45,22 @@ use self::State::*; /// let key = b"Jefe"; /// let data = b"what do ya want for nothing?"; /// let spec = b"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38"; /// let res = hmac(Type::MD5, key, data); /// let res = hmac(Type::MD5, key, data).unwrap(); /// assert_eq!(res, spec); /// ``` /// /// Use the `Write` trait to supply the input in chunks. /// /// ``` /// use std::io::prelude::*; /// use openssl::crypto::hash::Type; /// use openssl::crypto::hmac::HMAC; /// let key = b"Jefe"; /// let data: &[&[u8]] = &[b"what do ya ", b"want for nothing?"]; /// let spec = b"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38"; /// let mut h = HMAC::new(Type::MD5, &*key); /// h.write_all(data[0]); /// h.write_all(data[1]); /// let res = h.finish(); /// let mut h = HMAC::new(Type::MD5, &*key).unwrap(); /// h.update(data[0]).unwrap(); /// h.update(data[1]).unwrap(); /// let res = h.finish().unwrap(); /// assert_eq!(res, spec); /// ``` pub struct HMAC { Loading @@ -70,7 +71,7 @@ pub struct HMAC { impl HMAC { /// Creates a new `HMAC` with the specified hash type using the `key`. pub fn new(ty: Type, key: &[u8]) -> HMAC { pub fn new(ty: Type, key: &[u8]) -> Result<HMAC, ErrorStack> { ffi::init(); let ctx = unsafe { Loading @@ -85,86 +86,79 @@ impl HMAC { type_: ty, state: Finalized, }; h.init_once(md, key); h try!(h.init_once(md, key)); Ok(h) } #[inline] fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) { fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) -> Result<(), ErrorStack> { unsafe { let r = ffi_extras::HMAC_Init_ex(&mut self.ctx, try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, key.as_ptr(), key.len() as c_int, md, 0 as *const _); assert_eq!(r, 1); 0 as *const _)); } self.state = Reset; Ok(()) } #[inline] fn init(&mut self) { fn init(&mut self) -> Result<(), ErrorStack> { match self.state { Reset => return, Reset => return Ok(()), Updated => { self.finalize(); try!(self.finish()); } Finalized => (), } // If the key and/or md is not supplied it's reused from the last time // avoiding redundant initializations unsafe { let r = ffi_extras::HMAC_Init_ex(&mut self.ctx, try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, 0 as *const _, 0, 0 as *const _, 0 as *const _); assert_eq!(r, 1); 0 as *const _)); } self.state = Reset; Ok(()) } #[inline] fn update(&mut self, data: &[u8]) { pub fn update(&mut self, mut data: &[u8]) -> Result<(), ErrorStack> { if self.state == Finalized { self.init(); try!(self.init()); } while !data.is_empty() { let len = cmp::min(data.len(), c_uint::max_value() as usize); unsafe { let r = ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), data.len() as c_uint); assert_eq!(r, 1); try_ssl!(ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), len as c_uint)); } data = &data[len..]; } self.state = Updated; Ok(()) } #[inline] fn finalize(&mut self) -> Vec<u8> { /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. pub fn finish(&mut self) -> Result<Vec<u8>, ErrorStack> { if self.state == Finalized { self.init(); try!(self.init()); } let md_len = self.type_.md_len(); let mut res: Vec<u8> = repeat(0).take(md_len).collect(); unsafe { let mut len = 0; let r = ffi_extras::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len); let mut len = ffi::EVP_MAX_MD_SIZE; let mut res = vec![0; len as usize]; try_ssl!(ffi_extras::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len)); res.truncate(len as usize); self.state = Finalized; assert_eq!(len as usize, md_len); assert_eq!(r, 1); } res Ok(res) } /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. #[inline] pub fn finish(&mut self) -> Vec<u8> { self.finalize() } } impl Write for HMAC { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.update(buf); try!(self.update(buf)); Ok(buf.len()) } Loading Loading @@ -193,9 +187,7 @@ impl Drop for HMAC { fn drop(&mut self) { unsafe { if self.state != Finalized { let mut buf: Vec<u8> = repeat(0).take(self.type_.md_len()).collect(); let mut len = 0; ffi_extras::HMAC_Final(&mut self.ctx, buf.as_mut_ptr(), &mut len); drop(self.finish()); } ffi::HMAC_CTX_cleanup(&mut self.ctx); } Loading @@ -203,9 +195,9 @@ impl Drop for HMAC { } /// Computes the HMAC of the `data` with the hash `t` and `key`. pub fn hmac(t: Type, key: &[u8], data: &[u8]) -> Vec<u8> { let mut h = HMAC::new(t, key); let _ = h.write_all(data); pub fn hmac(t: Type, key: &[u8], data: &[u8]) -> Result<Vec<u8>, ErrorStack> { let mut h = try!(HMAC::new(t, key)); try!(h.update(data)); h.finish() } Loading @@ -220,14 +212,14 @@ mod tests { fn test_hmac(ty: Type, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) { for &(ref key, ref data, ref res) in tests.iter() { assert_eq!(hmac(ty, &**key, &**data), *res); assert_eq!(hmac(ty, &**key, &**data).unwrap(), *res); } } fn test_hmac_recycle(h: &mut HMAC, test: &(Vec<u8>, Vec<u8>, Vec<u8>)) { let &(_, ref data, ref res) = test; let _ = h.write_all(&**data); assert_eq!(h.finish(), *res); h.write_all(&**data).unwrap(); assert_eq!(h.finish().unwrap(), *res); } #[test] Loading Loading @@ -273,7 +265,7 @@ mod tests { .to_vec(), "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; let mut h = HMAC::new(MD5, &*tests[0].0); let mut h = HMAC::new(MD5, &*tests[0].0).unwrap(); for i in 0..100usize { let test = &tests[i % 2]; test_hmac_recycle(&mut h, test); Loading @@ -287,11 +279,11 @@ mod tests { b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd".from_hex().unwrap()); let mut h = HMAC::new(Type::MD5, &*test.0); let _ = h.write_all(&*test.1); let _ = h.finish(); let res = h.finish(); let null = hmac(Type::MD5, &*test.0, &[]); let mut h = HMAC::new(Type::MD5, &*test.0).unwrap(); h.write_all(&*test.1).unwrap(); h.finish().unwrap(); let res = h.finish().unwrap(); let null = hmac(Type::MD5, &*test.0, &[]).unwrap(); assert_eq!(res, null); } Loading @@ -307,26 +299,26 @@ mod tests { .to_vec(), "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; let p = tests[0].0.len() / 2; let h0 = HMAC::new(Type::MD5, &*tests[0].0); let h0 = HMAC::new(Type::MD5, &*tests[0].0).unwrap(); println!("Clone a new hmac"); let mut h1 = h0.clone(); let _ = h1.write_all(&tests[0].1[..p]); h1.write_all(&tests[0].1[..p]).unwrap(); { println!("Clone an updated hmac"); let mut h2 = h1.clone(); let _ = h2.write_all(&tests[0].1[p..]); let res = h2.finish(); h2.write_all(&tests[0].1[p..]).unwrap(); let res = h2.finish().unwrap(); assert_eq!(res, tests[0].2); } let _ = h1.write_all(&tests[0].1[p..]); let res = h1.finish(); h1.write_all(&tests[0].1[p..]).unwrap(); let res = h1.finish().unwrap(); assert_eq!(res, tests[0].2); println!("Clone a finished hmac"); let mut h3 = h1.clone(); let _ = h3.write_all(&*tests[1].1); let res = h3.finish(); h3.write_all(&*tests[1].1).unwrap(); let res = h3.finish().unwrap(); assert_eq!(res, tests[1].2); } Loading Loading @@ -373,7 +365,7 @@ mod tests { .to_vec(), "e8e99d0f45237d786d6bbaa7965c7808bbff1a91".from_hex().unwrap())]; let mut h = HMAC::new(SHA1, &*tests[0].0); let mut h = HMAC::new(SHA1, &*tests[0].0).unwrap(); for i in 0..100usize { let test = &tests[i % 2]; test_hmac_recycle(&mut h, test); Loading @@ -399,11 +391,11 @@ mod tests { .to_vec())]; for (&(ref key, ref data), res) in tests.iter().zip(results.iter()) { assert_eq!(hmac(ty, &**key, &**data), *res); assert_eq!(hmac(ty, &**key, &**data).unwrap(), *res); } // recycle test let mut h = HMAC::new(ty, &*tests[5].0); let mut h = HMAC::new(ty, &*tests[5].0).unwrap(); for i in 0..100usize { let test = &tests[4 + i % 2]; let tup = (test.0.clone(), test.1.clone(), results[4 + i % 2].clone()); Loading
openssl/src/crypto/mod.rs +0 −6 Original line number Diff line number Diff line Loading @@ -14,8 +14,6 @@ // limitations under the License. // use nid::Nid; pub mod hash; pub mod hmac; pub mod pkcs5; Loading @@ -28,7 +26,3 @@ pub mod dsa; mod util; mod symm_internal; trait HashTypeInternals { fn as_nid(&self) -> Nid; }