diff options
Diffstat (limited to 'openssl/src/crypto/pkcs5.rs')
| -rw-r--r-- | openssl/src/crypto/pkcs5.rs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/openssl/src/crypto/pkcs5.rs b/openssl/src/crypto/pkcs5.rs index b101c3ed..b5f69732 100644 --- a/openssl/src/crypto/pkcs5.rs +++ b/openssl/src/crypto/pkcs5.rs @@ -1,6 +1,69 @@ use libc::c_int; +use std::ptr::null; + +use crypto::symm_internal::evpc; +use crypto::hash; +use crypto::symm; use ffi; +#[derive(Clone, Eq, PartialEq, Hash, Debug)] +pub struct KeyIvPair +{ + pub key: Vec<u8>, + pub iv: Vec<u8> +} + +/// Derives a key and an IV from various parameters. +/// +/// If specified `salt` must be 8 bytes in length. +/// +/// If the total key and IV length is less than 16 bytes and MD5 is used then +/// the algorithm is compatible with the key derivation algorithm from PKCS#5 +/// v1.5 or PBKDF1 from PKCS#5 v2.0. +/// +/// 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, + data: &[u8], salt: Option<&[u8]>, + count: u32) -> KeyIvPair { + + unsafe { + + let salt_ptr = match salt { + Some(salt) => { + assert_eq!(salt.len(), ffi::PKCS5_SALT_LEN as usize); + salt.as_ptr() + }, + None => null() + }; + + ffi::init(); + + let (evp, keylen, _) = 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 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); + + KeyIvPair { + key: key, + iv: iv + } + } +} + /// Derives a key from a password and salt using the PBKDF2-HMAC-SHA1 algorithm. pub fn pbkdf2_hmac_sha1(pass: &str, salt: &[u8], iter: usize, keylen: usize) -> Vec<u8> { unsafe { @@ -27,6 +90,9 @@ pub fn pbkdf2_hmac_sha1(pass: &str, salt: &[u8], iter: usize, keylen: usize) -> #[cfg(test)] mod tests { + use crypto::hash; + use crypto::symm; + // Test vectors from // http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-06 #[test] @@ -116,4 +182,47 @@ mod tests { ) ); } + + #[test] + fn test_evp_bytes_to_key_pbkdf1_compatible() { + let salt = [ + 16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8 + ]; + + let data = [ + 143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, + 241_u8, 242_u8, 31_u8, 154_u8, 56_u8, 198_u8, 145_u8, 192_u8, 64_u8, + 2_u8, 245_u8, 167_u8, 220_u8, 55_u8, 119_u8, 233_u8, 136_u8, 139_u8, + 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, 65_u8, 207_u8 + ]; + + + + let expected_key = vec![ + 249_u8, 115_u8, 114_u8, 97_u8, 32_u8, 213_u8, 165_u8, 146_u8, 58_u8, + 87_u8, 234_u8, 3_u8, 43_u8, 250_u8, 97_u8, 114_u8, 26_u8, 98_u8, + 245_u8, 246_u8, 238_u8, 177_u8, 229_u8, 161_u8, 183_u8, 224_u8, + 174_u8, 3_u8, 6_u8, 244_u8, 236_u8, 255_u8 + ]; + let expected_iv = vec![ + 4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, + 69_u8, 98_u8, 107_u8, 208_u8, 14_u8, 236_u8, 60_u8, 0_u8, 0_u8, + 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, + 0_u8, 0_u8, 0_u8 + ]; + + assert_eq!( + super::evp_bytes_to_key_pbkdf1_compatible( + symm::Type::AES_256_CBC, + hash::Type::SHA1, + &data, + Some(&salt), + 1 + ), + super::KeyIvPair { + key: expected_key, + iv: expected_iv + } + ); + } } |