diff --git a/src/asn1/mod.rs b/src/asn1/mod.rs index 2cd4584f..89c79f74 100644 --- a/src/asn1/mod.rs +++ b/src/asn1/mod.rs @@ -20,6 +20,8 @@ impl Asn1Time { } fn new_with_period(period: u64) -> Result { + ffi::init(); + let handle = unsafe { try_ssl_null!(ffi::X509_gmtime_adj(ptr::null_mut(), period as c_long)) diff --git a/src/bio/mod.rs b/src/bio/mod.rs index 2ae66516..afc55849 100644 --- a/src/bio/mod.rs +++ b/src/bio/mod.rs @@ -24,6 +24,8 @@ impl Drop for MemBio { impl MemBio { /// Creates a new owned memory based BIO pub fn new() -> Result { + ffi::init(); + let bio = unsafe { ffi::BIO_new(ffi::BIO_s_mem()) }; try_ssl_null!(bio); diff --git a/src/bn/mod.rs b/src/bn/mod.rs index 129f6b90..510c9269 100644 --- a/src/bn/mod.rs +++ b/src/bn/mod.rs @@ -79,8 +79,10 @@ macro_rules! with_bn_in_ctx( ) impl BigNum { + // FIXME: squash 3 constructors into one pub fn new() -> Result { unsafe { + ffi::init(); let v = ffi::BN_new(); if v.is_null() { Err(SslError::get()) @@ -92,6 +94,7 @@ impl BigNum { pub fn new_from(n: u64) -> Result { unsafe { + ffi::init(); let bn = ffi::BN_new(); if bn.is_null() || ffi::BN_set_word(bn, n as c_ulong) == 0 { Err(SslError::get()) @@ -103,6 +106,7 @@ impl BigNum { pub fn new_from_slice(n: &[u8]) -> Result { unsafe { + ffi::init(); let bn = ffi::BN_new(); if bn.is_null() || ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, bn).is_null() { Err(SslError::get()) diff --git a/src/crypto/hash.rs b/src/crypto/hash.rs index 61221cb5..a72b8d9f 100644 --- a/src/crypto/hash.rs +++ b/src/crypto/hash.rs @@ -36,6 +36,8 @@ pub struct Hasher { impl Hasher { pub fn new(ht: HashType) -> Hasher { + ffi::init(); + let ctx = unsafe { ffi::EVP_MD_CTX_create() }; let (evp, mdlen) = evpmd(ht); unsafe { diff --git a/src/crypto/hmac.rs b/src/crypto/hmac.rs index 4c8617ca..ef2a0414 100644 --- a/src/crypto/hmac.rs +++ b/src/crypto/hmac.rs @@ -27,6 +27,8 @@ pub struct HMAC { #[allow(non_snake_case)] pub fn HMAC(ht: hash::HashType, key: &[u8]) -> HMAC { unsafe { + ffi::init(); + let (evp, mdlen) = hash::evpmd(ht); let mut ctx : ffi::HMAC_CTX = ::std::mem::uninitialized(); diff --git a/src/crypto/pkcs5.rs b/src/crypto/pkcs5.rs index ec6e0cef..feaff9c8 100644 --- a/src/crypto/pkcs5.rs +++ b/src/crypto/pkcs5.rs @@ -9,6 +9,8 @@ pub fn pbkdf2_hmac_sha1(pass: &str, salt: &[u8], iter: uint, keylen: uint) -> Ve let mut out = Vec::with_capacity(keylen); + ffi::init(); + let r = ffi::PKCS5_PBKDF2_HMAC_SHA1( pass.as_ptr(), pass.len() as c_int, salt.as_ptr(), salt.len() as c_int, diff --git a/src/crypto/pkey.rs b/src/crypto/pkey.rs index d95e7738..ac16f478 100644 --- a/src/crypto/pkey.rs +++ b/src/crypto/pkey.rs @@ -55,6 +55,8 @@ pub struct PKey { impl PKey { pub fn new() -> PKey { unsafe { + ffi::init(); + PKey { evp: ffi::EVP_PKEY_new(), parts: Neither, diff --git a/src/crypto/rand.rs b/src/crypto/rand.rs index dffddee7..5f94c93c 100644 --- a/src/crypto/rand.rs +++ b/src/crypto/rand.rs @@ -5,6 +5,7 @@ pub fn rand_bytes(len: uint) -> Vec { unsafe { let mut out = Vec::with_capacity(len); + ffi::init(); let r = ffi::RAND_bytes(out.as_mut_ptr(), len as c_int); if r != 1 as c_int { fail!() } diff --git a/src/crypto/symm.rs b/src/crypto/symm.rs index 9953ac7b..171c1b05 100644 --- a/src/crypto/symm.rs +++ b/src/crypto/symm.rs @@ -50,6 +50,8 @@ pub struct Crypter { impl Crypter { pub fn new(t: Type) -> Crypter { + ffi::init(); + let ctx = unsafe { ffi::EVP_CIPHER_CTX_new() }; let (evp, keylen, blocksz) = evpc(t); Crypter { evp: evp, ctx: ctx, keylen: keylen, blocksize: blocksz } diff --git a/src/ffi.rs b/src/ffi.rs index 4dc7b0cc..8b2cd467 100755 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -1,7 +1,9 @@ #![allow(non_camel_case_types, non_uppercase_statics, non_snake_case)] #![allow(dead_code)] use libc::{c_void, c_int, c_char, c_ulong, c_long, c_uint, c_uchar, size_t}; +use std::mem; use std::ptr; +use std::rt::mutex::NativeMutex; use sync::one::{Once, ONCE_INIT}; pub use bn::BIGNUM; @@ -182,13 +184,34 @@ extern {} #[link(name="wsock32")] extern { } +static mut MUTEXES: *mut Vec = 0 as *mut Vec; + +extern fn locking_function(mode: c_int, n: c_int, _file: *const c_char, + _line: c_int) { + unsafe { + let mutex = (*MUTEXES).get_mut(n as uint); + + if mode & CRYPTO_LOCK != 0 { + mutex.lock_noguard(); + } else { + mutex.unlock_noguard(); + } + } +} + pub fn init() { static mut INIT: Once = ONCE_INIT; unsafe { INIT.doit(|| { SSL_library_init(); - SSL_load_error_strings() + SSL_load_error_strings(); + + let num_locks = CRYPTO_num_locks(); + let mutexes = box Vec::from_fn(num_locks as uint, |_| NativeMutex::new()); + MUTEXES = mem::transmute(mutexes); + + CRYPTO_set_locking_callback(locking_function); }) } } diff --git a/src/ssl/mod.rs b/src/ssl/mod.rs index 86b3ec83..0ed3c2e8 100644 --- a/src/ssl/mod.rs +++ b/src/ssl/mod.rs @@ -1,8 +1,7 @@ -use libc::{c_int, c_void, c_char, c_long}; +use libc::{c_int, c_void, c_long}; use std::io::{IoResult, IoError, EndOfFile, Stream, Reader, Writer}; use std::mem; use std::ptr; -use std::rt::mutex::NativeMutex; use std::string; use sync::one::{Once, ONCE_INIT}; @@ -16,7 +15,6 @@ pub mod error; mod tests; static mut VERIFY_IDX: c_int = -1; -static mut MUTEXES: *mut Vec = 0 as *mut Vec; fn init() { static mut INIT: Once = ONCE_INIT; @@ -29,12 +27,6 @@ fn init() { None, None); assert!(verify_idx >= 0); VERIFY_IDX = verify_idx; - - let num_locks = ffi::CRYPTO_num_locks(); - let mutexes = box Vec::from_fn(num_locks as uint, |_| NativeMutex::new()); - MUTEXES = mem::transmute(mutexes); - - ffi::CRYPTO_set_locking_callback(locking_function); }); } } @@ -109,19 +101,6 @@ fn get_verify_data_idx() -> c_int { } } -extern fn locking_function(mode: c_int, n: c_int, _file: *const c_char, - _line: c_int) { - unsafe { - let mutex = (*MUTEXES).get_mut(n as uint); - - if mode & ffi::CRYPTO_LOCK != 0 { - mutex.lock_noguard(); - } else { - mutex.unlock_noguard(); - } - } -} - extern fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int { unsafe { diff --git a/src/x509/mod.rs b/src/x509/mod.rs index 88b81d7e..e3ececcc 100644 --- a/src/x509/mod.rs +++ b/src/x509/mod.rs @@ -272,6 +272,8 @@ impl X509Generator { /// Generates a private key and a signed certificate and returns them pub fn generate<'a>(&self) -> Result<(X509<'a>, PKey), SslError> { + ffi::init(); + let mut p_key = PKey::new(); p_key.gen(self.bits);