From 6ef819f9718c3b43551461b72c531c2eeee878f9 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 8 Feb 2015 23:30:34 -0800 Subject: [PATCH] Fix builds against 0.9.x OpenSSL Namely builds on OSX --- README.md | 11 ----- openssl-sys/Cargo.toml | 3 +- openssl-sys/build.rs | 70 ++++++++++++++++-------------- openssl-sys/src/lib.rs | 8 ++++ openssl-sys/src/old_openssl_shim.c | 49 +++++++++++++++++++++ openssl/src/crypto/hmac.rs | 17 ++++---- 6 files changed, 105 insertions(+), 53 deletions(-) create mode 100644 openssl-sys/src/old_openssl_shim.c diff --git a/README.md b/README.md index 4216ca78..f97332e7 100644 --- a/README.md +++ b/README.md @@ -40,17 +40,6 @@ Rust install's libs folder. The default should be: respectively. 5. Run `cargo build`. -###OS X - -OS X is shipped with extremely outdated openssl. We recommend to update it. If you're using Homebrew it should be as easy as: - -```bash -brew install openssl -brew link openssl --force -``` - -Note that you need to execute `cargo clean` in your project directory to rebuild `rust-openssl` with the new version of `openssl`. - ###Testing Several tests expect a local test server to be running to bounce requests off of. It's easy to do this. Open a separate terminal window and `cd` to the diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 8f7e2bce..e0f50ccc 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -18,7 +18,8 @@ sslv2 = [] aes_xts = [] [build-dependencies] -pkg-config = "0.1.1" +pkg-config = "0.2" +gcc = "0.1" [target.le32-unknown-nacl.dependencies] libressl-pnacl-sys = "2.1.0" diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index a7b39e84..f7b7463f 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -1,44 +1,50 @@ -#![feature(core, collections, env)] +#![feature(env)] extern crate "pkg-config" as pkg_config; +extern crate gcc; use std::env; +use std::default::Default; fn main() { let target = env::var_string("TARGET").unwrap(); - let is_android = target.find_str("android").is_some(); - // Without hackory, pkg-config will only look for host libraries. - // So, abandon ship if we're cross compiling. - if !is_android && !pkg_config::target_supported() { - panic!("unsupported target"); + if target.contains("android") { + let path = env::var_string("OPENSSL_PATH").ok() + .expect("Android does not provide openssl libraries, please build them yourself \ + (instructions in the README) and provide their location through \ + $OPENSSL_PATH."); + println!("cargo:rustc-flags=-L native={} -l crypto:static -l ssl:static", path); + return; } - if pkg_config::find_library("openssl").is_err() { - let mut flags = if is_android { - " -l crypto:static -l ssl:static" - } else { - " -l crypto -l ssl" - }.to_string(); - - let win_pos = target.find_str("windows") - .or(target.find_str("win32")) - .or(target.find_str("win64")); - - // It's fun, but it looks like win32 and win64 both - // have all the libs with 32 sufix - if win_pos.is_some() { - flags.push_str(" -l gdi32 -l wsock32"); - } - - if is_android { - let path = env::var_string("OPENSSL_PATH").ok() - .expect("Android does not provide openssl libraries, please build them yourselves \ - (instructions in the README) and provide their location through \ - $OPENSSL_PATH."); - flags.push_str(format!(" -L {}", path).as_slice()); - } - - println!("cargo:rustc-flags={}", flags); + if target.contains("win32") || target.contains("win64") { + println!("cargo:rustc-flags=-l crypto -l ssl -l gdi32 -l wsock32"); + return; } + + if pkg_config::Config::new().atleast_version("1.0.0").find("openssl").is_ok() { + build_old_openssl_shim(false); + return; + } + + if pkg_config::find_library("openssl").is_ok() { + build_old_openssl_shim(true); + return; + } + + panic!("Unable to find openssl libraries"); +} + +fn build_old_openssl_shim(is_old: bool) { + let mut config: gcc::Config = Default::default(); + if is_old { + config.definitions.push(("OLD_OPENSSL".to_string(), None)); + } + + gcc::compile_library("libold_openssl_shim.a", + &config, + &["src/old_openssl_shim.c"]); + let out_dir = env::var_string("OUT_DIR").unwrap(); + println!("cargo:rustc-flags=-L native={} -l old_openssl_shim:static", out_dir); } diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 70526fd5..5d4c4cb9 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -382,12 +382,20 @@ extern "C" { pub fn EVP_PKEY_set1_RSA(k: *mut EVP_PKEY, r: *mut RSA) -> c_int; pub fn HMAC_CTX_init(ctx: *mut HMAC_CTX); + #[deprecated = "use HMAC_Init_ex_shim instead"] pub fn HMAC_Init_ex(ctx: *mut HMAC_CTX, key: *const u8, keylen: c_int, md: *const EVP_MD, imple: *const ENGINE) -> c_int; + #[deprecated = "use HMAC_Final_shim instead"] pub fn HMAC_Final(ctx: *mut HMAC_CTX, output: *mut u8, len: *mut c_uint) -> c_int; + #[deprecated = "use HMAC_Update_shim instead"] pub fn HMAC_Update(ctx: *mut HMAC_CTX, input: *const u8, len: c_uint) -> c_int; pub fn HMAC_CTX_cleanup(ctx: *mut HMAC_CTX); pub fn HMAC_CTX_copy(dst: *mut HMAC_CTX, src: *const HMAC_CTX) -> c_int; + // Pre-1.0 versions of these didn't return anything, so the shims bridge that gap + pub fn HMAC_Init_ex_shim(ctx: *mut HMAC_CTX, key: *const u8, keylen: c_int, md: *const EVP_MD, imple: *const ENGINE) -> c_int; + pub fn HMAC_Final_shim(ctx: *mut HMAC_CTX, output: *mut u8, len: *mut c_uint) -> c_int; + pub fn HMAC_Update_shim(ctx: *mut HMAC_CTX, input: *const u8, len: c_uint) -> c_int; + pub fn PEM_read_bio_X509(bio: *mut BIO, out: *mut *mut X509, callback: Option, user_data: *mut c_void) -> *mut X509; diff --git a/openssl-sys/src/old_openssl_shim.c b/openssl-sys/src/old_openssl_shim.c new file mode 100644 index 00000000..473bd2ae --- /dev/null +++ b/openssl-sys/src/old_openssl_shim.c @@ -0,0 +1,49 @@ +#include + +#ifdef OLD_OPENSSL +// Copied from openssl crypto/hmac/hmac.c +int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) + { + if (!EVP_MD_CTX_copy(&dctx->i_ctx, &sctx->i_ctx)) + goto err; + if (!EVP_MD_CTX_copy(&dctx->o_ctx, &sctx->o_ctx)) + goto err; + if (!EVP_MD_CTX_copy(&dctx->md_ctx, &sctx->md_ctx)) + goto err; + memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK); + dctx->key_length = sctx->key_length; + dctx->md = sctx->md; + return 1; + err: + return 0; + } + +int HMAC_Init_ex_shim(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) { + HMAC_Init_ex(ctx, key, key_len, md, impl); + return 1; +} + +int HMAC_Update_shim(HMAC_CTX *ctx, const unsigned char *data, int len) { + HMAC_Update(ctx, data, len); + return 1; +} + +int HMAC_Final_shim(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) { + HMAC_Final(ctx, md, len); + return 1; +} + +#else /* OLD_OPENSSL */ + +int HMAC_Init_ex_shim(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) { + return HMAC_Init_ex(ctx, key, key_len, md, impl); +} + +int HMAC_Update_shim(HMAC_CTX *ctx, const unsigned char *data, int len) { + return HMAC_Update(ctx, data, len); +} + +int HMAC_Final_shim(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) { + return HMAC_Final(ctx, md, len); +} +#endif /* OLD_OPENSSL */ diff --git a/openssl/src/crypto/hmac.rs b/openssl/src/crypto/hmac.rs index 65808e58..f3f5aee6 100644 --- a/openssl/src/crypto/hmac.rs +++ b/openssl/src/crypto/hmac.rs @@ -87,9 +87,9 @@ impl HMAC { #[inline] fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) { unsafe { - let r = ffi::HMAC_Init_ex(&mut self.ctx, - key.as_ptr(), key.len() as c_int, - md, 0 as *const _); + let r = ffi::HMAC_Init_ex_shim(&mut self.ctx, + key.as_ptr(), key.len() as c_int, + md, 0 as *const _); assert_eq!(r, 1); } self.state = Reset; @@ -105,9 +105,9 @@ impl HMAC { // If the key and/or md is not supplied it's reused from the last time // avoiding redundant initializations unsafe { - let r = ffi::HMAC_Init_ex(&mut self.ctx, - 0 as *const _, 0, - 0 as *const _, 0 as *const _); + let r = ffi::HMAC_Init_ex_shim(&mut self.ctx, + 0 as *const _, 0, + 0 as *const _, 0 as *const _); assert_eq!(r, 1); } self.state = Reset; @@ -119,8 +119,7 @@ impl HMAC { self.init(); } unsafe { - let r = ffi::HMAC_Update(&mut self.ctx, data.as_ptr(), - data.len() as c_uint); + let r = ffi::HMAC_Update_shim(&mut self.ctx, data.as_ptr(), data.len() as c_uint); assert_eq!(r, 1); } self.state = Updated; @@ -135,7 +134,7 @@ impl HMAC { let mut res: Vec = repeat(0).take(md_len).collect(); unsafe { let mut len = 0; - let r = ffi::HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len); + let r = ffi::HMAC_Final_shim(&mut self.ctx, res.as_mut_ptr(), &mut len); self.state = Finalized; assert_eq!(len as usize, md_len); assert_eq!(r, 1);