diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 250bb054..6951a7db 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -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; diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs index 84024379..099657da 100644 --- a/openssl/src/crypto/dsa.rs +++ b/openssl/src/crypto/dsa.rs @@ -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}; @@ -249,9 +249,9 @@ mod test { let input: Vec = (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(); @@ -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(); @@ -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(); diff --git a/openssl/src/crypto/hash.rs b/openssl/src/crypto/hash.rs index 69d3a350..207a55f5 100644 --- a/openssl/src/crypto/hash.rs +++ b/openssl/src/crypto/hash.rs @@ -1,10 +1,12 @@ 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. @@ -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(), @@ -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); /// ``` /// @@ -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 { 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 { @@ -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()); } - unsafe { - let r = ffi::EVP_DigestUpdate(self.ctx, data.as_ptr(), data.len() as c_uint); - assert_eq!(r, 1); + while !data.is_empty() { + let len = cmp::min(data.len(), c_uint::max_value() as usize); + unsafe { + try_ssl!(ffi::EVP_DigestUpdate(self.ctx, data.as_ptr(), len as c_uint)); + } + data = &data[len..]; } self.state = Updated; - } - - #[inline] - fn finalize(&mut self) -> Vec { - if self.state == Finalized { - self.init(); - } - let md_len = self.type_.md_len(); - let mut res: Vec = 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); - self.state = Finalized; - assert_eq!(len as usize, md_len); - assert_eq!(r, 1); - } - res + Ok(()) } /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. - #[inline] - pub fn finish(&mut self) -> Vec { - self.finalize() + pub fn finish(&mut self) -> Result, ErrorStack> { + if self.state == Finalized { + try!(self.init()); + } + unsafe { + 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; + Ok(res) + } } } impl Write for Hasher { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { - self.update(buf); + try!(self.update(buf)); Ok(buf.len()) } @@ -223,9 +195,7 @@ impl Drop for Hasher { fn drop(&mut self) { unsafe { if self.state != Finalized { - let mut buf: Vec = 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); } @@ -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 { - let mut h = Hasher::new(t); - let _ = h.write_all(data); +pub fn hash(t: Type, data: &[u8]) -> Result, ErrorStack> { + let mut h = try!(Hasher::new(t)); + try!(h.update(data)); h.finish() } @@ -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); } @@ -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); } @@ -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); } @@ -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); } diff --git a/openssl/src/crypto/hmac.rs b/openssl/src/crypto/hmac.rs index 143c7b75..453511ac 100644 --- a/openssl/src/crypto/hmac.rs +++ b/openssl/src/crypto/hmac.rs @@ -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, @@ -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 { @@ -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 { ffi::init(); let ctx = unsafe { @@ -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, - key.as_ptr(), - key.len() as c_int, - md, - 0 as *const _); - assert_eq!(r, 1); + try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, + key.as_ptr(), + key.len() as c_int, + md, + 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, - 0 as *const _, - 0, - 0 as *const _, - 0 as *const _); - assert_eq!(r, 1); + try_ssl!(ffi_extras::HMAC_Init_ex(&mut self.ctx, + 0 as *const _, + 0, + 0 as *const _, + 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()); } - unsafe { - let r = ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), data.len() as c_uint); - assert_eq!(r, 1); + while !data.is_empty() { + let len = cmp::min(data.len(), c_uint::max_value() as usize); + unsafe { + try_ssl!(ffi_extras::HMAC_Update(&mut self.ctx, data.as_ptr(), len as c_uint)); + } + data = &data[len..]; } self.state = Updated; - } - - #[inline] - fn finalize(&mut self) -> Vec { - if self.state == Finalized { - self.init(); - } - let md_len = self.type_.md_len(); - let mut res: Vec = 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); - self.state = Finalized; - assert_eq!(len as usize, md_len); - assert_eq!(r, 1); - } - res + Ok(()) } /// Returns the hash of the data written since creation or /// the last `finish` and resets the hasher. - #[inline] - pub fn finish(&mut self) -> Vec { - self.finalize() + pub fn finish(&mut self) -> Result, ErrorStack> { + if self.state == Finalized { + try!(self.init()); + } + unsafe { + 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; + Ok(res) + } } } impl Write for HMAC { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { - self.update(buf); + try!(self.update(buf)); Ok(buf.len()) } @@ -193,9 +187,7 @@ impl Drop for HMAC { fn drop(&mut self) { unsafe { if self.state != Finalized { - let mut buf: Vec = 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); } @@ -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 { - let mut h = HMAC::new(t, key); - let _ = h.write_all(data); +pub fn hmac(t: Type, key: &[u8], data: &[u8]) -> Result, ErrorStack> { + let mut h = try!(HMAC::new(t, key)); + try!(h.update(data)); h.finish() } @@ -220,14 +212,14 @@ mod tests { fn test_hmac(ty: Type, tests: &[(Vec, Vec, Vec)]) { 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, Vec, Vec)) { 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] @@ -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); @@ -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); } @@ -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); } @@ -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); @@ -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()); diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs index 5b891ce7..873f9d47 100644 --- a/openssl/src/crypto/mod.rs +++ b/openssl/src/crypto/mod.rs @@ -14,8 +14,6 @@ // limitations under the License. // -use nid::Nid; - pub mod hash; pub mod hmac; pub mod pkcs5; @@ -28,7 +26,3 @@ pub mod dsa; mod util; mod symm_internal; - -trait HashTypeInternals { - fn as_nid(&self) -> Nid; -} diff --git a/openssl/src/crypto/pkcs5.rs b/openssl/src/crypto/pkcs5.rs index 0ba005cc..e23909d1 100644 --- a/openssl/src/crypto/pkcs5.rs +++ b/openssl/src/crypto/pkcs5.rs @@ -1,10 +1,12 @@ use libc::c_int; -use std::ptr::null; +use std::ptr; +use ffi; +use HashTypeInternals; use crypto::symm_internal::evpc; use crypto::hash; use crypto::symm; -use ffi; +use error::ErrorStack; #[derive(Clone, Eq, PartialEq, Hash, Debug)] pub struct KeyIvPair { @@ -27,7 +29,7 @@ pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, data: &[u8], salt: Option<&[u8]>, count: u32) - -> KeyIvPair { + -> Result { unsafe { @@ -36,30 +38,40 @@ pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, assert_eq!(salt.len(), ffi::PKCS5_SALT_LEN as usize); salt.as_ptr() } - None => null(), + None => ptr::null(), }; ffi::init(); - let (evp, keylen, _) = evpc(typ); + let (evp, _, _) = evpc(typ); let message_digest = message_digest_type.evp_md(); - let mut key = vec![0; keylen as usize]; - let mut iv = vec![0; keylen as usize]; + let len = ffi::EVP_BytesToKey(evp, + message_digest, + salt_ptr, + data.as_ptr(), + data.len() as c_int, + count as c_int, + ptr::null_mut(), + ptr::null_mut()); + if len == 0 { + return Err(ErrorStack::get()); + } + let mut key = vec![0; len as usize]; + let mut iv = vec![0; len as usize]; - let ret: c_int = ffi::EVP_BytesToKey(evp, - message_digest, - salt_ptr, - data.as_ptr(), - data.len() as c_int, - count as c_int, - key.as_mut_ptr(), - iv.as_mut_ptr()); - assert!(ret == keylen as c_int); + try_ssl!(ffi::EVP_BytesToKey(evp, + message_digest, + salt_ptr, + data.as_ptr(), + data.len() as c_int, + count as c_int, + key.as_mut_ptr(), + iv.as_mut_ptr())); - KeyIvPair { key: key, iv: iv } + Ok(KeyIvPair { key: key, iv: iv }) } } @@ -257,7 +269,7 @@ mod tests { hash::Type::SHA1, &data, Some(&salt), - 1), + 1).unwrap(), super::KeyIvPair { key: expected_key, iv: expected_iv, diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 9a3e140a..2a928b23 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -4,7 +4,7 @@ use std::mem; use std::ptr; use bio::{MemBio, MemBioSlice}; -use crypto::HashTypeInternals; +use HashTypeInternals; use crypto::hash; use crypto::hash::Type as HashType; use ffi; diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs index 73239731..c9433b10 100644 --- a/openssl/src/crypto/rsa.rs +++ b/openssl/src/crypto/rsa.rs @@ -6,7 +6,7 @@ use libc::{c_int, c_void, c_char}; use bn::{BigNum, BigNumRef}; use bio::{MemBio, MemBioSlice}; use error::ErrorStack; -use crypto::HashTypeInternals; +use HashTypeInternals; use crypto::hash; use crypto::util::{CallbackState, invoke_passwd_cb}; @@ -262,9 +262,9 @@ mod test { let key = include_bytes!("../../test/rsa.pem"); let private_key = RSA::private_key_from_pem(key).unwrap(); - let mut sha = Hasher::new(Type::SHA256); + let mut sha = Hasher::new(Type::SHA256).unwrap(); sha.write_all(&signing_input_rs256()).unwrap(); - let digest = sha.finish(); + let digest = sha.finish().unwrap(); let result = private_key.sign(Type::SHA256, &digest).unwrap(); @@ -276,9 +276,9 @@ mod test { let key = include_bytes!("../../test/rsa.pem.pub"); let public_key = RSA::public_key_from_pem(key).unwrap(); - let mut sha = Hasher::new(Type::SHA256); + let mut sha = Hasher::new(Type::SHA256).unwrap(); sha.write_all(&signing_input_rs256()).unwrap(); - let digest = sha.finish(); + let digest = sha.finish().unwrap(); let result = public_key.verify(Type::SHA256, &digest, &signature_rs256()).unwrap(); diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 4cd76613..8dc73dde 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -14,6 +14,8 @@ extern crate rustc_serialize as serialize; #[cfg(test)] extern crate net2; +use nid::Nid; + mod macros; pub mod asn1; @@ -26,3 +28,8 @@ pub mod nid; pub mod ssl; pub mod version; pub mod x509; + +trait HashTypeInternals { + fn as_nid(&self) -> Nid; + fn evp_md(&self) -> *const ffi::EVP_MD; +} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 82448212..22182d32 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -1,7 +1,5 @@ -use libc::{c_char, c_int, c_long, c_ulong, c_uint, c_void}; -use std::cmp::Ordering; +use libc::{c_char, c_int, c_long, c_ulong, c_void}; use std::ffi::CString; -use std::iter::repeat; use std::mem; use std::ptr; use std::ops::Deref; @@ -11,6 +9,7 @@ use std::slice; use std::collections::HashMap; use std::marker::PhantomData; +use HashTypeInternals; use asn1::Asn1Time; use bio::{MemBio, MemBioSlice}; use crypto::hash; @@ -434,28 +433,14 @@ impl<'a> X509Ref<'a> { } /// Returns certificate fingerprint calculated using provided hash - pub fn fingerprint(&self, hash_type: hash::Type) -> Option> { - let evp = hash_type.evp_md(); - let len = hash_type.md_len(); - let v: Vec = repeat(0).take(len as usize).collect(); - let act_len: c_uint = 0; - let res = unsafe { - ffi::X509_digest(self.0, - evp, - mem::transmute(v.as_ptr()), - mem::transmute(&act_len)) - }; - - match res { - 0 => None, - _ => { - let act_len = act_len as usize; - match len.cmp(&act_len) { - Ordering::Greater => None, - Ordering::Equal => Some(v), - Ordering::Less => panic!("Fingerprint buffer was corrupted!"), - } - } + pub fn fingerprint(&self, hash_type: hash::Type) -> Result, ErrorStack> { + unsafe { + let evp = hash_type.evp_md(); + let mut len = ffi::EVP_MAX_MD_SIZE; + let mut buf = vec![0u8; len as usize]; + try_ssl!(ffi::X509_digest(self.0, evp, buf.as_mut_ptr() as *mut _, &mut len)); + buf.truncate(len as usize); + Ok(buf) } }