parent
05089bacb3
commit
7ca5ccf064
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<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();
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<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 {
|
||||
|
|
@ -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<u8> {
|
||||
if self.state == Finalized {
|
||||
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);
|
||||
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<u8> {
|
||||
self.finalize()
|
||||
pub fn finish(&mut self) -> Result<Vec<u8>, 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<usize> {
|
||||
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<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);
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<HMAC, ErrorStack> {
|
||||
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<u8> {
|
||||
if self.state == Finalized {
|
||||
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);
|
||||
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<u8> {
|
||||
self.finalize()
|
||||
pub fn finish(&mut self) -> Result<Vec<u8>, 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<usize> {
|
||||
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<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);
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
@ -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]
|
||||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<KeyIvPair, ErrorStack> {
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Vec<u8>> {
|
||||
let evp = hash_type.evp_md();
|
||||
let len = hash_type.md_len();
|
||||
let v: Vec<u8> = 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<Vec<u8>, 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue