aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/crypto
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2015-08-31 19:11:10 -0700
committerSteven Fackler <[email protected]>2015-08-31 19:11:10 -0700
commitabde5382c92c342f4971a6edd1d2628be1b2bd0f (patch)
treeae911e33366468a0a06cefc1a3f2c468e2fec512 /openssl/src/crypto
parentMerge branch 'release-v0.6.4' into release (diff)
parentRelease v0.6.5 (diff)
downloadrust-openssl-0.6.5.tar.xz
rust-openssl-0.6.5.zip
Merge branch 'release-v0.6.5' into releasev0.6.5
Diffstat (limited to 'openssl/src/crypto')
-rw-r--r--openssl/src/crypto/mod.rs2
-rw-r--r--openssl/src/crypto/pkcs5.rs109
-rw-r--r--openssl/src/crypto/pkey.rs32
-rw-r--r--openssl/src/crypto/symm.rs43
-rw-r--r--openssl/src/crypto/symm_internal.rs26
5 files changed, 182 insertions, 30 deletions
diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs
index e695de33..a33c5eb8 100644
--- a/openssl/src/crypto/mod.rs
+++ b/openssl/src/crypto/mod.rs
@@ -22,3 +22,5 @@ pub mod pkey;
pub mod rand;
pub mod symm;
pub mod memcmp;
+
+mod symm_internal; \ No newline at end of file
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
+ }
+ );
+ }
}
diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs
index 1474e53c..48308381 100644
--- a/openssl/src/crypto/pkey.rs
+++ b/openssl/src/crypto/pkey.rs
@@ -182,6 +182,17 @@ impl PKey {
writer.write_all(&buf).map_err(StreamError)
}
+ /// Stores public key as a PEM
+ pub fn write_pub_pem<W: Write>(&self, writer: &mut W/*, password: Option<String>*/) -> Result<(), SslError> {
+ let mut mem_bio = try!(MemBio::new());
+ unsafe {
+ try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.get_handle(), self.evp))
+ }
+ let mut buf = vec![];
+ try!(mem_bio.read_to_end(&mut buf).map_err(StreamError));
+ writer.write_all(&buf).map_err(StreamError)
+ }
+
/**
* Returns the size of the public key modulus.
*/
@@ -500,4 +511,25 @@ mod tests {
assert!(!k0.public_eq(&p1));
assert!(!p0.public_eq(&k1));
}
+
+ #[test]
+ fn test_pem() {
+ let key_path = Path::new("test/key.pem");
+ let mut file = File::open(&key_path)
+ .ok()
+ .expect("Failed to open `test/key.pem`");
+
+ let key = super::PKey::private_key_from_pem(&mut file).unwrap();
+
+ let mut priv_key = Vec::new();
+ let mut pub_key = Vec::new();
+
+ key.write_pem(&mut priv_key).unwrap();
+ key.write_pub_pem(&mut pub_key).unwrap();
+
+ // As a super-simple verification, just check that the buffers contain
+ // the `PRIVATE KEY` or `PUBLIC KEY` strings.
+ assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY"));
+ assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY"));
+ }
}
diff --git a/openssl/src/crypto/symm.rs b/openssl/src/crypto/symm.rs
index 82c668ba..226b2cbf 100644
--- a/openssl/src/crypto/symm.rs
+++ b/openssl/src/crypto/symm.rs
@@ -2,6 +2,7 @@ use std::iter::repeat;
use std::convert::AsRef;
use libc::{c_int};
+use crypto::symm_internal::evpc;
use ffi;
#[derive(Copy, Clone)]
@@ -18,7 +19,8 @@ pub enum Type {
/// Requires the `aes_xts` feature
#[cfg(feature = "aes_xts")]
AES_128_XTS,
- // AES_128_CTR,
+ #[cfg(feature = "aes_ctr")]
+ AES_128_CTR,
//AES_128_GCM,
AES_256_ECB,
@@ -26,33 +28,13 @@ pub enum Type {
/// Requires the `aes_xts` feature
#[cfg(feature = "aes_xts")]
AES_256_XTS,
- // AES_256_CTR,
+ #[cfg(feature = "aes_ctr")]
+ AES_256_CTR,
//AES_256_GCM,
RC4_128,
}
-fn evpc(t: Type) -> (*const ffi::EVP_CIPHER, u32, u32) {
- unsafe {
- match t {
- Type::AES_128_ECB => (ffi::EVP_aes_128_ecb(), 16, 16),
- Type::AES_128_CBC => (ffi::EVP_aes_128_cbc(), 16, 16),
- #[cfg(feature = "aes_xts")]
- Type::AES_128_XTS => (ffi::EVP_aes_128_xts(), 32, 16),
- // AES_128_CTR => (EVP_aes_128_ctr(), 16, 0),
- //AES_128_GCM => (EVP_aes_128_gcm(), 16, 16),
-
- Type::AES_256_ECB => (ffi::EVP_aes_256_ecb(), 32, 16),
- Type::AES_256_CBC => (ffi::EVP_aes_256_cbc(), 32, 16),
- #[cfg(feature = "aes_xts")]
- Type::AES_256_XTS => (ffi::EVP_aes_256_xts(), 64, 16),
- // AES_256_CTR => (EVP_aes_256_ctr(), 32, 0),
- //AES_256_GCM => (EVP_aes_256_gcm(), 32, 16),
-
- Type::RC4_128 => (ffi::EVP_rc4(), 16, 0),
- }
- }
-}
/// Represents a symmetric cipher context.
pub struct Crypter {
@@ -288,16 +270,17 @@ mod tests {
cipher_test(super::Type::AES_256_XTS, pt, ct, key, iv);
}
- /*#[test]
+ #[test]
+ #[cfg(feature = "aes_ctr")]
fn test_aes128_ctr() {
- let pt = ~"6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710";
- let ct = ~"874D6191B620E3261BEF6864990DB6CE9806F66B7970FDFF8617187BB9FFFDFF5AE4DF3EDBD5D35E5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE";
- let key = ~"2B7E151628AED2A6ABF7158809CF4F3C";
- let iv = ~"F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF";
+ let pt = "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710";
+ let ct = "874D6191B620E3261BEF6864990DB6CE9806F66B7970FDFF8617187BB9FFFDFF5AE4DF3EDBD5D35E5B4F09020DB03EAB1E031DDA2FBE03D1792170A0F3009CEE";
+ let key = "2B7E151628AED2A6ABF7158809CF4F3C";
+ let iv = "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF";
- cipher_test(super::AES_128_CTR, pt, ct, key, iv);
- }*/
+ cipher_test(super::Type::AES_128_CTR, pt, ct, key, iv);
+ }
/*#[test]
fn test_aes128_gcm() {
diff --git a/openssl/src/crypto/symm_internal.rs b/openssl/src/crypto/symm_internal.rs
new file mode 100644
index 00000000..c42efb79
--- /dev/null
+++ b/openssl/src/crypto/symm_internal.rs
@@ -0,0 +1,26 @@
+use crypto::symm;
+use ffi;
+
+pub fn evpc(t: symm::Type) -> (*const ffi::EVP_CIPHER, u32, u32) {
+ unsafe {
+ match t {
+ symm::Type::AES_128_ECB => (ffi::EVP_aes_128_ecb(), 16, 16),
+ symm::Type::AES_128_CBC => (ffi::EVP_aes_128_cbc(), 16, 16),
+ #[cfg(feature = "aes_xts")]
+ symm::Type::AES_128_XTS => (ffi::EVP_aes_128_xts(), 32, 16),
+ #[cfg(feature = "aes_ctr")]
+ symm::Type::AES_128_CTR => (ffi::EVP_aes_128_ctr(), 16, 0),
+ //AES_128_GCM => (EVP_aes_128_gcm(), 16, 16),
+
+ symm::Type::AES_256_ECB => (ffi::EVP_aes_256_ecb(), 32, 16),
+ symm::Type::AES_256_CBC => (ffi::EVP_aes_256_cbc(), 32, 16),
+ #[cfg(feature = "aes_xts")]
+ symm::Type::AES_256_XTS => (ffi::EVP_aes_256_xts(), 64, 16),
+ #[cfg(feature = "aes_ctr")]
+ symm::Type::AES_256_CTR => (ffi::EVP_aes_256_ctr(), 32, 0),
+ //AES_256_GCM => (EVP_aes_256_gcm(), 32, 16),
+
+ symm::Type::RC4_128 => (ffi::EVP_rc4(), 16, 0),
+ }
+ }
+} \ No newline at end of file