From 14a2f5c5e9541d30b825bd7e2dc6961bc11e6200 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 17:23:57 -0700 Subject: [PATCH 01/32] Move X509 extensions to seperate module, implement ToString instead of custom AsStr --- openssl/src/x509/extension.rs | 69 +++++++++++++++++++++++++++++++ openssl/src/x509/mod.rs | 76 +++-------------------------------- 2 files changed, 75 insertions(+), 70 deletions(-) create mode 100644 openssl/src/x509/extension.rs diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs new file mode 100644 index 00000000..b7f5fc52 --- /dev/null +++ b/openssl/src/x509/extension.rs @@ -0,0 +1,69 @@ +use std::fmt; + +#[derive(Clone)] +pub enum Extension { + KeyUsage(Vec), + ExtKeyUsage(Vec), +} + +#[derive(Clone,Copy)] +pub enum KeyUsageOption { + DigitalSignature, + NonRepudiation, + KeyEncipherment, + DataEncipherment, + KeyAgreement, + KeyCertSign, + CRLSign, + EncipherOnly, + DecipherOnly, +} + +impl fmt::Display for KeyUsageOption { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.pad(match self { + &KeyUsageOption::DigitalSignature => "digitalSignature", + &KeyUsageOption::NonRepudiation => "nonRepudiation", + &KeyUsageOption::KeyEncipherment => "keyEncipherment", + &KeyUsageOption::DataEncipherment => "dataEncipherment", + &KeyUsageOption::KeyAgreement => "keyAgreement", + &KeyUsageOption::KeyCertSign => "keyCertSign", + &KeyUsageOption::CRLSign => "cRLSign", + &KeyUsageOption::EncipherOnly => "encipherOnly", + &KeyUsageOption::DecipherOnly => "decipherOnly", + }) + } +} + +#[derive(Clone,Copy)] +pub enum ExtKeyUsageOption { + ServerAuth, + ClientAuth, + CodeSigning, + EmailProtection, + TimeStamping, + MsCodeInd, + MsCodeCom, + MsCtlSign, + MsSgc, + MsEfs, + NsSgc, +} + +impl fmt::Display for ExtKeyUsageOption { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.pad(match self { + &ExtKeyUsageOption::ServerAuth => "serverAuth", + &ExtKeyUsageOption::ClientAuth => "clientAuth", + &ExtKeyUsageOption::CodeSigning => "codeSigning", + &ExtKeyUsageOption::EmailProtection => "emailProtection", + &ExtKeyUsageOption::TimeStamping => "timeStamping", + &ExtKeyUsageOption::MsCodeInd => "msCodeInd", + &ExtKeyUsageOption::MsCodeCom => "msCodeCom", + &ExtKeyUsageOption::MsCtlSign => "msCTLSign", + &ExtKeyUsageOption::MsSgc => "msSGC", + &ExtKeyUsageOption::MsEfs => "msEFS", + &ExtKeyUsageOption::NsSgc =>"nsSGC", + }) + } +} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 5446f125..6292579b 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -20,6 +20,7 @@ use ffi; use ssl::error::{SslError, StreamError}; use nid; +mod extension; #[cfg(test)] mod tests; @@ -98,74 +99,9 @@ impl X509StoreContext { } } -#[doc(hidden)] -trait AsStr<'a> { - fn as_str(&self) -> &'a str; -} - -#[derive(Clone, Copy)] -pub enum KeyUsage { - DigitalSignature, - NonRepudiation, - KeyEncipherment, - DataEncipherment, - KeyAgreement, - KeyCertSign, - CRLSign, - EncipherOnly, - DecipherOnly -} - -impl AsStr<'static> for KeyUsage { - fn as_str(&self) -> &'static str { - match self { - &KeyUsage::DigitalSignature => "digitalSignature", - &KeyUsage::NonRepudiation => "nonRepudiation", - &KeyUsage::KeyEncipherment => "keyEncipherment", - &KeyUsage::DataEncipherment => "dataEncipherment", - &KeyUsage::KeyAgreement => "keyAgreement", - &KeyUsage::KeyCertSign => "keyCertSign", - &KeyUsage::CRLSign => "cRLSign", - &KeyUsage::EncipherOnly => "encipherOnly", - &KeyUsage::DecipherOnly => "decipherOnly" - } - } -} - - -#[derive(Clone, Copy)] -pub enum ExtKeyUsage { - ServerAuth, - ClientAuth, - CodeSigning, - EmailProtection, - TimeStamping, - MsCodeInd, - MsCodeCom, - MsCtlSign, - MsSgc, - MsEfs, - NsSgc -} - -impl AsStr<'static> for ExtKeyUsage { - fn as_str(&self) -> &'static str { - match self { - &ExtKeyUsage::ServerAuth => "serverAuth", - &ExtKeyUsage::ClientAuth => "clientAuth", - &ExtKeyUsage::CodeSigning => "codeSigning", - &ExtKeyUsage::EmailProtection => "emailProtection", - &ExtKeyUsage::TimeStamping => "timeStamping", - &ExtKeyUsage::MsCodeInd => "msCodeInd", - &ExtKeyUsage::MsCodeCom => "msCodeCom", - &ExtKeyUsage::MsCtlSign => "msCTLSign", - &ExtKeyUsage::MsSgc => "msSGC", - &ExtKeyUsage::MsEfs => "msEFS", - &ExtKeyUsage::NsSgc =>"nsSGC" - } - } -} - +// Backwards-compatibility +pub use self::extension::KeyUsageOption as KeyUsage; +pub use self::extension::ExtKeyUsageOption as ExtKeyUsage; // FIXME: a dirty hack as there is no way to // implement ToString for Vec as both are defined @@ -175,11 +111,11 @@ trait ToStr { fn to_str(&self) -> String; } -impl<'a, T: AsStr<'a>> ToStr for Vec { +impl ToStr for Vec { fn to_str(&self) -> String { self.iter().enumerate().fold(String::new(), |mut acc, (idx, v)| { if idx > 0 { acc.push(',') }; - acc.push_str(v.as_str()); + acc.push_str(&v.to_string()); acc }) } From c4e398d39785e20640216ac595355d45a32c8618 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 17:27:44 -0700 Subject: [PATCH 02/32] Turn "dirty hack" into slightly less dirty hack, with potential to become non-dirty --- openssl/src/x509/mod.rs | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 6292579b..864e94c8 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -103,22 +103,14 @@ impl X509StoreContext { pub use self::extension::KeyUsageOption as KeyUsage; pub use self::extension::ExtKeyUsageOption as ExtKeyUsage; -// FIXME: a dirty hack as there is no way to -// implement ToString for Vec as both are defined -// in another crate -#[doc(hidden)] -trait ToStr { - fn to_str(&self) -> String; -} - -impl ToStr for Vec { - fn to_str(&self) -> String { - self.iter().enumerate().fold(String::new(), |mut acc, (idx, v)| { - if idx > 0 { acc.push(',') }; - acc.push_str(&v.to_string()); - acc - }) - } +// FIXME: This would be nicer as a method on Iterator. This can +// eventually be replaced by the successor to std::slice::SliceConcatExt.connect +fn join,T: ToString>(iter: I, sep: &str) -> String { + iter.enumerate().fold(String::new(), |mut acc, (idx, v)| { + if idx > 0 { acc.push_str(sep) }; + acc.push_str(&v.to_string()); + acc + }) } #[allow(non_snake_case)] @@ -314,12 +306,12 @@ impl X509Generator { if self.key_usage.len() > 0 { try!(X509Generator::add_extension(x509.handle, ffi::NID_key_usage, - &self.key_usage.to_str())); + &join(self.key_usage.iter(),","))); } if self.ext_key_usage.len() > 0 { try!(X509Generator::add_extension(x509.handle, ffi::NID_ext_key_usage, - &self.ext_key_usage.to_str())); + &join(self.ext_key_usage.iter(),","))); } let hash_fn = self.hash_type.evp_md(); From d5a4d48caba81ffcd46abc49d7373a2d81c370d9 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 18:52:17 -0700 Subject: [PATCH 03/32] Turn assertions into unwraps such that tests provide useful output on panic. --- openssl/src/x509/tests.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 4e1c4f15..ca9ce68c 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -19,13 +19,9 @@ fn test_cert_gen() { .set_usage(&[DigitalSignature, KeyEncipherment]) .set_ext_usage(&[ClientAuth, ServerAuth]); - let res = gen.generate(); - assert!(res.is_ok()); - - let (cert, pkey) = res.unwrap(); - - assert!(cert.write_pem(&mut io::sink()).is_ok()); - assert!(pkey.write_pem(&mut io::sink()).is_ok()); + let (cert, pkey) = gen.generate().unwrap(); + cert.write_pem(&mut io::sink()).unwrap(); + pkey.write_pem(&mut io::sink()).unwrap(); // FIXME: check data in result to be correct, needs implementation // of X509 getters From 8d1abf5156840cb718f637959a1f98f499a64519 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 18:54:48 -0700 Subject: [PATCH 04/32] Implement "extensions" field in X509generator, and change existing extensions to use that --- openssl/src/nid.rs | 2 +- openssl/src/x509/extension.rs | 42 +++++++++++++++++++++++++++++++++++ openssl/src/x509/mod.rs | 34 +++++++++------------------- 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/openssl/src/nid.rs b/openssl/src/nid.rs index c5b9e277..81cc4975 100644 --- a/openssl/src/nid.rs +++ b/openssl/src/nid.rs @@ -1,5 +1,5 @@ #[allow(non_camel_case_types)] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Hash, PartialEq, Eq)] #[repr(usize)] pub enum Nid { Undefined, diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index b7f5fc52..4f8a3c3b 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -1,4 +1,11 @@ use std::fmt; +use nid::Nid; + +#[derive(Clone,Copy,Hash,PartialEq,Eq)] +pub enum ExtensionType { + KeyUsage, + ExtKeyUsage, +} #[derive(Clone)] pub enum Extension { @@ -6,6 +13,41 @@ pub enum Extension { ExtKeyUsage(Vec), } +impl Extension { + pub fn get_type(&self) -> ExtensionType { + match self { + &Extension::KeyUsage(_) => ExtensionType::KeyUsage, + &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, + } + } + + pub fn get_nid(&self) -> Nid { + match self { + &Extension::KeyUsage(_) => Nid::KeyUsage, + &Extension::ExtKeyUsage(_) => Nid::ExtendedKeyUsage, + } + } +} + +// FIXME: This would be nicer as a method on Iterator. This can +// eventually be replaced by the successor to std::slice::SliceConcatExt.connect +fn join,T: ToString>(iter: I, sep: &str) -> String { + iter.enumerate().fold(String::new(), |mut acc, (idx, v)| { + if idx > 0 { acc.push_str(sep) }; + acc.push_str(&v.to_string()); + acc + }) +} + +impl ToString for Extension { + fn to_string(&self) -> String { + match self { + &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), + &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), + } + } +} + #[derive(Clone,Copy)] pub enum KeyUsageOption { DigitalSignature, diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 864e94c8..7d936f7e 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -9,6 +9,7 @@ use std::ptr; use std::ops::Deref; use std::fmt; use std::str; +use std::collections::HashMap; use asn1::{Asn1Time}; use bio::{MemBio}; @@ -22,6 +23,8 @@ use nid; mod extension; +use self::extension::{ExtensionType,Extension}; + #[cfg(test)] mod tests; @@ -103,16 +106,6 @@ impl X509StoreContext { pub use self::extension::KeyUsageOption as KeyUsage; pub use self::extension::ExtKeyUsageOption as ExtKeyUsage; -// FIXME: This would be nicer as a method on Iterator. This can -// eventually be replaced by the successor to std::slice::SliceConcatExt.connect -fn join,T: ToString>(iter: I, sep: &str) -> String { - iter.enumerate().fold(String::new(), |mut acc, (idx, v)| { - if idx > 0 { acc.push_str(sep) }; - acc.push_str(&v.to_string()); - acc - }) -} - #[allow(non_snake_case)] /// Generator of private key/certificate pairs /// @@ -153,8 +146,8 @@ pub struct X509Generator { bits: u32, days: u32, CN: String, - key_usage: Vec, - ext_key_usage: Vec, + // RFC 3280 §4.2: A certificate MUST NOT include more than one instance of a particular extension. + extensions: HashMap, hash_type: HashType, } @@ -173,8 +166,7 @@ impl X509Generator { bits: 1024, days: 365, CN: "rust-openssl".to_string(), - key_usage: Vec::new(), - ext_key_usage: Vec::new(), + extensions: HashMap::new(), hash_type: HashType::SHA1 } } @@ -200,13 +192,13 @@ impl X509Generator { /// Sets what for certificate could be used pub fn set_usage(mut self, purposes: &[KeyUsage]) -> X509Generator { - self.key_usage = purposes.to_vec(); + self.extensions.insert(ExtensionType::KeyUsage,Extension::KeyUsage(purposes.to_owned())); self } /// Sets allowed extended usage of certificate pub fn set_ext_usage(mut self, purposes: &[ExtKeyUsage]) -> X509Generator { - self.ext_key_usage = purposes.to_vec(); + self.extensions.insert(ExtensionType::ExtKeyUsage,Extension::ExtKeyUsage(purposes.to_owned())); self } @@ -304,14 +296,8 @@ impl X509Generator { try!(X509Generator::add_name(name, "CN", &self.CN)); ffi::X509_set_issuer_name(x509.handle, name); - if self.key_usage.len() > 0 { - try!(X509Generator::add_extension(x509.handle, ffi::NID_key_usage, - &join(self.key_usage.iter(),","))); - } - - if self.ext_key_usage.len() > 0 { - try!(X509Generator::add_extension(x509.handle, ffi::NID_ext_key_usage, - &join(self.ext_key_usage.iter(),","))); + for ext in self.extensions.values() { + try!(X509Generator::add_extension(x509.handle, ext.get_nid() as c_int, &ext.to_string())); } let hash_fn = self.hash_type.evp_md(); From 53b868697a754229ba457908f29af5e8fd83404a Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 22:25:00 -0700 Subject: [PATCH 05/32] Implement arbitrary X509 Extended Key Usage values --- openssl/src/x509/extension.rs | 5 ++++- openssl/src/x509/tests.rs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 4f8a3c3b..66b218ad 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -77,7 +77,7 @@ impl fmt::Display for KeyUsageOption { } } -#[derive(Clone,Copy)] +#[derive(Clone)] pub enum ExtKeyUsageOption { ServerAuth, ClientAuth, @@ -90,6 +90,8 @@ pub enum ExtKeyUsageOption { MsSgc, MsEfs, NsSgc, + /// An arbitrary key usage by OID. + Other(String), } impl fmt::Display for ExtKeyUsageOption { @@ -106,6 +108,7 @@ impl fmt::Display for ExtKeyUsageOption { &ExtKeyUsageOption::MsSgc => "msSGC", &ExtKeyUsageOption::MsEfs => "msEFS", &ExtKeyUsageOption::NsSgc =>"nsSGC", + &ExtKeyUsageOption::Other(ref s) => &s[..], }) } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index ca9ce68c..66dc33d3 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -6,7 +6,7 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; use x509::KeyUsage::{DigitalSignature, KeyEncipherment}; -use x509::ExtKeyUsage::{ClientAuth, ServerAuth}; +use x509::ExtKeyUsage::{self, ClientAuth, ServerAuth}; use nid::Nid; #[test] @@ -17,7 +17,7 @@ fn test_cert_gen() { .set_CN("test_me") .set_sign_hash(SHA256) .set_usage(&[DigitalSignature, KeyEncipherment]) - .set_ext_usage(&[ClientAuth, ServerAuth]); + .set_ext_usage(&[ClientAuth, ServerAuth, ExtKeyUsage::Other("2.999".to_owned())]); let (cert, pkey) = gen.generate().unwrap(); cert.write_pem(&mut io::sink()).unwrap(); From 2fa134436707454d8c46a0fba8a7e252fb9f1668 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 22:30:54 -0700 Subject: [PATCH 06/32] Add public generic extension interface to X509Generator * Add add_extension and add_extensions functions * Deprecate set_usage and set_ext_usage * Change test to use add_extension --- openssl/src/x509/mod.rs | 53 ++++++++++++++++++++++++++++++++------- openssl/src/x509/tests.rs | 9 ++++--- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 7d936f7e..42bb7a08 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -21,7 +21,7 @@ use ffi; use ssl::error::{SslError, StreamError}; use nid; -mod extension; +pub mod extension; use self::extension::{ExtensionType,Extension}; @@ -190,15 +190,50 @@ impl X509Generator { self } - /// Sets what for certificate could be used - pub fn set_usage(mut self, purposes: &[KeyUsage]) -> X509Generator { - self.extensions.insert(ExtensionType::KeyUsage,Extension::KeyUsage(purposes.to_owned())); + /// (deprecated) Sets what for certificate could be used + /// + /// This function is deprecated, use `X509Generator.add_extension` instead. + pub fn set_usage(self, purposes: &[KeyUsage]) -> X509Generator { + self.add_extension(Extension::KeyUsage(purposes.to_owned())) + } + + /// (deprecated) Sets allowed extended usage of certificate + /// + /// This function is deprecated, use `X509Generator.add_extension` instead. + pub fn set_ext_usage(self, purposes: &[ExtKeyUsage]) -> X509Generator { + self.add_extension(Extension::ExtKeyUsage(purposes.to_owned())) + } + + /// Add an extension to a certificate + /// + /// If the extension already exists, it will be replaced. + /// + /// ``` + /// use openssl::x509::extension::Extension::*; + /// use openssl::x509::extension::KeyUsageOption::*; + /// + /// # let generator = openssl::x509::X509Generator::new(); + /// generator.add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])); + /// ``` + pub fn add_extension(mut self, ext: extension::Extension) -> X509Generator { + self.extensions.insert(ext.get_type(),ext); self } - /// Sets allowed extended usage of certificate - pub fn set_ext_usage(mut self, purposes: &[ExtKeyUsage]) -> X509Generator { - self.extensions.insert(ExtensionType::ExtKeyUsage,Extension::ExtKeyUsage(purposes.to_owned())); + /// Add multiple extensions to a certificate + /// + /// If any of the extensions already exist, they will be replaced. + /// + /// ``` + /// use openssl::x509::extension::Extension::*; + /// use openssl::x509::extension::KeyUsageOption::*; + /// + /// # let generator = openssl::x509::X509Generator::new(); + /// generator.add_extensions(vec![KeyUsage(vec![DigitalSignature, KeyEncipherment])]); + /// ``` + pub fn add_extensions(mut self, exts: I) -> X509Generator + where I: IntoIterator { + self.extensions.extend(exts.into_iter().map(|ext|(ext.get_type(),ext))); self } @@ -207,7 +242,7 @@ impl X509Generator { self } - fn add_extension(x509: *mut ffi::X509, extension: c_int, value: &str) -> Result<(), SslError> { + fn add_extension_internal(x509: *mut ffi::X509, extension: c_int, value: &str) -> Result<(), SslError> { unsafe { let mut ctx: ffi::X509V3_CTX = mem::zeroed(); ffi::X509V3_set_ctx(&mut ctx, x509, x509, @@ -297,7 +332,7 @@ impl X509Generator { ffi::X509_set_issuer_name(x509.handle, name); for ext in self.extensions.values() { - try!(X509Generator::add_extension(x509.handle, ext.get_nid() as c_int, &ext.to_string())); + try!(X509Generator::add_extension_internal(x509.handle, ext.get_nid() as c_int, &ext.to_string())); } let hash_fn = self.hash_type.evp_md(); diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 66dc33d3..806bc671 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -5,8 +5,9 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; -use x509::KeyUsage::{DigitalSignature, KeyEncipherment}; -use x509::ExtKeyUsage::{self, ClientAuth, ServerAuth}; +use x509::extension::Extension::{KeyUsage,ExtKeyUsage}; +use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; +use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; use nid::Nid; #[test] @@ -16,8 +17,8 @@ fn test_cert_gen() { .set_valid_period(365*2) .set_CN("test_me") .set_sign_hash(SHA256) - .set_usage(&[DigitalSignature, KeyEncipherment]) - .set_ext_usage(&[ClientAuth, ServerAuth, ExtKeyUsage::Other("2.999".to_owned())]); + .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) + .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999".to_owned())])); let (cert, pkey) = gen.generate().unwrap(); cert.write_pem(&mut io::sink()).unwrap(); From e367567d00cdbd6b12906a424971146f6c3eea28 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 22:37:49 -0700 Subject: [PATCH 07/32] Add arbitrary X509 extensions by NID --- openssl/src/x509/extension.rs | 5 +++++ openssl/src/x509/tests.rs | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 66b218ad..4576ad1a 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -5,12 +5,14 @@ use nid::Nid; pub enum ExtensionType { KeyUsage, ExtKeyUsage, + OtherNid(Nid), } #[derive(Clone)] pub enum Extension { KeyUsage(Vec), ExtKeyUsage(Vec), + OtherNid(Nid,String), } impl Extension { @@ -18,6 +20,7 @@ impl Extension { match self { &Extension::KeyUsage(_) => ExtensionType::KeyUsage, &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, + &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), } } @@ -25,6 +28,7 @@ impl Extension { match self { &Extension::KeyUsage(_) => Nid::KeyUsage, &Extension::ExtKeyUsage(_) => Nid::ExtendedKeyUsage, + &Extension::OtherNid(nid,_) => nid, } } } @@ -44,6 +48,7 @@ impl ToString for Extension { match self { &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), + &Extension::OtherNid(_,ref value) => value.clone(), } } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 806bc671..0061453c 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -5,7 +5,7 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; -use x509::extension::Extension::{KeyUsage,ExtKeyUsage}; +use x509::extension::Extension::{KeyUsage,ExtKeyUsage,OtherNid}; use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; use nid::Nid; @@ -18,7 +18,8 @@ fn test_cert_gen() { .set_CN("test_me") .set_sign_hash(SHA256) .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) - .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999".to_owned())])); + .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999".to_owned())])) + .add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); let (cert, pkey) = gen.generate().unwrap(); cert.write_pem(&mut io::sink()).unwrap(); From b46574b63587dab26eb46aa8f45b2dc830053988 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:00:48 -0700 Subject: [PATCH 08/32] Add arbitrary X509 extensions by OID string --- openssl-sys/src/lib.rs | 1 + openssl/src/x509/extension.rs | 24 +++++++++++++++++++----- openssl/src/x509/mod.rs | 19 ++++++++++++------- openssl/src/x509/tests.rs | 7 ++++--- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 9f2041a4..950ca42f 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -603,6 +603,7 @@ extern "C" { pub fn X509_STORE_CTX_get_ex_data(ctx: *mut X509_STORE_CTX, idx: c_int) -> *mut c_void; pub fn X509V3_EXT_conf_nid(conf: *mut c_void, ctx: *mut X509V3_CTX, ext_nid: c_int, value: *mut c_char) -> *mut X509_EXTENSION; + pub fn X509V3_EXT_conf(conf: *mut c_void, ctx: *mut X509V3_CTX, name: *mut c_char, value: *mut c_char) -> *mut X509_EXTENSION; pub fn X509V3_set_ctx(ctx: *mut X509V3_CTX, issuer: *mut X509, subject: *mut X509, req: *mut X509_REQ, crl: *mut X509_CRL, flags: c_int); pub fn i2d_RSA_PUBKEY(k: *mut RSA, buf: *const *mut u8) -> c_int; diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 4576ad1a..78058b72 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -1,11 +1,12 @@ use std::fmt; use nid::Nid; -#[derive(Clone,Copy,Hash,PartialEq,Eq)] +#[derive(Clone,Hash,PartialEq,Eq)] pub enum ExtensionType { KeyUsage, ExtKeyUsage, OtherNid(Nid), + OtherStr(String), } #[derive(Clone)] @@ -13,6 +14,7 @@ pub enum Extension { KeyUsage(Vec), ExtKeyUsage(Vec), OtherNid(Nid,String), + OtherStr(String,String), } impl Extension { @@ -21,14 +23,25 @@ impl Extension { &Extension::KeyUsage(_) => ExtensionType::KeyUsage, &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), + &Extension::OtherStr(ref s,_) => ExtensionType::OtherStr(s.clone()), + } + } +} + +impl ExtensionType { + pub fn get_nid(&self) -> Option { + match self { + &ExtensionType::KeyUsage => Some(Nid::KeyUsage), + &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), + &ExtensionType::OtherNid(nid) => Some(nid), + &ExtensionType::OtherStr(_) => None, } } - pub fn get_nid(&self) -> Nid { + pub fn get_name<'a>(&'a self) -> Option<&'a str> { match self { - &Extension::KeyUsage(_) => Nid::KeyUsage, - &Extension::ExtKeyUsage(_) => Nid::ExtendedKeyUsage, - &Extension::OtherNid(nid,_) => nid, + &ExtensionType::OtherStr(ref s) => Some(s), + _ => None, } } } @@ -49,6 +62,7 @@ impl ToString for Extension { &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), &Extension::OtherNid(_,ref value) => value.clone(), + &Extension::OtherStr(_,ref value) => value.clone(), } } } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 42bb7a08..423a258f 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -242,17 +242,22 @@ impl X509Generator { self } - fn add_extension_internal(x509: *mut ffi::X509, extension: c_int, value: &str) -> Result<(), SslError> { + fn add_extension_internal(x509: *mut ffi::X509, exttype: &extension::ExtensionType, value: &str) -> Result<(), SslError> { unsafe { let mut ctx: ffi::X509V3_CTX = mem::zeroed(); ffi::X509V3_set_ctx(&mut ctx, x509, x509, ptr::null_mut(), ptr::null_mut(), 0); let value = CString::new(value.as_bytes()).unwrap(); - let ext = ffi::X509V3_EXT_conf_nid(ptr::null_mut(), + let ext=match exttype.get_nid() { + Some(nid) => ffi::X509V3_EXT_conf_nid(ptr::null_mut(), mem::transmute(&ctx), - extension, - value.as_ptr() as *mut c_char); - + nid as c_int, + value.as_ptr() as *mut c_char), + None => ffi::X509V3_EXT_conf(ptr::null_mut(), + mem::transmute(&ctx), + exttype.get_name().unwrap().as_ptr() as *mut c_char, + value.as_ptr() as *mut c_char), + }; let mut success = false; if ext != ptr::null_mut() { success = ffi::X509_add_ext(x509, ext, -1) != 0; @@ -331,8 +336,8 @@ impl X509Generator { try!(X509Generator::add_name(name, "CN", &self.CN)); ffi::X509_set_issuer_name(x509.handle, name); - for ext in self.extensions.values() { - try!(X509Generator::add_extension_internal(x509.handle, ext.get_nid() as c_int, &ext.to_string())); + for (exttype,ext) in self.extensions.iter() { + try!(X509Generator::add_extension_internal(x509.handle, exttype, &ext.to_string())); } let hash_fn = self.hash_type.evp_md(); diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 0061453c..ff7d1173 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -5,7 +5,7 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; -use x509::extension::Extension::{KeyUsage,ExtKeyUsage,OtherNid}; +use x509::extension::Extension::{KeyUsage,ExtKeyUsage,OtherNid,OtherStr}; use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; use nid::Nid; @@ -18,8 +18,9 @@ fn test_cert_gen() { .set_CN("test_me") .set_sign_hash(SHA256) .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) - .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999".to_owned())])) - .add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); + .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999.1".to_owned())])) + .add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())) + .add_extension(OtherStr("2.999.2".to_owned(),"ASN1:UTF8:example value".to_owned())); let (cert, pkey) = gen.generate().unwrap(); cert.write_pem(&mut io::sink()).unwrap(); From f4168b1161081523705657adc4a324e533483ca3 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:11:42 -0700 Subject: [PATCH 09/32] Add Subject Alternate Name extension --- openssl/src/x509/extension.rs | 32 ++++++++++++++++++++++++++++++++ openssl/src/x509/tests.rs | 4 +++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 78058b72..8091d058 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -5,6 +5,7 @@ use nid::Nid; pub enum ExtensionType { KeyUsage, ExtKeyUsage, + SubjectAltName, OtherNid(Nid), OtherStr(String), } @@ -13,6 +14,7 @@ pub enum ExtensionType { pub enum Extension { KeyUsage(Vec), ExtKeyUsage(Vec), + SubjectAltName(Vec<(AltNameOption,String)>), OtherNid(Nid,String), OtherStr(String,String), } @@ -22,6 +24,7 @@ impl Extension { match self { &Extension::KeyUsage(_) => ExtensionType::KeyUsage, &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, + &Extension::SubjectAltName(_) => ExtensionType::SubjectAltName, &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), &Extension::OtherStr(ref s,_) => ExtensionType::OtherStr(s.clone()), } @@ -33,6 +36,7 @@ impl ExtensionType { match self { &ExtensionType::KeyUsage => Some(Nid::KeyUsage), &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), + &ExtensionType::SubjectAltName => Some(Nid::SubjectAltName), &ExtensionType::OtherNid(nid) => Some(nid), &ExtensionType::OtherStr(_) => None, } @@ -61,6 +65,7 @@ impl ToString for Extension { match self { &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), + &Extension::SubjectAltName(ref names) => join(names.iter().map(|&(ref opt,ref val)|opt.to_string()+":"+&val),","), &Extension::OtherNid(_,ref value) => value.clone(), &Extension::OtherStr(_,ref value) => value.clone(), } @@ -131,3 +136,30 @@ impl fmt::Display for ExtKeyUsageOption { }) } } + +#[derive(Clone, Copy)] +pub enum AltNameOption { + Other, + Email, + DNS, + //X400, // Not supported by OpenSSL + Directory, + //EDIParty, // Not supported by OpenSSL + URI, + IPAddress, + RegisteredID, +} + +impl fmt::Display for AltNameOption { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.pad(match self { + &AltNameOption::Other => "otherName", + &AltNameOption::Email => "email", + &AltNameOption::DNS => "DNS", + &AltNameOption::Directory => "dirName", + &AltNameOption::URI => "URI", + &AltNameOption::IPAddress => "IP", + &AltNameOption::RegisteredID => "RID", + }) + } +} diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index ff7d1173..8417ee5c 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -5,7 +5,8 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; -use x509::extension::Extension::{KeyUsage,ExtKeyUsage,OtherNid,OtherStr}; +use x509::extension::Extension::{KeyUsage,ExtKeyUsage,SubjectAltName,OtherNid,OtherStr}; +use x509::extension::AltNameOption as SAN; use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; use nid::Nid; @@ -19,6 +20,7 @@ fn test_cert_gen() { .set_sign_hash(SHA256) .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999.1".to_owned())])) + .add_extension(SubjectAltName(vec![(SAN::DNS,"example.com".to_owned())])) .add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())) .add_extension(OtherStr("2.999.2".to_owned(),"ASN1:UTF8:example value".to_owned())); From e9cc8cb121b027a9f5faa46339820e573f2efdcf Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:13:30 -0700 Subject: [PATCH 10/32] Add Issuer Alternative Name extension --- openssl/src/x509/extension.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 8091d058..0b050b34 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -6,6 +6,7 @@ pub enum ExtensionType { KeyUsage, ExtKeyUsage, SubjectAltName, + IssuerAltName, OtherNid(Nid), OtherStr(String), } @@ -15,6 +16,7 @@ pub enum Extension { KeyUsage(Vec), ExtKeyUsage(Vec), SubjectAltName(Vec<(AltNameOption,String)>), + IssuerAltName(Vec<(AltNameOption,String)>), OtherNid(Nid,String), OtherStr(String,String), } @@ -25,6 +27,7 @@ impl Extension { &Extension::KeyUsage(_) => ExtensionType::KeyUsage, &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, &Extension::SubjectAltName(_) => ExtensionType::SubjectAltName, + &Extension::IssuerAltName(_) => ExtensionType::IssuerAltName, &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), &Extension::OtherStr(ref s,_) => ExtensionType::OtherStr(s.clone()), } @@ -37,6 +40,7 @@ impl ExtensionType { &ExtensionType::KeyUsage => Some(Nid::KeyUsage), &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), &ExtensionType::SubjectAltName => Some(Nid::SubjectAltName), + &ExtensionType::IssuerAltName => Some(Nid::IssuerAltName), &ExtensionType::OtherNid(nid) => Some(nid), &ExtensionType::OtherStr(_) => None, } @@ -66,6 +70,7 @@ impl ToString for Extension { &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), &Extension::SubjectAltName(ref names) => join(names.iter().map(|&(ref opt,ref val)|opt.to_string()+":"+&val),","), + &Extension::IssuerAltName(ref names) => join(names.iter().map(|&(ref opt,ref val)|opt.to_string()+":"+&val),","), &Extension::OtherNid(_,ref value) => value.clone(), &Extension::OtherStr(_,ref value) => value.clone(), } From 93eb0cfa2d4f7fe2c1091ad972c48e18b140807d Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:30:15 -0700 Subject: [PATCH 11/32] Add documentation on X509 Extensions --- openssl/src/x509/extension.rs | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 0b050b34..e6d992a1 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -1,6 +1,10 @@ use std::fmt; use nid::Nid; +/// Type-only version of the `Extension` enum. +/// +/// See the `Extension` documentation for more information on the different +/// variants. #[derive(Clone,Hash,PartialEq,Eq)] pub enum ExtensionType { KeyUsage, @@ -11,13 +15,42 @@ pub enum ExtensionType { OtherStr(String), } +/// A X.509 v3 certificate extension. +/// +/// Only one extension of each type is allow in a certificate. +/// See RFC 3280 for more information about extensions. #[derive(Clone)] pub enum Extension { + /// The purposes of the key contained in the certificate KeyUsage(Vec), + /// The extended purposes of the key contained in the certificate ExtKeyUsage(Vec), + /// Subject Alternative Names SubjectAltName(Vec<(AltNameOption,String)>), + /// Issuer Alternative Names IssuerAltName(Vec<(AltNameOption,String)>), + /// Arbitrary extensions by NID. See `man x509v3_config` for value syntax. + /// + /// You must not use this to add extensions which this enum can express directly. + /// + /// ``` + /// use openssl::x509::extension::Extension::*; + /// use openssl::nid::Nid; + /// + /// # let generator = openssl::x509::X509Generator::new(); + /// generator.add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); + /// ``` OtherNid(Nid,String), + /// Arbitrary extensions by OID string. See `man ASN1_generate_nconf` for value syntax. + /// + /// You must not use this to add extensions which this enum can express directly. + /// + /// ``` + /// use openssl::x509::extension::Extension::*; + /// + /// # let generator = openssl::x509::X509Generator::new(); + /// generator.add_extension(OtherStr("2.999.2".to_owned(),"ASN1:UTF8:example value".to_owned())); + /// ``` OtherStr(String,String), } @@ -144,6 +177,15 @@ impl fmt::Display for ExtKeyUsageOption { #[derive(Clone, Copy)] pub enum AltNameOption { + /// The value is specified as OID;content. See `man ASN1_generate_nconf` for more information on the content syntax. + /// + /// ``` + /// use openssl::x509::extension::Extension::*; + /// use openssl::x509::extension::AltNameOption::Other as OtherName; + /// + /// # let generator = openssl::x509::X509Generator::new(); + /// generator.add_extension(SubjectAltName(vec![(OtherName,"2.999.3;ASN1:UTF8:some other name".to_owned())])); + /// ``` Other, Email, DNS, From f9a836fae9a8b58513e4e0de6e27bf363bc88740 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:30:45 -0700 Subject: [PATCH 12/32] tabs to spaces --- openssl/src/x509/extension.rs | 152 +++++++++++++++++----------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index e6d992a1..3faa0996 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -7,12 +7,12 @@ use nid::Nid; /// variants. #[derive(Clone,Hash,PartialEq,Eq)] pub enum ExtensionType { - KeyUsage, - ExtKeyUsage, - SubjectAltName, - IssuerAltName, - OtherNid(Nid), - OtherStr(String), + KeyUsage, + ExtKeyUsage, + SubjectAltName, + IssuerAltName, + OtherNid(Nid), + OtherStr(String), } /// A X.509 v3 certificate extension. @@ -21,70 +21,70 @@ pub enum ExtensionType { /// See RFC 3280 for more information about extensions. #[derive(Clone)] pub enum Extension { - /// The purposes of the key contained in the certificate - KeyUsage(Vec), - /// The extended purposes of the key contained in the certificate - ExtKeyUsage(Vec), - /// Subject Alternative Names - SubjectAltName(Vec<(AltNameOption,String)>), - /// Issuer Alternative Names - IssuerAltName(Vec<(AltNameOption,String)>), - /// Arbitrary extensions by NID. See `man x509v3_config` for value syntax. - /// - /// You must not use this to add extensions which this enum can express directly. - /// + /// The purposes of the key contained in the certificate + KeyUsage(Vec), + /// The extended purposes of the key contained in the certificate + ExtKeyUsage(Vec), + /// Subject Alternative Names + SubjectAltName(Vec<(AltNameOption,String)>), + /// Issuer Alternative Names + IssuerAltName(Vec<(AltNameOption,String)>), + /// Arbitrary extensions by NID. See `man x509v3_config` for value syntax. + /// + /// You must not use this to add extensions which this enum can express directly. + /// /// ``` /// use openssl::x509::extension::Extension::*; - /// use openssl::nid::Nid; + /// use openssl::nid::Nid; /// /// # let generator = openssl::x509::X509Generator::new(); /// generator.add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); /// ``` - OtherNid(Nid,String), - /// Arbitrary extensions by OID string. See `man ASN1_generate_nconf` for value syntax. - /// - /// You must not use this to add extensions which this enum can express directly. - /// + OtherNid(Nid,String), + /// Arbitrary extensions by OID string. See `man ASN1_generate_nconf` for value syntax. + /// + /// You must not use this to add extensions which this enum can express directly. + /// /// ``` /// use openssl::x509::extension::Extension::*; /// /// # let generator = openssl::x509::X509Generator::new(); /// generator.add_extension(OtherStr("2.999.2".to_owned(),"ASN1:UTF8:example value".to_owned())); /// ``` - OtherStr(String,String), + OtherStr(String,String), } impl Extension { - pub fn get_type(&self) -> ExtensionType { - match self { - &Extension::KeyUsage(_) => ExtensionType::KeyUsage, - &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, - &Extension::SubjectAltName(_) => ExtensionType::SubjectAltName, - &Extension::IssuerAltName(_) => ExtensionType::IssuerAltName, - &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), - &Extension::OtherStr(ref s,_) => ExtensionType::OtherStr(s.clone()), - } - } + pub fn get_type(&self) -> ExtensionType { + match self { + &Extension::KeyUsage(_) => ExtensionType::KeyUsage, + &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, + &Extension::SubjectAltName(_) => ExtensionType::SubjectAltName, + &Extension::IssuerAltName(_) => ExtensionType::IssuerAltName, + &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), + &Extension::OtherStr(ref s,_) => ExtensionType::OtherStr(s.clone()), + } + } } impl ExtensionType { - pub fn get_nid(&self) -> Option { - match self { - &ExtensionType::KeyUsage => Some(Nid::KeyUsage), - &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), - &ExtensionType::SubjectAltName => Some(Nid::SubjectAltName), - &ExtensionType::IssuerAltName => Some(Nid::IssuerAltName), - &ExtensionType::OtherNid(nid) => Some(nid), - &ExtensionType::OtherStr(_) => None, - } - } + pub fn get_nid(&self) -> Option { + match self { + &ExtensionType::KeyUsage => Some(Nid::KeyUsage), + &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), + &ExtensionType::SubjectAltName => Some(Nid::SubjectAltName), + &ExtensionType::IssuerAltName => Some(Nid::IssuerAltName), + &ExtensionType::OtherNid(nid) => Some(nid), + &ExtensionType::OtherStr(_) => None, + } + } - pub fn get_name<'a>(&'a self) -> Option<&'a str> { - match self { - &ExtensionType::OtherStr(ref s) => Some(s), - _ => None, - } - } + pub fn get_name<'a>(&'a self) -> Option<&'a str> { + match self { + &ExtensionType::OtherStr(ref s) => Some(s), + _ => None, + } + } } // FIXME: This would be nicer as a method on Iterator. This can @@ -99,14 +99,14 @@ fn join,T: ToString>(iter: I, sep: &str) -> String { impl ToString for Extension { fn to_string(&self) -> String { - match self { - &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), - &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), - &Extension::SubjectAltName(ref names) => join(names.iter().map(|&(ref opt,ref val)|opt.to_string()+":"+&val),","), - &Extension::IssuerAltName(ref names) => join(names.iter().map(|&(ref opt,ref val)|opt.to_string()+":"+&val),","), - &Extension::OtherNid(_,ref value) => value.clone(), - &Extension::OtherStr(_,ref value) => value.clone(), - } + match self { + &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), + &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), + &Extension::SubjectAltName(ref names) => join(names.iter().map(|&(ref opt,ref val)|opt.to_string()+":"+&val),","), + &Extension::IssuerAltName(ref names) => join(names.iter().map(|&(ref opt,ref val)|opt.to_string()+":"+&val),","), + &Extension::OtherNid(_,ref value) => value.clone(), + &Extension::OtherStr(_,ref value) => value.clone(), + } } } @@ -178,7 +178,7 @@ impl fmt::Display for ExtKeyUsageOption { #[derive(Clone, Copy)] pub enum AltNameOption { /// The value is specified as OID;content. See `man ASN1_generate_nconf` for more information on the content syntax. - /// + /// /// ``` /// use openssl::x509::extension::Extension::*; /// use openssl::x509::extension::AltNameOption::Other as OtherName; @@ -186,27 +186,27 @@ pub enum AltNameOption { /// # let generator = openssl::x509::X509Generator::new(); /// generator.add_extension(SubjectAltName(vec![(OtherName,"2.999.3;ASN1:UTF8:some other name".to_owned())])); /// ``` - Other, - Email, - DNS, - //X400, // Not supported by OpenSSL - Directory, - //EDIParty, // Not supported by OpenSSL - URI, - IPAddress, - RegisteredID, + Other, + Email, + DNS, + //X400, // Not supported by OpenSSL + Directory, + //EDIParty, // Not supported by OpenSSL + URI, + IPAddress, + RegisteredID, } impl fmt::Display for AltNameOption { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { f.pad(match self { - &AltNameOption::Other => "otherName", - &AltNameOption::Email => "email", - &AltNameOption::DNS => "DNS", - &AltNameOption::Directory => "dirName", - &AltNameOption::URI => "URI", - &AltNameOption::IPAddress => "IP", - &AltNameOption::RegisteredID => "RID", + &AltNameOption::Other => "otherName", + &AltNameOption::Email => "email", + &AltNameOption::DNS => "DNS", + &AltNameOption::Directory => "dirName", + &AltNameOption::URI => "URI", + &AltNameOption::IPAddress => "IP", + &AltNameOption::RegisteredID => "RID", }) } } From aeefa364b7fd386584d90040592ae9b4b3dc42b4 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 1 Jul 2015 21:49:11 -0700 Subject: [PATCH 13/32] Decouple C SSL Option bit flags from Rust version The OpenSSL "SSL_OP_*" flags are in constant flux between different OpenSSL versions. To avoid having to change the Rust definitions, we implement our own numbering system in Rust, and use an automatically-generated C shim to convert the bitflags at runtime. --- openssl-sys/build.rs | 64 +++++++++++++++++++++++++++++ openssl-sys/src/lib.rs | 32 ++++++++++++--- openssl-sys/src/ssl_options.rs | 46 +++++++++++++++++++++ openssl/src/ssl/mod.rs | 75 +++++++++++++++++++++------------- 4 files changed, 182 insertions(+), 35 deletions(-) create mode 100644 openssl-sys/src/ssl_options.rs diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index c1f12034..841c7eec 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -2,7 +2,10 @@ extern crate pkg_config; extern crate gcc; use std::env; +use std::fmt::Write as FmtWrite; use std::path::PathBuf; +use std::fs::File; +use std::io::Write; fn main() { let target = env::var("TARGET").unwrap(); @@ -65,7 +68,67 @@ fn main() { build_openssl_shim(&include_dirs); } +macro_rules! import_options { + ( $( $name:ident $val:expr )* ) => { + &[ $( (stringify!($name),$val), )* ] + }; +} + +fn generate_options_shim() -> PathBuf { + let options: &[(&'static str,u64)]=include!("src/ssl_options.rs"); + let mut shim = String::new(); + writeln!(shim,"#include ").unwrap(); + writeln!(shim,"#include ").unwrap(); + + for &(name,value) in options { + writeln!(shim,"#define RUST_{} UINT64_C({})",name,value).unwrap(); + writeln!(shim,"#ifndef {}",name).unwrap(); + writeln!(shim,"# define {} 0",name).unwrap(); + writeln!(shim,"#endif").unwrap(); + } + + writeln!(shim,"#define COPY_MASK ( \\").unwrap(); + + let mut it=options.iter().peekable(); + while let Some(&(name,_))=it.next() { + let eol=match it.peek() { + Some(_) => " | \\", + None => " )" + }; + writeln!(shim," ((RUST_{0}==(uint64_t)(uint32_t){0})?RUST_{0}:UINT64_C(0)){1}",name,eol).unwrap(); + } + + writeln!(shim,"long rust_openssl_ssl_ctx_options_rust_to_c(uint64_t rustval) {{").unwrap(); + writeln!(shim," long cval=rustval©_MASK;").unwrap(); + for &(name,_) in options { + writeln!(shim,"#if RUST_{0}!={0}",name).unwrap(); + writeln!(shim," if (rustval&RUST_{0}) cval|={0};",name).unwrap(); + writeln!(shim,"#endif").unwrap(); + } + writeln!(shim," return cval;").unwrap(); + writeln!(shim,"}}").unwrap(); + + writeln!(shim,"uint64_t rust_openssl_ssl_ctx_options_c_to_rust(long cval) {{").unwrap(); + writeln!(shim," uint64_t rustval=cval©_MASK;").unwrap(); + for &(name,_) in options { + writeln!(shim,"#if RUST_{0}!={0}",name).unwrap(); + writeln!(shim," if (cval&{0}) rustval|=RUST_{0};",name).unwrap(); + writeln!(shim,"#endif").unwrap(); + } + writeln!(shim," return rustval;").unwrap(); + writeln!(shim,"}}").unwrap(); + + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_file = PathBuf::from(&out_dir).join("ssl_ctx_options_shim.c"); + let mut f = File::create(&dest_file).unwrap(); + + f.write_all(shim.as_bytes()).unwrap(); + + dest_file +} + fn build_openssl_shim(include_paths: &[PathBuf]) { + let options_shim_file = generate_options_shim(); let mut config = gcc::Config::new(); for path in include_paths { @@ -73,6 +136,7 @@ fn build_openssl_shim(include_paths: &[PathBuf]) { } config.file("src/openssl_shim.c") + .file(options_shim_file) .compile("libopenssl_shim.a"); } diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 9f2041a4..08b2199d 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -155,6 +155,14 @@ pub const SSL_TLSEXT_ERR_ALERT_WARNING: c_int = 1; pub const SSL_TLSEXT_ERR_ALERT_FATAL: c_int = 2; pub const SSL_TLSEXT_ERR_NOACK: c_int = 3; +macro_rules! import_options { + ( $( $name:ident $val:expr )* ) => { + $( pub const $name: u64 = $val; )* + }; +} + +include!("ssl_options.rs"); + #[cfg(feature = "npn")] pub const OPENSSL_NPN_UNSUPPORTED: c_int = 0; #[cfg(feature = "npn")] @@ -262,8 +270,23 @@ pub fn init() { } } +pub unsafe fn SSL_CTX_set_options(ssl: *mut SSL_CTX, op: u64) -> u64 { + rust_openssl_ssl_ctx_options_c_to_rust(SSL_CTX_set_options_shim(ssl, rust_openssl_ssl_ctx_options_rust_to_c(op))) +} + +pub unsafe fn SSL_CTX_get_options(ssl: *mut SSL_CTX) -> u64 { + rust_openssl_ssl_ctx_options_c_to_rust(SSL_CTX_get_options_shim(ssl)) +} + +pub unsafe fn SSL_CTX_clear_options(ssl: *mut SSL_CTX, op: u64) -> u64 { + rust_openssl_ssl_ctx_options_c_to_rust(SSL_CTX_clear_options_shim(ssl, rust_openssl_ssl_ctx_options_rust_to_c(op))) +} + // True functions extern "C" { + fn rust_openssl_ssl_ctx_options_rust_to_c(rustval: u64) -> c_long; + fn rust_openssl_ssl_ctx_options_c_to_rust(cval: c_long) -> u64; + pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int; pub fn ASN1_STRING_type_new(ty: c_int) -> *mut ASN1_STRING; pub fn ASN1_TIME_free(tm: *mut ASN1_TIME); @@ -615,12 +638,9 @@ extern "C" { pub fn BIO_eof(b: *mut BIO) -> c_int; #[link_name = "BIO_set_mem_eof_return_shim"] pub fn BIO_set_mem_eof_return(b: *mut BIO, v: c_int); - #[link_name = "SSL_CTX_set_options_shim"] - pub fn SSL_CTX_set_options(ctx: *mut SSL_CTX, options: c_long) -> c_long; - #[link_name = "SSL_CTX_get_options_shim"] - pub fn SSL_CTX_get_options(ctx: *mut SSL_CTX) -> c_long; - #[link_name = "SSL_CTX_clear_options_shim"] - pub fn SSL_CTX_clear_options(ctx: *mut SSL_CTX, options: c_long) -> c_long; + pub fn SSL_CTX_set_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long; + pub fn SSL_CTX_get_options_shim(ctx: *mut SSL_CTX) -> c_long; + pub fn SSL_CTX_clear_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long; #[link_name = "SSL_CTX_add_extra_chain_cert_shim"] pub fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -> c_long; #[link_name = "SSL_CTX_set_read_ahead_shim"] diff --git a/openssl-sys/src/ssl_options.rs b/openssl-sys/src/ssl_options.rs new file mode 100644 index 00000000..a1c778ac --- /dev/null +++ b/openssl-sys/src/ssl_options.rs @@ -0,0 +1,46 @@ +import_options!{ +// The following values are directly from recent OpenSSL +SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001 +SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002 +SSL_OP_LEGACY_SERVER_CONNECT 0x00000004 +SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008 +SSL_OP_TLSEXT_PADDING 0x00000010 +SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020 +SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040 +SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080 +SSL_OP_TLS_D5_BUG 0x00000100 +SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200 +// unused: 0x00000400 +SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800 +SSL_OP_NO_QUERY_MTU 0x00001000 +SSL_OP_COOKIE_EXCHANGE 0x00002000 +SSL_OP_NO_TICKET 0x00004000 +SSL_OP_CISCO_ANYCONNECT 0x00008000 +SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000 +SSL_OP_NO_COMPRESSION 0x00020000 +SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000 +SSL_OP_SINGLE_ECDH_USE 0x00080000 +SSL_OP_SINGLE_DH_USE 0x00100000 +// unused: 0x00200000 +SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000 +SSL_OP_TLS_ROLLBACK_BUG 0x00800000 +SSL_OP_NO_SSLv2 0x01000000 +SSL_OP_NO_SSLv3 0x02000000 +SSL_OP_NO_DTLSv1 0x04000000 +SSL_OP_NO_TLSv1 0x04000000 +SSL_OP_NO_DTLSv1_2 0x08000000 +SSL_OP_NO_TLSv1_2 0x08000000 +SSL_OP_NO_TLSv1_1 0x10000000 +SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000 +SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000 +SSL_OP_CRYPTOPRO_TLSEXT_BUG 0x80000000 + +// The following values were in 32-bit range in old OpenSSL +SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x100000000 +SSL_OP_MSIE_SSLV2_RSA_PADDING 0x200000000 +SSL_OP_PKCS1_CHECK_1 0x400000000 +SSL_OP_PKCS1_CHECK_2 0x800000000 + +// The following values were redefined to 0 for security reasons +SSL_OP_EPHEMERAL_RSA 0x0 +} diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 88ba9af4..1338b1cb 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -46,35 +46,52 @@ fn init() { } bitflags! { - flags SslContextOptions: c_long { - const SSL_OP_LEGACY_SERVER_CONNECT = 0x00000004, - const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000008, - const SSL_OP_TLSEXT_PADDING = 0x00000010, - const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 0x00000020, - const SSL_OP_SAFARI_ECDHE_ECDSA_BUG = 0x00000040, - const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 0x00000080, - const SSL_OP_TLS_D5_BUG = 0x00000100, - const SSL_OP_TLS_BLOCK_PADDING_BUG = 0x00000200, - const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00000800, - const SSL_OP_ALL = 0x80000BFF, - const SSL_OP_NO_QUERY_MTU = 0x00001000, - const SSL_OP_COOKIE_EXCHANGE = 0x00002000, - const SSL_OP_NO_TICKET = 0x00004000, - const SSL_OP_CISCO_ANYCONNECT = 0x00008000, - const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00010000, - const SSL_OP_NO_COMPRESSION = 0x00020000, - const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = 0x00040000, - const SSL_OP_SINGLE_ECDH_USE = 0x00080000, - const SSL_OP_SINGLE_DH_USE = 0x00100000, - const SSL_OP_CIPHER_SERVER_PREFERENCE = 0x00400000, - const SSL_OP_TLS_ROLLBACK_BUG = 0x00800000, - const SSL_OP_NO_SSLV2 = 0x00000000, - const SSL_OP_NO_SSLV3 = 0x02000000, - const SSL_OP_NO_TLSV1 = 0x04000000, - const SSL_OP_NO_TLSV1_2 = 0x08000000, - const SSL_OP_NO_TLSV1_1 = 0x10000000, - const SSL_OP_NO_DTLSV1 = 0x04000000, - const SSL_OP_NO_DTLSV1_2 = 0x08000000 + flags SslContextOptions: u64 { + const SSL_OP_MICROSOFT_SESS_ID_BUG = ffi::SSL_OP_MICROSOFT_SESS_ID_BUG, + const SSL_OP_NETSCAPE_CHALLENGE_BUG = ffi::SSL_OP_NETSCAPE_CHALLENGE_BUG, + const SSL_OP_LEGACY_SERVER_CONNECT = ffi::SSL_OP_LEGACY_SERVER_CONNECT, + const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = ffi::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG, + const SSL_OP_TLSEXT_PADDING = ffi::SSL_OP_TLSEXT_PADDING, + const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = ffi::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER, + const SSL_OP_SAFARI_ECDHE_ECDSA_BUG = ffi::SSL_OP_SAFARI_ECDHE_ECDSA_BUG, + const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = ffi::SSL_OP_SSLEAY_080_CLIENT_DH_BUG, + const SSL_OP_TLS_D5_BUG = ffi::SSL_OP_TLS_D5_BUG, + const SSL_OP_TLS_BLOCK_PADDING_BUG = ffi::SSL_OP_TLS_BLOCK_PADDING_BUG, + const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS, + const SSL_OP_NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU, + const SSL_OP_COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE, + const SSL_OP_NO_TICKET = ffi::SSL_OP_NO_TICKET, + const SSL_OP_CISCO_ANYCONNECT = ffi::SSL_OP_CISCO_ANYCONNECT, + const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, + const SSL_OP_NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION, + const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, + const SSL_OP_SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE, + const SSL_OP_SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE, + const SSL_OP_CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE, + const SSL_OP_TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG, + const SSL_OP_NO_SSLV2 = ffi::SSL_OP_NO_SSLv2, + const SSL_OP_NO_SSLV3 = ffi::SSL_OP_NO_SSLv3, + const SSL_OP_NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1, + const SSL_OP_NO_TLSV1 = ffi::SSL_OP_NO_TLSv1, + const SSL_OP_NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2, + const SSL_OP_NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2, + const SSL_OP_NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1, + const SSL_OP_NETSCAPE_CA_DN_BUG = ffi::SSL_OP_NETSCAPE_CA_DN_BUG, + const SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = ffi::SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG, + const SSL_OP_CRYPTOPRO_TLSEXT_BUG = ffi::SSL_OP_CRYPTOPRO_TLSEXT_BUG, + const SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = ffi::SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG, + const SSL_OP_MSIE_SSLV2_RSA_PADDING = ffi::SSL_OP_MSIE_SSLV2_RSA_PADDING, + const SSL_OP_PKCS1_CHECK_1 = ffi::SSL_OP_PKCS1_CHECK_1, + const SSL_OP_PKCS1_CHECK_2 = ffi::SSL_OP_PKCS1_CHECK_2, + const SSL_OP_EPHEMERAL_RSA = ffi::SSL_OP_EPHEMERAL_RSA, + const SSL_OP_ALL = SSL_OP_MICROSOFT_SESS_ID_BUG.bits|SSL_OP_NETSCAPE_CHALLENGE_BUG.bits + |SSL_OP_LEGACY_SERVER_CONNECT.bits|SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG.bits + |SSL_OP_TLSEXT_PADDING.bits|SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER.bits + |SSL_OP_SAFARI_ECDHE_ECDSA_BUG.bits|SSL_OP_SSLEAY_080_CLIENT_DH_BUG.bits + |SSL_OP_TLS_D5_BUG.bits|SSL_OP_TLS_BLOCK_PADDING_BUG.bits + |SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS.bits|SSL_OP_CRYPTOPRO_TLSEXT_BUG.bits, + const SSL_OP_NO_SSL_MASK = SSL_OP_NO_SSLV2.bits|SSL_OP_NO_SSLV3.bits|SSL_OP_NO_TLSV1.bits + |SSL_OP_NO_TLSV1_1.bits|SSL_OP_NO_TLSV1_2.bits, } } From 6a725acf4ddb949dbc3b1365ebc340b5066bebad Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Mon, 22 Jun 2015 22:28:07 -0700 Subject: [PATCH 14/32] Remove #ifs for same-value shimmed SSL options. Depend on compiler optimization instead. --- openssl-sys/build.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index 841c7eec..b4a00566 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -101,9 +101,7 @@ fn generate_options_shim() -> PathBuf { writeln!(shim,"long rust_openssl_ssl_ctx_options_rust_to_c(uint64_t rustval) {{").unwrap(); writeln!(shim," long cval=rustval©_MASK;").unwrap(); for &(name,_) in options { - writeln!(shim,"#if RUST_{0}!={0}",name).unwrap(); writeln!(shim," if (rustval&RUST_{0}) cval|={0};",name).unwrap(); - writeln!(shim,"#endif").unwrap(); } writeln!(shim," return cval;").unwrap(); writeln!(shim,"}}").unwrap(); @@ -111,9 +109,7 @@ fn generate_options_shim() -> PathBuf { writeln!(shim,"uint64_t rust_openssl_ssl_ctx_options_c_to_rust(long cval) {{").unwrap(); writeln!(shim," uint64_t rustval=cval©_MASK;").unwrap(); for &(name,_) in options { - writeln!(shim,"#if RUST_{0}!={0}",name).unwrap(); writeln!(shim," if (cval&{0}) rustval|=RUST_{0};",name).unwrap(); - writeln!(shim,"#endif").unwrap(); } writeln!(shim," return rustval;").unwrap(); writeln!(shim,"}}").unwrap(); From 11bcac01ecd1b7ba8d758b814ff65dc1dc3ac7e6 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Sun, 14 Jun 2015 17:25:05 -0700 Subject: [PATCH 15/32] Replace CN field by names vector --- openssl/src/x509/mod.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 423a258f..b8114384 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -145,7 +145,7 @@ pub use self::extension::ExtKeyUsageOption as ExtKeyUsage; pub struct X509Generator { bits: u32, days: u32, - CN: String, + names: Vec<(String,String)>, // RFC 3280 §4.2: A certificate MUST NOT include more than one instance of a particular extension. extensions: HashMap, hash_type: HashType, @@ -165,7 +165,7 @@ impl X509Generator { X509Generator { bits: 1024, days: 365, - CN: "rust-openssl".to_string(), + names: vec![], extensions: HashMap::new(), hash_type: HashType::SHA1 } @@ -186,7 +186,13 @@ impl X509Generator { #[allow(non_snake_case)] /// Sets Common Name of certificate pub fn set_CN(mut self, CN: &str) -> X509Generator { - self.CN = CN.to_string(); + match self.names.get_mut(0) { + Some(&mut(_,ref mut val)) => *val=CN.to_string(), + _ => {} /* would move push here, but borrow checker won't let me */ + } + if self.names.len()==0 { + self.names.push(("CN".to_string(),CN.to_string())); + } self } @@ -333,7 +339,15 @@ impl X509Generator { let name = ffi::X509_get_subject_name(x509.handle); try_ssl_null!(name); - try!(X509Generator::add_name(name, "CN", &self.CN)); + let default=[("CN","rust-openssl")]; + let default_iter=&mut default.iter().map(|&(k,v)|(k,v)); + let arg_iter=&mut self.names.iter().map(|&(ref k,ref v)|(&k[..],&v[..])); + let iter: &mut Iterator = + if self.names.len()==0 { default_iter } else { arg_iter }; + + for (key,val) in iter { + try!(X509Generator::add_name(name, &key, &val)); + } ffi::X509_set_issuer_name(x509.handle, name); for (exttype,ext) in self.extensions.iter() { From f2b0da1de79b0980b851f704d0eb28baaf985fc2 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Sun, 14 Jun 2015 17:25:35 -0700 Subject: [PATCH 16/32] Add public add_name method to X509Generator --- openssl/src/x509/mod.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index b8114384..f624d7ab 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -184,7 +184,10 @@ impl X509Generator { } #[allow(non_snake_case)] - /// Sets Common Name of certificate + /// (deprecated) Sets Common Name of certificate + /// + /// This function is deprecated, use `X509Generator.add_name` instead. + /// Don't use this function AND the `add_name` method pub fn set_CN(mut self, CN: &str) -> X509Generator { match self.names.get_mut(0) { Some(&mut(_,ref mut val)) => *val=CN.to_string(), @@ -196,6 +199,16 @@ impl X509Generator { self } + /// Add attribute to the name of the certificate + /// + /// ```ignore + /// generator.add_name("CN".to_string(),"example.com".to_string()) + /// ``` + pub fn add_name(mut self, attr_type: String, attr_value: String) -> X509Generator { + self.names.push((attr_type,attr_value)); + self + } + /// (deprecated) Sets what for certificate could be used /// /// This function is deprecated, use `X509Generator.add_extension` instead. @@ -273,7 +286,7 @@ impl X509Generator { } } - fn add_name(name: *mut ffi::X509_NAME, key: &str, value: &str) -> Result<(), SslError> { + fn add_name_internal(name: *mut ffi::X509_NAME, key: &str, value: &str) -> Result<(), SslError> { let value_len = value.len() as c_int; lift_ssl!(unsafe { let key = CString::new(key.as_bytes()).unwrap(); @@ -346,7 +359,7 @@ impl X509Generator { if self.names.len()==0 { default_iter } else { arg_iter }; for (key,val) in iter { - try!(X509Generator::add_name(name, &key, &val)); + try!(X509Generator::add_name_internal(name, &key, &val)); } ffi::X509_set_issuer_name(x509.handle, name); From 1bcbe8f4bc3f06f3e4ac08d060b27c81e42ad68b Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 15:40:36 -0700 Subject: [PATCH 17/32] Add X509generator.add_names method --- openssl/src/x509/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index f624d7ab..717afa65 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -209,6 +209,17 @@ impl X509Generator { self } + /// Add multiple attributes to the name of the certificate + /// + /// ```ignore + /// generator.add_names(vec![("CN".to_string(),"example.com".to_string())]); + /// ``` + pub fn add_names(mut self, attrs: I) -> X509Generator + where I: IntoIterator { + self.names.extend(attrs); + self + } + /// (deprecated) Sets what for certificate could be used /// /// This function is deprecated, use `X509Generator.add_extension` instead. From e3c562d6a04649e97863224a7c32d1130650c755 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 15:41:20 -0700 Subject: [PATCH 18/32] Fix/add more X509generator tests --- openssl/src/x509/mod.rs | 8 +++++--- openssl/src/x509/tests.rs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 717afa65..67258da5 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -201,8 +201,9 @@ impl X509Generator { /// Add attribute to the name of the certificate /// - /// ```ignore - /// generator.add_name("CN".to_string(),"example.com".to_string()) + /// ``` + /// # let generator = openssl::x509::X509Generator::new(); + /// generator.add_name("CN".to_string(),"example.com".to_string()); /// ``` pub fn add_name(mut self, attr_type: String, attr_value: String) -> X509Generator { self.names.push((attr_type,attr_value)); @@ -211,7 +212,8 @@ impl X509Generator { /// Add multiple attributes to the name of the certificate /// - /// ```ignore + /// ``` + /// # let generator = openssl::x509::X509Generator::new(); /// generator.add_names(vec![("CN".to_string(),"example.com".to_string())]); /// ``` pub fn add_names(mut self, attrs: I) -> X509Generator diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 8417ee5c..0aed364b 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -16,7 +16,7 @@ fn test_cert_gen() { let gen = X509Generator::new() .set_bitlength(2048) .set_valid_period(365*2) - .set_CN("test_me") + .add_name("CN".to_string(),"test_me".to_string()) .set_sign_hash(SHA256) .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999.1".to_owned())])) From 1e4cba36e8f302942df229f53ec5c4f5467d4c7c Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 8 Jul 2015 11:05:18 -0700 Subject: [PATCH 19/32] Add missing C-string conversion, fixing recent build errors --- openssl/src/x509/mod.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 67258da5..a5df80f5 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -285,10 +285,13 @@ impl X509Generator { mem::transmute(&ctx), nid as c_int, value.as_ptr() as *mut c_char), - None => ffi::X509V3_EXT_conf(ptr::null_mut(), + None => { + let name=CString::new(exttype.get_name().unwrap().as_bytes()).unwrap(); + ffi::X509V3_EXT_conf(ptr::null_mut(), mem::transmute(&ctx), - exttype.get_name().unwrap().as_ptr() as *mut c_char, - value.as_ptr() as *mut c_char), + name.as_ptr() as *mut c_char, + value.as_ptr() as *mut c_char) + } }; let mut success = false; if ext != ptr::null_mut() { From 90dd54b541cb632ca450e68c88c9f36068a559d5 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Wed, 8 Jul 2015 13:37:35 -0700 Subject: [PATCH 20/32] Implement certificate extensions for certificate requests --- openssl-sys/src/lib.rs | 6 ++++++ openssl-sys/src/openssl_shim.c | 4 ++++ openssl/src/x509/mod.rs | 17 +++++++++++++---- openssl/src/x509/tests.rs | 25 ++++++++++++++++++++----- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 5317ff20..f9a60941 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -37,6 +37,7 @@ pub type X509_NAME = c_void; pub type X509_NAME_ENTRY = c_void; pub type X509_REQ = c_void; pub type X509_STORE_CTX = c_void; +pub type stack_st_X509_EXTENSION = c_void; #[repr(C)] pub struct EVP_MD_CTX { @@ -629,6 +630,9 @@ extern "C" { pub fn X509V3_EXT_conf(conf: *mut c_void, ctx: *mut X509V3_CTX, name: *mut c_char, value: *mut c_char) -> *mut X509_EXTENSION; pub fn X509V3_set_ctx(ctx: *mut X509V3_CTX, issuer: *mut X509, subject: *mut X509, req: *mut X509_REQ, crl: *mut X509_CRL, flags: c_int); + pub fn X509_REQ_add_extensions(req: *mut X509_REQ, exts: *mut stack_st_X509_EXTENSION) -> c_int; + pub fn X509_REQ_sign(x: *mut X509_REQ, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int; + pub fn i2d_RSA_PUBKEY(k: *mut RSA, buf: *const *mut u8) -> c_int; pub fn d2i_RSA_PUBKEY(k: *const *mut RSA, buf: *const *const u8, len: c_uint) -> *mut RSA; pub fn i2d_RSAPrivateKey(k: *mut RSA, buf: *const *mut u8) -> c_int; @@ -648,6 +652,8 @@ extern "C" { pub fn SSL_CTX_set_read_ahead(ctx: *mut SSL_CTX, m: c_long) -> c_long; #[link_name = "SSL_set_tlsext_host_name_shim"] pub fn SSL_set_tlsext_host_name(s: *mut SSL, name: *const c_char) -> c_long; + #[link_name = "X509_get_extensions_shim"] + pub fn X509_get_extensions(x: *mut X509) -> *mut stack_st_X509_EXTENSION; } pub mod probe; diff --git a/openssl-sys/src/openssl_shim.c b/openssl-sys/src/openssl_shim.c index 7b4f9c74..f0622d2d 100644 --- a/openssl-sys/src/openssl_shim.c +++ b/openssl-sys/src/openssl_shim.c @@ -82,3 +82,7 @@ long SSL_CTX_set_read_ahead_shim(SSL_CTX *ctx, long m) { long SSL_set_tlsext_host_name_shim(SSL *s, char *name) { return SSL_set_tlsext_host_name(s, name); } + +STACK_OF(X509_EXTENSION) *X509_get_extensions_shim(X509 *x) { + return x->cert_info ? x->cert_info->extensions : NULL; +} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index a5df80f5..91daa66a 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -396,11 +396,20 @@ impl X509Generator { Err(x) => return Err(x) }; - let hash_fn = self.hash_type.evp_md(); - let req = unsafe { ffi::X509_to_X509_REQ(cert.handle, p_key.get_handle(), hash_fn) }; - try_ssl_null!(req); + unsafe { + let req = ffi::X509_to_X509_REQ(cert.handle, ptr::null_mut(), ptr::null()); + try_ssl_null!(req); - Ok(X509Req::new(req)) + let exts = ffi::X509_get_extensions(cert.handle); + if exts != ptr::null_mut() { + try_ssl!(ffi::X509_REQ_add_extensions(req,exts)); + } + + let hash_fn = self.hash_type.evp_md(); + try_ssl!(ffi::X509_REQ_sign(req, p_key.get_handle(), hash_fn)); + + Ok(X509Req::new(req)) + } } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 0aed364b..692539ba 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -4,6 +4,7 @@ use std::path::Path; use std::fs::File; use crypto::hash::Type::{SHA256}; +use crypto::pkey::PKey; use x509::{X509, X509Generator}; use x509::extension::Extension::{KeyUsage,ExtKeyUsage,SubjectAltName,OtherNid,OtherStr}; use x509::extension::AltNameOption as SAN; @@ -11,9 +12,8 @@ use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; use nid::Nid; -#[test] -fn test_cert_gen() { - let gen = X509Generator::new() +fn get_generator() -> X509Generator { + X509Generator::new() .set_bitlength(2048) .set_valid_period(365*2) .add_name("CN".to_string(),"test_me".to_string()) @@ -22,9 +22,12 @@ fn test_cert_gen() { .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999.1".to_owned())])) .add_extension(SubjectAltName(vec![(SAN::DNS,"example.com".to_owned())])) .add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())) - .add_extension(OtherStr("2.999.2".to_owned(),"ASN1:UTF8:example value".to_owned())); + .add_extension(OtherStr("2.999.2".to_owned(),"ASN1:UTF8:example value".to_owned())) +} - let (cert, pkey) = gen.generate().unwrap(); +#[test] +fn test_cert_gen() { + let (cert, pkey) = get_generator().generate().unwrap(); cert.write_pem(&mut io::sink()).unwrap(); pkey.write_pem(&mut io::sink()).unwrap(); @@ -34,6 +37,18 @@ fn test_cert_gen() { assert_eq!(pkey.save_pub(), cert.public_key().save_pub()); } +#[test] +fn test_req_gen() { + let mut pkey = PKey::new(); + pkey.gen(512); + + let req = get_generator().request(&pkey).unwrap(); + req.write_pem(&mut io::sink()).unwrap(); + + // FIXME: check data in result to be correct, needs implementation + // of X509_REQ getters +} + #[test] fn test_cert_loading() { let cert_path = Path::new("test/cert.pem"); From b478c29151b7818dcf5b789408e76c379df1c9b1 Mon Sep 17 00:00:00 2001 From: Allen Welkie Date: Wed, 15 Jul 2015 20:45:18 -0400 Subject: [PATCH 21/32] Added AES CTR-mode under feature flag. --- openssl-sys/Cargo.toml | 1 + openssl-sys/src/lib.rs | 6 ++++-- openssl/Cargo.toml | 1 + openssl/src/crypto/symm.rs | 27 ++++++++++++++++----------- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 5ed9d068..85a6aeb5 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -18,6 +18,7 @@ dtlsv1 = [] dtlsv1_2 = [] sslv2 = [] aes_xts = [] +aes_ctr = [] npn = [] alpn = [] diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 5317ff20..556f3c8d 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -397,13 +397,15 @@ extern "C" { pub fn EVP_aes_128_ecb() -> *const EVP_CIPHER; #[cfg(feature = "aes_xts")] pub fn EVP_aes_128_xts() -> *const EVP_CIPHER; - // fn EVP_aes_128_ctr() -> EVP_CIPHER; + #[cfg(feature = "aes_ctr")] + pub fn EVP_aes_128_ctr() -> *const EVP_CIPHER; // fn EVP_aes_128_gcm() -> EVP_CIPHER; pub fn EVP_aes_256_cbc() -> *const EVP_CIPHER; pub fn EVP_aes_256_ecb() -> *const EVP_CIPHER; #[cfg(feature = "aes_xts")] pub fn EVP_aes_256_xts() -> *const EVP_CIPHER; - // fn EVP_aes_256_ctr() -> EVP_CIPHER; + #[cfg(feature = "aes_ctr")] + pub fn EVP_aes_256_ctr() -> *const EVP_CIPHER; // fn EVP_aes_256_gcm() -> EVP_CIPHER; pub fn EVP_rc4() -> *const EVP_CIPHER; diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 8a6b4ddc..c230aa04 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -16,6 +16,7 @@ dtlsv1 = ["openssl-sys/dtlsv1"] dtlsv1_2 = ["openssl-sys/dtlsv1_2"] sslv2 = ["openssl-sys/sslv2"] aes_xts = ["openssl-sys/aes_xts"] +aes_ctr = ["openssl-sys/aes_ctr"] npn = ["openssl-sys/npn"] alpn = ["openssl-sys/alpn"] diff --git a/openssl/src/crypto/symm.rs b/openssl/src/crypto/symm.rs index 82c668ba..79cffcc6 100644 --- a/openssl/src/crypto/symm.rs +++ b/openssl/src/crypto/symm.rs @@ -18,7 +18,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,7 +27,8 @@ 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, @@ -39,14 +41,16 @@ fn evpc(t: Type) -> (*const ffi::EVP_CIPHER, u32, u32) { 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), + #[cfg(feature = "aes_ctr")] + Type::AES_128_CTR => (ffi::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), + #[cfg(feature = "aes_ctr")] + Type::AES_256_CTR => (ffi::EVP_aes_256_ctr(), 32, 0), //AES_256_GCM => (EVP_aes_256_gcm(), 32, 16), Type::RC4_128 => (ffi::EVP_rc4(), 16, 0), @@ -288,16 +292,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() { From a43011d77c26b0a371565ffe284611091cfd1de3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6lling?= Date: Sat, 18 Jul 2015 12:48:40 +0200 Subject: [PATCH 22/32] Fix probelms with DTLS when no packets are pending. When using DTLS you might run into the situation where no packets are pending, so SSL_read returns len=0. On a TLS connection this means that the connection was closed, but on DTLS it does not (a DTLS connection cannot be closed in the usual sense). This commit fixes a bug introduced by c8d23f3. Conflicts: openssl/src/ssl/mod.rs --- openssl-sys/src/lib.rs | 1 + openssl/src/ssl/mod.rs | 36 +++++++++++++++++++++++++++++++++++- openssl/src/ssl/tests.rs | 7 ++++++- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 5317ff20..a76b5e95 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -525,6 +525,7 @@ extern "C" { pub fn SSL_get_SSL_CTX(ssl: *mut SSL) -> *mut SSL_CTX; pub fn SSL_get_current_compression(ssl: *mut SSL) -> *const COMP_METHOD; pub fn SSL_get_peer_certificate(ssl: *mut SSL) -> *mut X509; + pub fn SSL_get_ssl_method(ssl: *mut SSL) -> *const SSL_METHOD; pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 1338b1cb..bd077922 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -141,6 +141,25 @@ impl SslMethod { } } + unsafe fn from_raw(method: *const ffi::SSL_METHOD) -> Option { + match method { + #[cfg(feature = "sslv2")] + x if x == ffi::SSLv2_method() => Some(SslMethod::Sslv2), + x if x == ffi::SSLv3_method() => Some(SslMethod::Sslv3), + x if x == ffi::TLSv1_method() => Some(SslMethod::Tlsv1), + x if x == ffi::SSLv23_method() => Some(SslMethod::Sslv23), + #[cfg(feature = "tlsv1_1")] + x if x == ffi::TLSv1_1_method() => Some(SslMethod::Tlsv1_1), + #[cfg(feature = "tlsv1_2")] + x if x == ffi::TLSv1_2_method() => Some(SslMethod::Tlsv1_2), + #[cfg(feature = "dtlsv1")] + x if x == ffi::DTLSv1_method() => Some(SslMethod::Dtlsv1), + #[cfg(feature = "dtlsv1_2")] + x if x == ffi::DTLSv1_2_method() => Some(SslMethod::Dtlsv1_2), + _ => None, + } + } + #[cfg(feature = "dtlsv1")] pub fn is_dtlsv1(&self) -> bool { *self == SslMethod::Dtlsv1 @@ -787,6 +806,13 @@ impl Ssl { ffi::SSL_pending(self.ssl) as usize } } + + pub fn get_ssl_method(&self) -> Option { + unsafe { + let method = ffi::SSL_get_ssl_method(self.ssl); + SslMethod::from_raw(method) + } + } } macro_rules! make_LibSslError { @@ -888,8 +914,16 @@ impl IndirectStream { LibSslError::ErrorWantRead => { try_ssl_stream!(self.flush()); let len = try_ssl_stream!(self.stream.read(&mut self.buf[..])); + + if len == 0 { - self.ssl.get_rbio().set_eof(true); + let method = self.ssl.get_ssl_method(); + + if method.map(|m| m.is_dtls()).unwrap_or(false) { + return Ok(0); + } else { + self.ssl.get_rbio().set_eof(true); + } } else { try_ssl_stream!(self.ssl.get_rbio().write_all(&self.buf[..len])); } diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index 8401836d..3a8ffa2b 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -51,7 +51,7 @@ macro_rules! run_test( use std::net::TcpStream; use ssl; use ssl::SslMethod; - use ssl::{SslContext, SslStream, VerifyCallback}; + use ssl::{SslContext, Ssl, SslStream, VerifyCallback}; use ssl::SSL_VERIFY_PEER; use crypto::hash::Type::SHA256; use x509::X509StoreContext; @@ -86,6 +86,11 @@ run_test!(new_sslstream, |method, stream| { SslStream::connect_generic(&SslContext::new(method).unwrap(), stream).unwrap(); }); +run_test!(get_ssl_method, |method, _| { + let ssl = Ssl::new(&SslContext::new(method).unwrap()).unwrap(); + assert_eq!(ssl.get_ssl_method(), Some(method)); +}); + run_test!(verify_untrusted, |method, stream| { let mut ctx = SslContext::new(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER, None); From 3fc8482d368530ff619cc580f9d4f16344cbb3c5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 23 Jul 2015 21:50:49 -0700 Subject: [PATCH 23/32] Make curl follow redirects --- openssl/test/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/test/build.sh b/openssl/test/build.sh index 27def60a..9334083d 100755 --- a/openssl/test/build.sh +++ b/openssl/test/build.sh @@ -4,7 +4,7 @@ set -e mkdir /tmp/openssl cd /tmp/openssl sudo apt-get install gcc make -curl https://openssl.org/source/openssl-1.0.2-latest.tar.gz | tar --strip-components=1 -xzf - +curl -L https://openssl.org/source/openssl-1.0.2-latest.tar.gz | tar --strip-components=1 -xzf - ./config --prefix=/usr/ shared make sudo make install From ab7bfad225c36bc29c3513fb8c2b5b97743dfe3e Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Sun, 19 Jul 2015 00:11:07 -0700 Subject: [PATCH 24/32] Add function to write RSA public key as PEM --- openssl-sys/src/lib.rs | 1 + openssl/src/crypto/pkey.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 5317ff20..7ff600c3 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -468,6 +468,7 @@ extern "C" { kstr: *mut c_char, klen: c_int, callback: Option, user_data: *mut c_void) -> c_int; + pub fn PEM_write_bio_PUBKEY(bp: *mut BIO, x: *mut EVP_PKEY) -> c_int; pub fn PEM_write_bio_X509(bio: *mut BIO, x509: *mut X509) -> c_int; pub fn PEM_write_bio_X509_REQ(bio: *mut BIO, x509: *mut X509_REQ) -> c_int; 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(&self, writer: &mut W/*, password: Option*/) -> 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")); + } } From c7eded31a76fad3b746420f502132c8b71377808 Mon Sep 17 00:00:00 2001 From: panicbit Date: Sun, 26 Jul 2015 18:28:25 +0200 Subject: [PATCH 25/32] Expose ssl::init --- openssl/src/ssl/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 1338b1cb..4d7b7ab8 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -30,7 +30,9 @@ mod tests; static mut VERIFY_IDX: c_int = -1; -fn init() { +/// Manually initialize SSL. +/// It is optional to call this function and safe to do so more than once. +pub fn init() { static mut INIT: Once = ONCE_INIT; unsafe { From d193198ae9fa57907ad0454b084a8719f121d629 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 2 Aug 2015 22:25:33 -0400 Subject: [PATCH 26/32] Add new feature to travis tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7df1431a..2b056d10 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ os: - linux env: global: - - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv2 aes_xts npn alpn" + - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv2 aes_xts npn alpn aes_ctr" before_install: - (test $TRAVIS_OS_NAME == "osx" || ./openssl/test/build.sh) before_script: From 69cbd145407288e3b22b7336fe6a679546b4b2fd Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 8 Aug 2015 12:24:21 -0700 Subject: [PATCH 27/32] Handle WantWrite and WantRead errors --- openssl/src/ssl/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 6cbd6f88..9781efe5 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1046,6 +1046,14 @@ impl DirectStream { err } } + LibSslError::ErrorWantWrite => { + SslError::StreamError(io::Error::new(io::ErrorKind::TimedOut, + "socket write timed out")) + } + LibSslError::ErrorWantRead => { + SslError::StreamError(io::Error::new(io::ErrorKind::TimedOut, + "socket read timed out")) + } err => panic!("unexpected error {:?} with ret {}", err, ret), } } From df32e53afad3e62ff845ab9cf8d3d22e1c7c9dcb Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 10 Aug 2015 22:29:34 -0400 Subject: [PATCH 28/32] Grab errno for directstream want errors --- openssl/src/ssl/mod.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 9781efe5..0d7351dc 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1046,13 +1046,8 @@ impl DirectStream { err } } - LibSslError::ErrorWantWrite => { - SslError::StreamError(io::Error::new(io::ErrorKind::TimedOut, - "socket write timed out")) - } - LibSslError::ErrorWantRead => { - SslError::StreamError(io::Error::new(io::ErrorKind::TimedOut, - "socket read timed out")) + LibSslError::ErrorWantWrite | LibSslError::ErrorWantRead => { + SslError::StreamError(io::Error::last_os_error()) } err => panic!("unexpected error {:?} with ret {}", err, ret), } From fa5c4cb5dfb1abfcd999fb7a16891f5da155b105 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 15 Aug 2015 14:37:03 -0700 Subject: [PATCH 29/32] Fix openssl source link in tests --- openssl/test/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/test/build.sh b/openssl/test/build.sh index 9334083d..db517ab3 100755 --- a/openssl/test/build.sh +++ b/openssl/test/build.sh @@ -4,7 +4,7 @@ set -e mkdir /tmp/openssl cd /tmp/openssl sudo apt-get install gcc make -curl -L https://openssl.org/source/openssl-1.0.2-latest.tar.gz | tar --strip-components=1 -xzf - +curl https://openssl.org/source/openssl-1.0.2d.tar.gz | tar --strip-components=1 -xzf - ./config --prefix=/usr/ shared make sudo make install From 3fe3d57976664c76212ac9b8abcf876baeb3d1f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6lling?= Date: Fri, 14 Aug 2015 20:16:10 +0200 Subject: [PATCH 30/32] Add get_state_string() --- openssl-sys/src/lib.rs | 2 ++ openssl/src/ssl/mod.rs | 27 +++++++++++++++++++++++++++ openssl/src/ssl/tests.rs | 8 ++++++++ 3 files changed, 37 insertions(+) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 55ec30bb..f901a454 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -529,6 +529,8 @@ extern "C" { pub fn SSL_get_current_compression(ssl: *mut SSL) -> *const COMP_METHOD; pub fn SSL_get_peer_certificate(ssl: *mut SSL) -> *mut X509; pub fn SSL_get_ssl_method(ssl: *mut SSL) -> *const SSL_METHOD; + pub fn SSL_state_string(ssl: *mut SSL) -> *const c_char; + pub fn SSL_state_string_long(ssl: *mut SSL) -> *const c_char; pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 0d7351dc..35180d3a 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -6,6 +6,7 @@ use std::fmt; use std::io; use std::io::prelude::*; use std::mem; +use std::str; use std::net; use std::path::Path; use std::ptr; @@ -690,6 +691,24 @@ impl Ssl { Ok(ssl) } + pub fn get_state_string(&self) -> &'static str { + let state = unsafe { + let ptr = ffi::SSL_state_string(self.ssl); + CStr::from_ptr(ptr) + }; + + str::from_utf8(state.to_bytes()).unwrap() + } + + pub fn get_state_string_long(&self) -> &'static str { + let state = unsafe { + let ptr = ffi::SSL_state_string_long(self.ssl); + CStr::from_ptr(ptr) + }; + + str::from_utf8(state.to_bytes()).unwrap() + } + fn get_rbio<'a>(&'a self) -> MemBioRef<'a> { unsafe { self.wrap_bio(ffi::SSL_get_rbio(self.ssl)) } } @@ -1316,6 +1335,14 @@ impl SslStream { pub fn pending(&self) -> usize { self.kind.ssl().pending() } + + pub fn get_state_string(&self) -> &'static str { + self.kind.ssl().get_state_string() + } + + pub fn get_state_string_long(&self) -> &'static str { + self.kind.ssl().get_state_string_long() + } } impl Read for SslStream { diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs index 3a8ffa2b..9198a642 100644 --- a/openssl/src/ssl/tests.rs +++ b/openssl/src/ssl/tests.rs @@ -395,6 +395,14 @@ fn test_pending() { assert_eq!(pending, len); } +#[test] +fn test_state() { + let tcp = TcpStream::connect("127.0.0.1:15418").unwrap(); + let stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + assert_eq!(stream.get_state_string(), "SSLOK "); + assert_eq!(stream.get_state_string_long(), "SSL negotiation finished successfully"); +} + /// Tests that connecting with the client using NPN, but the server not does not /// break the existing connection behavior. #[test] From 8067565707d69c67b4815113764d26d820ae2bbf Mon Sep 17 00:00:00 2001 From: Edward Barnard Date: Mon, 3 Aug 2015 18:22:07 +0100 Subject: [PATCH 31/32] Expose EVP_BytesToKey This is based on work by pyrho. Closes #88 --- openssl-sys/src/lib.rs | 6 ++ openssl/src/crypto/mod.rs | 2 + openssl/src/crypto/pkcs5.rs | 109 ++++++++++++++++++++++++++++ openssl/src/crypto/symm.rs | 24 +----- openssl/src/crypto/symm_internal.rs | 26 +++++++ 5 files changed, 144 insertions(+), 23 deletions(-) create mode 100644 openssl/src/crypto/symm_internal.rs diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 55ec30bb..e5efbdfa 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -128,6 +128,8 @@ pub const MBSTRING_UTF8: c_int = MBSTRING_FLAG; pub const NID_ext_key_usage: c_int = 126; pub const NID_key_usage: c_int = 83; +pub const PKCS5_SALT_LEN: c_int = 8; + pub const SSL_CTRL_OPTIONS: c_int = 32; pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77; @@ -409,6 +411,10 @@ extern "C" { // fn EVP_aes_256_gcm() -> EVP_CIPHER; pub fn EVP_rc4() -> *const EVP_CIPHER; + pub fn EVP_BytesToKey(typ: *const EVP_CIPHER, md: *const EVP_MD, + salt: *const u8, data: *const u8, datalen: c_int, + count: c_int, key: *mut u8, iv: *mut u8) -> c_int; + pub fn EVP_CIPHER_CTX_new() -> *mut EVP_CIPHER_CTX; pub fn EVP_CIPHER_CTX_set_padding(ctx: *mut EVP_CIPHER_CTX, padding: c_int) -> c_int; pub fn EVP_CIPHER_CTX_free(ctx: *mut EVP_CIPHER_CTX); 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, + pub iv: Vec +} + +/// 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 { 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/symm.rs b/openssl/src/crypto/symm.rs index 79cffcc6..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)] @@ -34,29 +35,6 @@ pub enum Type { 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), - #[cfg(feature = "aes_ctr")] - Type::AES_128_CTR => (ffi::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), - #[cfg(feature = "aes_ctr")] - Type::AES_256_CTR => (ffi::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 { 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 From 7b0b70bd13f43a66d1e58e58e8d5707814262ef9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 31 Aug 2015 19:10:27 -0700 Subject: [PATCH 32/32] Release v0.6.5 --- README.md | 2 +- openssl-sys/Cargo.toml | 4 ++-- openssl-sys/src/lib.rs | 2 +- openssl/Cargo.toml | 4 ++-- openssl/src/lib.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index aafabaee..06b9b7f8 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/sfackler/rust-openssl.svg?branch=master)](https://travis-ci.org/sfackler/rust-openssl) -[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.6.4/openssl). +[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.6.5/openssl). ## Building diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 85a6aeb5..437f7fb6 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "openssl-sys" -version = "0.6.4" +version = "0.6.5" authors = ["Alex Crichton ", "Steven Fackler "] license = "MIT" description = "FFI bindings to OpenSSL" repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.4/openssl_sys" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.5/openssl_sys" links = "openssl" build = "build.rs" diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index b3025be1..0e0ef8a5 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] #![allow(dead_code)] -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.4")] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.5")] extern crate libc; diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index c230aa04..b8bc357d 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "openssl" -version = "0.6.4" +version = "0.6.5" authors = ["Steven Fackler "] license = "Apache-2.0" description = "OpenSSL bindings" repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.4/openssl" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.6.5/openssl" readme = "../README.md" keywords = ["crypto", "tls", "ssl", "dtls"] diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 62d18dce..17e625b9 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.4")] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.6.5")] #[macro_use] extern crate bitflags;