diff --git a/openssl/src/bn.rs b/openssl/src/bn.rs index 700367bd..fb0c286c 100644 --- a/openssl/src/bn.rs +++ b/openssl/src/bn.rs @@ -1,11 +1,12 @@ use ffi; -use libc::{c_int, c_void}; +use libc::c_int; use std::cmp::Ordering; -use std::ffi::{CStr, CString}; +use std::ffi::CString; use std::{fmt, ptr}; use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref, DerefMut}; use {cvt, cvt_p, cvt_n}; +use crypto::CryptoString; use error::ErrorStack; use opaque::Opaque; @@ -473,15 +474,12 @@ impl BigNumRef { /// # use openssl::bn::BigNum; /// let s = -BigNum::from_u32(12345).unwrap(); /// - /// assert_eq!(s.to_dec_str().unwrap(), "-12345"); + /// assert_eq!(&*s.to_dec_str().unwrap(), "-12345"); /// ``` - pub fn to_dec_str(&self) -> Result { + pub fn to_dec_str(&self) -> Result { unsafe { let buf = try!(cvt_p(ffi::BN_bn2dec(self.as_ptr()))); - let str = String::from_utf8(CStr::from_ptr(buf as *const _).to_bytes().to_vec()) - .unwrap(); - CRYPTO_free!(buf as *mut c_void); - Ok(str) + Ok(CryptoString::from_null_terminated(buf)) } } @@ -491,15 +489,12 @@ impl BigNumRef { /// # use openssl::bn::BigNum; /// let s = -BigNum::from_u32(0x99ff).unwrap(); /// - /// assert_eq!(s.to_hex_str().unwrap(), "-99FF"); + /// assert_eq!(&*s.to_hex_str().unwrap(), "-99FF"); /// ``` - pub fn to_hex_str(&self) -> Result { + pub fn to_hex_str(&self) -> Result { unsafe { let buf = try!(cvt_p(ffi::BN_bn2hex(self.as_ptr()))); - let str = String::from_utf8(CStr::from_ptr(buf as *const _).to_bytes().to_vec()) - .unwrap(); - CRYPTO_free!(buf as *mut c_void); - Ok(str) + Ok(CryptoString::from_null_terminated(buf)) } } } diff --git a/openssl/src/crypto.rs b/openssl/src/crypto.rs new file mode 100644 index 00000000..ce83cbae --- /dev/null +++ b/openssl/src/crypto.rs @@ -0,0 +1,59 @@ +use libc::{c_char, c_int, c_void}; +use std::fmt; +use std::ffi::CStr; +use std::slice; +use std::ops::Deref; +use std::str; + +pub struct CryptoString(&'static str); + +impl Drop for CryptoString { + fn drop(&mut self) { + unsafe { + CRYPTO_free(self.0.as_ptr() as *mut c_void, + concat!(file!(), "\0").as_ptr() as *const c_char, + line!() as c_int); + } + } +} + +impl Deref for CryptoString { + type Target = str; + + fn deref(&self) -> &str { + self.0 + } +} + +impl CryptoString { + pub unsafe fn from_raw_parts(buf: *mut u8, len: usize) -> CryptoString { + let slice = slice::from_raw_parts(buf, len); + CryptoString(str::from_utf8_unchecked(slice)) + } + + pub unsafe fn from_null_terminated(buf: *mut c_char) -> CryptoString { + let slice = CStr::from_ptr(buf).to_bytes(); + CryptoString(str::from_utf8_unchecked(slice)) + } +} + +impl fmt::Display for CryptoString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.0, f) + } +} + +impl fmt::Debug for CryptoString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.0, f) + } +} + +#[cfg(not(ossl110))] +#[allow(non_snake_case)] +unsafe fn CRYPTO_free(buf: *mut c_void, _: *const c_char, _: c_int) { + ::ffi::CRYPTO_free(buf); +} + +#[cfg(ossl110)] +use ffi::CRYPTO_free; diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 9ed02207..b191ec5b 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -20,13 +20,12 @@ use libc::c_int; use error::ErrorStack; -mod macros; - mod bio; mod opaque; mod util; pub mod asn1; pub mod bn; +pub mod crypto; pub mod dh; pub mod dsa; pub mod error; diff --git a/openssl/src/macros.rs b/openssl/src/macros.rs deleted file mode 100644 index 85175445..00000000 --- a/openssl/src/macros.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![macro_use] - -#[cfg(ossl10x)] -macro_rules! CRYPTO_free { - ($e:expr) => (::ffi::CRYPTO_free($e)) -} - -#[cfg(ossl110)] -macro_rules! CRYPTO_free { - ($e:expr) => ( - ::ffi::CRYPTO_free($e, - concat!(file!(), "\0").as_ptr() as *const _, - line!() as i32) - ) -} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index af5c722a..b92462d4 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -15,6 +15,7 @@ use {cvt, cvt_p}; use asn1::Asn1Time; use asn1::Asn1TimeRef; use bio::{MemBio, MemBioSlice}; +use crypto::CryptoString; use hash::MessageDigest; use pkey::PKey; use rand::rand_bytes; @@ -46,43 +47,6 @@ use self::extension::{ExtensionType, Extension}; #[cfg(test)] mod tests; -pub struct SslString(&'static str); - -impl<'s> Drop for SslString { - fn drop(&mut self) { - unsafe { - CRYPTO_free!(self.0.as_ptr() as *mut c_void); - } - } -} - -impl Deref for SslString { - type Target = str; - - fn deref(&self) -> &str { - self.0 - } -} - -impl SslString { - unsafe fn new(buf: *const u8, len: c_int) -> SslString { - let slice = slice::from_raw_parts(buf, len as usize); - SslString(str::from_utf8_unchecked(slice)) - } -} - -impl fmt::Display for SslString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self.0, f) - } -} - -impl fmt::Debug for SslString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self.0, f) - } -} - #[derive(Copy, Clone)] #[repr(i32)] pub enum X509FileType { @@ -551,7 +515,7 @@ impl X509NameRef { self as *const _ as *mut _ } - pub fn text_by_nid(&self, nid: Nid) -> Option { + pub fn text_by_nid(&self, nid: Nid) -> Option { unsafe { let loc = ffi::X509_NAME_get_index_by_NID(self.as_ptr(), nid.as_raw(), -1); if loc == -1 { @@ -577,7 +541,7 @@ impl X509NameRef { assert!(!str_from_asn1.is_null()); - Some(SslString::new(str_from_asn1, len)) + Some(CryptoString::from_raw_parts(str_from_asn1, len as usize)) } } }