Fix builds against 0.9.x OpenSSL

Namely builds on OSX
This commit is contained in:
Steven Fackler 2015-02-08 23:30:34 -08:00
parent b41f3dd72f
commit 6ef819f971
6 changed files with 105 additions and 53 deletions

View File

@ -40,17 +40,6 @@ Rust install's libs folder. The default should be:
respectively. respectively.
5. Run `cargo build`. 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 ###Testing
Several tests expect a local test server to be running to bounce requests off 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 of. It's easy to do this. Open a separate terminal window and `cd` to the

View File

@ -18,7 +18,8 @@ sslv2 = []
aes_xts = [] aes_xts = []
[build-dependencies] [build-dependencies]
pkg-config = "0.1.1" pkg-config = "0.2"
gcc = "0.1"
[target.le32-unknown-nacl.dependencies] [target.le32-unknown-nacl.dependencies]
libressl-pnacl-sys = "2.1.0" libressl-pnacl-sys = "2.1.0"

View File

@ -1,44 +1,50 @@
#![feature(core, collections, env)] #![feature(env)]
extern crate "pkg-config" as pkg_config; extern crate "pkg-config" as pkg_config;
extern crate gcc;
use std::env; use std::env;
use std::default::Default;
fn main() { fn main() {
let target = env::var_string("TARGET").unwrap(); 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. if target.contains("android") {
// So, abandon ship if we're cross compiling. let path = env::var_string("OPENSSL_PATH").ok()
if !is_android && !pkg_config::target_supported() { .expect("Android does not provide openssl libraries, please build them yourself \
panic!("unsupported target"); (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() { if target.contains("win32") || target.contains("win64") {
let mut flags = if is_android { println!("cargo:rustc-flags=-l crypto -l ssl -l gdi32 -l wsock32");
" -l crypto:static -l ssl:static" return;
} 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 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);
} }

View File

@ -382,12 +382,20 @@ extern "C" {
pub fn EVP_PKEY_set1_RSA(k: *mut EVP_PKEY, r: *mut RSA) -> c_int; pub fn EVP_PKEY_set1_RSA(k: *mut EVP_PKEY, r: *mut RSA) -> c_int;
pub fn HMAC_CTX_init(ctx: *mut HMAC_CTX); 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; 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; 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_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_cleanup(ctx: *mut HMAC_CTX);
pub fn HMAC_CTX_copy(dst: *mut HMAC_CTX, src: *const HMAC_CTX) -> c_int; 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<PasswordCallback>, pub fn PEM_read_bio_X509(bio: *mut BIO, out: *mut *mut X509, callback: Option<PasswordCallback>,
user_data: *mut c_void) -> *mut X509; user_data: *mut c_void) -> *mut X509;

View File

@ -0,0 +1,49 @@
#include <openssl/hmac.h>
#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 */

View File

@ -87,9 +87,9 @@ impl HMAC {
#[inline] #[inline]
fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) { fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) {
unsafe { unsafe {
let r = ffi::HMAC_Init_ex(&mut self.ctx, let r = ffi::HMAC_Init_ex_shim(&mut self.ctx,
key.as_ptr(), key.len() as c_int, key.as_ptr(), key.len() as c_int,
md, 0 as *const _); md, 0 as *const _);
assert_eq!(r, 1); assert_eq!(r, 1);
} }
self.state = Reset; 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 // If the key and/or md is not supplied it's reused from the last time
// avoiding redundant initializations // avoiding redundant initializations
unsafe { unsafe {
let r = ffi::HMAC_Init_ex(&mut self.ctx, let r = ffi::HMAC_Init_ex_shim(&mut self.ctx,
0 as *const _, 0, 0 as *const _, 0,
0 as *const _, 0 as *const _); 0 as *const _, 0 as *const _);
assert_eq!(r, 1); assert_eq!(r, 1);
} }
self.state = Reset; self.state = Reset;
@ -119,8 +119,7 @@ impl HMAC {
self.init(); self.init();
} }
unsafe { unsafe {
let r = ffi::HMAC_Update(&mut self.ctx, data.as_ptr(), let r = ffi::HMAC_Update_shim(&mut self.ctx, data.as_ptr(), data.len() as c_uint);
data.len() as c_uint);
assert_eq!(r, 1); assert_eq!(r, 1);
} }
self.state = Updated; self.state = Updated;
@ -135,7 +134,7 @@ impl HMAC {
let mut res: Vec<u8> = repeat(0).take(md_len).collect(); let mut res: Vec<u8> = repeat(0).take(md_len).collect();
unsafe { unsafe {
let mut len = 0; 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; self.state = Finalized;
assert_eq!(len as usize, md_len); assert_eq!(len as usize, md_len);
assert_eq!(r, 1); assert_eq!(r, 1);