Commit c171be55 authored by Steven Fackler's avatar Steven Fackler
Browse files

De-enumify message digests

parent 6609a816
Loading
Loading
Loading
Loading
+61 −51
Original line number Diff line number Diff line
@@ -8,47 +8,56 @@ use ffi::{EVP_MD_CTX_new, EVP_MD_CTX_free};
#[cfg(any(ossl101, ossl102))]
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};

use HashTypeInternals;
use error::ErrorStack;
use nid::Nid;

/// Message digest (hash) type.
#[derive(Copy, Clone)]
pub enum Type {
    MD5,
    SHA1,
    SHA224,
    SHA256,
    SHA384,
    SHA512,
    RIPEMD160,
}

impl HashTypeInternals for Type {
    fn as_nid(&self) -> Nid {
        match *self {
            Type::MD5 => Nid::MD5,
            Type::SHA1 => Nid::SHA1,
            Type::SHA224 => Nid::SHA224,
            Type::SHA256 => Nid::SHA256,
            Type::SHA384 => Nid::SHA384,
            Type::SHA512 => Nid::SHA512,
            Type::RIPEMD160 => Nid::RIPEMD160,
        }
    }

    fn evp_md(&self) -> *const ffi::EVP_MD {
pub struct MessageDigest(*const ffi::EVP_MD);

impl MessageDigest {
    pub fn md5() -> MessageDigest {
        unsafe {
            MessageDigest(ffi::EVP_md5())
        }
    }

    pub fn sha1() -> MessageDigest {
        unsafe {
            MessageDigest(ffi::EVP_sha1())
        }
    }

    pub fn sha224() -> MessageDigest {
        unsafe {
            MessageDigest(ffi::EVP_sha224())
        }
    }

    pub fn sha256() -> MessageDigest {
        unsafe {
            MessageDigest(ffi::EVP_sha256())
        }
    }

    pub fn sha384() -> MessageDigest {
        unsafe {
            MessageDigest(ffi::EVP_sha384())
        }
    }

    pub fn sha512() -> MessageDigest {
        unsafe {
            match *self {
                Type::MD5 => ffi::EVP_md5(),
                Type::SHA1 => ffi::EVP_sha1(),
                Type::SHA224 => ffi::EVP_sha224(),
                Type::SHA256 => ffi::EVP_sha256(),
                Type::SHA384 => ffi::EVP_sha384(),
                Type::SHA512 => ffi::EVP_sha512(),
                Type::RIPEMD160 => ffi::EVP_ripemd160(),
            MessageDigest(ffi::EVP_sha512())
        }
    }

    pub fn ripemd160() -> MessageDigest {
        unsafe {
            MessageDigest(ffi::EVP_ripemd160())
        }
    }

    pub fn as_ptr(&self) -> *const ffi::EVP_MD {
        self.0
    }
}

@@ -68,20 +77,22 @@ use self::State::*;
/// Calculate a hash in one go.
///
/// ```
/// use openssl::crypto::hash::{hash, Type};
/// use openssl::crypto::hash::{hash, MessageDigest};
///
/// 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).unwrap();
/// let res = hash(MessageDigest::md5(), data).unwrap();
/// assert_eq!(res, spec);
/// ```
///
/// Use the `Write` trait to supply the input in chunks.
///
/// ```
/// use openssl::crypto::hash::{Hasher, Type};
/// use openssl::crypto::hash::{Hasher, MessageDigest};
///
/// 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).unwrap();
/// let mut h = Hasher::new(MessageDigest::md5()).unwrap();
/// h.update(data[0]).unwrap();
/// h.update(data[1]).unwrap();
/// let res = h.finish().unwrap();
@@ -96,21 +107,20 @@ use self::State::*;
pub struct Hasher {
    ctx: *mut ffi::EVP_MD_CTX,
    md: *const ffi::EVP_MD,
    type_: Type,
    type_: MessageDigest,
    state: State,
}

impl Hasher {
    /// Creates a new `Hasher` with the specified hash type.
    pub fn new(ty: Type) -> Result<Hasher, ErrorStack> {
    pub fn new(ty: MessageDigest) -> Result<Hasher, ErrorStack> {
        ffi::init();

        let ctx = unsafe { try_ssl_null!(EVP_MD_CTX_new()) };
        let md = ty.evp_md();

        let mut h = Hasher {
            ctx: ctx,
            md: md,
            md: ty.as_ptr(),
            type_: ty,
            state: Finalized,
        };
@@ -204,7 +214,7 @@ impl Drop for Hasher {
}

/// Computes the hash of the `data` with the hash `t`.
pub fn hash(t: Type, data: &[u8]) -> Result<Vec<u8>, ErrorStack> {
pub fn hash(t: MessageDigest, data: &[u8]) -> Result<Vec<u8>, ErrorStack> {
    let mut h = try!(Hasher::new(t));
    try!(h.update(data));
    h.finish()
@@ -213,10 +223,10 @@ pub fn hash(t: Type, data: &[u8]) -> Result<Vec<u8>, ErrorStack> {
#[cfg(test)]
mod tests {
    use serialize::hex::{FromHex, ToHex};
    use super::{hash, Hasher, Type};
    use super::{hash, Hasher, MessageDigest};
    use std::io::prelude::*;

    fn hash_test(hashtype: Type, hashtest: &(&str, &str)) {
    fn hash_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
        let res = hash(hashtype, &*hashtest.0.from_hex().unwrap()).unwrap();
        assert_eq!(res.to_hex(), hashtest.1);
    }
@@ -259,13 +269,13 @@ mod tests {
    #[test]
    fn test_md5() {
        for test in md5_tests.iter() {
            hash_test(Type::MD5, test);
            hash_test(MessageDigest::md5(), test);
        }
    }

    #[test]
    fn test_md5_recycle() {
        let mut h = Hasher::new(Type::MD5).unwrap();
        let mut h = Hasher::new(MessageDigest::md5()).unwrap();
        for test in md5_tests.iter() {
            hash_recycle_test(&mut h, test);
        }
@@ -273,11 +283,11 @@ mod tests {

    #[test]
    fn test_finish_twice() {
        let mut h = Hasher::new(Type::MD5).unwrap();
        let mut h = Hasher::new(MessageDigest::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();
        let null = hash(MessageDigest::md5(), &[]).unwrap();
        assert_eq!(res, null);
    }

@@ -287,7 +297,7 @@ 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).unwrap();
        let h0 = Hasher::new(MessageDigest::md5()).unwrap();

        println!("Clone a new hasher");
        let mut h1 = h0.clone();
@@ -315,7 +325,7 @@ mod tests {
        let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")];

        for test in tests.iter() {
            hash_test(Type::SHA1, test);
            hash_test(MessageDigest::sha1(), test);
        }
    }

@@ -325,7 +335,7 @@ mod tests {
                      "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")];

        for test in tests.iter() {
            hash_test(Type::SHA256, test);
            hash_test(MessageDigest::sha256(), test);
        }
    }

@@ -334,7 +344,7 @@ mod tests {
        let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];

        for test in tests.iter() {
            hash_test(Type::RIPEMD160, test);
            hash_test(MessageDigest::ripemd160(), test);
        }
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ mod compat {

#[cfg(test)]
mod test {
    use crypto::hash::Type::SHA1;
    use crypto::hash::MessageDigest;
    use serialize::hex::ToHex;

    use super::*;
@@ -108,11 +108,11 @@ mod test {
        let pkcs12 = Pkcs12::from_der(der).unwrap();
        let parsed = pkcs12.parse("mypass").unwrap();

        assert_eq!(parsed.cert.fingerprint(SHA1).unwrap().to_hex(),
        assert_eq!(parsed.cert.fingerprint(MessageDigest::sha1()).unwrap().to_hex(),
                   "59172d9313e84459bcff27f967e79e6e9217e584");

        assert_eq!(parsed.chain.len(), 1);
        assert_eq!(parsed.chain[0].fingerprint(SHA1).unwrap().to_hex(),
        assert_eq!(parsed.chain[0].fingerprint(MessageDigest::sha1()).unwrap().to_hex(),
                   "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875");
    }
}
+12 −13
Original line number Diff line number Diff line
@@ -2,8 +2,7 @@ use libc::c_int;
use std::ptr;
use ffi;

use HashTypeInternals;
use crypto::hash;
use crypto::hash::MessageDigest;
use crypto::symm;
use error::ErrorStack;

@@ -24,7 +23,7 @@ pub struct KeyIvPair {
/// New applications should not use this and instead use `pbkdf2_hmac_sha1` or
/// another more modern key derivation algorithm.
pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type,
                                          message_digest_type: hash::Type,
                                          message_digest_type: MessageDigest,
                                          data: &[u8],
                                          salt: Option<&[u8]>,
                                          count: u32)
@@ -41,7 +40,7 @@ pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type,
        ffi::init();

        let typ = typ.as_ptr();
        let message_digest_type = message_digest_type.evp_md();
        let message_digest_type = message_digest_type.as_ptr();

        let len = ffi::EVP_BytesToKey(typ,
                                      message_digest_type,
@@ -97,7 +96,7 @@ pub fn pbkdf2_hmac_sha1(pass: &[u8],
pub fn pbkdf2_hmac(pass: &[u8],
                   salt: &[u8],
                   iter: usize,
                   hash: hash::Type,
                   hash: MessageDigest,
                   keylen: usize)
                   -> Result<Vec<u8>, ErrorStack> {
    unsafe {
@@ -108,7 +107,7 @@ pub fn pbkdf2_hmac(pass: &[u8],
                                        salt.as_ptr(),
                                        salt.len() as c_int,
                                        iter as c_int,
                                        hash.evp_md(),
                                        hash.as_ptr(),
                                        keylen as c_int,
                                        out.as_mut_ptr()));
        Ok(out)
@@ -117,7 +116,7 @@ pub fn pbkdf2_hmac(pass: &[u8],

#[cfg(test)]
mod tests {
    use crypto::hash;
    use crypto::hash::MessageDigest;
    use crypto::symm;

    // Test vectors from
@@ -162,11 +161,11 @@ mod tests {
    // https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
    #[test]
    fn test_pbkdf2_hmac_sha256() {
        assert_eq!(super::pbkdf2_hmac(b"passwd", b"salt", 1, hash::Type::SHA256, 16).unwrap(),
        assert_eq!(super::pbkdf2_hmac(b"passwd", b"salt", 1, MessageDigest::sha256(), 16).unwrap(),
                   vec![0x55_u8, 0xac_u8, 0x04_u8, 0x6e_u8, 0x56_u8, 0xe3_u8, 0x08_u8, 0x9f_u8,
                        0xec_u8, 0x16_u8, 0x91_u8, 0xc2_u8, 0x25_u8, 0x44_u8, 0xb6_u8, 0x05_u8]);

        assert_eq!(super::pbkdf2_hmac(b"Password", b"NaCl", 80000, hash::Type::SHA256, 16).unwrap(),
        assert_eq!(super::pbkdf2_hmac(b"Password", b"NaCl", 80000, MessageDigest::sha256(), 16).unwrap(),
                   vec![0x4d_u8, 0xdc_u8, 0xd8_u8, 0xf6_u8, 0x0b_u8, 0x98_u8, 0xbe_u8, 0x21_u8,
                        0x83_u8, 0x0c_u8, 0xee_u8, 0x5e_u8, 0xf2_u8, 0x27_u8, 0x01_u8, 0xf9_u8]);
    }
@@ -175,7 +174,7 @@ mod tests {
    // https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
    #[test]
    fn test_pbkdf2_hmac_sha512() {
        assert_eq!(super::pbkdf2_hmac(b"password", b"NaCL", 1, hash::Type::SHA512, 64).unwrap(),
        assert_eq!(super::pbkdf2_hmac(b"password", b"NaCL", 1, MessageDigest::sha512(), 64).unwrap(),
                   vec![0x73_u8, 0xde_u8, 0xcf_u8, 0xa5_u8, 0x8a_u8, 0xa2_u8, 0xe8_u8, 0x4f_u8,
                        0x94_u8, 0x77_u8, 0x1a_u8, 0x75_u8, 0x73_u8, 0x6b_u8, 0xb8_u8, 0x8b_u8,
                        0xd3_u8, 0xc7_u8, 0xb3_u8, 0x82_u8, 0x70_u8, 0xcf_u8, 0xb5_u8, 0x0c_u8,
@@ -185,7 +184,7 @@ mod tests {
                        0x60_u8, 0x60_u8, 0xa0_u8, 0x9f_u8, 0x76_u8, 0x41_u8, 0x5e_u8, 0x9f_u8,
                        0x71_u8, 0xea_u8, 0x47_u8, 0xf9_u8, 0xe9_u8, 0x06_u8, 0x43_u8, 0x06_u8]);

        assert_eq!(super::pbkdf2_hmac(b"pass\0word", b"sa\0lt", 1, hash::Type::SHA512, 64).unwrap(),
        assert_eq!(super::pbkdf2_hmac(b"pass\0word", b"sa\0lt", 1, MessageDigest::sha512(), 64).unwrap(),
                   vec![0x71_u8, 0xa0_u8, 0xec_u8, 0x84_u8, 0x2a_u8, 0xbd_u8, 0x5c_u8, 0x67_u8,
                        0x8b_u8, 0xcf_u8, 0xd1_u8, 0x45_u8, 0xf0_u8, 0x9d_u8, 0x83_u8, 0x52_u8,
                        0x2f_u8, 0x93_u8, 0x36_u8, 0x15_u8, 0x60_u8, 0x56_u8, 0x3c_u8, 0x4d_u8,
@@ -198,7 +197,7 @@ mod tests {
        assert_eq!(super::pbkdf2_hmac(b"passwordPASSWORDpassword",
                                      b"salt\0\0\0",
                                      50,
                                      hash::Type::SHA512,
                                      MessageDigest::sha512(),
                                      64).unwrap(),
                   vec![0x01_u8, 0x68_u8, 0x71_u8, 0xa4_u8, 0xc4_u8, 0xb7_u8, 0x5f_u8, 0x96_u8,
                        0x85_u8, 0x7f_u8, 0xd2_u8, 0xb9_u8, 0xf8_u8, 0xca_u8, 0x28_u8, 0x02_u8,
@@ -230,7 +229,7 @@ mod tests {
                               0_u8, 0_u8, 0_u8];

        assert_eq!(super::evp_bytes_to_key_pbkdf1_compatible(symm::Type::AES_256_CBC,
                                                             hash::Type::SHA1,
                                                             MessageDigest::sha1(),
                                                             &data,
                                                             Some(&salt),
                                                             1).unwrap(),
+21 −22
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@
//! use openssl::crypto::sign::{Signer, Verifier};
//! use openssl::crypto::rsa::RSA;
//! use openssl::crypto::pkey::PKey;
//! use openssl::crypto::hash::Type;
//! use openssl::crypto::hash::MessageDigest;
//!
//! // Generate a keypair
//! let keypair = RSA::generate(2048).unwrap();
@@ -23,13 +23,13 @@
//! let data2 = b"hola, mundo!";
//!
//! // Sign the data
//! let mut signer = Signer::new(Type::SHA256, &keypair).unwrap();
//! let mut signer = Signer::new(MessageDigest::sha256(), &keypair).unwrap();
//! signer.update(data).unwrap();
//! signer.update(data2).unwrap();
//! let signature = signer.finish().unwrap();
//!
//! // Verify the data
//! let mut verifier = Verifier::new(Type::SHA256, &keypair).unwrap();
//! let mut verifier = Verifier::new(MessageDigest::sha256(), &keypair).unwrap();
//! verifier.update(data).unwrap();
//! verifier.update(data2).unwrap();
//! assert!(verifier.finish(&signature).unwrap());
@@ -40,7 +40,7 @@
//! ```rust
//! use openssl::crypto::sign::Signer;
//! use openssl::crypto::pkey::PKey;
//! use openssl::crypto::hash::Type;
//! use openssl::crypto::hash::MessageDigest;
//!
//! // Create a PKey
//! let key = PKey::hmac(b"my secret").unwrap();
@@ -49,7 +49,7 @@
//! let data2 = b"hola, mundo!";
//!
//! // Compute the HMAC
//! let mut signer = Signer::new(Type::SHA256, &key).unwrap();
//! let mut signer = Signer::new(MessageDigest::sha256(), &key).unwrap();
//! signer.update(data).unwrap();
//! signer.update(data2).unwrap();
//! let hmac = signer.finish().unwrap();
@@ -59,8 +59,7 @@ use std::io::{self, Write};
use std::marker::PhantomData;
use std::ptr;

use HashTypeInternals;
use crypto::hash::Type;
use crypto::hash::MessageDigest;
use crypto::pkey::PKey;
use error::ErrorStack;

@@ -80,14 +79,14 @@ impl<'a> Drop for Signer<'a> {
}

impl<'a> Signer<'a> {
    pub fn new(type_: Type, pkey: &'a PKey) -> Result<Signer<'a>, ErrorStack> {
    pub fn new(type_: MessageDigest, pkey: &'a PKey) -> Result<Signer<'a>, ErrorStack> {
        unsafe {
            ffi::init();

            let ctx = try_ssl_null!(EVP_MD_CTX_new());
            let r = ffi::EVP_DigestSignInit(ctx,
                                            ptr::null_mut(),
                                            type_.evp_md(),
                                            type_.as_ptr(),
                                            ptr::null_mut(),
                                            pkey.as_ptr());
            if r != 1 {
@@ -142,14 +141,14 @@ impl<'a> Drop for Verifier<'a> {
}

impl<'a> Verifier<'a> {
    pub fn new(type_: Type, pkey: &'a PKey) -> Result<Verifier<'a>, ErrorStack> {
    pub fn new(type_: MessageDigest, pkey: &'a PKey) -> Result<Verifier<'a>, ErrorStack> {
        unsafe {
            ffi::init();

            let ctx = try_ssl_null!(EVP_MD_CTX_new());
            let r = ffi::EVP_DigestVerifyInit(ctx,
                                              ptr::null_mut(),
                                              type_.evp_md(),
                                              type_.as_ptr(),
                                              ptr::null_mut(),
                                              pkey.as_ptr());
            if r != 1 {
@@ -212,7 +211,7 @@ mod test {
    use serialize::hex::FromHex;
    use std::iter;

    use crypto::hash::Type;
    use crypto::hash::MessageDigest;
    use crypto::sign::{Signer, Verifier};
    use crypto::rsa::RSA;
    use crypto::dsa::DSA;
@@ -248,7 +247,7 @@ mod test {
        let private_key = RSA::private_key_from_pem(key).unwrap();
        let pkey = PKey::from_rsa(private_key).unwrap();

        let mut signer = Signer::new(Type::SHA256, &pkey).unwrap();
        let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap();
        signer.update(INPUT).unwrap();
        let result = signer.finish().unwrap();

@@ -261,7 +260,7 @@ mod test {
        let private_key = RSA::private_key_from_pem(key).unwrap();
        let pkey = PKey::from_rsa(private_key).unwrap();

        let mut verifier = Verifier::new(Type::SHA256, &pkey).unwrap();
        let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
        verifier.update(INPUT).unwrap();
        assert!(verifier.finish(SIGNATURE).unwrap());
    }
@@ -272,7 +271,7 @@ mod test {
        let private_key = RSA::private_key_from_pem(key).unwrap();
        let pkey = PKey::from_rsa(private_key).unwrap();

        let mut verifier = Verifier::new(Type::SHA256, &pkey).unwrap();
        let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
        verifier.update(INPUT).unwrap();
        verifier.update(b"foobar").unwrap();
        assert!(!verifier.finish(SIGNATURE).unwrap());
@@ -292,11 +291,11 @@ mod test {
            PKey::from_dsa(DSA::public_key_from_pem(key).unwrap()).unwrap()
        };

        let mut signer = Signer::new(Type::SHA1, &private_key).unwrap();
        let mut signer = Signer::new(MessageDigest::sha1(), &private_key).unwrap();
        signer.update(&input).unwrap();
        let sig = signer.finish().unwrap();

        let mut verifier = Verifier::new(Type::SHA1, &public_key).unwrap();
        let mut verifier = Verifier::new(MessageDigest::sha1(), &public_key).unwrap();
        verifier.update(&input).unwrap();
        assert!(verifier.finish(&sig).unwrap());
    }
@@ -315,12 +314,12 @@ mod test {
            PKey::from_dsa(DSA::public_key_from_pem(key).unwrap()).unwrap()
        };

        let mut signer = Signer::new(Type::SHA1, &private_key).unwrap();
        let mut signer = Signer::new(MessageDigest::sha1(), &private_key).unwrap();
        signer.update(&input).unwrap();
        let mut sig = signer.finish().unwrap();
        sig[0] -= 1;

        let mut verifier = Verifier::new(Type::SHA1, &public_key).unwrap();
        let mut verifier = Verifier::new(MessageDigest::sha1(), &public_key).unwrap();
        verifier.update(&input).unwrap();
        match verifier.finish(&sig) {
            Ok(true) => panic!("unexpected success"),
@@ -328,7 +327,7 @@ mod test {
        }
    }

    fn test_hmac(ty: Type, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) {
    fn test_hmac(ty: MessageDigest, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) {
        for &(ref key, ref data, ref res) in tests.iter() {
            let pkey = PKey::hmac(key).unwrap();
            let mut signer = Signer::new(ty, &pkey).unwrap();
@@ -365,7 +364,7 @@ mod test {
                 .to_vec(),
             "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())];

        test_hmac(Type::MD5, &tests);
        test_hmac(MessageDigest::md5(), &tests);
    }

    #[test]
@@ -396,6 +395,6 @@ mod test {
                 .to_vec(),
             "e8e99d0f45237d786d6bbaa7965c7808bbff1a91".from_hex().unwrap())];

        test_hmac(Type::SHA1, &tests);
        test_hmac(MessageDigest::sha1(), &tests);
    }
}
+0 −7
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@ extern crate tempdir;
#[doc(inline)]
pub use ffi::init;

use nid::Nid;

mod macros;

pub mod asn1;
@@ -30,8 +28,3 @@ 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;
}
Loading