From 0598561f0ec961001cb5b5a67a945ec39b7b2cd7 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 28 Jan 2017 17:49:41 -0800 Subject: [PATCH 01/12] Macro-expand OpenSSL headers for feature checks Closes #564 --- openssl-sys/Cargo.toml | 3 +- openssl-sys/build.rs | 230 +++++++++++++++++++---------------------- 2 files changed, 109 insertions(+), 124 deletions(-) diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 1f1750dc..76bd9172 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -16,11 +16,12 @@ libc = "0.2" [build-dependencies] pkg-config = "0.3.9" +gcc = "0.3.42" [target.'cfg(windows)'.dependencies] user32-sys = "0.2" gdi32-sys = "0.2" -# We don't actually use metadeps for annoying reasons but this is still hear for tooling +# We don't actually use metadeps for annoying reasons but this is still here for tooling [package.metadata.pkg-config] openssl = "1.0.1" diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index 0e1cdc46..1b717693 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -1,13 +1,37 @@ extern crate pkg_config; +extern crate gcc; use std::collections::HashSet; use std::env; use std::ffi::OsString; use std::fs::File; -use std::io::Read; +use std::io::{BufWriter, Write}; use std::path::{Path, PathBuf}; use std::process::Command; +// The set of `OPENSSL_NO_`s that we care about. +const DEFINES: &'static [&'static str] = &[ + "OPENSSL_NO_BUF_FREELISTS", + "OPENSSL_NO_COMP", + "OPENSSL_NO_EC", + "OPENSSL_NO_ENGINE", + "OPENSSL_NO_KRB5", + "OPENSSL_NO_NEXTPROTONEG", + "OPENSSL_NO_PSK", + "OPENSSL_NO_RFC3779", + "OPENSSL_NO_SHA", + "OPENSSL_NO_SRP", + "OPENSSL_NO_SSL3_METHOD", + "OPENSSL_NO_TLSEXT", +]; + +enum Version { + Openssl110, + Openssl102, + Openssl101, + Libressl, +} + fn main() { let target = env::var("TARGET").unwrap(); @@ -38,17 +62,14 @@ fn main() { println!("cargo:rustc-link-search=native={}", lib_dir.to_string_lossy()); println!("cargo:include={}", include_dir.to_string_lossy()); - let version = validate_headers(&[include_dir.clone().into()], - &[lib_dir.clone().into()]); + let version = validate_headers(&[include_dir.clone().into()]); - let libs = if (version.contains("0x10001") || - version.contains("0x10002")) && - target.contains("windows") { - ["ssleay32", "libeay32"] - } else if target.contains("windows") { - ["libssl", "libcrypto"] - } else { - ["ssl", "crypto"] + let libs = match version { + Version::Openssl101 | Version::Openssl102 if target.contains("windows") => { + ["ssleay32", "libeay32"] + } + Version::Openssl110 if target.contains("windows") => ["libssl", "libcrypto"], + _ => ["ssl", "crypto"], }; let kind = determine_mode(Path::new(&lib_dir), &libs); @@ -209,7 +230,7 @@ See rust-openssl README for more information: "); } - validate_headers(&lib.include_paths, &lib.link_paths); + validate_headers(&lib.include_paths); for include in lib.include_paths.iter() { println!("cargo:include={}", include.display()); @@ -225,74 +246,11 @@ See rust-openssl README for more information: /// Validates the header files found in `include_dir` and then returns the /// version string of OpenSSL. -fn validate_headers(include_dirs: &[PathBuf], - libdirs: &[PathBuf]) -> String { +fn validate_headers(include_dirs: &[PathBuf]) -> Version { // This `*-sys` crate only works with OpenSSL 1.0.1, 1.0.2, and 1.1.0. To // correctly expose the right API from this crate, take a look at // `opensslv.h` to see what version OpenSSL claims to be. - let mut version_header = String::new(); - let mut include = include_dirs.iter() - .map(|p| p.join("openssl/opensslv.h")) - .filter(|p| p.exists()); - let mut f = match include.next() { - Some(f) => File::open(f).unwrap(), - None => { - panic!("failed to open header file at `openssl/opensslv.h` to learn - about OpenSSL's version number, looked inside:\n\n{:#?}\n\n", - include_dirs); - } - }; - f.read_to_string(&mut version_header).unwrap(); - - // Do a bit of string parsing to find `#define OPENSSL_VERSION_NUMBER ...` - let version_line = version_header.lines().find(|l| { - l.contains("define ") && l.contains("OPENSSL_VERSION_NUMBER") - }).and_then(|line| { - let start = match line.find("0x") { - Some(start) => start, - None => return None, - }; - Some(line[start..].trim()) - }); - let version_text = match version_line { - Some(text) => text, - None => { - panic!("header file at `{}` did not include `OPENSSL_VERSION_NUMBER` \ - that this crate recognized, failed to learn about the \ - OpenSSL version number"); - } - }; - if version_text.contains("0x10001") { - println!("cargo:rustc-cfg=ossl101"); - println!("cargo:version=101"); - } else if version_text.contains("0x10002") { - println!("cargo:rustc-cfg=ossl102"); - println!("cargo:version=102"); - } else if version_text.contains("0x10100") { - println!("cargo:rustc-cfg=ossl110"); - println!("cargo:version=110"); - } else if version_text.contains("0x20000000L") { - // Check if it is really LibreSSL - if version_header.lines().any(|l| { - l.contains("define ") && l.contains("LIBRESSL_VERSION_NUMBER") - }) { - println!("cargo:rustc-cfg=libressl"); - println!("cargo:libressl=true"); - println!("cargo:version=101"); - } - } else { - panic!(" - -This crate is only compatible with OpenSSL 1.0.1, 1.0.2, and 1.1.0, but a -different version of OpenSSL was found: - - {} - -The build is now aborting due to this version mismatch. - -", version_text); - } - + // // OpenSSL has a number of build-time configuration options which affect // various structs and such. Since OpenSSL 1.1.0 this isn't really a problem // as the library is much more FFI-friendly, but 1.0.{1,2} suffer this problem. @@ -301,56 +259,82 @@ The build is now aborting due to this version mismatch. // file of OpenSSL, `opensslconf.h`, and then dump out everything it defines // as our own #[cfg] directives. That way the `ossl10x.rs` bindings can // account for compile differences and such. - let mut conf_header = String::new(); - let mut include = include_dirs.iter() - .map(|p| p.join("openssl/opensslconf.h")) - .filter(|p| p.exists()); - let mut f = match include.next() { - Some(f) => File::open(f).unwrap(), - None => { - // It's been seen that on linux the include dir printed out by - // `pkg-config` doesn't actually have opensslconf.h. Instead - // it's in an architecture-specific include directory. - // - // Try to detect that case to see if it exists. - let mut libdirs = libdirs.iter().map(|p| { - p.iter() - .map(|p| if p == "lib" {"include".as_ref()} else {p}) - .collect::() - }).map(|p| { - p.join("openssl/opensslconf.h") - }).filter(|p| p.exists()); - match libdirs.next() { - Some(f) => File::open(f).unwrap(), - None => { - panic!("failed to open header file at - `openssl/opensslconf.h` to learn about \ - OpenSSL's version number, looked \ - inside:\n\n{:#?}\n\n", - include_dirs); - } - } - } - }; - f.read_to_string(&mut conf_header).unwrap(); + let mut path = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + path.push("expando.c"); + let mut file = BufWriter::new(File::create(&path).unwrap()); - // Look for `#define OPENSSL_FOO`, print out everything as our own - // #[cfg] flag. - let mut vars = vec![]; - for line in conf_header.lines() { - let i = match line.find("define ") { - Some(i) => i, - None => continue, - }; - let var = line[i + "define ".len()..].trim(); - if var.starts_with("OPENSSL") && !var.contains(" ") { - println!("cargo:rustc-cfg=osslconf=\"{}\"", var); - vars.push(var); + write!(file, "\ +#include +#include + +#ifdef LIBRESSL_VERSION_NUMBER +RUST_LIBRESSL +#elif OPENSSL_VERSION_NUMBER >= 0x10200000 +RUST_OPENSSL_NEW +#elif OPENSSL_VERSION_NUMBER >= 0x10100000 +RUST_OPENSSL_110 +#elif OPENSSL_VERSION_NUMBER >= 0x10002000 +RUST_OPENSSL_102 +#elif OPENSSL_VERSION_NUMBER >= 0x10001000 +RUST_OPENSSL_101 +#else +RUST_OPENSSL_OLD +#endif +").unwrap(); + + for define in DEFINES { + write!(file, "\ +#ifdef {define} +RUST_{define} +#endif +", define = define).unwrap(); + } + + file.flush().unwrap(); + drop(file); + + let mut gcc = gcc::Config::new(); + for include_dir in include_dirs { + gcc.include(include_dir); + } + let expanded = gcc.file(&path).expand(); + let expanded = String::from_utf8(expanded).unwrap(); + + let mut enabled = vec![]; + for &define in DEFINES { + if expanded.contains(&format!("RUST_{}", define)) { + println!("cargo:rustc-cfg=osslconf=\"{}\"", define); + enabled.push(define); } } - println!("cargo:conf={}", vars.join(",")); + println!("cargo:conf={}", enabled.join(",")); - return version_text.to_string() + if expanded.contains("RUST_LIBRESSL") { + println!("cargo:rustc-cfg=libressl"); + println!("cargo:libressl=true"); + println!("cargo:version=101"); + Version::Libressl + } else if expanded.contains("RUST_OPENSSL_110") { + println!("cargo:rustc-cfg=ossl110"); + println!("cargo:version=110"); + Version::Openssl110 + } else if expanded.contains("RUST_OPENSSL_102") { + println!("cargo:rustc-cfg=ossl102"); + println!("cargo:version=102"); + Version::Openssl102 + } else if expanded.contains("RUST_OPENSSL_101") { + println!("cargo:rustc-cfg=ossl101"); + println!("cargo:version=101"); + Version::Openssl101 + } else { + panic!(" + +This crate is only compatible with OpenSSL 1.0.1, 1.0.2, and 1.1.0, or LibreSSL, +but a different version of OpenSSL was found. The build is now aborting due to +this version mismatch. + +"); + } } /// Given a libdir for OpenSSL (where artifacts are located) as well as the name From caeade39a13697000a2fcf449ee48bfe859848bf Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 28 Jan 2017 20:04:51 -0800 Subject: [PATCH 02/12] Bump test versions --- .travis.yml | 12 ++++++------ appveyor.yml | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index e8d89347..795c9370 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ matrix: # ARM-bit version compat - env: > TARGET=arm-unknown-linux-gnueabihf - BUILD_OPENSSL_VERSION=1.0.2h + BUILD_OPENSSL_VERSION=1.0.2k CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf RUST_TEST_THREADS=1 @@ -32,7 +32,7 @@ matrix: - binfmt-support - env: > TARGET=arm-unknown-linux-gnueabihf - BUILD_OPENSSL_VERSION=1.1.0c + BUILD_OPENSSL_VERSION=1.1.0d CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf RUST_TEST_THREADS=1 @@ -52,8 +52,8 @@ matrix: - rust: nightly # 64-bit version compat - - env: BUILD_OPENSSL_VERSION=1.0.2h - - env: BUILD_OPENSSL_VERSION=1.1.0c + - env: BUILD_OPENSSL_VERSION=1.0.2k + - env: BUILD_OPENSSL_VERSION=1.1.0d # 32-bit version compat - env: TARGET=i686-unknown-linux-gnu BUILD_OPENSSL_VERSION=1.0.1u @@ -61,12 +61,12 @@ matrix: apt: packages: - gcc-multilib - - env: TARGET=i686-unknown-linux-gnu BUILD_OPENSSL_VERSION=1.0.2h + - env: TARGET=i686-unknown-linux-gnu BUILD_OPENSSL_VERSION=1.0.2k addons: apt: packages: - gcc-multilib - - env: TARGET=i686-unknown-linux-gnu BUILD_OPENSSL_VERSION=1.1.0c + - env: TARGET=i686-unknown-linux-gnu BUILD_OPENSSL_VERSION=1.1.0d addons: apt: packages: diff --git a/appveyor.yml b/appveyor.yml index 9b4a3f02..d396bd62 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,20 +5,20 @@ environment: - TARGET: i686-pc-windows-gnu BITS: 32 MSYS2: 1 - OPENSSL_VERSION: 1_1_0c + OPENSSL_VERSION: 1_1_0d - TARGET: x86_64-pc-windows-msvc BITS: 64 - OPENSSL_VERSION: 1_1_0c + OPENSSL_VERSION: 1_1_0d OPENSSL_DIR: C:\OpenSSL # 1.0.2, 64/32 bit - TARGET: x86_64-pc-windows-gnu BITS: 64 MSYS2: 1 - OPENSSL_VERSION: 1_0_2j + OPENSSL_VERSION: 1_0_2k - TARGET: i686-pc-windows-msvc BITS: 32 - OPENSSL_VERSION: 1_0_2j + OPENSSL_VERSION: 1_0_2k OPENSSL_DIR: C:\OpenSSL install: # install OpenSSL From ddc0066211fb9adadd658bd04547dc143dcfbc5a Mon Sep 17 00:00:00 2001 From: Brian Chin Date: Fri, 27 Jan 2017 18:16:22 -0800 Subject: [PATCH 03/12] Add the necessary constants to access the pkey ctx stuff. --- openssl-sys/src/lib.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 01be1b23..6b61aab7 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -151,6 +151,8 @@ pub const EVP_PKEY_DSA: c_int = NID_dsa; pub const EVP_PKEY_DH: c_int = NID_dhKeyAgreement; pub const EVP_PKEY_EC: c_int = NID_X9_62_id_ecPublicKey; +pub const EVP_PKEY_ALG_CTRL: c_int = 0x1000; + pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9; pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10; pub const EVP_CTRL_GCM_SET_TAG: c_int = 0x11; @@ -1121,6 +1123,10 @@ pub const RSA_NO_PADDING: c_int = 3; pub const RSA_PKCS1_OAEP_PADDING: c_int = 4; pub const RSA_X931_PADDING: c_int = 5; +pub const RSA_PKEY_CTRL_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 1; + +pub const RSA_PKEY_CTRL_GET_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 6; + pub const SSL_CTRL_SET_TMP_DH: c_int = 3; pub const SSL_CTRL_SET_TMP_ECDH: c_int = 4; pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; @@ -1726,6 +1732,7 @@ extern { pub fn RSA_new() -> *mut RSA; pub fn RSA_free(rsa: *mut RSA); pub fn RSA_generate_key_ex(rsa: *mut RSA, bits: c_int, e: *mut BIGNUM, cb: *mut BN_GENCB) -> c_int; + pub fn RSA_pkey_ctx_ctrl(ctx: *mut EVP_PKEY_CTX, optype: c_int, cmd: c_int, p1: c_int, p2: *mut c_void) -> c_int; pub fn RSA_private_decrypt(flen: c_int, from: *const u8, to: *mut u8, k: *mut RSA, pad: c_int) -> c_int; pub fn RSA_public_decrypt(flen: c_int, from: *const u8, to: *mut u8, k: *mut RSA, @@ -1996,3 +2003,12 @@ extern { md: *mut c_uchar, len: *mut c_uint) -> c_int; } + +// EVP_PKEY_CTX_ctrl macros +unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int { + RSA_pkey_ctx_ctrl(ctx, -1, RSA_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) +} + +unsafe fn EVP_PKEY_CTX_get_rsa_padding(ctx: *mut EVP_PKEY_CTX, ppad: *mut c_int) -> c_int { + RSA_pkey_ctx_ctrl(ctx, -1, RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) +} From 588fd33552f9c84e8ed67c4cff35264b671362d9 Mon Sep 17 00:00:00 2001 From: Brian Chin Date: Mon, 30 Jan 2017 10:08:25 -0800 Subject: [PATCH 04/12] Testing first version that works with signer. --- openssl-sys/src/lib.rs | 12 +++++++----- openssl/src/pkey.rs | 6 ++++++ openssl/src/rsa.rs | 19 ++++++++++++++++++- openssl/src/sign.rs | 17 ++++++++++++----- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 6b61aab7..7ef5f7fe 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1638,6 +1638,9 @@ extern { key: *const c_uchar, keylen: c_int) -> *mut EVP_PKEY; + + pub fn EVP_PKEY_CTX_ctrl(ctx: *mut EVP_PKEY_CTX, keytype: c_int, optype: c_int, cmd: c_int, p1: c_int, p2: *mut c_void) -> c_int; + pub fn HMAC_CTX_copy(dst: *mut HMAC_CTX, src: *mut HMAC_CTX) -> c_int; pub fn OCSP_BASICRESP_new() -> *mut OCSP_BASICRESP; @@ -1732,7 +1735,6 @@ extern { pub fn RSA_new() -> *mut RSA; pub fn RSA_free(rsa: *mut RSA); pub fn RSA_generate_key_ex(rsa: *mut RSA, bits: c_int, e: *mut BIGNUM, cb: *mut BN_GENCB) -> c_int; - pub fn RSA_pkey_ctx_ctrl(ctx: *mut EVP_PKEY_CTX, optype: c_int, cmd: c_int, p1: c_int, p2: *mut c_void) -> c_int; pub fn RSA_private_decrypt(flen: c_int, from: *const u8, to: *mut u8, k: *mut RSA, pad: c_int) -> c_int; pub fn RSA_public_decrypt(flen: c_int, from: *const u8, to: *mut u8, k: *mut RSA, @@ -2005,10 +2007,10 @@ extern { } // EVP_PKEY_CTX_ctrl macros -unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int { - RSA_pkey_ctx_ctrl(ctx, -1, RSA_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) +pub unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int { + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, RSA_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) } -unsafe fn EVP_PKEY_CTX_get_rsa_padding(ctx: *mut EVP_PKEY_CTX, ppad: *mut c_int) -> c_int { - RSA_pkey_ctx_ctrl(ctx, -1, RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) +pub unsafe fn EVP_PKEY_CTX_get_rsa_padding(ctx: *mut EVP_PKEY_CTX, ppad: *mut c_int) -> c_int { + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) } diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index 7a32692b..fd963c24 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -151,6 +151,12 @@ impl PKey { } } +pub struct PKeyCtxRef(::util::Opaque); + +impl ::types::OpenSslTypeRef for PKeyCtxRef { + type CType = ffi::EVP_PKEY_CTX; +} + #[cfg(test)] mod tests { use symm::Cipher; diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index 8c3507f4..75893545 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -10,9 +10,10 @@ use bio::MemBioSlice; use error::ErrorStack; use util::{CallbackState, invoke_passwd_cb_old}; use types::OpenSslTypeRef; +use pkey::PKeyCtxRef; /// Type of encryption padding to use. -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct Padding(c_int); pub const NO_PADDING: Padding = Padding(ffi::RSA_NO_PADDING); @@ -343,6 +344,22 @@ mod compat { } } +impl PKeyCtxRef { + pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> { + unsafe { + try!(cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(self.as_ptr(), pad.0))); + } + Ok(()) + } + + pub fn get_rsa_padding(&mut self) -> Result { + let mut pad: c_int = 0; + unsafe { + try!(cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))); + }; + Ok(Padding(pad)) + } +} #[cfg(test)] mod test { diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs index ec37c885..d1fcffd5 100644 --- a/openssl/src/sign.rs +++ b/openssl/src/sign.rs @@ -68,7 +68,7 @@ use std::ptr; use {cvt, cvt_p}; use hash::MessageDigest; -use pkey::PKeyRef; +use pkey::{PKeyRef, PKeyCtxRef}; use error::ErrorStack; use types::OpenSslTypeRef; @@ -77,7 +77,7 @@ use ffi::{EVP_MD_CTX_new, EVP_MD_CTX_free}; #[cfg(any(ossl101, ossl102))] use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free}; -pub struct Signer<'a>(*mut ffi::EVP_MD_CTX, PhantomData<&'a PKeyRef>); +pub struct Signer<'a>(*mut ffi::EVP_MD_CTX, *mut ffi::EVP_PKEY_CTX, PhantomData<&'a PKeyRef>, PhantomData<&'a PKeyCtxRef>); impl<'a> Drop for Signer<'a> { fn drop(&mut self) { @@ -93,8 +93,9 @@ impl<'a> Signer<'a> { ffi::init(); let ctx = try!(cvt_p(EVP_MD_CTX_new())); + let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut(); let r = ffi::EVP_DigestSignInit(ctx, - ptr::null_mut(), + &mut pctx, type_.as_ptr(), ptr::null_mut(), pkey.as_ptr()); @@ -102,10 +103,14 @@ impl<'a> Signer<'a> { EVP_MD_CTX_free(ctx); return Err(ErrorStack::get()); } - Ok(Signer(ctx, PhantomData)) + Ok(Signer(ctx, pctx, PhantomData, PhantomData)) } } + pub fn pkey_ctx(&mut self) -> Option<&mut PKeyCtxRef> { + unsafe { self.1.as_mut().map(|ctx| ::types::OpenSslTypeRef::from_ptr_mut(ctx)) } + } + pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EVP_DigestUpdate(self.0, buf.as_ptr() as *const _, buf.len())).map(|_| ()) @@ -219,7 +224,7 @@ mod test { use sign::{Signer, Verifier}; use ec::{EcGroup, EcKey}; use nid; - use rsa::Rsa; + use rsa::{Rsa, PKCS1_PADDING}; use dsa::Dsa; use pkey::PKey; @@ -254,6 +259,8 @@ mod test { let pkey = PKey::from_rsa(private_key).unwrap(); let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap(); + assert_eq!(signer.pkey_ctx().unwrap().get_rsa_padding().unwrap(), PKCS1_PADDING); + signer.pkey_ctx().unwrap().set_rsa_padding(PKCS1_PADDING).unwrap(); signer.update(INPUT).unwrap(); let result = signer.finish().unwrap(); From 20eed1e762f01ddac0a46b6471105dca8284ff8b Mon Sep 17 00:00:00 2001 From: Brian Chin Date: Mon, 30 Jan 2017 10:19:06 -0800 Subject: [PATCH 05/12] Simplify code, so that openssl-sys really doesn't contain anything aside from bindings --- openssl-sys/src/lib.rs | 9 ------- openssl/src/rsa.rs | 13 ++++++++-- openssl/src/sign.rs | 54 ++++++++++++++++++++++++++++++++---------- 3 files changed, 52 insertions(+), 24 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 7ef5f7fe..9f89762b 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -2005,12 +2005,3 @@ extern { md: *mut c_uchar, len: *mut c_uint) -> c_int; } - -// EVP_PKEY_CTX_ctrl macros -pub unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int { - EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, RSA_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) -} - -pub unsafe fn EVP_PKEY_CTX_get_rsa_padding(ctx: *mut EVP_PKEY_CTX, ppad: *mut c_int) -> c_int { - EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) -} diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index 75893545..63ed874a 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -344,10 +344,19 @@ mod compat { } } +// EVP_PKEY_CTX_ctrl macros +unsafe fn pkey_ctx_set_rsa_padding(ctx: *mut ffi::EVP_PKEY_CTX, pad: c_int) -> c_int { + ffi::EVP_PKEY_CTX_ctrl(ctx, ffi::EVP_PKEY_RSA, -1, ffi::RSA_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) +} + +unsafe fn pkey_ctx_get_rsa_padding(ctx: *mut ffi::EVP_PKEY_CTX, ppad: *mut c_int) -> c_int { + ffi::EVP_PKEY_CTX_ctrl(ctx, ffi::EVP_PKEY_RSA, -1, ffi::RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) +} + impl PKeyCtxRef { pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> { unsafe { - try!(cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(self.as_ptr(), pad.0))); + try!(cvt(pkey_ctx_set_rsa_padding(self.as_ptr(), pad.0))); } Ok(()) } @@ -355,7 +364,7 @@ impl PKeyCtxRef { pub fn get_rsa_padding(&mut self) -> Result { let mut pad: c_int = 0; unsafe { - try!(cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))); + try!(cvt(pkey_ctx_get_rsa_padding(self.as_ptr(), &mut pad))); }; Ok(Padding(pad)) } diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs index d1fcffd5..41314a84 100644 --- a/openssl/src/sign.rs +++ b/openssl/src/sign.rs @@ -77,12 +77,18 @@ use ffi::{EVP_MD_CTX_new, EVP_MD_CTX_free}; #[cfg(any(ossl101, ossl102))] use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free}; -pub struct Signer<'a>(*mut ffi::EVP_MD_CTX, *mut ffi::EVP_PKEY_CTX, PhantomData<&'a PKeyRef>, PhantomData<&'a PKeyCtxRef>); +pub struct Signer<'a> { + md_ctx: *mut ffi::EVP_MD_CTX, + pkey_ctx: *mut ffi::EVP_PKEY_CTX, + pkey_pd: PhantomData<&'a PKeyRef>, + pkey_ctx_pd: PhantomData<&'a PKeyCtxRef> +} impl<'a> Drop for Signer<'a> { fn drop(&mut self) { + // pkey_ctx is owned by the md_ctx, so no need to explicitly free it. unsafe { - EVP_MD_CTX_free(self.0); + EVP_MD_CTX_free(self.md_ctx); } } } @@ -103,26 +109,31 @@ impl<'a> Signer<'a> { EVP_MD_CTX_free(ctx); return Err(ErrorStack::get()); } - Ok(Signer(ctx, pctx, PhantomData, PhantomData)) + Ok(Signer { + md_ctx: ctx, + pkey_ctx: pctx, + pkey_pd: PhantomData, + pkey_ctx_pd: PhantomData + }) } } pub fn pkey_ctx(&mut self) -> Option<&mut PKeyCtxRef> { - unsafe { self.1.as_mut().map(|ctx| ::types::OpenSslTypeRef::from_ptr_mut(ctx)) } + unsafe { self.pkey_ctx.as_mut().map(|ctx| ::types::OpenSslTypeRef::from_ptr_mut(ctx)) } } pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { unsafe { - cvt(ffi::EVP_DigestUpdate(self.0, buf.as_ptr() as *const _, buf.len())).map(|_| ()) + cvt(ffi::EVP_DigestUpdate(self.md_ctx, buf.as_ptr() as *const _, buf.len())).map(|_| ()) } } pub fn finish(&self) -> Result, ErrorStack> { unsafe { let mut len = 0; - try!(cvt(ffi::EVP_DigestSignFinal(self.0, ptr::null_mut(), &mut len))); + try!(cvt(ffi::EVP_DigestSignFinal(self.md_ctx, ptr::null_mut(), &mut len))); let mut buf = vec![0; len]; - try!(cvt(ffi::EVP_DigestSignFinal(self.0, buf.as_mut_ptr() as *mut _, &mut len))); + try!(cvt(ffi::EVP_DigestSignFinal(self.md_ctx, buf.as_mut_ptr() as *mut _, &mut len))); // The advertised length is not always equal to the real length for things like DSA buf.truncate(len); Ok(buf) @@ -141,12 +152,18 @@ impl<'a> Write for Signer<'a> { } } -pub struct Verifier<'a>(*mut ffi::EVP_MD_CTX, PhantomData<&'a PKeyRef>); +pub struct Verifier<'a> { + md_ctx: *mut ffi::EVP_MD_CTX, + pkey_ctx: *mut ffi::EVP_PKEY_CTX, + pkey_pd: PhantomData<&'a PKeyRef>, + pkey_ctx_pd: PhantomData<&'a PKeyCtxRef>, +} impl<'a> Drop for Verifier<'a> { fn drop(&mut self) { + // pkey_ctx is owned by the md_ctx, so no need to explicitly free it. unsafe { - EVP_MD_CTX_free(self.0); + EVP_MD_CTX_free(self.md_ctx); } } } @@ -157,8 +174,9 @@ impl<'a> Verifier<'a> { ffi::init(); let ctx = try!(cvt_p(EVP_MD_CTX_new())); + let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut(); let r = ffi::EVP_DigestVerifyInit(ctx, - ptr::null_mut(), + &mut pctx, type_.as_ptr(), ptr::null_mut(), pkey.as_ptr()); @@ -167,19 +185,28 @@ impl<'a> Verifier<'a> { return Err(ErrorStack::get()); } - Ok(Verifier(ctx, PhantomData)) + Ok(Verifier { + md_ctx: ctx, + pkey_ctx: pctx, + pkey_pd: PhantomData, + pkey_ctx_pd: PhantomData, + }) } } + pub fn pkey_ctx(&mut self) -> Option<&mut PKeyCtxRef> { + unsafe { self.pkey_ctx.as_mut().map(|ctx| ::types::OpenSslTypeRef::from_ptr_mut(ctx)) } + } + pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { unsafe { - cvt(ffi::EVP_DigestUpdate(self.0, buf.as_ptr() as *const _, buf.len())).map(|_| ()) + cvt(ffi::EVP_DigestUpdate(self.md_ctx, buf.as_ptr() as *const _, buf.len())).map(|_| ()) } } pub fn finish(&self, signature: &[u8]) -> Result { unsafe { - let r = EVP_DigestVerifyFinal(self.0, signature.as_ptr() as *const _, signature.len()); + let r = EVP_DigestVerifyFinal(self.md_ctx, signature.as_ptr() as *const _, signature.len()); match r { 1 => Ok(true), 0 => { @@ -274,6 +301,7 @@ mod test { let pkey = PKey::from_rsa(private_key).unwrap(); let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); + assert_eq!(verifier.pkey_ctx().unwrap().get_rsa_padding().unwrap(), PKCS1_PADDING); verifier.update(INPUT).unwrap(); assert!(verifier.finish(SIGNATURE).unwrap()); } From e1fc5b2b7ea46161d83f91f4e372fd52423107b9 Mon Sep 17 00:00:00 2001 From: Brian Chin Date: Mon, 30 Jan 2017 10:29:06 -0800 Subject: [PATCH 06/12] Simplify protocol based on the semantics defined by openssl. --- openssl/src/sign.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs index 41314a84..fe38a9a8 100644 --- a/openssl/src/sign.rs +++ b/openssl/src/sign.rs @@ -109,6 +109,9 @@ impl<'a> Signer<'a> { EVP_MD_CTX_free(ctx); return Err(ErrorStack::get()); } + + assert!(!pctx.is_null()); + Ok(Signer { md_ctx: ctx, pkey_ctx: pctx, @@ -118,8 +121,8 @@ impl<'a> Signer<'a> { } } - pub fn pkey_ctx(&mut self) -> Option<&mut PKeyCtxRef> { - unsafe { self.pkey_ctx.as_mut().map(|ctx| ::types::OpenSslTypeRef::from_ptr_mut(ctx)) } + pub fn pkey_ctx(&mut self) -> &mut PKeyCtxRef { + unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.pkey_ctx) } } pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { @@ -185,6 +188,8 @@ impl<'a> Verifier<'a> { return Err(ErrorStack::get()); } + assert!(!pctx.is_null()); + Ok(Verifier { md_ctx: ctx, pkey_ctx: pctx, @@ -194,8 +199,8 @@ impl<'a> Verifier<'a> { } } - pub fn pkey_ctx(&mut self) -> Option<&mut PKeyCtxRef> { - unsafe { self.pkey_ctx.as_mut().map(|ctx| ::types::OpenSslTypeRef::from_ptr_mut(ctx)) } + pub fn pkey_ctx(&mut self) -> &mut PKeyCtxRef { + unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.pkey_ctx) } } pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { @@ -286,8 +291,8 @@ mod test { let pkey = PKey::from_rsa(private_key).unwrap(); let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap(); - assert_eq!(signer.pkey_ctx().unwrap().get_rsa_padding().unwrap(), PKCS1_PADDING); - signer.pkey_ctx().unwrap().set_rsa_padding(PKCS1_PADDING).unwrap(); + assert_eq!(signer.pkey_ctx().get_rsa_padding().unwrap(), PKCS1_PADDING); + signer.pkey_ctx().set_rsa_padding(PKCS1_PADDING).unwrap(); signer.update(INPUT).unwrap(); let result = signer.finish().unwrap(); @@ -301,7 +306,7 @@ mod test { let pkey = PKey::from_rsa(private_key).unwrap(); let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); - assert_eq!(verifier.pkey_ctx().unwrap().get_rsa_padding().unwrap(), PKCS1_PADDING); + assert_eq!(verifier.pkey_ctx().get_rsa_padding().unwrap(), PKCS1_PADDING); verifier.update(INPUT).unwrap(); assert!(verifier.finish(SIGNATURE).unwrap()); } From ef61b814ff51d516adbc33d522dd0d84f2344196 Mon Sep 17 00:00:00 2001 From: Brian Chin Date: Mon, 30 Jan 2017 10:30:25 -0800 Subject: [PATCH 07/12] Small amount of docs. --- openssl/src/rsa.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index 63ed874a..433efd56 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -353,6 +353,7 @@ unsafe fn pkey_ctx_get_rsa_padding(ctx: *mut ffi::EVP_PKEY_CTX, ppad: *mut c_int ffi::EVP_PKEY_CTX_ctrl(ctx, ffi::EVP_PKEY_RSA, -1, ffi::RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) } +// This is needed here, as it needs access to the privade data of Padding. impl PKeyCtxRef { pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> { unsafe { From 72a10f3e65c1bed4689ba609d67865fbe766c92f Mon Sep 17 00:00:00 2001 From: Brian Chin Date: Mon, 30 Jan 2017 10:35:57 -0800 Subject: [PATCH 08/12] Fixing typo --- openssl/src/rsa.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index 433efd56..d9e599c8 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -353,7 +353,7 @@ unsafe fn pkey_ctx_get_rsa_padding(ctx: *mut ffi::EVP_PKEY_CTX, ppad: *mut c_int ffi::EVP_PKEY_CTX_ctrl(ctx, ffi::EVP_PKEY_RSA, -1, ffi::RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) } -// This is needed here, as it needs access to the privade data of Padding. +// This is needed here, as it needs access to the private data of Padding. impl PKeyCtxRef { pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> { unsafe { From 302ee77d32acb0b92fe563f29c36882e3b9b7d62 Mon Sep 17 00:00:00 2001 From: Brian Chin Date: Mon, 30 Jan 2017 16:51:10 -0800 Subject: [PATCH 09/12] Adding suggestions from review. --- openssl-sys/src/lib.rs | 9 +++++++++ openssl/src/pkey.rs | 19 ++++++++++++++++++- openssl/src/rsa.rs | 38 ++++++++++---------------------------- openssl/src/sign.rs | 14 +++++--------- 4 files changed, 42 insertions(+), 38 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 9f89762b..1859c3ba 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1310,6 +1310,15 @@ pub unsafe fn BIO_set_retry_write(b: *mut BIO) { BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY) } +// EVP_PKEY_CTX_ctrl macros +pub unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int { + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, RSA_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) +} + +pub unsafe fn EVP_PKEY_CTX_get_rsa_padding(ctx: *mut EVP_PKEY_CTX, ppad: *mut c_int) -> c_int { + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) +} + pub unsafe fn SSL_CTX_set_mode(ctx: *mut SSL_CTX, op: c_long) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, op, ptr::null_mut()) } diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index fd963c24..0d8de1dd 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -8,7 +8,7 @@ use bio::MemBioSlice; use dh::Dh; use dsa::Dsa; use ec::EcKey; -use rsa::Rsa; +use rsa::{Rsa, Padding}; use error::ErrorStack; use util::{CallbackState, invoke_passwd_cb_old}; use types::{OpenSslType, OpenSslTypeRef}; @@ -153,6 +153,23 @@ impl PKey { pub struct PKeyCtxRef(::util::Opaque); +impl PKeyCtxRef { + pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> { + unsafe { + try!(cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(self.as_ptr(), pad.as_raw()))); + } + Ok(()) + } + + pub fn rsa_padding(&mut self) -> Result { + let mut pad: c_int = 0; + unsafe { + try!(cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))); + }; + Ok(Padding::from_raw(pad)) + } +} + impl ::types::OpenSslTypeRef for PKeyCtxRef { type CType = ffi::EVP_PKEY_CTX; } diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index d9e599c8..dc760f7a 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -10,12 +10,21 @@ use bio::MemBioSlice; use error::ErrorStack; use util::{CallbackState, invoke_passwd_cb_old}; use types::OpenSslTypeRef; -use pkey::PKeyCtxRef; /// Type of encryption padding to use. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct Padding(c_int); +impl Padding { + pub fn from_raw(value: c_int) -> Padding { + Padding(value) + } + + pub fn as_raw(&self) -> c_int { + self.0 + } +} + pub const NO_PADDING: Padding = Padding(ffi::RSA_NO_PADDING); pub const PKCS1_PADDING: Padding = Padding(ffi::RSA_PKCS1_PADDING); pub const PKCS1_OAEP_PADDING: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING); @@ -344,33 +353,6 @@ mod compat { } } -// EVP_PKEY_CTX_ctrl macros -unsafe fn pkey_ctx_set_rsa_padding(ctx: *mut ffi::EVP_PKEY_CTX, pad: c_int) -> c_int { - ffi::EVP_PKEY_CTX_ctrl(ctx, ffi::EVP_PKEY_RSA, -1, ffi::RSA_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) -} - -unsafe fn pkey_ctx_get_rsa_padding(ctx: *mut ffi::EVP_PKEY_CTX, ppad: *mut c_int) -> c_int { - ffi::EVP_PKEY_CTX_ctrl(ctx, ffi::EVP_PKEY_RSA, -1, ffi::RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) -} - -// This is needed here, as it needs access to the private data of Padding. -impl PKeyCtxRef { - pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> { - unsafe { - try!(cvt(pkey_ctx_set_rsa_padding(self.as_ptr(), pad.0))); - } - Ok(()) - } - - pub fn get_rsa_padding(&mut self) -> Result { - let mut pad: c_int = 0; - unsafe { - try!(cvt(pkey_ctx_get_rsa_padding(self.as_ptr(), &mut pad))); - }; - Ok(Padding(pad)) - } -} - #[cfg(test)] mod test { use symm::Cipher; diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs index fe38a9a8..3ae8f1a2 100644 --- a/openssl/src/sign.rs +++ b/openssl/src/sign.rs @@ -81,7 +81,6 @@ pub struct Signer<'a> { md_ctx: *mut ffi::EVP_MD_CTX, pkey_ctx: *mut ffi::EVP_PKEY_CTX, pkey_pd: PhantomData<&'a PKeyRef>, - pkey_ctx_pd: PhantomData<&'a PKeyCtxRef> } impl<'a> Drop for Signer<'a> { @@ -116,12 +115,11 @@ impl<'a> Signer<'a> { md_ctx: ctx, pkey_ctx: pctx, pkey_pd: PhantomData, - pkey_ctx_pd: PhantomData }) } } - pub fn pkey_ctx(&mut self) -> &mut PKeyCtxRef { + pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.pkey_ctx) } } @@ -159,7 +157,6 @@ pub struct Verifier<'a> { md_ctx: *mut ffi::EVP_MD_CTX, pkey_ctx: *mut ffi::EVP_PKEY_CTX, pkey_pd: PhantomData<&'a PKeyRef>, - pkey_ctx_pd: PhantomData<&'a PKeyCtxRef>, } impl<'a> Drop for Verifier<'a> { @@ -194,12 +191,11 @@ impl<'a> Verifier<'a> { md_ctx: ctx, pkey_ctx: pctx, pkey_pd: PhantomData, - pkey_ctx_pd: PhantomData, }) } } - pub fn pkey_ctx(&mut self) -> &mut PKeyCtxRef { + pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.pkey_ctx) } } @@ -291,8 +287,8 @@ mod test { let pkey = PKey::from_rsa(private_key).unwrap(); let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap(); - assert_eq!(signer.pkey_ctx().get_rsa_padding().unwrap(), PKCS1_PADDING); - signer.pkey_ctx().set_rsa_padding(PKCS1_PADDING).unwrap(); + assert_eq!(signer.pkey_ctx_mut().rsa_padding().unwrap(), PKCS1_PADDING); + signer.pkey_ctx_mut().set_rsa_padding(PKCS1_PADDING).unwrap(); signer.update(INPUT).unwrap(); let result = signer.finish().unwrap(); @@ -306,7 +302,7 @@ mod test { let pkey = PKey::from_rsa(private_key).unwrap(); let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); - assert_eq!(verifier.pkey_ctx().get_rsa_padding().unwrap(), PKCS1_PADDING); + assert_eq!(verifier.pkey_ctx_mut().rsa_padding().unwrap(), PKCS1_PADDING); verifier.update(INPUT).unwrap(); assert!(verifier.finish(SIGNATURE).unwrap()); } From 4900d3fe5d8fe9f581940bd60e2d919155839fa8 Mon Sep 17 00:00:00 2001 From: Brian Chin Date: Tue, 31 Jan 2017 11:59:59 -0800 Subject: [PATCH 10/12] Fixed constant names from openssl/rsa.h Fixed PKeyCtxRef method that didn't need to be mutable. Added non-mutable accessors for PKeyCtxRef for Signer and Verifier. --- openssl-sys/src/lib.rs | 12 ++++++------ openssl/src/pkey.rs | 2 +- openssl/src/sign.rs | 8 ++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 1859c3ba..d18fa5ad 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -153,6 +153,10 @@ pub const EVP_PKEY_EC: c_int = NID_X9_62_id_ecPublicKey; pub const EVP_PKEY_ALG_CTRL: c_int = 0x1000; +pub const EVP_PKEY_CTRL_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 1; + +pub const EVP_PKEY_CTRL_GET_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 6; + pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9; pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10; pub const EVP_CTRL_GCM_SET_TAG: c_int = 0x11; @@ -1123,10 +1127,6 @@ pub const RSA_NO_PADDING: c_int = 3; pub const RSA_PKCS1_OAEP_PADDING: c_int = 4; pub const RSA_X931_PADDING: c_int = 5; -pub const RSA_PKEY_CTRL_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 1; - -pub const RSA_PKEY_CTRL_GET_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 6; - pub const SSL_CTRL_SET_TMP_DH: c_int = 3; pub const SSL_CTRL_SET_TMP_ECDH: c_int = 4; pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; @@ -1312,11 +1312,11 @@ pub unsafe fn BIO_set_retry_write(b: *mut BIO) { // EVP_PKEY_CTX_ctrl macros pub unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int { - EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, RSA_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, ptr::null_mut()) } pub unsafe fn EVP_PKEY_CTX_get_rsa_padding(ctx: *mut EVP_PKEY_CTX, ppad: *mut c_int) -> c_int { - EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, RSA_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad as *mut c_void) } pub unsafe fn SSL_CTX_set_mode(ctx: *mut SSL_CTX, op: c_long) -> c_long { diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index 0d8de1dd..c9f5ec1b 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -161,7 +161,7 @@ impl PKeyCtxRef { Ok(()) } - pub fn rsa_padding(&mut self) -> Result { + pub fn rsa_padding(&self) -> Result { let mut pad: c_int = 0; unsafe { try!(cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))); diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs index 3ae8f1a2..ac33bd07 100644 --- a/openssl/src/sign.rs +++ b/openssl/src/sign.rs @@ -119,6 +119,10 @@ impl<'a> Signer<'a> { } } + pub fn pkey_ctx(&self) -> &PKeyCtxRef { + unsafe { ::types::OpenSslTypeRef::from_ptr(self.pkey_ctx) } + } + pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.pkey_ctx) } } @@ -195,6 +199,10 @@ impl<'a> Verifier<'a> { } } + pub fn pkey_ctx(&self) -> &PKeyCtxRef { + unsafe { ::types::OpenSslTypeRef::from_ptr(self.pkey_ctx) } + } + pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.pkey_ctx) } } From 5e3dd07ee477fc30779b438be50dc6157b716d22 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 3 Feb 2017 01:27:11 -0800 Subject: [PATCH 11/12] Clean up pkg-config logic Now that we're letting the C compiler track down headers this is no longer necessary. --- openssl-sys/build.rs | 75 +++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index 1b717693..fc0f4680 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -7,6 +7,7 @@ use std::ffi::OsString; use std::fs::File; use std::io::{BufWriter, Write}; use std::path::{Path, PathBuf}; +use std::panic::{self, AssertUnwindSafe}; use std::process::Command; // The set of `OPENSSL_NO_`s that we care about. @@ -189,46 +190,10 @@ fn try_pkg_config() { return } - // We're going to be looking at header files, so show us all the system - // cflags dirs for showing us lots of `-I`. - env::set_var("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS", "1"); - - // This is more complex than normal because we need to track down opensslconf.h. - // To do that, we need the inlude paths even if they're on the default search path, but the - // linkage directories emitted from that cause all kinds of issues if other libraries happen to - // live in them. So, we run pkg-config twice, once asking for system dirs but not emitting - // metadata, and a second time emitting metadata but not asking for system dirs. Yay. - let lib = match pkg_config::Config::new() - .cargo_metadata(false) - .print_system_libs(true) - .find("openssl") { - Ok(lib) => lib, - Err(_) => return, - }; - - if lib.include_paths.len() == 0 { - panic!(" - -Used pkg-config to discover the OpenSSL installation, but pkg-config did not -return any include paths for the installation. This crate needs to take a peek -at the header files so it cannot proceed unless they're found. - -You can try fixing this setting the `OPENSSL_DIR` environment variable -pointing to your OpenSSL installation or installing OpenSSL headers package -specific to your distribution: - - # On Ubuntu - sudo apt-get install libssl-dev - # On Arch Linux - sudo pacman -S openssl - # On Fedora - sudo dnf install openssl-devel - -See rust-openssl README for more information: - - https://github.com/sfackler/rust-openssl#linux -"); - } + let lib = pkg_config::Config::new() + .print_system_libs(false) + .find("openssl") + .unwrap(); validate_headers(&lib.include_paths); @@ -236,11 +201,6 @@ See rust-openssl README for more information: println!("cargo:include={}", include.display()); } - pkg_config::Config::new() - .print_system_libs(false) - .find("openssl") - .unwrap(); - std::process::exit(0); } @@ -297,7 +257,30 @@ RUST_{define} for include_dir in include_dirs { gcc.include(include_dir); } - let expanded = gcc.file(&path).expand(); + // https://github.com/alexcrichton/gcc-rs/issues/133 + let expanded = match panic::catch_unwind(AssertUnwindSafe(|| gcc.file(&path).expand())) { + Ok(expanded) => expanded, + Err(_) => { + panic!(" +Failed to find OpenSSL development headers. + +You can try fixing this setting the `OPENSSL_DIR` environment variable +pointing to your OpenSSL installation or installing OpenSSL headers package +specific to your distribution: + + # On Ubuntu + sudo apt-get install libssl-dev + # On Arch Linux + sudo pacman -S openssl + # On Fedora + sudo dnf install openssl-devel + +See rust-openssl README for more information: + + https://github.com/sfackler/rust-openssl#linux +"); + } + }; let expanded = String::from_utf8(expanded).unwrap(); let mut enabled = vec![]; From 12ae31ad476d373ce93b4222d3875b9663f3da17 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 3 Feb 2017 01:24:05 -0800 Subject: [PATCH 12/12] Switch to foreign_types --- openssl/Cargo.toml | 1 + openssl/src/asn1.rs | 26 +++++++++++++++--- openssl/src/bn.rs | 18 ++++++++++--- openssl/src/dh.rs | 11 ++++++-- openssl/src/dsa.rs | 14 +++++++--- openssl/src/ec.rs | 35 ++++++++++++++++++++---- openssl/src/lib.rs | 2 ++ openssl/src/macros.rs | 47 +++----------------------------- openssl/src/ocsp.rs | 42 ++++++++++++++++++++++++----- openssl/src/pkcs12.rs | 10 +++++-- openssl/src/pkey.rs | 14 +++++++--- openssl/src/rsa.rs | 10 +++++-- openssl/src/sign.rs | 10 +++---- openssl/src/ssl/mod.rs | 30 ++++++++++++++++----- openssl/src/ssl/tests/mod.rs | 2 +- openssl/src/stack.rs | 17 ++++++------ openssl/src/string.rs | 10 +++++-- openssl/src/types.rs | 43 +++-------------------------- openssl/src/verify.rs | 10 +++++-- openssl/src/x509/mod.rs | 52 ++++++++++++++++++++++++++++++------ openssl/src/x509/store.rs | 18 ++++++++++--- 21 files changed, 272 insertions(+), 150 deletions(-) diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index d1893fe8..5d9aab92 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -19,6 +19,7 @@ v110 = [] [dependencies] bitflags = "0.7" +foreign-types = "0.1" lazy_static = "0.2" libc = "0.2" openssl-sys = { version = "0.9.6", path = "../openssl-sys" } diff --git a/openssl/src/asn1.rs b/openssl/src/asn1.rs index d177885e..fd932723 100644 --- a/openssl/src/asn1.rs +++ b/openssl/src/asn1.rs @@ -1,4 +1,5 @@ use ffi; +use foreign_types::{ForeignType, ForeignTypeRef}; use libc::{c_long, c_char}; use std::fmt; use std::ptr; @@ -8,10 +9,15 @@ use std::str; use {cvt, cvt_p}; use bio::MemBio; use error::ErrorStack; -use types::{OpenSslType, OpenSslTypeRef}; use string::OpensslString; -type_!(Asn1GeneralizedTime, Asn1GeneralizedTimeRef, ffi::ASN1_GENERALIZEDTIME, ffi::ASN1_GENERALIZEDTIME_free); +foreign_type! { + type CType = ffi::ASN1_GENERALIZEDTIME; + fn drop = ffi::ASN1_GENERALIZEDTIME_free; + + pub struct Asn1GeneralizedTime; + pub struct Asn1GeneralizedTimeRef; +} impl fmt::Display for Asn1GeneralizedTimeRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -23,7 +29,13 @@ impl fmt::Display for Asn1GeneralizedTimeRef { } } -type_!(Asn1Time, Asn1TimeRef, ffi::ASN1_TIME, ffi::ASN1_TIME_free); +foreign_type! { + type CType = ffi::ASN1_TIME; + fn drop = ffi::ASN1_TIME_free; + + pub struct Asn1Time; + pub struct Asn1TimeRef; +} impl fmt::Display for Asn1TimeRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -51,7 +63,13 @@ impl Asn1Time { } } -type_!(Asn1String, Asn1StringRef, ffi::ASN1_STRING, ffi::ASN1_STRING_free); +foreign_type! { + type CType = ffi::ASN1_STRING; + fn drop = ffi::ASN1_STRING_free; + + pub struct Asn1String; + pub struct Asn1StringRef; +} impl Asn1StringRef { pub fn as_utf8(&self) -> Result { diff --git a/openssl/src/bn.rs b/openssl/src/bn.rs index 01c0b428..7d288eee 100644 --- a/openssl/src/bn.rs +++ b/openssl/src/bn.rs @@ -1,4 +1,5 @@ use ffi; +use foreign_types::{ForeignType, ForeignTypeRef}; use libc::c_int; use std::cmp::Ordering; use std::ffi::CString; @@ -8,7 +9,6 @@ use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref}; use {cvt, cvt_p, cvt_n}; use error::ErrorStack; use string::OpensslString; -use types::{OpenSslType, OpenSslTypeRef}; #[cfg(ossl10x)] use ffi::{get_rfc2409_prime_768 as BN_get_rfc2409_prime_768, @@ -40,7 +40,13 @@ pub const MSB_ONE: MsbOption = MsbOption(0); /// of bits in the original numbers. pub const TWO_MSB_ONE: MsbOption = MsbOption(1); -type_!(BigNumContext, BigNumContextRef, ffi::BN_CTX, ffi::BN_CTX_free); +foreign_type! { + type CType = ffi::BN_CTX; + fn drop = ffi::BN_CTX_free; + + pub struct BigNumContext; + pub struct BigNumContextRef; +} impl BigNumContext { /// Returns a new `BigNumContext`. @@ -509,7 +515,13 @@ impl BigNumRef { } } -type_!(BigNum, BigNumRef, ffi::BIGNUM, ffi::BN_free); +foreign_type! { + type CType = ffi::BIGNUM; + fn drop = ffi::BN_free; + + pub struct BigNum; + pub struct BigNumRef; +} impl BigNum { /// Creates a new `BigNum` with the value 0. diff --git a/openssl/src/dh.rs b/openssl/src/dh.rs index 64494f95..a7454150 100644 --- a/openssl/src/dh.rs +++ b/openssl/src/dh.rs @@ -1,13 +1,20 @@ use error::ErrorStack; use ffi; +use foreign_types::ForeignTypeRef; use std::mem; use std::ptr; use {cvt, cvt_p, init}; use bn::BigNum; -use types::OpenSslTypeRef; -type_!(Dh, DhRef, ffi::DH, ffi::DH_free); +foreign_type! { + type CType = ffi::DH; + fn drop = ffi::DH_free; + + pub struct Dh; + + pub struct DhRef; +} impl DhRef { to_pem!(ffi::PEM_write_bio_DHparams); diff --git a/openssl/src/dsa.rs b/openssl/src/dsa.rs index a4a8bf30..60a1afde 100644 --- a/openssl/src/dsa.rs +++ b/openssl/src/dsa.rs @@ -1,16 +1,22 @@ -use error::ErrorStack; use ffi; +use foreign_types::ForeignTypeRef; use libc::{c_int, c_char, c_void}; use std::fmt; use std::ptr; +use {cvt, cvt_p}; use bio::MemBioSlice; use bn::BigNumRef; -use {cvt, cvt_p}; -use types::OpenSslTypeRef; +use error::ErrorStack; use util::{CallbackState, invoke_passwd_cb_old}; -type_!(Dsa, DsaRef, ffi::DSA, ffi::DSA_free); +foreign_type! { + type CType = ffi::DSA; + fn drop = ffi::DSA_free; + + pub struct Dsa; + pub struct DsaRef; +} impl DsaRef { private_key_to_pem!(ffi::PEM_write_bio_DSAPrivateKey); diff --git a/openssl/src/ec.rs b/openssl/src/ec.rs index ebb631e8..37815021 100644 --- a/openssl/src/ec.rs +++ b/openssl/src/ec.rs @@ -1,4 +1,5 @@ use ffi; +use foreign_types::{ForeignType, ForeignTypeRef}; use std::ptr; use std::mem; use libc::c_int; @@ -7,7 +8,6 @@ use {cvt, cvt_n, cvt_p, init}; use bn::{BigNumRef, BigNumContextRef}; use error::ErrorStack; use nid::Nid; -use types::{OpenSslType, OpenSslTypeRef}; pub const POINT_CONVERSION_COMPRESSED: PointConversionForm = PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_COMPRESSED); @@ -29,7 +29,13 @@ pub struct PointConversionForm(ffi::point_conversion_form_t); #[derive(Copy, Clone)] pub struct Asn1Flag(c_int); -type_!(EcGroup, EcGroupRef, ffi::EC_GROUP, ffi::EC_GROUP_free); +foreign_type! { + type CType = ffi::EC_GROUP; + fn drop = ffi::EC_GROUP_free; + + pub struct EcGroup; + pub struct EcGroupRef; +} impl EcGroup { /// Returns the group of a standard named curve. @@ -103,7 +109,13 @@ impl EcGroupRef { } } -type_!(EcPoint, EcPointRef, ffi::EC_POINT, ffi::EC_POINT_free); +foreign_type! { + type CType = ffi::EC_POINT; + fn drop = ffi::EC_POINT_free; + + pub struct EcPoint; + pub struct EcPointRef; +} impl EcPointRef { /// Computes `a + b`, storing the result in `self`. @@ -253,7 +265,13 @@ impl EcPoint { } } -type_!(EcKey, EcKeyRef, ffi::EC_KEY, ffi::EC_KEY_free); +foreign_type! { + type CType = ffi::EC_KEY; + fn drop = ffi::EC_KEY_free; + + pub struct EcKey; + pub struct EcKeyRef; +} impl EcKeyRef { private_key_to_pem!(ffi::PEM_write_bio_ECPrivateKey); @@ -355,7 +373,14 @@ impl EcKey { private_key_from_der!(EcKey, ffi::d2i_ECPrivateKey); } -type_!(EcKeyBuilder, EcKeyBuilderRef, ffi::EC_KEY, ffi::EC_KEY_free); + +foreign_type! { + type CType = ffi::EC_KEY; + fn drop = ffi::EC_KEY_free; + + pub struct EcKeyBuilder; + pub struct EcKeyBuilderRef; +} impl EcKeyBuilder { pub fn new() -> Result { diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index ea71a269..507af1d4 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -2,6 +2,8 @@ #[macro_use] extern crate bitflags; +#[macro_use] +extern crate foreign_types; extern crate libc; #[macro_use] extern crate lazy_static; diff --git a/openssl/src/macros.rs b/openssl/src/macros.rs index b36e8319..b2fe0c18 100644 --- a/openssl/src/macros.rs +++ b/openssl/src/macros.rs @@ -1,45 +1,4 @@ -macro_rules! type_ { - ($n:ident, $r:ident, $c:path, $d:path) => { - pub struct $n(*mut $c); - - impl ::types::OpenSslType for $n { - type CType = $c; - type Ref = $r; - - unsafe fn from_ptr(ptr: *mut $c) -> $n { - $n(ptr) - } - } - - impl Drop for $n { - fn drop(&mut self) { - unsafe { $d(self.0) } - } - } - - impl ::std::ops::Deref for $n { - type Target = $r; - - fn deref(&self) -> &$r { - unsafe { ::types::OpenSslTypeRef::from_ptr(self.0) } - } - } - - impl ::std::ops::DerefMut for $n { - fn deref_mut(&mut self) -> &mut $r { - unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.0) } - } - } - - pub struct $r(::util::Opaque); - - impl ::types::OpenSslTypeRef for $r { - type CType = $c; - } - } -} - macro_rules! private_key_from_pem { ($t:ident, $f:path) => { from_pem_inner!(/// Deserializes a PEM-formatted private key. @@ -161,9 +120,11 @@ macro_rules! to_der_inner { #[$m] pub fn $n(&self) -> Result, ::error::ErrorStack> { unsafe { - let len = try!(::cvt($f(::types::OpenSslTypeRef::as_ptr(self), ptr::null_mut()))); + let len = try!(::cvt($f(::foreign_types::ForeignTypeRef::as_ptr(self), + ptr::null_mut()))); let mut buf = vec![0; len as usize]; - try!(::cvt($f(::types::OpenSslTypeRef::as_ptr(self), &mut buf.as_mut_ptr()))); + try!(::cvt($f(::foreign_types::ForeignTypeRef::as_ptr(self), + &mut buf.as_mut_ptr()))); Ok(buf) } } diff --git a/openssl/src/ocsp.rs b/openssl/src/ocsp.rs index 708c3561..67d51838 100644 --- a/openssl/src/ocsp.rs +++ b/openssl/src/ocsp.rs @@ -1,4 +1,5 @@ use ffi; +use foreign_types::ForeignTypeRef; use libc::{c_int, c_long, c_ulong}; use std::ptr; use std::mem; @@ -8,7 +9,6 @@ use asn1::Asn1GeneralizedTimeRef; use error::ErrorStack; use hash::MessageDigest; use stack::StackRef; -use types::OpenSslTypeRef; use x509::store::X509StoreRef; use x509::{X509, X509Ref}; @@ -135,7 +135,13 @@ impl<'a> Status<'a> { } } -type_!(OcspBasicResponse, OcspBasicResponseRef, ffi::OCSP_BASICRESP, ffi::OCSP_BASICRESP_free); +foreign_type! { + type CType = ffi::OCSP_BASICRESP; + fn drop = ffi::OCSP_BASICRESP_free; + + pub struct OcspBasicResponse; + pub struct OcspBasicResponseRef; +} impl OcspBasicResponseRef { /// Verifies the validity of the response. @@ -189,7 +195,13 @@ impl OcspBasicResponseRef { } } -type_!(OcspCertId, OcspCertIdRef, ffi::OCSP_CERTID, ffi::OCSP_CERTID_free); +foreign_type! { + type CType = ffi::OCSP_CERTID; + fn drop = ffi::OCSP_CERTID_free; + + pub struct OcspCertId; + pub struct OcspCertIdRef; +} impl OcspCertId { /// Constructs a certificate ID for certificate `subject`. @@ -204,7 +216,13 @@ impl OcspCertId { } } -type_!(OcspResponse, OcspResponseRef, ffi::OCSP_RESPONSE, ffi::OCSP_RESPONSE_free); +foreign_type! { + type CType = ffi::OCSP_RESPONSE; + fn drop = ffi::OCSP_RESPONSE_free; + + pub struct OcspResponse; + pub struct OcspResponseRef; +} impl OcspResponse { /// Creates an OCSP response from the status and optional body. @@ -245,7 +263,13 @@ impl OcspResponseRef { } } -type_!(OcspRequest, OcspRequestRef, ffi::OCSP_REQUEST, ffi::OCSP_REQUEST_free); +foreign_type! { + type CType = ffi::OCSP_REQUEST; + fn drop = ffi::OCSP_REQUEST_free; + + pub struct OcspRequest; + pub struct OcspRequestRef; +} impl OcspRequest { pub fn new() -> Result { @@ -271,4 +295,10 @@ impl OcspRequestRef { } } -type_!(OcspOneReq, OcspOneReqRef, ffi::OCSP_ONEREQ, ffi::OCSP_ONEREQ_free); +foreign_type! { + type CType = ffi::OCSP_ONEREQ; + fn drop = ffi::OCSP_ONEREQ_free; + + pub struct OcspOneReq; + pub struct OcspOneReqRef; +} diff --git a/openssl/src/pkcs12.rs b/openssl/src/pkcs12.rs index 44a67af0..1e23668e 100644 --- a/openssl/src/pkcs12.rs +++ b/openssl/src/pkcs12.rs @@ -1,6 +1,7 @@ //! PKCS #12 archives. use ffi; +use foreign_types::{ForeignType, ForeignTypeRef}; use libc::c_int; use std::ptr; use std::ffi::CString; @@ -9,11 +10,16 @@ use {cvt, cvt_p}; use pkey::{PKey, PKeyRef}; use error::ErrorStack; use x509::X509; -use types::{OpenSslType, OpenSslTypeRef}; use stack::Stack; use nid; -type_!(Pkcs12, Pkcs12Ref, ffi::PKCS12, ffi::PKCS12_free); +foreign_type! { + type CType = ffi::PKCS12; + fn drop = ffi::PKCS12_free; + + pub struct Pkcs12; + pub struct Pkcs12Ref; +} impl Pkcs12Ref { to_der!(ffi::i2d_PKCS12); diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index c9f5ec1b..5608dd51 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -2,6 +2,7 @@ use libc::{c_void, c_char, c_int}; use std::ptr; use std::mem; use ffi; +use foreign_types::{Opaque, ForeignType, ForeignTypeRef}; use {cvt, cvt_p}; use bio::MemBioSlice; @@ -11,9 +12,14 @@ use ec::EcKey; use rsa::{Rsa, Padding}; use error::ErrorStack; use util::{CallbackState, invoke_passwd_cb_old}; -use types::{OpenSslType, OpenSslTypeRef}; -type_!(PKey, PKeyRef, ffi::EVP_PKEY, ffi::EVP_PKEY_free); +foreign_type! { + type CType = ffi::EVP_PKEY; + fn drop = ffi::EVP_PKEY_free; + + pub struct PKey; + pub struct PKeyRef; +} impl PKeyRef { /// Returns a copy of the internal RSA key. @@ -151,7 +157,7 @@ impl PKey { } } -pub struct PKeyCtxRef(::util::Opaque); +pub struct PKeyCtxRef(Opaque); impl PKeyCtxRef { pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> { @@ -170,7 +176,7 @@ impl PKeyCtxRef { } } -impl ::types::OpenSslTypeRef for PKeyCtxRef { +impl ForeignTypeRef for PKeyCtxRef { type CType = ffi::EVP_PKEY_CTX; } diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index dc760f7a..792f7070 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -3,13 +3,13 @@ use std::fmt; use std::ptr; use std::mem; use libc::{c_int, c_void, c_char}; +use foreign_types::ForeignTypeRef; use {cvt, cvt_p, cvt_n}; use bn::{BigNum, BigNumRef}; use bio::MemBioSlice; use error::ErrorStack; use util::{CallbackState, invoke_passwd_cb_old}; -use types::OpenSslTypeRef; /// Type of encryption padding to use. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -29,7 +29,13 @@ pub const NO_PADDING: Padding = Padding(ffi::RSA_NO_PADDING); pub const PKCS1_PADDING: Padding = Padding(ffi::RSA_PKCS1_PADDING); pub const PKCS1_OAEP_PADDING: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING); -type_!(Rsa, RsaRef, ffi::RSA, ffi::RSA_free); +foreign_type! { + type CType = ffi::RSA; + fn drop = ffi::RSA_free; + + pub struct Rsa; + pub struct RsaRef; +} impl RsaRef { private_key_to_pem!(ffi::PEM_write_bio_RSAPrivateKey); diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs index ac33bd07..279f294d 100644 --- a/openssl/src/sign.rs +++ b/openssl/src/sign.rs @@ -62,6 +62,7 @@ //! assert!(memcmp::eq(&hmac, &target)); //! ``` use ffi; +use foreign_types::ForeignTypeRef; use std::io::{self, Write}; use std::marker::PhantomData; use std::ptr; @@ -70,7 +71,6 @@ use {cvt, cvt_p}; use hash::MessageDigest; use pkey::{PKeyRef, PKeyCtxRef}; use error::ErrorStack; -use types::OpenSslTypeRef; #[cfg(ossl110)] use ffi::{EVP_MD_CTX_new, EVP_MD_CTX_free}; @@ -120,11 +120,11 @@ impl<'a> Signer<'a> { } pub fn pkey_ctx(&self) -> &PKeyCtxRef { - unsafe { ::types::OpenSslTypeRef::from_ptr(self.pkey_ctx) } + unsafe { PKeyCtxRef::from_ptr(self.pkey_ctx) } } pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { - unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.pkey_ctx) } + unsafe { PKeyCtxRef::from_ptr_mut(self.pkey_ctx) } } pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { @@ -200,11 +200,11 @@ impl<'a> Verifier<'a> { } pub fn pkey_ctx(&self) -> &PKeyCtxRef { - unsafe { ::types::OpenSslTypeRef::from_ptr(self.pkey_ctx) } + unsafe { PKeyCtxRef::from_ptr(self.pkey_ctx) } } pub fn pkey_ctx_mut(&mut self) -> &mut PKeyCtxRef { - unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.pkey_ctx) } + unsafe { PKeyCtxRef::from_ptr_mut(self.pkey_ctx) } } pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index dd7f72cc..860e2e00 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -71,6 +71,7 @@ //! } //! ``` use ffi; +use foreign_types::{ForeignType, ForeignTypeRef}; use libc::{c_int, c_void, c_long, c_ulong}; use libc::{c_uchar, c_uint}; use std::any::Any; @@ -102,7 +103,6 @@ use x509::store::{X509StoreBuilderRef, X509StoreRef}; use verify::X509VerifyParamRef; use pkey::PKeyRef; use error::ErrorStack; -use types::{OpenSslType, OpenSslTypeRef}; use util::Opaque; use stack::{Stack, StackRef}; @@ -966,7 +966,13 @@ impl SslContextBuilder { } } -type_!(SslContext, SslContextRef, ffi::SSL_CTX, ffi::SSL_CTX_free); +foreign_type! { + type CType = ffi::SSL_CTX; + fn drop = ffi::SSL_CTX_free; + + pub struct SslContext; + pub struct SslContextRef; +} unsafe impl Send for SslContext {} unsafe impl Sync for SslContext {} @@ -1051,7 +1057,7 @@ pub struct CipherBits { pub struct SslCipher(*mut ffi::SSL_CIPHER); -impl OpenSslType for SslCipher { +impl ForeignType for SslCipher { type CType = ffi::SSL_CIPHER; type Ref = SslCipherRef; @@ -1076,7 +1082,7 @@ impl DerefMut for SslCipher { pub struct SslCipherRef(Opaque); -impl OpenSslTypeRef for SslCipherRef { +impl ForeignTypeRef for SslCipherRef { type CType = ffi::SSL_CIPHER; } @@ -1124,7 +1130,13 @@ impl SslCipherRef { } } -type_!(SslSession, SslSessionRef, ffi::SSL_SESSION, ffi::SSL_SESSION_free); +foreign_type! { + type CType = ffi::SSL_SESSION; + fn drop = ffi::SSL_SESSION_free; + + pub struct SslSession; + pub struct SslSessionRef; +} impl SslSessionRef { /// Returns the SSL session ID. @@ -1149,7 +1161,13 @@ impl SslSessionRef { } } -type_!(Ssl, SslRef, ffi::SSL, ffi::SSL_free); +foreign_type! { + type CType = ffi::SSL; + fn drop = ffi::SSL_free; + + pub struct Ssl; + pub struct SslRef; +} impl fmt::Debug for SslRef { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 536088ab..9c00e3ed 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -174,7 +174,7 @@ macro_rules! run_test( use hash::MessageDigest; use x509::X509StoreContext; use hex::FromHex; - use types::OpenSslTypeRef; + use foreign_types::ForeignTypeRef; use super::Server; #[test] diff --git a/openssl/src/stack.rs b/openssl/src/stack.rs index dae42ca8..372040aa 100644 --- a/openssl/src/stack.rs +++ b/openssl/src/stack.rs @@ -1,12 +1,12 @@ -use std::ops::{Deref, DerefMut, Index, IndexMut}; -use std::iter; +use foreign_types::{ForeignTypeRef, ForeignType}; +use libc::c_int; use std::borrow::Borrow; use std::convert::AsRef; +use std::iter; use std::marker::PhantomData; -use libc::c_int; use std::mem; +use std::ops::{Deref, DerefMut, Index, IndexMut}; -use types::{OpenSslType, OpenSslTypeRef}; use util::Opaque; #[cfg(ossl10x)] @@ -17,9 +17,8 @@ use ffi::{OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value, OPE /// Trait implemented by types which can be placed in a stack. /// -/// Like `OpenSslType`, it should not be implemented for any type outside -/// of this crate. -pub trait Stackable: OpenSslType { +/// It should not be implemented for any type outside of this crate. +pub trait Stackable: ForeignType { /// The C stack type for this element. /// /// Generally called `stack_st_{ELEMENT_TYPE}`, normally hidden by the @@ -72,7 +71,7 @@ impl Borrow> for Stack { } } -impl OpenSslType for Stack { +impl ForeignType for Stack { type CType = T::StackType; type Ref = StackRef; @@ -140,7 +139,7 @@ impl ExactSizeIterator for IntoIter {} pub struct StackRef(Opaque, PhantomData); -impl OpenSslTypeRef for StackRef { +impl ForeignTypeRef for StackRef { type CType = T::StackType; } diff --git a/openssl/src/string.rs b/openssl/src/string.rs index 37d44d16..4a1d3479 100644 --- a/openssl/src/string.rs +++ b/openssl/src/string.rs @@ -1,14 +1,20 @@ use ffi; +use foreign_types::{ForeignType, ForeignTypeRef}; use libc::{c_char, c_void}; use std::fmt; use std::ffi::CStr; use std::ops::Deref; use std::str; -use types::{OpenSslType, OpenSslTypeRef}; use stack::Stackable; -type_!(OpensslString, OpensslStringRef, c_char, free); +foreign_type! { + type CType = c_char; + fn drop = free; + + pub struct OpensslString; + pub struct OpensslStringRef; +} impl OpensslString { #[deprecated(note = "use from_ptr", since = "0.9.7")] diff --git a/openssl/src/types.rs b/openssl/src/types.rs index 2fadfd42..25ffe501 100644 --- a/openssl/src/types.rs +++ b/openssl/src/types.rs @@ -1,40 +1,5 @@ -//! Items used by other types. +#[deprecated(note = "use foreign_types instead", since = "0.9.7")] +pub use foreign_types::ForeignType as OpenSslType; -/// A type implemented by wrappers over OpenSSL types. -/// -/// This should not be implemented by anything outside of this crate; new methods may be added at -/// any time. -pub trait OpenSslType: Sized { - /// The raw C type. - type CType; - - /// The type representing a reference to this type. - type Ref: OpenSslTypeRef; - - /// Constructs an instance of this type from its raw type. - unsafe fn from_ptr(ptr: *mut Self::CType) -> Self; -} - -/// A trait implemented by types which reference borrowed OpenSSL types. -/// -/// This should not be implemented by anything outside of this crate; new methods may be added at -/// any time. -pub trait OpenSslTypeRef: Sized { - /// The raw C type. - type CType; - - /// Constructs a shared instance of this type from its raw type. - unsafe fn from_ptr<'a>(ptr: *mut Self::CType) -> &'a Self { - &*(ptr as *mut _) - } - - /// Constructs a mutable reference of this type from its raw type. - unsafe fn from_ptr_mut<'a>(ptr: *mut Self::CType) -> &'a mut Self { - &mut *(ptr as *mut _) - } - - /// Returns a raw pointer to the wrapped value. - fn as_ptr(&self) -> *mut Self::CType { - self as *const _ as *mut _ - } -} +#[deprecated(note = "use foreign_types instead", since = "0.9.7")] +pub use foreign_types::ForeignTypeRef as OpenSslTypeRef; diff --git a/openssl/src/verify.rs b/openssl/src/verify.rs index 2f070fe5..f554127a 100644 --- a/openssl/src/verify.rs +++ b/openssl/src/verify.rs @@ -1,9 +1,9 @@ use libc::c_uint; use ffi; +use foreign_types::ForeignTypeRef; use cvt; use error::ErrorStack; -use types::OpenSslTypeRef; bitflags! { pub flags X509CheckFlags: c_uint { @@ -19,7 +19,13 @@ bitflags! { } } -type_!(X509VerifyParam, X509VerifyParamRef, ffi::X509_VERIFY_PARAM, ffi::X509_VERIFY_PARAM_free); +foreign_type! { + type CType = ffi::X509_VERIFY_PARAM; + fn drop = ffi::X509_VERIFY_PARAM_free; + + pub struct X509VerifyParam; + pub struct X509VerifyParamRef; +} impl X509VerifyParamRef { pub fn set_hostflags(&mut self, hostflags: X509CheckFlags) { diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index e75dcf5d..a0b76fef 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -1,3 +1,5 @@ +use ffi; +use foreign_types::{ForeignType, ForeignTypeRef}; use libc::{c_char, c_int, c_long, c_ulong}; use std::borrow::Borrow; use std::collections::HashMap; @@ -17,9 +19,7 @@ use hash::MessageDigest; use pkey::{PKey, PKeyRef}; use rand::rand_bytes; use error::ErrorStack; -use ffi; use nid::Nid; -use types::{OpenSslType, OpenSslTypeRef}; use string::OpensslString; use stack::{Stack, StackRef, Stackable}; @@ -53,7 +53,13 @@ pub const X509_FILETYPE_PEM: X509FileType = X509FileType(ffi::X509_FILETYPE_PEM) pub const X509_FILETYPE_ASN1: X509FileType = X509FileType(ffi::X509_FILETYPE_ASN1); pub const X509_FILETYPE_DEFAULT: X509FileType = X509FileType(ffi::X509_FILETYPE_DEFAULT); -type_!(X509StoreContext, X509StoreContextRef, ffi::X509_STORE_CTX, ffi::X509_STORE_CTX_free); +foreign_type! { + type CType = ffi::X509_STORE_CTX; + fn drop = ffi::X509_STORE_CTX_free; + + pub struct X509StoreContext; + pub struct X509StoreContextRef; +} impl X509StoreContextRef { pub fn error(&self) -> Option { @@ -354,7 +360,13 @@ impl X509Generator { } } -type_!(X509, X509Ref, ffi::X509, ffi::X509_free); +foreign_type! { + type CType = ffi::X509; + fn drop = ffi::X509_free; + + pub struct X509; + pub struct X509Ref; +} impl X509Ref { pub fn subject_name(&self) -> &X509NameRef { @@ -513,7 +525,13 @@ impl Stackable for X509 { type StackType = ffi::stack_st_X509; } -type_!(X509Name, X509NameRef, ffi::X509_NAME, ffi::X509_NAME_free); +foreign_type! { + type CType = ffi::X509_NAME; + fn drop = ffi::X509_NAME_free; + + pub struct X509Name; + pub struct X509NameRef; +} impl X509Name { /// Loads subject names from a file containing PEM-formatted certificates. @@ -567,7 +585,13 @@ impl<'a> Iterator for X509NameEntries<'a> { } } -type_!(X509NameEntry, X509NameEntryRef, ffi::X509_NAME_ENTRY, ffi::X509_NAME_ENTRY_free); +foreign_type! { + type CType = ffi::X509_NAME_ENTRY; + fn drop = ffi::X509_NAME_ENTRY_free; + + pub struct X509NameEntry; + pub struct X509NameEntryRef; +} impl X509NameEntryRef { pub fn data(&self) -> &Asn1StringRef { @@ -578,7 +602,13 @@ impl X509NameEntryRef { } } -type_!(X509Req, X509ReqRef, ffi::X509_REQ, ffi::X509_REQ_free); +foreign_type! { + type CType = ffi::X509_REQ; + fn drop = ffi::X509_REQ_free; + + pub struct X509Req; + pub struct X509ReqRef; +} impl X509Req { /// Reads CSR from PEM @@ -724,7 +754,13 @@ impl X509VerifyError { } } -type_!(GeneralName, GeneralNameRef, ffi::GENERAL_NAME, ffi::GENERAL_NAME_free); +foreign_type! { + type CType = ffi::GENERAL_NAME; + fn drop = ffi::GENERAL_NAME_free; + + pub struct GeneralName; + pub struct GeneralNameRef; +} impl GeneralNameRef { /// Returns the contents of this `GeneralName` if it is a `dNSName`. diff --git a/openssl/src/x509/store.rs b/openssl/src/x509/store.rs index dd08a49b..8b7a084b 100644 --- a/openssl/src/x509/store.rs +++ b/openssl/src/x509/store.rs @@ -1,12 +1,18 @@ use ffi; +use foreign_types::ForeignTypeRef; use std::mem; use {cvt, cvt_p}; use error::ErrorStack; -use types::OpenSslTypeRef; use x509::X509; -type_!(X509StoreBuilder, X509StoreBuilderRef, ffi::X509_STORE, ffi::X509_STORE_free); +foreign_type! { + type CType = ffi::X509_STORE; + fn drop = ffi::X509_STORE_free; + + pub struct X509StoreBuilder; + pub struct X509StoreBuilderRef; +} impl X509StoreBuilder { /// Returns a builder for a certificate store. @@ -50,4 +56,10 @@ impl X509StoreBuilderRef { } } -type_!(X509Store, X509StoreRef, ffi::X509_STORE, ffi::X509_STORE_free); +foreign_type! { + type CType = ffi::X509_STORE; + fn drop = ffi::X509_STORE_free; + + pub struct X509Store; + pub struct X509StoreRef; +}