This commit is contained in:
Steven Fackler 2017-07-15 21:46:11 -07:00
parent 5c2410c38a
commit bcd0dcafcb
39 changed files with 4303 additions and 2526 deletions

View File

@ -11,7 +11,8 @@ use std::panic::{self, AssertUnwindSafe};
use std::process::Command; use std::process::Command;
// The set of `OPENSSL_NO_<FOO>`s that we care about. // The set of `OPENSSL_NO_<FOO>`s that we care about.
const DEFINES: &'static [&'static str] = &["OPENSSL_NO_BUF_FREELISTS", const DEFINES: &'static [&'static str] = &[
"OPENSSL_NO_BUF_FREELISTS",
"OPENSSL_NO_COMP", "OPENSSL_NO_COMP",
"OPENSSL_NO_EC", "OPENSSL_NO_EC",
"OPENSSL_NO_EC2M", "OPENSSL_NO_EC2M",
@ -23,7 +24,8 @@ const DEFINES: &'static [&'static str] = &["OPENSSL_NO_BUF_FREELISTS",
"OPENSSL_NO_SHA", "OPENSSL_NO_SHA",
"OPENSSL_NO_SRP", "OPENSSL_NO_SRP",
"OPENSSL_NO_SSL3_METHOD", "OPENSSL_NO_SSL3_METHOD",
"OPENSSL_NO_TLSEXT"]; "OPENSSL_NO_TLSEXT",
];
enum Version { enum Version {
Openssl110, Openssl110,
@ -52,16 +54,22 @@ fn main() {
}; };
if !Path::new(&lib_dir).exists() { if !Path::new(&lib_dir).exists() {
panic!("OpenSSL library directory does not exist: {}", panic!(
lib_dir.to_string_lossy()); "OpenSSL library directory does not exist: {}",
lib_dir.to_string_lossy()
);
} }
if !Path::new(&include_dir).exists() { if !Path::new(&include_dir).exists() {
panic!("OpenSSL include directory does not exist: {}", panic!(
include_dir.to_string_lossy()); "OpenSSL include directory does not exist: {}",
include_dir.to_string_lossy()
);
} }
println!("cargo:rustc-link-search=native={}", println!(
lib_dir.to_string_lossy()); "cargo:rustc-link-search=native={}",
lib_dir.to_string_lossy()
);
println!("cargo:include={}", include_dir.to_string_lossy()); println!("cargo:include={}", include_dir.to_string_lossy());
let version = validate_headers(&[include_dir.clone().into()]); let version = validate_headers(&[include_dir.clone().into()]);
@ -103,7 +111,8 @@ fn find_openssl_dir(target: &str) -> OsString {
try_pkg_config(); try_pkg_config();
let mut msg = format!(" let mut msg = format!(
"
Could not find directory of OpenSSL installation, and this `-sys` crate cannot Could not find directory of OpenSSL installation, and this `-sys` crate cannot
proceed without this knowledge. If OpenSSL is installed and this crate had proceed without this knowledge. If OpenSSL is installed and this crate had
@ -121,12 +130,14 @@ and include information about your system as well as this message.
", ",
host, host,
target, target,
env!("CARGO_PKG_VERSION")); env!("CARGO_PKG_VERSION")
);
if host.contains("apple-darwin") && target.contains("apple-darwin") { if host.contains("apple-darwin") && target.contains("apple-darwin") {
let system = Path::new("/usr/lib/libssl.0.9.8.dylib"); let system = Path::new("/usr/lib/libssl.0.9.8.dylib");
if system.exists() { if system.exists() {
msg.push_str(&format!(" msg.push_str(&format!(
"
It looks like you're compiling on macOS, where the system contains a version of It looks like you're compiling on macOS, where the system contains a version of
OpenSSL 0.9.8. This crate no longer supports OpenSSL 0.9.8. OpenSSL 0.9.8. This crate no longer supports OpenSSL 0.9.8.
@ -137,24 +148,28 @@ install the `openssl` package, or as a maintainer you can use the openssl-sys
Unfortunately though the compile cannot continue, so aborting. Unfortunately though the compile cannot continue, so aborting.
")); "
));
} }
} }
if host.contains("unknown-linux") && target.contains("unknown-linux-gnu") { if host.contains("unknown-linux") && target.contains("unknown-linux-gnu") {
if Command::new("pkg-config").output().is_err() { if Command::new("pkg-config").output().is_err() {
msg.push_str(&format!(" msg.push_str(&format!(
"
It looks like you're compiling on Linux and also targeting Linux. Currently this It looks like you're compiling on Linux and also targeting Linux. Currently this
requires the `pkg-config` utility to find OpenSSL but unfortunately `pkg-config` requires the `pkg-config` utility to find OpenSSL but unfortunately `pkg-config`
could not be found. If you have OpenSSL installed you can likely fix this by could not be found. If you have OpenSSL installed you can likely fix this by
installing `pkg-config`. installing `pkg-config`.
")); "
));
} }
} }
if host.contains("windows") && target.contains("windows-gnu") { if host.contains("windows") && target.contains("windows-gnu") {
msg.push_str(&format!(" msg.push_str(&format!(
"
It looks like you're compiling for MinGW but you may not have either OpenSSL or It looks like you're compiling for MinGW but you may not have either OpenSSL or
pkg-config installed. You can install these two dependencies with: pkg-config installed. You can install these two dependencies with:
@ -162,11 +177,13 @@ pkg-config installed. You can install these two dependencies with:
and try building this crate again. and try building this crate again.
")); "
));
} }
if host.contains("windows") && target.contains("windows-msvc") { if host.contains("windows") && target.contains("windows-msvc") {
msg.push_str(&format!(" msg.push_str(&format!(
"
It looks like you're compiling for MSVC but we couldn't detect an OpenSSL It looks like you're compiling for MSVC but we couldn't detect an OpenSSL
installation. If there isn't one installed then you can try the rust-openssl installation. If there isn't one installed then you can try the rust-openssl
README for more information about how to download precompiled binaries of README for more information about how to download precompiled binaries of
@ -174,7 +191,8 @@ OpenSSL:
https://github.com/sfackler/rust-openssl#windows https://github.com/sfackler/rust-openssl#windows
")); "
));
} }
panic!(msg); panic!(msg);
@ -198,9 +216,9 @@ fn try_pkg_config() {
return; return;
} }
let lib = match pkg_config::Config::new() let lib = match pkg_config::Config::new().print_system_libs(false).find(
.print_system_libs(false) "openssl",
.find("openssl") { ) {
Ok(lib) => lib, Ok(lib) => lib,
Err(e) => { Err(e) => {
println!("run pkg_config fail: {:?}", e); println!("run pkg_config fail: {:?}", e);
@ -236,7 +254,8 @@ fn validate_headers(include_dirs: &[PathBuf]) -> Version {
path.push("expando.c"); path.push("expando.c");
let mut file = BufWriter::new(File::create(&path).unwrap()); let mut file = BufWriter::new(File::create(&path).unwrap());
write!(file, write!(
file,
"\ "\
#include <openssl/opensslv.h> #include <openssl/opensslv.h>
#include <openssl/opensslconf.h> #include <openssl/opensslconf.h>
@ -270,18 +289,19 @@ RUST_OPENSSL_101
#else #else
RUST_OPENSSL_OLD RUST_OPENSSL_OLD
#endif #endif
") "
.unwrap(); ).unwrap();
for define in DEFINES { for define in DEFINES {
write!(file, write!(
file,
"\ "\
#ifdef {define} #ifdef {define}
RUST_{define} RUST_{define}
#endif #endif
", ",
define = define) define = define
.unwrap(); ).unwrap();
} }
file.flush().unwrap(); file.flush().unwrap();
@ -295,7 +315,8 @@ RUST_{define}
let expanded = match panic::catch_unwind(AssertUnwindSafe(|| gcc.file(&path).expand())) { let expanded = match panic::catch_unwind(AssertUnwindSafe(|| gcc.file(&path).expand())) {
Ok(expanded) => expanded, Ok(expanded) => expanded,
Err(_) => { Err(_) => {
panic!(" panic!(
"
Failed to find OpenSSL development headers. Failed to find OpenSSL development headers.
You can try fixing this setting the `OPENSSL_DIR` environment variable You can try fixing this setting the `OPENSSL_DIR` environment variable
@ -312,7 +333,8 @@ specific to your distribution:
See rust-openssl README for more information: See rust-openssl README for more information:
https://github.com/sfackler/rust-openssl#linux https://github.com/sfackler/rust-openssl#linux
"); "
);
} }
}; };
let expanded = String::from_utf8(expanded).unwrap(); let expanded = String::from_utf8(expanded).unwrap();
@ -381,13 +403,15 @@ See rust-openssl README for more information:
println!("cargo:version=101"); println!("cargo:version=101");
Version::Openssl101 Version::Openssl101
} else { } else {
panic!(" panic!(
"
This crate is only compatible with OpenSSL 1.0.1, 1.0.2, and 1.1.0, or LibreSSL This crate is only compatible with OpenSSL 1.0.1, 1.0.2, and 1.1.0, or LibreSSL
2.5.0, 2.5.1, 2.5.2, 2.5.3, and 2.5.4, but a different version of OpenSSL was 2.5.0, 2.5.1, 2.5.2, 2.5.3, and 2.5.4, but a different version of OpenSSL was
found. The build is now aborting due to this version mismatch. found. The build is now aborting due to this version mismatch.
"); "
);
} }
} }
@ -413,13 +437,10 @@ fn determine_mode(libdir: &Path, libs: &[&str]) -> &'static str {
.map(|e| e.file_name()) .map(|e| e.file_name())
.filter_map(|e| e.into_string().ok()) .filter_map(|e| e.into_string().ok())
.collect::<HashSet<_>>(); .collect::<HashSet<_>>();
let can_static = let can_static = libs.iter().all(|l| {
libs.iter()
.all(|l| {
files.contains(&format!("lib{}.a", l)) || files.contains(&format!("{}.lib", l)) files.contains(&format!("lib{}.a", l)) || files.contains(&format!("{}.lib", l))
}); });
let can_dylib = libs.iter() let can_dylib = libs.iter().all(|l| {
.all(|l| {
files.contains(&format!("lib{}.so", l)) || files.contains(&format!("{}.dll", l)) || files.contains(&format!("lib{}.so", l)) || files.contains(&format!("{}.dll", l)) ||
files.contains(&format!("lib{}.dylib", l)) files.contains(&format!("lib{}.dylib", l))
}); });
@ -427,9 +448,11 @@ fn determine_mode(libdir: &Path, libs: &[&str]) -> &'static str {
(true, false) => return "static", (true, false) => return "static",
(false, true) => return "dylib", (false, true) => return "dylib",
(false, false) => { (false, false) => {
panic!("OpenSSL libdir at `{}` does not contain the required files \ panic!(
"OpenSSL libdir at `{}` does not contain the required files \
to either statically or dynamically link OpenSSL", to either statically or dynamically link OpenSSL",
libdir.display()); libdir.display()
);
} }
(true, true) => {} (true, true) => {}
} }

File diff suppressed because it is too large Load Diff

View File

@ -148,13 +148,15 @@ pub struct EVP_PKEY {
#[repr(C)] #[repr(C)]
pub struct BIO { pub struct BIO {
pub method: *mut ::BIO_METHOD, pub method: *mut ::BIO_METHOD,
pub callback: Option<unsafe extern "C" fn(*mut ::BIO, pub callback: Option<
unsafe extern "C" fn(*mut ::BIO,
c_int, c_int,
*const c_char, *const c_char,
c_int, c_int,
c_long, c_long,
c_long) c_long)
-> c_long>, -> c_long,
>,
pub cb_arg: *mut c_char, pub cb_arg: *mut c_char,
pub init: c_int, pub init: c_int,
pub shutdown: c_int, pub shutdown: c_int,
@ -192,23 +194,28 @@ pub struct EVP_CIPHER {
pub key_len: c_int, pub key_len: c_int,
pub iv_len: c_int, pub iv_len: c_int,
pub flags: c_ulong, pub flags: c_ulong,
pub init: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, pub init: Option<
unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX,
*const c_uchar, *const c_uchar,
*const c_uchar, *const c_uchar,
c_int) c_int)
-> c_int>, -> c_int,
pub do_cipher: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, >,
pub do_cipher: Option<
unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX,
*mut c_uchar, *mut c_uchar,
*const c_uchar, *const c_uchar,
size_t) size_t)
-> c_int>, -> c_int,
>,
pub cleanup: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX) -> c_int>, pub cleanup: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX) -> c_int>,
pub ctx_size: c_int, pub ctx_size: c_int,
pub set_asn1_parameters: pub set_asn1_parameters:
Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, *mut ::ASN1_TYPE) -> c_int>, Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, *mut ::ASN1_TYPE) -> c_int>,
pub get_asn1_parameters: pub get_asn1_parameters:
Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, *mut ::ASN1_TYPE) -> c_int>, Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, *mut ::ASN1_TYPE) -> c_int>,
pub ctrl: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, c_int, c_int, *mut c_void) -> c_int>, pub ctrl:
Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, c_int, c_int, *mut c_void) -> c_int>,
pub app_data: *mut c_void, pub app_data: *mut c_void,
} }
@ -369,8 +376,8 @@ pub const CRYPTO_LOCK_SSL_CTX: c_int = 12;
pub const CRYPTO_LOCK_SSL_SESSION: c_int = 14; pub const CRYPTO_LOCK_SSL_SESSION: c_int = 14;
static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>; static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>;
static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> = static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> = 0 as
0 as *mut Vec<Option<MutexGuard<'static, ()>>>; *mut Vec<Option<MutexGuard<'static, ()>>>;
unsafe extern "C" fn locking_function(mode: c_int, n: c_int, _file: *const c_char, _line: c_int) { unsafe extern "C" fn locking_function(mode: c_int, n: c_int, _file: *const c_char, _line: c_int) {
let mutex = &(*MUTEXES)[n as usize]; let mutex = &(*MUTEXES)[n as usize];
@ -378,9 +385,7 @@ unsafe extern "C" fn locking_function(mode: c_int, n: c_int, _file: *const c_cha
if mode & ::CRYPTO_LOCK != 0 { if mode & ::CRYPTO_LOCK != 0 {
(*GUARDS)[n as usize] = Some(mutex.lock().unwrap()); (*GUARDS)[n as usize] = Some(mutex.lock().unwrap());
} else { } else {
&(*GUARDS)[n as usize] &(*GUARDS)[n as usize].take().expect("lock already unlocked");
.take()
.expect("lock already unlocked");
} }
} }
@ -424,17 +429,21 @@ fn set_id_callback() {}
// macros // macros
pub unsafe fn SSL_CTX_set_ecdh_auto(ctx: *mut SSL_CTX, onoff: c_int) -> c_int { pub unsafe fn SSL_CTX_set_ecdh_auto(ctx: *mut SSL_CTX, onoff: c_int) -> c_int {
::SSL_CTX_ctrl(ctx, ::SSL_CTX_ctrl(
ctx,
SSL_CTRL_SET_ECDH_AUTO, SSL_CTRL_SET_ECDH_AUTO,
onoff as c_long, onoff as c_long,
ptr::null_mut()) as c_int ptr::null_mut(),
) as c_int
} }
pub unsafe fn SSL_set_ecdh_auto(ssl: *mut ::SSL, onoff: c_int) -> c_int { pub unsafe fn SSL_set_ecdh_auto(ssl: *mut ::SSL, onoff: c_int) -> c_int {
::SSL_ctrl(ssl, ::SSL_ctrl(
ssl,
SSL_CTRL_SET_ECDH_AUTO, SSL_CTRL_SET_ECDH_AUTO,
onoff as c_long, onoff as c_long,
ptr::null_mut()) as c_int ptr::null_mut(),
) as c_int
} }
pub unsafe fn SSL_session_reused(ssl: *mut ::SSL) -> c_int { pub unsafe fn SSL_session_reused(ssl: *mut ::SSL) -> c_int {
@ -458,26 +467,28 @@ extern "C" {
pub fn CRYPTO_malloc(num: c_int, file: *const c_char, line: c_int) -> *mut c_void; pub fn CRYPTO_malloc(num: c_int, file: *const c_char, line: c_int) -> *mut c_void;
pub fn CRYPTO_free(buf: *mut c_void); pub fn CRYPTO_free(buf: *mut c_void);
pub fn CRYPTO_num_locks() -> c_int; pub fn CRYPTO_num_locks() -> c_int;
pub fn CRYPTO_set_locking_callback(func: unsafe extern "C" fn(mode: c_int, pub fn CRYPTO_set_locking_callback(
n: c_int, func: unsafe extern "C" fn(mode: c_int, n: c_int, file: *const c_char, line: c_int),
file: *const c_char, );
line: c_int));
pub fn CRYPTO_set_id_callback(func: unsafe extern "C" fn() -> c_ulong); pub fn CRYPTO_set_id_callback(func: unsafe extern "C" fn() -> c_ulong);
pub fn ERR_load_crypto_strings(); pub fn ERR_load_crypto_strings();
pub fn RSA_generate_key(modsz: c_int, pub fn RSA_generate_key(
modsz: c_int,
e: c_ulong, e: c_ulong,
cb: Option<extern "C" fn(c_int, c_int, *mut c_void)>, cb: Option<extern "C" fn(c_int, c_int, *mut c_void)>,
cbarg: *mut c_void) cbarg: *mut c_void,
-> *mut RSA; ) -> *mut RSA;
pub fn OCSP_cert_to_id(dgst: *const ::EVP_MD, pub fn OCSP_cert_to_id(
dgst: *const ::EVP_MD,
subject: *mut ::X509, subject: *mut ::X509,
issuer: *mut ::X509) issuer: *mut ::X509,
-> *mut ::OCSP_CERTID; ) -> *mut ::OCSP_CERTID;
pub fn PKCS12_create(pass: *mut c_char, pub fn PKCS12_create(
pass: *mut c_char,
friendly_name: *mut c_char, friendly_name: *mut c_char,
pkey: *mut EVP_PKEY, pkey: *mut EVP_PKEY,
cert: *mut X509, cert: *mut X509,
@ -486,8 +497,8 @@ extern "C" {
nid_cert: c_int, nid_cert: c_int,
iter: c_int, iter: c_int,
mac_iter: c_int, mac_iter: c_int,
keytype: c_int) keytype: c_int,
-> *mut PKCS12; ) -> *mut PKCS12;
pub fn SSL_library_init() -> c_int; pub fn SSL_library_init() -> c_int;
pub fn SSL_load_error_strings(); pub fn SSL_load_error_strings();
@ -499,66 +510,73 @@ extern "C" {
pub fn TLSv1_1_method() -> *const ::SSL_METHOD; pub fn TLSv1_1_method() -> *const ::SSL_METHOD;
pub fn TLSv1_2_method() -> *const ::SSL_METHOD; pub fn TLSv1_2_method() -> *const ::SSL_METHOD;
pub fn DTLSv1_method() -> *const ::SSL_METHOD; pub fn DTLSv1_method() -> *const ::SSL_METHOD;
pub fn SSL_get_ex_new_index(argl: c_long, pub fn SSL_get_ex_new_index(
argl: c_long,
argp: *mut c_void, argp: *mut c_void,
new_func: Option<::CRYPTO_EX_new>, new_func: Option<::CRYPTO_EX_new>,
dup_func: Option<::CRYPTO_EX_dup>, dup_func: Option<::CRYPTO_EX_dup>,
free_func: Option<::CRYPTO_EX_free>) free_func: Option<::CRYPTO_EX_free>,
-> c_int; ) -> c_int;
pub fn SSL_set_tmp_ecdh_callback(ssl: *mut ::SSL, pub fn SSL_set_tmp_ecdh_callback(
ecdh: unsafe extern "C" fn(ssl: *mut ::SSL, ssl: *mut ::SSL,
is_export: c_int, ecdh: unsafe extern "C" fn(ssl: *mut ::SSL, is_export: c_int, keylength: c_int)
keylength: c_int) -> *mut ::EC_KEY,
-> *mut ::EC_KEY); );
pub fn SSL_CIPHER_get_version(cipher: *const ::SSL_CIPHER) -> *mut c_char; pub fn SSL_CIPHER_get_version(cipher: *const ::SSL_CIPHER) -> *mut c_char;
pub fn SSL_CTX_get_ex_new_index(argl: c_long, pub fn SSL_CTX_get_ex_new_index(
argl: c_long,
argp: *mut c_void, argp: *mut c_void,
new_func: Option<::CRYPTO_EX_new>, new_func: Option<::CRYPTO_EX_new>,
dup_func: Option<::CRYPTO_EX_dup>, dup_func: Option<::CRYPTO_EX_dup>,
free_func: Option<::CRYPTO_EX_free>) free_func: Option<::CRYPTO_EX_free>,
-> c_int; ) -> c_int;
pub fn SSL_CTX_set_tmp_ecdh_callback(ctx: *mut ::SSL_CTX, pub fn SSL_CTX_set_tmp_ecdh_callback(
ecdh: unsafe extern "C" fn(ssl: *mut ::SSL, ctx: *mut ::SSL_CTX,
is_export: c_int, ecdh: unsafe extern "C" fn(ssl: *mut ::SSL, is_export: c_int, keylength: c_int)
keylength: c_int) -> *mut ::EC_KEY,
-> *mut ::EC_KEY); );
pub fn X509_get_subject_name(x: *mut ::X509) -> *mut ::X509_NAME; pub fn X509_get_subject_name(x: *mut ::X509) -> *mut ::X509_NAME;
pub fn X509_set_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int; pub fn X509_set_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
pub fn X509_set_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int; pub fn X509_set_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
pub fn X509_get_ext_d2i(x: *mut ::X509, pub fn X509_get_ext_d2i(
x: *mut ::X509,
nid: c_int, nid: c_int,
crit: *mut c_int, crit: *mut c_int,
idx: *mut c_int) idx: *mut c_int,
-> *mut c_void; ) -> *mut c_void;
pub fn X509_NAME_add_entry_by_NID(x: *mut ::X509_NAME, pub fn X509_NAME_add_entry_by_NID(
x: *mut ::X509_NAME,
field: c_int, field: c_int,
ty: c_int, ty: c_int,
bytes: *mut c_uchar, bytes: *mut c_uchar,
len: c_int, len: c_int,
loc: c_int, loc: c_int,
set: c_int) set: c_int,
-> c_int; ) -> c_int;
pub fn X509_NAME_get_entry(n: *mut ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY; pub fn X509_NAME_get_entry(n: *mut ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY;
pub fn X509_NAME_ENTRY_get_data(ne: *mut ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING; pub fn X509_NAME_ENTRY_get_data(ne: *mut ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING;
pub fn X509_STORE_CTX_get_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509; pub fn X509_STORE_CTX_get_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509;
pub fn X509V3_EXT_nconf_nid(conf: *mut ::CONF, pub fn X509V3_EXT_nconf_nid(
conf: *mut ::CONF,
ctx: *mut ::X509V3_CTX, ctx: *mut ::X509V3_CTX,
ext_nid: c_int, ext_nid: c_int,
value: *mut c_char) value: *mut c_char,
-> *mut ::X509_EXTENSION; ) -> *mut ::X509_EXTENSION;
pub fn X509V3_EXT_nconf(conf: *mut ::CONF, pub fn X509V3_EXT_nconf(
conf: *mut ::CONF,
ctx: *mut ::X509V3_CTX, ctx: *mut ::X509V3_CTX,
name: *mut c_char, name: *mut c_char,
value: *mut c_char) value: *mut c_char,
-> *mut ::X509_EXTENSION; ) -> *mut ::X509_EXTENSION;
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *mut ::ASN1_STRING) -> c_int; pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *mut ::ASN1_STRING) -> c_int;
pub fn ASN1_STRING_data(x: *mut ::ASN1_STRING) -> *mut c_uchar; pub fn ASN1_STRING_data(x: *mut ::ASN1_STRING) -> *mut c_uchar;
pub fn CRYPTO_add_lock(pointer: *mut c_int, pub fn CRYPTO_add_lock(
pointer: *mut c_int,
amount: c_int, amount: c_int,
type_: c_int, type_: c_int,
file: *const c_char, file: *const c_char,
line: c_int) line: c_int,
-> c_int; ) -> c_int;
pub fn EVP_MD_CTX_create() -> *mut EVP_MD_CTX; pub fn EVP_MD_CTX_create() -> *mut EVP_MD_CTX;
pub fn EVP_MD_CTX_destroy(ctx: *mut EVP_MD_CTX); pub fn EVP_MD_CTX_destroy(ctx: *mut EVP_MD_CTX);
pub fn EVP_PKEY_bits(key: *mut EVP_PKEY) -> c_int; pub fn EVP_PKEY_bits(key: *mut EVP_PKEY) -> c_int;

View File

@ -28,13 +28,15 @@ pub struct SSL {
s3: *mut c_void, s3: *mut c_void,
d1: *mut c_void, d1: *mut c_void,
read_ahead: c_int, read_ahead: c_int,
msg_callback: Option<unsafe extern "C" fn(c_int, msg_callback: Option<
unsafe extern "C" fn(c_int,
c_int, c_int,
c_int, c_int,
*const c_void, *const c_void,
size_t, size_t,
*mut SSL, *mut SSL,
*mut c_void)>, *mut c_void),
>,
msg_callback_arg: *mut c_void, msg_callback_arg: *mut c_void,
hit: c_int, hit: c_int,
param: *mut c_void, param: *mut c_void,

View File

@ -141,13 +141,15 @@ pub struct EVP_PKEY {
#[repr(C)] #[repr(C)]
pub struct BIO { pub struct BIO {
pub method: *mut ::BIO_METHOD, pub method: *mut ::BIO_METHOD,
pub callback: Option<unsafe extern "C" fn(*mut ::BIO, pub callback: Option<
unsafe extern "C" fn(*mut ::BIO,
c_int, c_int,
*const c_char, *const c_char,
c_int, c_int,
c_long, c_long,
c_long) c_long)
-> c_long>, -> c_long,
>,
pub cb_arg: *mut c_char, pub cb_arg: *mut c_char,
pub init: c_int, pub init: c_int,
pub shutdown: c_int, pub shutdown: c_int,
@ -186,23 +188,28 @@ pub struct EVP_CIPHER {
pub key_len: c_int, pub key_len: c_int,
pub iv_len: c_int, pub iv_len: c_int,
pub flags: c_ulong, pub flags: c_ulong,
pub init: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, pub init: Option<
unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX,
*const c_uchar, *const c_uchar,
*const c_uchar, *const c_uchar,
c_int) c_int)
-> c_int>, -> c_int,
pub do_cipher: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, >,
pub do_cipher: Option<
unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX,
*mut c_uchar, *mut c_uchar,
*const c_uchar, *const c_uchar,
size_t) size_t)
-> c_int>, -> c_int,
>,
pub cleanup: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX) -> c_int>, pub cleanup: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX) -> c_int>,
pub ctx_size: c_int, pub ctx_size: c_int,
pub set_asn1_parameters: pub set_asn1_parameters:
Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, *mut ::ASN1_TYPE) -> c_int>, Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, *mut ::ASN1_TYPE) -> c_int>,
pub get_asn1_parameters: pub get_asn1_parameters:
Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, *mut ::ASN1_TYPE) -> c_int>, Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, *mut ::ASN1_TYPE) -> c_int>,
pub ctrl: Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, c_int, c_int, *mut c_void) -> c_int>, pub ctrl:
Option<unsafe extern "C" fn(*mut ::EVP_CIPHER_CTX, c_int, c_int, *mut c_void) -> c_int>,
pub app_data: *mut c_void, pub app_data: *mut c_void,
} }
@ -355,13 +362,15 @@ pub struct SSL {
s3: *mut c_void, s3: *mut c_void,
d1: *mut c_void, d1: *mut c_void,
read_ahead: c_int, read_ahead: c_int,
msg_callback: Option<unsafe extern "C" fn(c_int, msg_callback: Option<
unsafe extern "C" fn(c_int,
c_int, c_int,
c_int, c_int,
*const c_void, *const c_void,
size_t, size_t,
*mut SSL, *mut SSL,
*mut c_void)>, *mut c_void),
>,
msg_callback_arg: *mut c_void, msg_callback_arg: *mut c_void,
hit: c_int, hit: c_int,
param: *mut c_void, param: *mut c_void,
@ -387,13 +396,15 @@ pub struct SSL {
#[cfg(not(osslconf = "OPENSSL_NO_KRB5"))] #[cfg(not(osslconf = "OPENSSL_NO_KRB5"))]
kssl_ctx: *mut c_void, kssl_ctx: *mut c_void,
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))] #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
psk_client_callback: Option<unsafe extern "C" fn(*mut SSL, psk_client_callback: Option<
unsafe extern "C" fn(*mut SSL,
*const c_char, *const c_char,
*mut c_char, *mut c_char,
c_uint, c_uint,
*mut c_uchar, *mut c_uchar,
c_uint) c_uint)
-> c_uint>, -> c_uint,
>,
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))] #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
psk_server_callback: psk_server_callback:
Option<unsafe extern "C" fn(*mut SSL, *const c_char, *mut c_uchar, c_uint) -> c_uint>, Option<unsafe extern "C" fn(*mut SSL, *const c_char, *mut c_uchar, c_uint) -> c_uint>,
@ -726,8 +737,8 @@ pub const CRYPTO_LOCK_SSL_CTX: c_int = 12;
pub const CRYPTO_LOCK_SSL_SESSION: c_int = 14; pub const CRYPTO_LOCK_SSL_SESSION: c_int = 14;
static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>; static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>;
static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> = static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> = 0 as
0 as *mut Vec<Option<MutexGuard<'static, ()>>>; *mut Vec<Option<MutexGuard<'static, ()>>>;
unsafe extern "C" fn locking_function(mode: c_int, n: c_int, _file: *const c_char, _line: c_int) { unsafe extern "C" fn locking_function(mode: c_int, n: c_int, _file: *const c_char, _line: c_int) {
let mutex = &(*MUTEXES)[n as usize]; let mutex = &(*MUTEXES)[n as usize];
@ -735,9 +746,7 @@ unsafe extern "C" fn locking_function(mode: c_int, n: c_int, _file: *const c_cha
if mode & ::CRYPTO_LOCK != 0 { if mode & ::CRYPTO_LOCK != 0 {
(*GUARDS)[n as usize] = Some(mutex.lock().unwrap()); (*GUARDS)[n as usize] = Some(mutex.lock().unwrap());
} else { } else {
&(*GUARDS)[n as usize] &(*GUARDS)[n as usize].take().expect("lock already unlocked");
.take()
.expect("lock already unlocked");
} }
} }
@ -782,18 +791,22 @@ fn set_id_callback() {}
#[cfg(ossl102)] #[cfg(ossl102)]
pub unsafe fn SSL_CTX_set_ecdh_auto(ctx: *mut SSL_CTX, onoff: c_int) -> c_int { pub unsafe fn SSL_CTX_set_ecdh_auto(ctx: *mut SSL_CTX, onoff: c_int) -> c_int {
::SSL_CTX_ctrl(ctx, ::SSL_CTX_ctrl(
ctx,
SSL_CTRL_SET_ECDH_AUTO, SSL_CTRL_SET_ECDH_AUTO,
onoff as c_long, onoff as c_long,
ptr::null_mut()) as c_int ptr::null_mut(),
) as c_int
} }
#[cfg(ossl102)] #[cfg(ossl102)]
pub unsafe fn SSL_set_ecdh_auto(ssl: *mut ::SSL, onoff: c_int) -> c_int { pub unsafe fn SSL_set_ecdh_auto(ssl: *mut ::SSL, onoff: c_int) -> c_int {
::SSL_ctrl(ssl, ::SSL_ctrl(
ssl,
SSL_CTRL_SET_ECDH_AUTO, SSL_CTRL_SET_ECDH_AUTO,
onoff as c_long, onoff as c_long,
ptr::null_mut()) as c_int ptr::null_mut(),
) as c_int
} }
pub unsafe fn SSL_session_reused(ssl: *mut ::SSL) -> c_int { pub unsafe fn SSL_session_reused(ssl: *mut ::SSL) -> c_int {
@ -817,26 +830,28 @@ extern "C" {
pub fn CRYPTO_malloc(num: c_int, file: *const c_char, line: c_int) -> *mut c_void; pub fn CRYPTO_malloc(num: c_int, file: *const c_char, line: c_int) -> *mut c_void;
pub fn CRYPTO_free(buf: *mut c_void); pub fn CRYPTO_free(buf: *mut c_void);
pub fn CRYPTO_num_locks() -> c_int; pub fn CRYPTO_num_locks() -> c_int;
pub fn CRYPTO_set_locking_callback(func: unsafe extern "C" fn(mode: c_int, pub fn CRYPTO_set_locking_callback(
n: c_int, func: unsafe extern "C" fn(mode: c_int, n: c_int, file: *const c_char, line: c_int),
file: *const c_char, );
line: c_int));
pub fn CRYPTO_set_id_callback(func: unsafe extern "C" fn() -> c_ulong); pub fn CRYPTO_set_id_callback(func: unsafe extern "C" fn() -> c_ulong);
pub fn ERR_load_crypto_strings(); pub fn ERR_load_crypto_strings();
pub fn RSA_generate_key(modsz: c_int, pub fn RSA_generate_key(
modsz: c_int,
e: c_ulong, e: c_ulong,
cb: Option<extern "C" fn(c_int, c_int, *mut c_void)>, cb: Option<extern "C" fn(c_int, c_int, *mut c_void)>,
cbarg: *mut c_void) cbarg: *mut c_void,
-> *mut RSA; ) -> *mut RSA;
pub fn OCSP_cert_to_id(dgst: *const ::EVP_MD, pub fn OCSP_cert_to_id(
dgst: *const ::EVP_MD,
subject: *mut ::X509, subject: *mut ::X509,
issuer: *mut ::X509) issuer: *mut ::X509,
-> *mut ::OCSP_CERTID; ) -> *mut ::OCSP_CERTID;
pub fn PKCS12_create(pass: *mut c_char, pub fn PKCS12_create(
pass: *mut c_char,
friendly_name: *mut c_char, friendly_name: *mut c_char,
pkey: *mut EVP_PKEY, pkey: *mut EVP_PKEY,
cert: *mut X509, cert: *mut X509,
@ -845,8 +860,8 @@ extern "C" {
nid_cert: c_int, nid_cert: c_int,
iter: c_int, iter: c_int,
mac_iter: c_int, mac_iter: c_int,
keytype: c_int) keytype: c_int,
-> *mut PKCS12; ) -> *mut PKCS12;
pub fn SSL_library_init() -> c_int; pub fn SSL_library_init() -> c_int;
pub fn SSL_load_error_strings(); pub fn SSL_load_error_strings();
@ -862,77 +877,88 @@ extern "C" {
pub fn DTLSv1_method() -> *const ::SSL_METHOD; pub fn DTLSv1_method() -> *const ::SSL_METHOD;
#[cfg(ossl102)] #[cfg(ossl102)]
pub fn DTLSv1_2_method() -> *const ::SSL_METHOD; pub fn DTLSv1_2_method() -> *const ::SSL_METHOD;
pub fn SSL_get_ex_new_index(argl: c_long, pub fn SSL_get_ex_new_index(
argl: c_long,
argp: *mut c_void, argp: *mut c_void,
new_func: Option<::CRYPTO_EX_new>, new_func: Option<::CRYPTO_EX_new>,
dup_func: Option<::CRYPTO_EX_dup>, dup_func: Option<::CRYPTO_EX_dup>,
free_func: Option<::CRYPTO_EX_free>) free_func: Option<::CRYPTO_EX_free>,
-> c_int; ) -> c_int;
pub fn SSL_set_tmp_ecdh_callback(ssl: *mut ::SSL, pub fn SSL_set_tmp_ecdh_callback(
ecdh: unsafe extern "C" fn(ssl: *mut ::SSL, ssl: *mut ::SSL,
is_export: c_int, ecdh: unsafe extern "C" fn(ssl: *mut ::SSL, is_export: c_int, keylength: c_int)
keylength: c_int) -> *mut ::EC_KEY,
-> *mut ::EC_KEY); );
pub fn SSL_CIPHER_get_version(cipher: *const ::SSL_CIPHER) -> *mut c_char; pub fn SSL_CIPHER_get_version(cipher: *const ::SSL_CIPHER) -> *mut c_char;
pub fn SSL_CTX_get_ex_new_index(argl: c_long, pub fn SSL_CTX_get_ex_new_index(
argl: c_long,
argp: *mut c_void, argp: *mut c_void,
new_func: Option<::CRYPTO_EX_new>, new_func: Option<::CRYPTO_EX_new>,
dup_func: Option<::CRYPTO_EX_dup>, dup_func: Option<::CRYPTO_EX_dup>,
free_func: Option<::CRYPTO_EX_free>) free_func: Option<::CRYPTO_EX_free>,
-> c_int; ) -> c_int;
pub fn SSL_CTX_set_tmp_ecdh_callback(ctx: *mut ::SSL_CTX, pub fn SSL_CTX_set_tmp_ecdh_callback(
ecdh: unsafe extern "C" fn(ssl: *mut ::SSL, ctx: *mut ::SSL_CTX,
is_export: c_int, ecdh: unsafe extern "C" fn(ssl: *mut ::SSL, is_export: c_int, keylength: c_int)
keylength: c_int) -> *mut ::EC_KEY,
-> *mut ::EC_KEY); );
pub fn X509_get_subject_name(x: *mut ::X509) -> *mut ::X509_NAME; pub fn X509_get_subject_name(x: *mut ::X509) -> *mut ::X509_NAME;
pub fn X509_set_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int; pub fn X509_set_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
pub fn X509_set_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int; pub fn X509_set_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
pub fn X509_get_ext_d2i(x: *mut ::X509, pub fn X509_get_ext_d2i(
x: *mut ::X509,
nid: c_int, nid: c_int,
crit: *mut c_int, crit: *mut c_int,
idx: *mut c_int) idx: *mut c_int,
-> *mut c_void; ) -> *mut c_void;
pub fn X509_NAME_add_entry_by_NID(x: *mut ::X509_NAME, pub fn X509_NAME_add_entry_by_NID(
x: *mut ::X509_NAME,
field: c_int, field: c_int,
ty: c_int, ty: c_int,
bytes: *mut c_uchar, bytes: *mut c_uchar,
len: c_int, len: c_int,
loc: c_int, loc: c_int,
set: c_int) set: c_int,
-> c_int; ) -> c_int;
#[cfg(not(ossl101))] #[cfg(not(ossl101))]
pub fn X509_get0_signature(psig: *mut *mut ::ASN1_BIT_STRING, pub fn X509_get0_signature(
psig: *mut *mut ::ASN1_BIT_STRING,
palg: *mut *mut ::X509_ALGOR, palg: *mut *mut ::X509_ALGOR,
x: *const ::X509); x: *const ::X509,
);
#[cfg(not(ossl101))] #[cfg(not(ossl101))]
pub fn X509_get_signature_nid(x: *const X509) -> c_int; pub fn X509_get_signature_nid(x: *const X509) -> c_int;
#[cfg(not(ossl101))] #[cfg(not(ossl101))]
pub fn X509_ALGOR_get0(paobj: *mut *mut ::ASN1_OBJECT, pub fn X509_ALGOR_get0(
paobj: *mut *mut ::ASN1_OBJECT,
pptype: *mut c_int, pptype: *mut c_int,
ppval: *mut *mut c_void, ppval: *mut *mut c_void,
alg: *mut ::X509_ALGOR); alg: *mut ::X509_ALGOR,
);
pub fn X509_NAME_get_entry(n: *mut ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY; pub fn X509_NAME_get_entry(n: *mut ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY;
pub fn X509_NAME_ENTRY_get_data(ne: *mut ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING; pub fn X509_NAME_ENTRY_get_data(ne: *mut ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING;
pub fn X509_STORE_CTX_get_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509; pub fn X509_STORE_CTX_get_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509;
pub fn X509V3_EXT_nconf_nid(conf: *mut ::CONF, pub fn X509V3_EXT_nconf_nid(
conf: *mut ::CONF,
ctx: *mut ::X509V3_CTX, ctx: *mut ::X509V3_CTX,
ext_nid: c_int, ext_nid: c_int,
value: *mut c_char) value: *mut c_char,
-> *mut ::X509_EXTENSION; ) -> *mut ::X509_EXTENSION;
pub fn X509V3_EXT_nconf(conf: *mut ::CONF, pub fn X509V3_EXT_nconf(
conf: *mut ::CONF,
ctx: *mut ::X509V3_CTX, ctx: *mut ::X509V3_CTX,
name: *mut c_char, name: *mut c_char,
value: *mut c_char) value: *mut c_char,
-> *mut ::X509_EXTENSION; ) -> *mut ::X509_EXTENSION;
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *mut ::ASN1_STRING) -> c_int; pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *mut ::ASN1_STRING) -> c_int;
pub fn ASN1_STRING_data(x: *mut ::ASN1_STRING) -> *mut c_uchar; pub fn ASN1_STRING_data(x: *mut ::ASN1_STRING) -> *mut c_uchar;
pub fn CRYPTO_add_lock(pointer: *mut c_int, pub fn CRYPTO_add_lock(
pointer: *mut c_int,
amount: c_int, amount: c_int,
type_: c_int, type_: c_int,
file: *const c_char, file: *const c_char,
line: c_int) line: c_int,
-> c_int; ) -> c_int;
pub fn EVP_MD_CTX_create() -> *mut EVP_MD_CTX; pub fn EVP_MD_CTX_create() -> *mut EVP_MD_CTX;
pub fn EVP_MD_CTX_destroy(ctx: *mut EVP_MD_CTX); pub fn EVP_MD_CTX_destroy(ctx: *mut EVP_MD_CTX);
pub fn EVP_PKEY_bits(key: *mut EVP_PKEY) -> c_int; pub fn EVP_PKEY_bits(key: *mut EVP_PKEY) -> c_int;

View File

@ -89,10 +89,11 @@ extern "C" {
pub fn HMAC_CTX_new() -> *mut HMAC_CTX; pub fn HMAC_CTX_new() -> *mut HMAC_CTX;
pub fn HMAC_CTX_free(ctx: *mut HMAC_CTX); pub fn HMAC_CTX_free(ctx: *mut HMAC_CTX);
pub fn OCSP_cert_to_id(dgst: *const ::EVP_MD, pub fn OCSP_cert_to_id(
dgst: *const ::EVP_MD,
subject: *const ::X509, subject: *const ::X509,
issuer: *const ::X509) issuer: *const ::X509,
-> *mut ::OCSP_CERTID; ) -> *mut ::OCSP_CERTID;
pub fn TLS_method() -> *const ::SSL_METHOD; pub fn TLS_method() -> *const ::SSL_METHOD;
pub fn DTLS_method() -> *const ::SSL_METHOD; pub fn DTLS_method() -> *const ::SSL_METHOD;
@ -100,42 +101,49 @@ extern "C" {
pub fn X509_get_subject_name(x: *const ::X509) -> *mut ::X509_NAME; pub fn X509_get_subject_name(x: *const ::X509) -> *mut ::X509_NAME;
pub fn X509_set1_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int; pub fn X509_set1_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
pub fn X509_set1_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int; pub fn X509_set1_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
pub fn X509_get_ext_d2i(x: *const ::X509, pub fn X509_get_ext_d2i(
x: *const ::X509,
nid: c_int, nid: c_int,
crit: *mut c_int, crit: *mut c_int,
idx: *mut c_int) idx: *mut c_int,
-> *mut c_void; ) -> *mut c_void;
pub fn X509_NAME_add_entry_by_NID(x: *mut ::X509_NAME, pub fn X509_NAME_add_entry_by_NID(
x: *mut ::X509_NAME,
field: c_int, field: c_int,
ty: c_int, ty: c_int,
bytes: *const c_uchar, bytes: *const c_uchar,
len: c_int, len: c_int,
loc: c_int, loc: c_int,
set: c_int) set: c_int,
-> c_int; ) -> c_int;
pub fn X509_get_signature_nid(x: *const X509) -> c_int; pub fn X509_get_signature_nid(x: *const X509) -> c_int;
pub fn X509_ALGOR_get0(paobj: *mut *const ::ASN1_OBJECT, pub fn X509_ALGOR_get0(
paobj: *mut *const ::ASN1_OBJECT,
pptype: *mut c_int, pptype: *mut c_int,
ppval: *mut *const c_void, ppval: *mut *const c_void,
alg: *const ::X509_ALGOR); alg: *const ::X509_ALGOR,
);
pub fn X509_NAME_get_entry(n: *const ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY; pub fn X509_NAME_get_entry(n: *const ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY;
pub fn X509_NAME_ENTRY_get_data(ne: *const ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING; pub fn X509_NAME_ENTRY_get_data(ne: *const ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING;
pub fn X509V3_EXT_nconf_nid(conf: *mut ::CONF, pub fn X509V3_EXT_nconf_nid(
conf: *mut ::CONF,
ctx: *mut ::X509V3_CTX, ctx: *mut ::X509V3_CTX,
ext_nid: c_int, ext_nid: c_int,
value: *const c_char) value: *const c_char,
-> *mut ::X509_EXTENSION; ) -> *mut ::X509_EXTENSION;
pub fn X509V3_EXT_nconf(conf: *mut ::CONF, pub fn X509V3_EXT_nconf(
conf: *mut ::CONF,
ctx: *mut ::X509V3_CTX, ctx: *mut ::X509V3_CTX,
name: *const c_char, name: *const c_char,
value: *const c_char) value: *const c_char,
-> *mut ::X509_EXTENSION; ) -> *mut ::X509_EXTENSION;
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *const ::ASN1_STRING) -> c_int; pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *const ::ASN1_STRING) -> c_int;
pub fn BN_is_negative(b: *const ::BIGNUM) -> c_int; pub fn BN_is_negative(b: *const ::BIGNUM) -> c_int;
pub fn EVP_CIPHER_key_length(cipher: *const EVP_CIPHER) -> c_int; pub fn EVP_CIPHER_key_length(cipher: *const EVP_CIPHER) -> c_int;
pub fn EVP_CIPHER_block_size(cipher: *const EVP_CIPHER) -> c_int; pub fn EVP_CIPHER_block_size(cipher: *const EVP_CIPHER) -> c_int;
pub fn EVP_CIPHER_iv_length(cipher: *const EVP_CIPHER) -> c_int; pub fn EVP_CIPHER_iv_length(cipher: *const EVP_CIPHER) -> c_int;
pub fn EVP_PBE_scrypt(pass: *const c_char, pub fn EVP_PBE_scrypt(
pass: *const c_char,
passlen: size_t, passlen: size_t,
salt: *const c_uchar, salt: *const c_uchar,
saltlen: size_t, saltlen: size_t,
@ -144,31 +152,39 @@ extern "C" {
p: u64, p: u64,
maxmem: u64, maxmem: u64,
key: *mut c_uchar, key: *mut c_uchar,
keylen: size_t) keylen: size_t,
-> c_int; ) -> c_int;
pub fn DSA_get0_pqg(d: *const ::DSA, pub fn DSA_get0_pqg(
d: *const ::DSA,
p: *mut *const ::BIGNUM, p: *mut *const ::BIGNUM,
q: *mut *const ::BIGNUM, q: *mut *const ::BIGNUM,
q: *mut *const ::BIGNUM); q: *mut *const ::BIGNUM,
pub fn DSA_get0_key(d: *const ::DSA, );
pub fn DSA_get0_key(
d: *const ::DSA,
pub_key: *mut *const ::BIGNUM, pub_key: *mut *const ::BIGNUM,
priv_key: *mut *const ::BIGNUM); priv_key: *mut *const ::BIGNUM,
pub fn RSA_get0_key(r: *const ::RSA, );
pub fn RSA_get0_key(
r: *const ::RSA,
n: *mut *const ::BIGNUM, n: *mut *const ::BIGNUM,
e: *mut *const ::BIGNUM, e: *mut *const ::BIGNUM,
d: *mut *const ::BIGNUM); d: *mut *const ::BIGNUM,
);
pub fn RSA_get0_factors(r: *const ::RSA, p: *mut *const ::BIGNUM, q: *mut *const ::BIGNUM); pub fn RSA_get0_factors(r: *const ::RSA, p: *mut *const ::BIGNUM, q: *mut *const ::BIGNUM);
pub fn RSA_set0_key(r: *mut ::RSA, pub fn RSA_set0_key(
r: *mut ::RSA,
n: *mut ::BIGNUM, n: *mut ::BIGNUM,
e: *mut ::BIGNUM, e: *mut ::BIGNUM,
d: *mut ::BIGNUM) d: *mut ::BIGNUM,
-> c_int; ) -> c_int;
pub fn RSA_set0_factors(r: *mut ::RSA, p: *mut ::BIGNUM, q: *mut ::BIGNUM) -> c_int; pub fn RSA_set0_factors(r: *mut ::RSA, p: *mut ::BIGNUM, q: *mut ::BIGNUM) -> c_int;
pub fn RSA_set0_crt_params(r: *mut ::RSA, pub fn RSA_set0_crt_params(
r: *mut ::RSA,
dmp1: *mut ::BIGNUM, dmp1: *mut ::BIGNUM,
dmq1: *mut ::BIGNUM, dmq1: *mut ::BIGNUM,
iqmp: *mut ::BIGNUM) iqmp: *mut ::BIGNUM,
-> c_int; ) -> c_int;
pub fn ASN1_STRING_get0_data(x: *const ::ASN1_STRING) -> *const c_uchar; pub fn ASN1_STRING_get0_data(x: *const ::ASN1_STRING) -> *const c_uchar;
pub fn OPENSSL_sk_num(stack: *const ::OPENSSL_STACK) -> c_int; pub fn OPENSSL_sk_num(stack: *const ::OPENSSL_STACK) -> c_int;
pub fn OPENSSL_sk_value(stack: *const ::OPENSSL_STACK, idx: c_int) -> *mut c_void; pub fn OPENSSL_sk_value(stack: *const ::OPENSSL_STACK, idx: c_int) -> *mut c_void;
@ -177,53 +193,62 @@ extern "C" {
pub fn SSL_CTX_clear_options(ctx: *mut ::SSL_CTX, op: c_ulong) -> c_ulong; pub fn SSL_CTX_clear_options(ctx: *mut ::SSL_CTX, op: c_ulong) -> c_ulong;
pub fn X509_getm_notAfter(x: *const ::X509) -> *mut ::ASN1_TIME; pub fn X509_getm_notAfter(x: *const ::X509) -> *mut ::ASN1_TIME;
pub fn X509_getm_notBefore(x: *const ::X509) -> *mut ::ASN1_TIME; pub fn X509_getm_notBefore(x: *const ::X509) -> *mut ::ASN1_TIME;
pub fn X509_get0_signature(psig: *mut *const ::ASN1_BIT_STRING, pub fn X509_get0_signature(
psig: *mut *const ::ASN1_BIT_STRING,
palg: *mut *const ::X509_ALGOR, palg: *mut *const ::X509_ALGOR,
x: *const ::X509); x: *const ::X509,
pub fn DH_set0_pqg(dh: *mut ::DH, );
pub fn DH_set0_pqg(
dh: *mut ::DH,
p: *mut ::BIGNUM, p: *mut ::BIGNUM,
q: *mut ::BIGNUM, q: *mut ::BIGNUM,
g: *mut ::BIGNUM) g: *mut ::BIGNUM,
-> c_int; ) -> c_int;
pub fn BIO_set_init(a: *mut ::BIO, init: c_int); pub fn BIO_set_init(a: *mut ::BIO, init: c_int);
pub fn BIO_set_data(a: *mut ::BIO, data: *mut c_void); pub fn BIO_set_data(a: *mut ::BIO, data: *mut c_void);
pub fn BIO_get_data(a: *mut ::BIO) -> *mut c_void; pub fn BIO_get_data(a: *mut ::BIO) -> *mut c_void;
pub fn BIO_meth_new(type_: c_int, name: *const c_char) -> *mut ::BIO_METHOD; pub fn BIO_meth_new(type_: c_int, name: *const c_char) -> *mut ::BIO_METHOD;
pub fn BIO_meth_free(biom: *mut ::BIO_METHOD); pub fn BIO_meth_free(biom: *mut ::BIO_METHOD);
pub fn BIO_meth_set_write(biom: *mut ::BIO_METHOD, pub fn BIO_meth_set_write(
write: unsafe extern "C" fn(*mut ::BIO, *const c_char, c_int) biom: *mut ::BIO_METHOD,
-> c_int) write: unsafe extern "C" fn(*mut ::BIO, *const c_char, c_int) -> c_int,
-> c_int; ) -> c_int;
pub fn BIO_meth_set_read(biom: *mut ::BIO_METHOD, pub fn BIO_meth_set_read(
read: unsafe extern "C" fn(*mut ::BIO, *mut c_char, c_int) -> c_int) biom: *mut ::BIO_METHOD,
-> c_int; read: unsafe extern "C" fn(*mut ::BIO, *mut c_char, c_int) -> c_int,
pub fn BIO_meth_set_puts(biom: *mut ::BIO_METHOD, ) -> c_int;
read: unsafe extern "C" fn(*mut ::BIO, *const c_char) -> c_int) pub fn BIO_meth_set_puts(
-> c_int; biom: *mut ::BIO_METHOD,
pub fn BIO_meth_set_ctrl(biom: *mut ::BIO_METHOD, read: unsafe extern "C" fn(*mut ::BIO, *const c_char) -> c_int,
read: unsafe extern "C" fn(*mut ::BIO, c_int, c_long, *mut c_void) ) -> c_int;
-> c_long) pub fn BIO_meth_set_ctrl(
-> c_int; biom: *mut ::BIO_METHOD,
pub fn BIO_meth_set_create(biom: *mut ::BIO_METHOD, read: unsafe extern "C" fn(*mut ::BIO, c_int, c_long, *mut c_void) -> c_long,
create: unsafe extern "C" fn(*mut ::BIO) -> c_int) ) -> c_int;
-> c_int; pub fn BIO_meth_set_create(
pub fn BIO_meth_set_destroy(biom: *mut ::BIO_METHOD, biom: *mut ::BIO_METHOD,
destroy: unsafe extern "C" fn(*mut ::BIO) -> c_int) create: unsafe extern "C" fn(*mut ::BIO) -> c_int,
-> c_int; ) -> c_int;
pub fn CRYPTO_get_ex_new_index(class_index: c_int, pub fn BIO_meth_set_destroy(
biom: *mut ::BIO_METHOD,
destroy: unsafe extern "C" fn(*mut ::BIO) -> c_int,
) -> c_int;
pub fn CRYPTO_get_ex_new_index(
class_index: c_int,
argl: c_long, argl: c_long,
argp: *mut c_void, argp: *mut c_void,
new_func: Option<::CRYPTO_EX_new>, new_func: Option<::CRYPTO_EX_new>,
dup_func: Option<::CRYPTO_EX_dup>, dup_func: Option<::CRYPTO_EX_dup>,
free_func: Option<::CRYPTO_EX_free>) free_func: Option<::CRYPTO_EX_free>,
-> c_int; ) -> c_int;
pub fn X509_up_ref(x: *mut X509) -> c_int; pub fn X509_up_ref(x: *mut X509) -> c_int;
pub fn SSL_CTX_up_ref(x: *mut SSL_CTX) -> c_int; pub fn SSL_CTX_up_ref(x: *mut SSL_CTX) -> c_int;
pub fn SSL_session_reused(ssl: *mut SSL) -> c_int; pub fn SSL_session_reused(ssl: *mut SSL) -> c_int;
pub fn SSL_SESSION_get_master_key(session: *const SSL_SESSION, pub fn SSL_SESSION_get_master_key(
session: *const SSL_SESSION,
out: *mut c_uchar, out: *mut c_uchar,
outlen: size_t) outlen: size_t,
-> size_t; ) -> size_t;
pub fn SSL_SESSION_up_ref(ses: *mut SSL_SESSION) -> c_int; pub fn SSL_SESSION_up_ref(ses: *mut SSL_SESSION) -> c_int;
pub fn X509_get0_extensions(req: *const ::X509) -> *const stack_st_X509_EXTENSION; pub fn X509_get0_extensions(req: *const ::X509) -> *const stack_st_X509_EXTENSION;
pub fn X509_STORE_CTX_get0_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509; pub fn X509_STORE_CTX_get0_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509;
@ -236,12 +261,15 @@ extern "C" {
pub fn OPENSSL_init_ssl(opts: u64, settings: *const OPENSSL_INIT_SETTINGS) -> c_int; pub fn OPENSSL_init_ssl(opts: u64, settings: *const OPENSSL_INIT_SETTINGS) -> c_int;
pub fn OPENSSL_sk_new_null() -> *mut ::OPENSSL_STACK; pub fn OPENSSL_sk_new_null() -> *mut ::OPENSSL_STACK;
pub fn OPENSSL_sk_free(st: *mut ::OPENSSL_STACK); pub fn OPENSSL_sk_free(st: *mut ::OPENSSL_STACK);
pub fn OPENSSL_sk_pop_free(st: *mut ::OPENSSL_STACK, pub fn OPENSSL_sk_pop_free(
free: Option<unsafe extern "C" fn(*mut c_void)>); st: *mut ::OPENSSL_STACK,
free: Option<unsafe extern "C" fn(*mut c_void)>,
);
pub fn OPENSSL_sk_push(st: *mut ::OPENSSL_STACK, data: *const c_void) -> c_int; pub fn OPENSSL_sk_push(st: *mut ::OPENSSL_STACK, data: *const c_void) -> c_int;
pub fn OPENSSL_sk_pop(st: *mut ::OPENSSL_STACK) -> *mut c_void; pub fn OPENSSL_sk_pop(st: *mut ::OPENSSL_STACK) -> *mut c_void;
pub fn PKCS12_create(pass: *const c_char, pub fn PKCS12_create(
pass: *const c_char,
friendly_name: *const c_char, friendly_name: *const c_char,
pkey: *mut EVP_PKEY, pkey: *mut EVP_PKEY,
cert: *mut X509, cert: *mut X509,
@ -250,8 +278,8 @@ extern "C" {
nid_cert: c_int, nid_cert: c_int,
iter: c_int, iter: c_int,
mac_iter: c_int, mac_iter: c_int,
keytype: c_int) keytype: c_int,
-> *mut PKCS12; ) -> *mut PKCS12;
pub fn X509_REQ_get_version(req: *const X509_REQ) -> c_long; pub fn X509_REQ_get_version(req: *const X509_REQ) -> c_long;
pub fn X509_REQ_get_subject_name(req: *const X509_REQ) -> *mut ::X509_NAME; pub fn X509_REQ_get_subject_name(req: *const X509_REQ) -> *mut ::X509_NAME;
} }

View File

@ -23,9 +23,11 @@ impl AesKey {
assert!(key.len() <= c_int::max_value() as usize / 8); assert!(key.len() <= c_int::max_value() as usize / 8);
let mut aes_key = mem::uninitialized(); let mut aes_key = mem::uninitialized();
let r = ffi::AES_set_encrypt_key(key.as_ptr() as *const _, let r = ffi::AES_set_encrypt_key(
key.as_ptr() as *const _,
key.len() as c_int * 8, key.len() as c_int * 8,
&mut aes_key); &mut aes_key,
);
if r == 0 { if r == 0 {
Ok(AesKey(aes_key)) Ok(AesKey(aes_key))
} else { } else {
@ -44,9 +46,11 @@ impl AesKey {
assert!(key.len() <= c_int::max_value() as usize / 8); assert!(key.len() <= c_int::max_value() as usize / 8);
let mut aes_key = mem::uninitialized(); let mut aes_key = mem::uninitialized();
let r = ffi::AES_set_decrypt_key(key.as_ptr() as *const _, let r = ffi::AES_set_decrypt_key(
key.as_ptr() as *const _,
key.len() as c_int * 8, key.len() as c_int * 8,
&mut aes_key); &mut aes_key,
);
if r == 0 { if r == 0 {
Ok(AesKey(aes_key)) Ok(AesKey(aes_key))
@ -73,12 +77,14 @@ pub fn aes_ige(in_: &[u8], out: &mut [u8], key: &AesKey, iv: &mut [u8], mode: Mo
Mode::Encrypt => ffi::AES_ENCRYPT, Mode::Encrypt => ffi::AES_ENCRYPT,
Mode::Decrypt => ffi::AES_DECRYPT, Mode::Decrypt => ffi::AES_DECRYPT,
}; };
ffi::AES_ige_encrypt(in_.as_ptr() as *const _, ffi::AES_ige_encrypt(
in_.as_ptr() as *const _,
out.as_mut_ptr() as *mut _, out.as_mut_ptr() as *mut _,
in_.len(), in_.len(),
&key.0, &key.0,
iv.as_mut_ptr() as *mut _, iv.as_mut_ptr() as *mut _,
mode); mode,
);
} }
} }

View File

@ -24,7 +24,10 @@ impl fmt::Display for Asn1GeneralizedTimeRef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
unsafe { unsafe {
let mem_bio = try!(MemBio::new()); let mem_bio = try!(MemBio::new());
try!(cvt(ffi::ASN1_GENERALIZEDTIME_print(mem_bio.as_ptr(), self.as_ptr()))); try!(cvt(ffi::ASN1_GENERALIZEDTIME_print(
mem_bio.as_ptr(),
self.as_ptr(),
)));
write!(f, "{}", str::from_utf8_unchecked(mem_bio.get_buf())) write!(f, "{}", str::from_utf8_unchecked(mem_bio.get_buf()))
} }
} }
@ -104,16 +107,11 @@ foreign_type! {
impl Asn1IntegerRef { impl Asn1IntegerRef {
pub fn get(&self) -> i64 { pub fn get(&self) -> i64 {
unsafe { unsafe { ::ffi::ASN1_INTEGER_get(self.as_ptr()) as i64 }
::ffi::ASN1_INTEGER_get(self.as_ptr()) as i64
}
} }
pub fn set(&mut self, value: i32) -> Result<(), ErrorStack> pub fn set(&mut self, value: i32) -> Result<(), ErrorStack> {
{ unsafe { cvt(::ffi::ASN1_INTEGER_set(self.as_ptr(), value as c_long)).map(|_| ()) }
unsafe {
cvt(::ffi::ASN1_INTEGER_set(self.as_ptr(), value as c_long)).map(|_| ())
}
} }
} }
@ -146,9 +144,7 @@ foreign_type! {
impl Asn1ObjectRef { impl Asn1ObjectRef {
/// Returns the NID associated with this OID. /// Returns the NID associated with this OID.
pub fn nid(&self) -> Nid { pub fn nid(&self) -> Nid {
unsafe { unsafe { Nid::from_raw(ffi::OBJ_obj2nid(self.as_ptr())) }
Nid::from_raw(ffi::OBJ_obj2nid(self.as_ptr()))
}
} }
} }
@ -156,10 +152,12 @@ impl fmt::Display for Asn1ObjectRef {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
unsafe { unsafe {
let mut buf = [0; 80]; let mut buf = [0; 80];
let len = ffi::OBJ_obj2txt(buf.as_mut_ptr() as *mut _, let len = ffi::OBJ_obj2txt(
buf.as_mut_ptr() as *mut _,
buf.len() as c_int, buf.len() as c_int,
self.as_ptr(), self.as_ptr(),
0); 0,
);
let s = try!(str::from_utf8(&buf[..len as usize]).map_err(|_| fmt::Error)); let s = try!(str::from_utf8(&buf[..len as usize]).map_err(|_| fmt::Error));
fmt.write_str(s) fmt.write_str(s)
} }

View File

@ -22,8 +22,12 @@ impl<'a> MemBioSlice<'a> {
ffi::init(); ffi::init();
assert!(buf.len() <= c_int::max_value() as usize); assert!(buf.len() <= c_int::max_value() as usize);
let bio = let bio = unsafe {
unsafe { try!(cvt_p(BIO_new_mem_buf(buf.as_ptr() as *const _, buf.len() as c_int))) }; try!(cvt_p(BIO_new_mem_buf(
buf.as_ptr() as *const _,
buf.len() as c_int,
)))
};
Ok(MemBioSlice(bio, PhantomData)) Ok(MemBioSlice(bio, PhantomData))
} }

View File

@ -225,13 +225,25 @@ impl BigNumRef {
/// * `msb`: The desired properties of the number. /// * `msb`: The desired properties of the number.
/// * `odd`: If `true`, the generated number will be odd. /// * `odd`: If `true`, the generated number will be odd.
pub fn rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> { pub fn rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::BN_rand(self.as_ptr(), bits.into(), msb.0, odd as c_int)).map(|_| ()) } unsafe {
cvt(ffi::BN_rand(
self.as_ptr(),
bits.into(),
msb.0,
odd as c_int,
)).map(|_| ())
}
} }
/// The cryptographically weak counterpart to `rand`. /// The cryptographically weak counterpart to `rand`.
pub fn pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> { pub fn pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_pseudo_rand(self.as_ptr(), bits.into(), msb.0, odd as c_int)).map(|_| ()) cvt(ffi::BN_pseudo_rand(
self.as_ptr(),
bits.into(),
msb.0,
odd as c_int,
)).map(|_| ())
} }
} }
@ -243,78 +255,94 @@ impl BigNumRef {
/// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime. /// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime.
/// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the /// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the
/// generated prime and `rem` is `1` if not specified (`None`). /// generated prime and `rem` is `1` if not specified (`None`).
pub fn generate_prime(&mut self, pub fn generate_prime(
&mut self,
bits: i32, bits: i32,
safe: bool, safe: bool,
add: Option<&BigNumRef>, add: Option<&BigNumRef>,
rem: Option<&BigNumRef>) rem: Option<&BigNumRef>,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_generate_prime_ex(self.as_ptr(), cvt(ffi::BN_generate_prime_ex(
self.as_ptr(),
bits as c_int, bits as c_int,
safe as c_int, safe as c_int,
add.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()), add.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
rem.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()), rem.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()),
ptr::null_mut())) ptr::null_mut(),
.map(|_| ()) )).map(|_| ())
} }
} }
/// Places the result of `a * b` in `self`. /// Places the result of `a * b` in `self`.
pub fn checked_mul(&mut self, pub fn checked_mul(
&mut self,
a: &BigNumRef, a: &BigNumRef,
b: &BigNumRef, b: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::BN_mul(self.as_ptr(), a.as_ptr(), b.as_ptr(), ctx.as_ptr())).map(|_| ()) } unsafe {
cvt(ffi::BN_mul(
self.as_ptr(),
a.as_ptr(),
b.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
}
} }
/// Places the result of `a / b` in `self`. /// Places the result of `a / b` in `self`.
pub fn checked_div(&mut self, pub fn checked_div(
&mut self,
a: &BigNumRef, a: &BigNumRef,
b: &BigNumRef, b: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_div(self.as_ptr(), cvt(ffi::BN_div(
self.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
a.as_ptr(), a.as_ptr(),
b.as_ptr(), b.as_ptr(),
ctx.as_ptr())) ctx.as_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
/// Places the result of `a % b` in `self`. /// Places the result of `a % b` in `self`.
pub fn checked_rem(&mut self, pub fn checked_rem(
&mut self,
a: &BigNumRef, a: &BigNumRef,
b: &BigNumRef, b: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_div(ptr::null_mut(), cvt(ffi::BN_div(
ptr::null_mut(),
self.as_ptr(), self.as_ptr(),
a.as_ptr(), a.as_ptr(),
b.as_ptr(), b.as_ptr(),
ctx.as_ptr())) ctx.as_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
/// Places the result of `a / b` in `self` and `a % b` in `rem`. /// Places the result of `a / b` in `self` and `a % b` in `rem`.
pub fn div_rem(&mut self, pub fn div_rem(
&mut self,
rem: &mut BigNumRef, rem: &mut BigNumRef,
a: &BigNumRef, a: &BigNumRef,
b: &BigNumRef, b: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_div(self.as_ptr(), cvt(ffi::BN_div(
self.as_ptr(),
rem.as_ptr(), rem.as_ptr(),
a.as_ptr(), a.as_ptr(),
b.as_ptr(), b.as_ptr(),
ctx.as_ptr())) ctx.as_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
@ -324,107 +352,164 @@ impl BigNumRef {
} }
/// Places the result of `a mod m` in `self`. /// Places the result of `a mod m` in `self`.
pub fn nnmod(&mut self, pub fn nnmod(
&mut self,
a: &BigNumRef, a: &BigNumRef,
m: &BigNumRef, m: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_nnmod(self.as_ptr(), a.as_ptr(), m.as_ptr(), ctx.as_ptr())).map(|_| ()) cvt(ffi::BN_nnmod(
self.as_ptr(),
a.as_ptr(),
m.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
} }
} }
/// Places the result of `(a + b) mod m` in `self`. /// Places the result of `(a + b) mod m` in `self`.
pub fn mod_add(&mut self, pub fn mod_add(
&mut self,
a: &BigNumRef, a: &BigNumRef,
b: &BigNumRef, b: &BigNumRef,
m: &BigNumRef, m: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_mod_add(self.as_ptr(), a.as_ptr(), b.as_ptr(), m.as_ptr(), ctx.as_ptr())) cvt(ffi::BN_mod_add(
.map(|_| ()) self.as_ptr(),
a.as_ptr(),
b.as_ptr(),
m.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
} }
} }
/// Places the result of `(a - b) mod m` in `self`. /// Places the result of `(a - b) mod m` in `self`.
pub fn mod_sub(&mut self, pub fn mod_sub(
&mut self,
a: &BigNumRef, a: &BigNumRef,
b: &BigNumRef, b: &BigNumRef,
m: &BigNumRef, m: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_mod_sub(self.as_ptr(), a.as_ptr(), b.as_ptr(), m.as_ptr(), ctx.as_ptr())) cvt(ffi::BN_mod_sub(
.map(|_| ()) self.as_ptr(),
a.as_ptr(),
b.as_ptr(),
m.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
} }
} }
/// Places the result of `(a * b) mod m` in `self`. /// Places the result of `(a * b) mod m` in `self`.
pub fn mod_mul(&mut self, pub fn mod_mul(
&mut self,
a: &BigNumRef, a: &BigNumRef,
b: &BigNumRef, b: &BigNumRef,
m: &BigNumRef, m: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_mod_mul(self.as_ptr(), a.as_ptr(), b.as_ptr(), m.as_ptr(), ctx.as_ptr())) cvt(ffi::BN_mod_mul(
.map(|_| ()) self.as_ptr(),
a.as_ptr(),
b.as_ptr(),
m.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
} }
} }
/// Places the result of `a² mod m` in `self`. /// Places the result of `a² mod m` in `self`.
pub fn mod_sqr(&mut self, pub fn mod_sqr(
&mut self,
a: &BigNumRef, a: &BigNumRef,
m: &BigNumRef, m: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_mod_sqr(self.as_ptr(), a.as_ptr(), m.as_ptr(), ctx.as_ptr())).map(|_| ()) cvt(ffi::BN_mod_sqr(
self.as_ptr(),
a.as_ptr(),
m.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
} }
} }
/// Places the result of `a^p` in `self`. /// Places the result of `a^p` in `self`.
pub fn exp(&mut self, pub fn exp(
&mut self,
a: &BigNumRef, a: &BigNumRef,
p: &BigNumRef, p: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::BN_exp(self.as_ptr(), a.as_ptr(), p.as_ptr(), ctx.as_ptr())).map(|_| ()) } unsafe {
cvt(ffi::BN_exp(
self.as_ptr(),
a.as_ptr(),
p.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
}
} }
/// Places the result of `a^p mod m` in `self`. /// Places the result of `a^p mod m` in `self`.
pub fn mod_exp(&mut self, pub fn mod_exp(
&mut self,
a: &BigNumRef, a: &BigNumRef,
p: &BigNumRef, p: &BigNumRef,
m: &BigNumRef, m: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::BN_mod_exp(self.as_ptr(), a.as_ptr(), p.as_ptr(), m.as_ptr(), ctx.as_ptr())) cvt(ffi::BN_mod_exp(
.map(|_| ()) self.as_ptr(),
a.as_ptr(),
p.as_ptr(),
m.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
} }
} }
/// Places the inverse of `a` modulo `n` in `self`. /// Places the inverse of `a` modulo `n` in `self`.
pub fn mod_inverse(&mut self, pub fn mod_inverse(
&mut self,
a: &BigNumRef, a: &BigNumRef,
n: &BigNumRef, n: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt_p(ffi::BN_mod_inverse(self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx.as_ptr())) cvt_p(ffi::BN_mod_inverse(
.map(|_| ()) self.as_ptr(),
a.as_ptr(),
n.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
} }
} }
/// Places the greatest common denominator of `a` and `b` in `self`. /// Places the greatest common denominator of `a` and `b` in `self`.
pub fn gcd(&mut self, pub fn gcd(
&mut self,
a: &BigNumRef, a: &BigNumRef,
b: &BigNumRef, b: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::BN_gcd(self.as_ptr(), a.as_ptr(), b.as_ptr(), ctx.as_ptr())).map(|_| ()) } unsafe {
cvt(ffi::BN_gcd(
self.as_ptr(),
a.as_ptr(),
b.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
}
} }
/// Checks whether `self` is prime. /// Checks whether `self` is prime.
@ -434,8 +519,12 @@ impl BigNumRef {
/// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`. /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
pub fn is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result<bool, ErrorStack> { pub fn is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result<bool, ErrorStack> {
unsafe { unsafe {
cvt_n(ffi::BN_is_prime_ex(self.as_ptr(), checks.into(), ctx.as_ptr(), ptr::null_mut())) cvt_n(ffi::BN_is_prime_ex(
.map(|r| r != 0) self.as_ptr(),
checks.into(),
ctx.as_ptr(),
ptr::null_mut(),
)).map(|r| r != 0)
} }
} }
@ -448,18 +537,20 @@ impl BigNumRef {
/// # Return Value /// # Return Value
/// ///
/// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`. /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
pub fn is_prime_fasttest(&self, pub fn is_prime_fasttest(
&self,
checks: i32, checks: i32,
ctx: &mut BigNumContextRef, ctx: &mut BigNumContextRef,
do_trial_division: bool) do_trial_division: bool,
-> Result<bool, ErrorStack> { ) -> Result<bool, ErrorStack> {
unsafe { unsafe {
cvt_n(ffi::BN_is_prime_fasttest_ex(self.as_ptr(), cvt_n(ffi::BN_is_prime_fasttest_ex(
self.as_ptr(),
checks.into(), checks.into(),
ctx.as_ptr(), ctx.as_ptr(),
do_trial_division as c_int, do_trial_division as c_int,
ptr::null_mut())) ptr::null_mut(),
.map(|r| r != 0) )).map(|r| r != 0)
} }
} }
@ -639,8 +730,11 @@ impl BigNum {
unsafe { unsafe {
ffi::init(); ffi::init();
assert!(n.len() <= c_int::max_value() as usize); assert!(n.len() <= c_int::max_value() as usize);
cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, ptr::null_mut())) cvt_p(ffi::BN_bin2bn(
.map(|p| BigNum::from_ptr(p)) n.as_ptr(),
n.len() as c_int,
ptr::null_mut(),
)).map(|p| BigNum::from_ptr(p))
} }
} }
} }
@ -936,8 +1030,7 @@ mod tests {
#[test] #[test]
fn test_rand_range() { fn test_rand_range() {
let range = BigNum::from_u32(909829283).unwrap(); let range = BigNum::from_u32(909829283).unwrap();
let mut result = BigNum::from_dec_str( let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
&range.to_dec_str().unwrap()).unwrap();
range.rand_range(&mut result).unwrap(); range.rand_range(&mut result).unwrap();
assert!(result >= BigNum::from_u32(0).unwrap() && result < range); assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
} }
@ -945,8 +1038,7 @@ mod tests {
#[test] #[test]
fn test_pseudo_rand_range() { fn test_pseudo_rand_range() {
let range = BigNum::from_u32(909829283).unwrap(); let range = BigNum::from_u32(909829283).unwrap();
let mut result = BigNum::from_dec_str( let mut result = BigNum::from_dec_str(&range.to_dec_str().unwrap()).unwrap();
&range.to_dec_str().unwrap()).unwrap();
range.pseudo_rand_range(&mut result).unwrap(); range.pseudo_rand_range(&mut result).unwrap();
assert!(result >= BigNum::from_u32(0).unwrap() && result < range); assert!(result >= BigNum::from_u32(0).unwrap() && result < range);
} }

View File

@ -26,7 +26,12 @@ impl Dh {
unsafe { unsafe {
init(); init();
let dh = Dh(try!(cvt_p(ffi::DH_new()))); let dh = Dh(try!(cvt_p(ffi::DH_new())));
try!(cvt(compat::DH_set0_pqg(dh.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))); try!(cvt(compat::DH_set0_pqg(
dh.0,
p.as_ptr(),
q.as_ptr(),
g.as_ptr(),
)));
mem::forget((p, g, q)); mem::forget((p, g, q));
Ok(dh) Ok(dh)
} }
@ -65,11 +70,12 @@ mod compat {
use ffi; use ffi;
use libc::c_int; use libc::c_int;
pub unsafe fn DH_set0_pqg(dh: *mut ffi::DH, pub unsafe fn DH_set0_pqg(
dh: *mut ffi::DH,
p: *mut ffi::BIGNUM, p: *mut ffi::BIGNUM,
q: *mut ffi::BIGNUM, q: *mut ffi::BIGNUM,
g: *mut ffi::BIGNUM) g: *mut ffi::BIGNUM,
-> c_int { ) -> c_int {
(*dh).p = p; (*dh).p = p;
(*dh).q = q; (*dh).q = q;
(*dh).g = g; (*dh).g = g;
@ -98,7 +104,8 @@ mod tests {
#[test] #[test]
fn test_dh() { fn test_dh() {
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435\ let p = BigNum::from_hex_str(
"87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435\
E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF429\ E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF429\
6D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C02\ 6D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C02\
2E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF1230\ 2E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF1230\
@ -106,9 +113,10 @@ mod tests {
A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251C\ A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251C\
CACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE\ CACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE\
621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D227\ 621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D227\
6E11715F693877FAD7EF09CADB094AE91E1A1597") 6E11715F693877FAD7EF09CADB094AE91E1A1597",
.unwrap(); ).unwrap();
let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0\ let g = BigNum::from_hex_str(
"3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0\
BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773\ BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773\
BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2D\ BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2D\
DF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428E\ DF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428E\
@ -116,11 +124,12 @@ mod tests {
FE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7\ FE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7\
D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92\ D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92\
B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148\ B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148\
D47954515E2327CFEF98C582664B4C0F6CC41659") D47954515E2327CFEF98C582664B4C0F6CC41659",
.unwrap(); ).unwrap();
let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F\ let q = BigNum::from_hex_str(
5FBD3") "8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F\
.unwrap(); 5FBD3",
).unwrap();
let dh = Dh::from_params(p, g, q).unwrap(); let dh = Dh::from_params(p, g, q).unwrap();
ctx.set_tmp_dh(&dh).unwrap(); ctx.set_tmp_dh(&dh).unwrap();
} }

View File

@ -81,13 +81,15 @@ impl Dsa {
pub fn generate(bits: u32) -> Result<Dsa, ErrorStack> { pub fn generate(bits: u32) -> Result<Dsa, ErrorStack> {
unsafe { unsafe {
let dsa = Dsa(try!(cvt_p(ffi::DSA_new()))); let dsa = Dsa(try!(cvt_p(ffi::DSA_new())));
try!(cvt(ffi::DSA_generate_parameters_ex(dsa.0, try!(cvt(ffi::DSA_generate_parameters_ex(
dsa.0,
bits as c_int, bits as c_int,
ptr::null(), ptr::null(),
0, 0,
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut()))); ptr::null_mut(),
)));
try!(cvt(ffi::DSA_generate_key(dsa.0))); try!(cvt(ffi::DSA_generate_key(dsa.0)));
Ok(dsa) Ok(dsa)
} }
@ -100,7 +102,8 @@ impl Dsa {
#[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")] #[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")]
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<Dsa, ErrorStack> pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<Dsa, ErrorStack>
where F: FnOnce(&mut [c_char]) -> usize where
F: FnOnce(&mut [c_char]) -> usize,
{ {
ffi::init(); ffi::init();
let mut cb = CallbackState::new(pass_cb); let mut cb = CallbackState::new(pass_cb);
@ -108,10 +111,12 @@ impl Dsa {
unsafe { unsafe {
let cb_ptr = &mut cb as *mut _ as *mut c_void; let cb_ptr = &mut cb as *mut _ as *mut c_void;
let dsa = try!(cvt_p(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.as_ptr(), let dsa = try!(cvt_p(ffi::PEM_read_bio_DSAPrivateKey(
mem_bio.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
Some(invoke_passwd_cb_old::<F>), Some(invoke_passwd_cb_old::<F>),
cb_ptr))); cb_ptr,
)));
Ok(Dsa(dsa)) Ok(Dsa(dsa))
} }
} }
@ -174,7 +179,8 @@ mod test {
#[test] #[test]
fn test_to_password() { fn test_to_password() {
let key = Dsa::generate(2048).unwrap(); let key = Dsa::generate(2048).unwrap();
let pem = key.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar").unwrap(); let pem = key.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
.unwrap();
Dsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap(); Dsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
assert!(Dsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err()); assert!(Dsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
} }
@ -187,8 +193,7 @@ mod test {
password_queried = true; password_queried = true;
password[..6].copy_from_slice(b"mypass"); password[..6].copy_from_slice(b"mypass");
Ok(6) Ok(6)
}) }).unwrap();
.unwrap();
assert!(password_queried); assert!(password_queried);
} }

View File

@ -49,37 +49,41 @@ impl EcGroup {
impl EcGroupRef { impl EcGroupRef {
/// Places the components of a curve over a prime field in the provided `BigNum`s. /// Places the components of a curve over a prime field in the provided `BigNum`s.
pub fn components_gfp(&self, pub fn components_gfp(
&self,
p: &mut BigNumRef, p: &mut BigNumRef,
a: &mut BigNumRef, a: &mut BigNumRef,
b: &mut BigNumRef, b: &mut BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_GROUP_get_curve_GFp(self.as_ptr(), cvt(ffi::EC_GROUP_get_curve_GFp(
self.as_ptr(),
p.as_ptr(), p.as_ptr(),
a.as_ptr(), a.as_ptr(),
b.as_ptr(), b.as_ptr(),
ctx.as_ptr())) ctx.as_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
/// Places the components of a curve over a binary field in the provided `BigNum`s. /// Places the components of a curve over a binary field in the provided `BigNum`s.
#[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))]
pub fn components_gf2m(&self, pub fn components_gf2m(
&self,
p: &mut BigNumRef, p: &mut BigNumRef,
a: &mut BigNumRef, a: &mut BigNumRef,
b: &mut BigNumRef, b: &mut BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_GROUP_get_curve_GF2m(self.as_ptr(), cvt(ffi::EC_GROUP_get_curve_GF2m(
self.as_ptr(),
p.as_ptr(), p.as_ptr(),
a.as_ptr(), a.as_ptr(),
b.as_ptr(), b.as_ptr(),
ctx.as_ptr())) ctx.as_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
@ -89,12 +93,17 @@ impl EcGroupRef {
} }
/// Places the order of the curve in the provided `BigNum`. /// Places the order of the curve in the provided `BigNum`.
pub fn order(&self, pub fn order(
&self,
order: &mut BigNumRef, order: &mut BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_GROUP_get_order(self.as_ptr(), order.as_ptr(), ctx.as_ptr())).map(|_| ()) cvt(ffi::EC_GROUP_get_order(
self.as_ptr(),
order.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
} }
} }
@ -120,106 +129,123 @@ foreign_type! {
impl EcPointRef { impl EcPointRef {
/// Computes `a + b`, storing the result in `self`. /// Computes `a + b`, storing the result in `self`.
pub fn add(&mut self, pub fn add(
&mut self,
group: &EcGroupRef, group: &EcGroupRef,
a: &EcPointRef, a: &EcPointRef,
b: &EcPointRef, b: &EcPointRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_POINT_add(group.as_ptr(), cvt(ffi::EC_POINT_add(
group.as_ptr(),
self.as_ptr(), self.as_ptr(),
a.as_ptr(), a.as_ptr(),
b.as_ptr(), b.as_ptr(),
ctx.as_ptr())) ctx.as_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
/// Computes `q * m`, storing the result in `self`. /// Computes `q * m`, storing the result in `self`.
pub fn mul(&mut self, pub fn mul(
&mut self,
group: &EcGroupRef, group: &EcGroupRef,
q: &EcPointRef, q: &EcPointRef,
m: &BigNumRef, m: &BigNumRef,
ctx: &BigNumContextRef) ctx: &BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_POINT_mul(group.as_ptr(), cvt(ffi::EC_POINT_mul(
group.as_ptr(),
self.as_ptr(), self.as_ptr(),
ptr::null(), ptr::null(),
q.as_ptr(), q.as_ptr(),
m.as_ptr(), m.as_ptr(),
ctx.as_ptr())) ctx.as_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
/// Computes `generator * n`, storing the result ing `self`. /// Computes `generator * n`, storing the result ing `self`.
pub fn mul_generator(&mut self, pub fn mul_generator(
&mut self,
group: &EcGroupRef, group: &EcGroupRef,
n: &BigNumRef, n: &BigNumRef,
ctx: &BigNumContextRef) ctx: &BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_POINT_mul(group.as_ptr(), cvt(ffi::EC_POINT_mul(
group.as_ptr(),
self.as_ptr(), self.as_ptr(),
n.as_ptr(), n.as_ptr(),
ptr::null(), ptr::null(),
ptr::null(), ptr::null(),
ctx.as_ptr())) ctx.as_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
/// Computes `generator * n + q * m`, storing the result in `self`. /// Computes `generator * n + q * m`, storing the result in `self`.
pub fn mul_full(&mut self, pub fn mul_full(
&mut self,
group: &EcGroupRef, group: &EcGroupRef,
n: &BigNumRef, n: &BigNumRef,
q: &EcPointRef, q: &EcPointRef,
m: &BigNumRef, m: &BigNumRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_POINT_mul(group.as_ptr(), cvt(ffi::EC_POINT_mul(
group.as_ptr(),
self.as_ptr(), self.as_ptr(),
n.as_ptr(), n.as_ptr(),
q.as_ptr(), q.as_ptr(),
m.as_ptr(), m.as_ptr(),
ctx.as_ptr())) ctx.as_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
/// Inverts `self`. /// Inverts `self`.
pub fn invert(&mut self, group: &EcGroupRef, ctx: &BigNumContextRef) -> Result<(), ErrorStack> { pub fn invert(&mut self, group: &EcGroupRef, ctx: &BigNumContextRef) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_POINT_invert(group.as_ptr(), self.as_ptr(), ctx.as_ptr())).map(|_| ()) cvt(ffi::EC_POINT_invert(
group.as_ptr(),
self.as_ptr(),
ctx.as_ptr(),
)).map(|_| ())
} }
} }
/// Serializes the point to a binary representation. /// Serializes the point to a binary representation.
pub fn to_bytes(&self, pub fn to_bytes(
&self,
group: &EcGroupRef, group: &EcGroupRef,
form: PointConversionForm, form: PointConversionForm,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<Vec<u8>, ErrorStack> { ) -> Result<Vec<u8>, ErrorStack> {
unsafe { unsafe {
let len = ffi::EC_POINT_point2oct(group.as_ptr(), let len = ffi::EC_POINT_point2oct(
group.as_ptr(),
self.as_ptr(), self.as_ptr(),
form.0, form.0,
ptr::null_mut(), ptr::null_mut(),
0, 0,
ctx.as_ptr()); ctx.as_ptr(),
);
if len == 0 { if len == 0 {
return Err(ErrorStack::get()); return Err(ErrorStack::get());
} }
let mut buf = vec![0; len]; let mut buf = vec![0; len];
let len = ffi::EC_POINT_point2oct(group.as_ptr(), let len = ffi::EC_POINT_point2oct(
group.as_ptr(),
self.as_ptr(), self.as_ptr(),
form.0, form.0,
buf.as_mut_ptr(), buf.as_mut_ptr(),
len, len,
ctx.as_ptr()); ctx.as_ptr(),
);
if len == 0 { if len == 0 {
Err(ErrorStack::get()) Err(ErrorStack::get())
} else { } else {
@ -229,16 +255,19 @@ impl EcPointRef {
} }
/// Determines if this point is equal to another. /// Determines if this point is equal to another.
pub fn eq(&self, pub fn eq(
&self,
group: &EcGroupRef, group: &EcGroupRef,
other: &EcPointRef, other: &EcPointRef,
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<bool, ErrorStack> { ) -> Result<bool, ErrorStack> {
unsafe { unsafe {
let res = try!(cvt_n(ffi::EC_POINT_cmp(group.as_ptr(), let res = try!(cvt_n(ffi::EC_POINT_cmp(
group.as_ptr(),
self.as_ptr(), self.as_ptr(),
other.as_ptr(), other.as_ptr(),
ctx.as_ptr()))); ctx.as_ptr(),
)));
Ok(res == 0) Ok(res == 0)
} }
} }
@ -250,17 +279,20 @@ impl EcPoint {
unsafe { cvt_p(ffi::EC_POINT_new(group.as_ptr())).map(EcPoint) } unsafe { cvt_p(ffi::EC_POINT_new(group.as_ptr())).map(EcPoint) }
} }
pub fn from_bytes(group: &EcGroupRef, pub fn from_bytes(
group: &EcGroupRef,
buf: &[u8], buf: &[u8],
ctx: &mut BigNumContextRef) ctx: &mut BigNumContextRef,
-> Result<EcPoint, ErrorStack> { ) -> Result<EcPoint, ErrorStack> {
let point = try!(EcPoint::new(group)); let point = try!(EcPoint::new(group));
unsafe { unsafe {
try!(cvt(ffi::EC_POINT_oct2point(group.as_ptr(), try!(cvt(ffi::EC_POINT_oct2point(
group.as_ptr(),
point.as_ptr(), point.as_ptr(),
buf.as_ptr(), buf.as_ptr(),
buf.len(), buf.len(),
ctx.as_ptr()))); ctx.as_ptr(),
)));
} }
Ok(point) Ok(point)
} }
@ -354,7 +386,10 @@ impl EcKey {
/// let point = EcPoint::from_bytes(&group, &public_key, &mut ctx).unwrap(); /// let point = EcPoint::from_bytes(&group, &public_key, &mut ctx).unwrap();
/// let key = EcKey::from_public_key(&group, &point); /// let key = EcKey::from_public_key(&group, &point);
/// ``` /// ```
pub fn from_public_key(group: &EcGroupRef, public_key: &EcPointRef) -> Result<EcKey, ErrorStack> { pub fn from_public_key(
group: &EcGroupRef,
public_key: &EcPointRef,
) -> Result<EcKey, ErrorStack> {
let mut builder = try!(EcKeyBuilder::new()); let mut builder = try!(EcKeyBuilder::new());
try!(builder.set_group(group)); try!(builder.set_group(group));
try!(builder.set_public_key(public_key)); try!(builder.set_public_key(public_key));
@ -406,23 +441,23 @@ impl EcKeyBuilder {
impl EcKeyBuilderRef { impl EcKeyBuilderRef {
pub fn set_group(&mut self, group: &EcGroupRef) -> Result<&mut EcKeyBuilderRef, ErrorStack> { pub fn set_group(&mut self, group: &EcGroupRef) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
unsafe { unsafe { cvt(ffi::EC_KEY_set_group(self.as_ptr(), group.as_ptr())).map(|_| self) }
cvt(ffi::EC_KEY_set_group(self.as_ptr(), group.as_ptr())).map(|_| self)
}
} }
pub fn set_public_key(&mut self, pub fn set_public_key(
public_key: &EcPointRef) &mut self,
-> Result<&mut EcKeyBuilderRef, ErrorStack> { public_key: &EcPointRef,
) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
unsafe { unsafe {
cvt(ffi::EC_KEY_set_public_key(self.as_ptr(), public_key.as_ptr())).map(|_| self) cvt(ffi::EC_KEY_set_public_key(
self.as_ptr(),
public_key.as_ptr(),
)).map(|_| self)
} }
} }
pub fn generate_key(&mut self) -> Result<&mut EcKeyBuilderRef, ErrorStack> { pub fn generate_key(&mut self) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
unsafe { unsafe { cvt(ffi::EC_KEY_generate_key(self.as_ptr())).map(|_| self) }
cvt(ffi::EC_KEY_generate_key(self.as_ptr())).map(|_| self)
}
} }
} }
@ -464,7 +499,9 @@ mod test {
let key = EcKey::generate(&group).unwrap(); let key = EcKey::generate(&group).unwrap();
let point = key.public_key().unwrap(); let point = key.public_key().unwrap();
let mut ctx = BigNumContext::new().unwrap(); let mut ctx = BigNumContext::new().unwrap();
let bytes = point.to_bytes(&group, POINT_CONVERSION_COMPRESSED, &mut ctx).unwrap(); let bytes = point
.to_bytes(&group, POINT_CONVERSION_COMPRESSED, &mut ctx)
.unwrap();
let point2 = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap(); let point2 = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap();
assert!(point.eq(&group, &point2, &mut ctx).unwrap()); assert!(point.eq(&group, &point2, &mut ctx).unwrap());
} }
@ -475,8 +512,14 @@ mod test {
let key = EcKey::generate(&group).unwrap(); let key = EcKey::generate(&group).unwrap();
let mut ctx = BigNumContext::new().unwrap(); let mut ctx = BigNumContext::new().unwrap();
let mut public_key = EcPoint::new(&group).unwrap(); let mut public_key = EcPoint::new(&group).unwrap();
public_key.mul_generator(&group, key.private_key().unwrap(), &mut ctx).unwrap(); public_key
assert!(public_key.eq(&group, key.public_key().unwrap(), &mut ctx).unwrap()); .mul_generator(&group, key.private_key().unwrap(), &mut ctx)
.unwrap();
assert!(
public_key
.eq(&group, key.public_key().unwrap(), &mut ctx)
.unwrap()
);
} }
#[test] #[test]
@ -484,7 +527,10 @@ mod test {
let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap(); let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).unwrap(); let key = EcKey::generate(&group).unwrap();
let mut ctx = BigNumContext::new().unwrap(); let mut ctx = BigNumContext::new().unwrap();
let bytes = key.public_key().unwrap().to_bytes(&group, POINT_CONVERSION_COMPRESSED, &mut ctx).unwrap(); let bytes = key.public_key()
.unwrap()
.to_bytes(&group, POINT_CONVERSION_COMPRESSED, &mut ctx)
.unwrap();
drop(key); drop(key);
let public_key = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap(); let public_key = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap();

View File

@ -210,7 +210,13 @@ impl fmt::Display for Error {
Some(r) => try!(write!(fmt, ":{}", r)), Some(r) => try!(write!(fmt, ":{}", r)),
None => try!(write!(fmt, ":reason({})", ffi::ERR_GET_FUNC(self.code()))), None => try!(write!(fmt, ":reason({})", ffi::ERR_GET_FUNC(self.code()))),
} }
write!(fmt, ":{}:{}:{}", self.file(), self.line(), self.data().unwrap_or("")) write!(
fmt,
":{}:{}:{}",
self.file(),
self.line(),
self.data().unwrap_or("")
)
} }
} }

View File

@ -137,7 +137,11 @@ impl Hasher {
try!(self.init()); try!(self.init());
} }
unsafe { unsafe {
try!(cvt(ffi::EVP_DigestUpdate(self.ctx, data.as_ptr() as *mut _, data.len()))); try!(cvt(ffi::EVP_DigestUpdate(
self.ctx,
data.as_ptr() as *mut _,
data.len(),
)));
} }
self.state = Updated; self.state = Updated;
Ok(()) Ok(())
@ -158,7 +162,11 @@ impl Hasher {
unsafe { unsafe {
let mut len = ffi::EVP_MAX_MD_SIZE; let mut len = ffi::EVP_MAX_MD_SIZE;
let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize]; let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize];
try!(cvt(ffi::EVP_DigestFinal_ex(self.ctx, buf.as_mut_ptr(), &mut len))); try!(cvt(ffi::EVP_DigestFinal_ex(
self.ctx,
buf.as_mut_ptr(),
&mut len,
)));
self.state = Finalized; self.state = Finalized;
Ok(DigestBytes { Ok(DigestBytes {
buf: buf, buf: buf,
@ -290,7 +298,8 @@ mod tests {
// Test vectors from http://www.nsrl.nist.gov/testdata/ // Test vectors from http://www.nsrl.nist.gov/testdata/
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
const md5_tests: [(&'static str, &'static str); 13] = const md5_tests: [(&'static str, &'static str); 13] =
[("", "d41d8cd98f00b204e9800998ecf8427e"), [
("", "d41d8cd98f00b204e9800998ecf8427e"),
("7F", "83acb6e67e50e31db6ed341dd2de1595"), ("7F", "83acb6e67e50e31db6ed341dd2de1595"),
("EC9C", "0b07f0d4ca797d8ac58874f887cb0b68"), ("EC9C", "0b07f0d4ca797d8ac58874f887cb0b68"),
("FEE57A", "e0d583171eb06d56198fc0ef22173907"), ("FEE57A", "e0d583171eb06d56198fc0ef22173907"),
@ -302,7 +311,11 @@ mod tests {
("C9FFDEE7788EFB4EC9", "e0841a231ab698db30c6c0f3f246c014"), ("C9FFDEE7788EFB4EC9", "e0841a231ab698db30c6c0f3f246c014"),
("66AC4B7EBA95E53DC10B", "a3b3cea71910d9af56742aa0bb2fe329"), ("66AC4B7EBA95E53DC10B", "a3b3cea71910d9af56742aa0bb2fe329"),
("A510CD18F7A56852EB0319", "577e216843dd11573574d3fb209b97d8"), ("A510CD18F7A56852EB0319", "577e216843dd11573574d3fb209b97d8"),
("AAED18DBE8938C19ED734A8D", "6f80fb775f27e0a4ce5c2f42fc72c5f1")]; (
"AAED18DBE8938C19ED734A8D",
"6f80fb775f27e0a4ce5c2f42fc72c5f1",
),
];
#[test] #[test]
fn test_md5() { fn test_md5() {
@ -322,7 +335,8 @@ mod tests {
#[test] #[test]
fn test_finish_twice() { fn test_finish_twice() {
let mut h = Hasher::new(MessageDigest::md5()).unwrap(); let mut h = Hasher::new(MessageDigest::md5()).unwrap();
h.write_all(&Vec::from_hex(md5_tests[6].0).unwrap()).unwrap(); h.write_all(&Vec::from_hex(md5_tests[6].0).unwrap())
.unwrap();
h.finish2().unwrap(); h.finish2().unwrap();
let res = h.finish2().unwrap(); let res = h.finish2().unwrap();
let null = hash2(MessageDigest::md5(), &[]).unwrap(); let null = hash2(MessageDigest::md5(), &[]).unwrap();
@ -353,7 +367,8 @@ mod tests {
println!("Clone a finished hasher"); println!("Clone a finished hasher");
let mut h3 = h1.clone(); let mut h3 = h1.clone();
h3.write_all(&Vec::from_hex(md5_tests[i + 1].0).unwrap()).unwrap(); h3.write_all(&Vec::from_hex(md5_tests[i + 1].0).unwrap())
.unwrap();
let res = h3.finish2().unwrap(); let res = h3.finish2().unwrap();
assert_eq!(res.to_hex(), md5_tests[i + 1].1); assert_eq!(res.to_hex(), md5_tests[i + 1].1);
} }
@ -369,8 +384,12 @@ mod tests {
#[test] #[test]
fn test_sha256() { fn test_sha256() {
let tests = [("616263", let tests = [
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")]; (
"616263",
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
),
];
for test in tests.iter() { for test in tests.iter() {
hash_test(MessageDigest::sha256(), test); hash_test(MessageDigest::sha256(), test);

View File

@ -13,9 +13,11 @@ use ffi;
pub fn eq(a: &[u8], b: &[u8]) -> bool { pub fn eq(a: &[u8], b: &[u8]) -> bool {
assert!(a.len() == b.len()); assert!(a.len() == b.len());
let ret = unsafe { let ret = unsafe {
ffi::CRYPTO_memcmp(a.as_ptr() as *const _, ffi::CRYPTO_memcmp(
a.as_ptr() as *const _,
b.as_ptr() as *const _, b.as_ptr() as *const _,
a.len() as size_t) a.len() as size_t,
)
}; };
ret == 0 ret == 0
} }

View File

@ -126,11 +126,12 @@ impl<'a> Status<'a> {
/// very old responses. /// very old responses.
pub fn check_validity(&self, nsec: u32, maxsec: Option<u32>) -> Result<(), ErrorStack> { pub fn check_validity(&self, nsec: u32, maxsec: Option<u32>) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::OCSP_check_validity(self.this_update.as_ptr(), cvt(ffi::OCSP_check_validity(
self.this_update.as_ptr(),
self.next_update.as_ptr(), self.next_update.as_ptr(),
nsec as c_long, nsec as c_long,
maxsec.map(|n| n as c_long).unwrap_or(-1))) maxsec.map(|n| n as c_long).unwrap_or(-1),
.map(|_| ()) )).map(|_| ())
} }
} }
} }
@ -148,14 +149,19 @@ impl OcspBasicResponseRef {
/// ///
/// The `certs` parameter contains a set of certificates that will be searched when locating the /// The `certs` parameter contains a set of certificates that will be searched when locating the
/// OCSP response signing certificate. Some responders do not include this in the response. /// OCSP response signing certificate. Some responders do not include this in the response.
pub fn verify(&self, pub fn verify(
&self,
certs: &StackRef<X509>, certs: &StackRef<X509>,
store: &X509StoreRef, store: &X509StoreRef,
flags: Flag) flags: Flag,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::OCSP_basic_verify(self.as_ptr(), certs.as_ptr(), store.as_ptr(), flags.bits())) cvt(ffi::OCSP_basic_verify(
.map(|_| ()) self.as_ptr(),
certs.as_ptr(),
store.as_ptr(),
flags.bits(),
)).map(|_| ())
} }
} }
@ -168,13 +174,15 @@ impl OcspBasicResponseRef {
let mut this_update = ptr::null_mut(); let mut this_update = ptr::null_mut();
let mut next_update = ptr::null_mut(); let mut next_update = ptr::null_mut();
let r = ffi::OCSP_resp_find_status(self.as_ptr(), let r = ffi::OCSP_resp_find_status(
self.as_ptr(),
id.as_ptr(), id.as_ptr(),
&mut status, &mut status,
&mut reason, &mut reason,
&mut revocation_time, &mut revocation_time,
&mut this_update, &mut this_update,
&mut next_update); &mut next_update,
);
if r == 1 { if r == 1 {
let revocation_time = if revocation_time.is_null() { let revocation_time = if revocation_time.is_null() {
None None
@ -205,13 +213,17 @@ foreign_type! {
impl OcspCertId { impl OcspCertId {
/// Constructs a certificate ID for certificate `subject`. /// Constructs a certificate ID for certificate `subject`.
pub fn from_cert(digest: MessageDigest, pub fn from_cert(
digest: MessageDigest,
subject: &X509Ref, subject: &X509Ref,
issuer: &X509Ref) issuer: &X509Ref,
-> Result<OcspCertId, ErrorStack> { ) -> Result<OcspCertId, ErrorStack> {
unsafe { unsafe {
cvt_p(ffi::OCSP_cert_to_id(digest.as_ptr(), subject.as_ptr(), issuer.as_ptr())) cvt_p(ffi::OCSP_cert_to_id(
.map(OcspCertId) digest.as_ptr(),
subject.as_ptr(),
issuer.as_ptr(),
)).map(OcspCertId)
} }
} }
} }
@ -228,15 +240,17 @@ impl OcspResponse {
/// Creates an OCSP response from the status and optional body. /// Creates an OCSP response from the status and optional body.
/// ///
/// A body should only be provided if `status` is `RESPONSE_STATUS_SUCCESSFUL`. /// A body should only be provided if `status` is `RESPONSE_STATUS_SUCCESSFUL`.
pub fn create(status: OcspResponseStatus, pub fn create(
body: Option<&OcspBasicResponseRef>) status: OcspResponseStatus,
-> Result<OcspResponse, ErrorStack> { body: Option<&OcspBasicResponseRef>,
) -> Result<OcspResponse, ErrorStack> {
unsafe { unsafe {
ffi::init(); ffi::init();
cvt_p(ffi::OCSP_response_create(status.as_raw(), cvt_p(ffi::OCSP_response_create(
body.map(|r| r.as_ptr()).unwrap_or(ptr::null_mut()))) status.as_raw(),
.map(OcspResponse) body.map(|r| r.as_ptr()).unwrap_or(ptr::null_mut()),
)).map(OcspResponse)
} }
} }
@ -248,18 +262,14 @@ impl OcspResponseRef {
/// Returns the status of the response. /// Returns the status of the response.
pub fn status(&self) -> OcspResponseStatus { pub fn status(&self) -> OcspResponseStatus {
unsafe { unsafe { OcspResponseStatus(ffi::OCSP_response_status(self.as_ptr())) }
OcspResponseStatus(ffi::OCSP_response_status(self.as_ptr()))
}
} }
/// Returns the basic response. /// Returns the basic response.
/// ///
/// This will only succeed if `status()` returns `RESPONSE_STATUS_SUCCESSFUL`. /// This will only succeed if `status()` returns `RESPONSE_STATUS_SUCCESSFUL`.
pub fn basic(&self) -> Result<OcspBasicResponse, ErrorStack> { pub fn basic(&self) -> Result<OcspBasicResponse, ErrorStack> {
unsafe { unsafe { cvt_p(ffi::OCSP_response_get1_basic(self.as_ptr())).map(OcspBasicResponse) }
cvt_p(ffi::OCSP_response_get1_basic(self.as_ptr())).map(OcspBasicResponse)
}
} }
} }

View File

@ -34,11 +34,13 @@ impl Pkcs12Ref {
let mut cert = ptr::null_mut(); let mut cert = ptr::null_mut();
let mut chain = ptr::null_mut(); let mut chain = ptr::null_mut();
try!(cvt(ffi::PKCS12_parse(self.as_ptr(), try!(cvt(ffi::PKCS12_parse(
self.as_ptr(),
pass.as_ptr(), pass.as_ptr(),
&mut pkey, &mut pkey,
&mut cert, &mut cert,
&mut chain))); &mut chain,
)));
let pkey = PKey::from_ptr(pkey); let pkey = PKey::from_ptr(pkey);
let cert = X509::from_ptr(cert); let cert = X509::from_ptr(cert);
@ -140,17 +142,21 @@ impl Pkcs12Builder {
/// * `friendly_name` - user defined name for the certificate /// * `friendly_name` - user defined name for the certificate
/// * `pkey` - key to store /// * `pkey` - key to store
/// * `cert` - certificate to store /// * `cert` - certificate to store
pub fn build(self, pub fn build(
self,
password: &str, password: &str,
friendly_name: &str, friendly_name: &str,
pkey: &PKeyRef, pkey: &PKeyRef,
cert: &X509) -> Result<Pkcs12, ErrorStack> { cert: &X509,
) -> Result<Pkcs12, ErrorStack> {
unsafe { unsafe {
let pass = CString::new(password).unwrap(); let pass = CString::new(password).unwrap();
let friendly_name = CString::new(friendly_name).unwrap(); let friendly_name = CString::new(friendly_name).unwrap();
let pkey = pkey.as_ptr(); let pkey = pkey.as_ptr();
let cert = cert.as_ptr(); let cert = cert.as_ptr();
let ca = self.ca.as_ref().map(|ca| ca.as_ptr()).unwrap_or(ptr::null_mut()); let ca = self.ca.as_ref().map(|ca| ca.as_ptr()).unwrap_or(
ptr::null_mut(),
);
let nid_key = self.nid_key.as_raw(); let nid_key = self.nid_key.as_raw();
let nid_cert = self.nid_cert.as_raw(); let nid_cert = self.nid_cert.as_raw();
@ -159,7 +165,8 @@ impl Pkcs12Builder {
// https://www.openssl.org/docs/man1.0.2/crypto/PKCS12_create.html // https://www.openssl.org/docs/man1.0.2/crypto/PKCS12_create.html
let keytype = 0; let keytype = 0;
cvt_p(ffi::PKCS12_create(pass.as_ptr() as *const _ as *mut _, cvt_p(ffi::PKCS12_create(
pass.as_ptr() as *const _ as *mut _,
friendly_name.as_ptr() as *const _ as *mut _, friendly_name.as_ptr() as *const _ as *mut _,
pkey, pkey,
cert, cert,
@ -168,8 +175,8 @@ impl Pkcs12Builder {
nid_cert, nid_cert,
self.iter, self.iter,
self.mac_iter, self.mac_iter,
keytype)) keytype,
.map(Pkcs12) )).map(Pkcs12)
} }
} }
} }
@ -194,12 +201,23 @@ mod test {
let pkcs12 = Pkcs12::from_der(der).unwrap(); let pkcs12 = Pkcs12::from_der(der).unwrap();
let parsed = pkcs12.parse("mypass").unwrap(); let parsed = pkcs12.parse("mypass").unwrap();
assert_eq!(parsed.cert.fingerprint(MessageDigest::sha1()).unwrap().to_hex(), assert_eq!(
"59172d9313e84459bcff27f967e79e6e9217e584"); parsed
.cert
.fingerprint(MessageDigest::sha1())
.unwrap()
.to_hex(),
"59172d9313e84459bcff27f967e79e6e9217e584"
);
assert_eq!(parsed.chain.len(), 1); assert_eq!(parsed.chain.len(), 1);
assert_eq!(parsed.chain[0].fingerprint(MessageDigest::sha1()).unwrap().to_hex(), assert_eq!(
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"); parsed.chain[0]
.fingerprint(MessageDigest::sha1())
.unwrap()
.to_hex(),
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
);
} }
#[test] #[test]
@ -219,15 +237,20 @@ mod test {
let pkey = PKey::from_rsa(rsa).unwrap(); let pkey = PKey::from_rsa(rsa).unwrap();
let mut name = X509Name::builder().unwrap(); let mut name = X509Name::builder().unwrap();
name.append_entry_by_nid(nid::COMMONNAME, subject_name).unwrap(); name.append_entry_by_nid(nid::COMMONNAME, subject_name)
.unwrap();
let name = name.build(); let name = name.build();
let key_usage = KeyUsage::new().digital_signature().build().unwrap();; let key_usage = KeyUsage::new().digital_signature().build().unwrap();
let mut builder = X509::builder().unwrap(); let mut builder = X509::builder().unwrap();
builder.set_version(2).unwrap(); builder.set_version(2).unwrap();
builder.set_not_before(&Asn1Time::days_from_now(0).unwrap()).unwrap(); builder
builder.set_not_after(&Asn1Time::days_from_now(365).unwrap()).unwrap(); .set_not_before(&Asn1Time::days_from_now(0).unwrap())
.unwrap();
builder
.set_not_after(&Asn1Time::days_from_now(365).unwrap())
.unwrap();
builder.set_subject_name(&name).unwrap(); builder.set_subject_name(&name).unwrap();
builder.set_issuer_name(&name).unwrap(); builder.set_issuer_name(&name).unwrap();
builder.append_extension(key_usage).unwrap(); builder.append_extension(key_usage).unwrap();
@ -236,13 +259,18 @@ mod test {
let cert = builder.build(); let cert = builder.build();
let pkcs12_builder = Pkcs12::builder(); let pkcs12_builder = Pkcs12::builder();
let pkcs12 = pkcs12_builder.build("mypass", subject_name, &pkey, &cert).unwrap(); let pkcs12 = pkcs12_builder
.build("mypass", subject_name, &pkey, &cert)
.unwrap();
let der = pkcs12.to_der().unwrap(); let der = pkcs12.to_der().unwrap();
let pkcs12 = Pkcs12::from_der(&der).unwrap(); let pkcs12 = Pkcs12::from_der(&der).unwrap();
let parsed = pkcs12.parse("mypass").unwrap(); let parsed = pkcs12.parse("mypass").unwrap();
assert_eq!(parsed.cert.fingerprint(MessageDigest::sha1()).unwrap(), cert.fingerprint(MessageDigest::sha1()).unwrap()); assert_eq!(
parsed.cert.fingerprint(MessageDigest::sha1()).unwrap(),
cert.fingerprint(MessageDigest::sha1()).unwrap()
);
assert!(parsed.pkey.public_eq(&pkey)); assert!(parsed.pkey.public_eq(&pkey));
} }
} }

View File

@ -23,12 +23,13 @@ pub struct KeyIvPair {
/// ///
/// New applications should not use this and instead use /// New applications should not use this and instead use
/// `pbkdf2_hmac` or another more modern key derivation algorithm. /// `pbkdf2_hmac` or another more modern key derivation algorithm.
pub fn bytes_to_key(cipher: Cipher, pub fn bytes_to_key(
cipher: Cipher,
digest: MessageDigest, digest: MessageDigest,
data: &[u8], data: &[u8],
salt: Option<&[u8]>, salt: Option<&[u8]>,
count: i32) count: i32,
-> Result<KeyIvPair, ErrorStack> { ) -> Result<KeyIvPair, ErrorStack> {
unsafe { unsafe {
assert!(data.len() <= c_int::max_value() as usize); assert!(data.len() <= c_int::max_value() as usize);
let salt_ptr = match salt { let salt_ptr = match salt {
@ -46,53 +47,61 @@ pub fn bytes_to_key(cipher: Cipher,
let cipher = cipher.as_ptr(); let cipher = cipher.as_ptr();
let digest = digest.as_ptr(); let digest = digest.as_ptr();
let len = try!(cvt(ffi::EVP_BytesToKey(cipher, let len = try!(cvt(ffi::EVP_BytesToKey(
cipher,
digest, digest,
salt_ptr, salt_ptr,
ptr::null(), ptr::null(),
data.len() as c_int, data.len() as c_int,
count.into(), count.into(),
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut()))); ptr::null_mut(),
)));
let mut key = vec![0; len as usize]; let mut key = vec![0; len as usize];
let iv_ptr = iv.as_mut().map(|v| v.as_mut_ptr()).unwrap_or(ptr::null_mut()); let iv_ptr = iv.as_mut().map(|v| v.as_mut_ptr()).unwrap_or(
ptr::null_mut(),
);
try!(cvt(ffi::EVP_BytesToKey(cipher, try!(cvt(ffi::EVP_BytesToKey(
cipher,
digest, digest,
salt_ptr, salt_ptr,
data.as_ptr(), data.as_ptr(),
data.len() as c_int, data.len() as c_int,
count as c_int, count as c_int,
key.as_mut_ptr(), key.as_mut_ptr(),
iv_ptr))); iv_ptr,
)));
Ok(KeyIvPair { key: key, iv: iv }) Ok(KeyIvPair { key: key, iv: iv })
} }
} }
/// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function. /// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function.
pub fn pbkdf2_hmac(pass: &[u8], pub fn pbkdf2_hmac(
pass: &[u8],
salt: &[u8], salt: &[u8],
iter: usize, iter: usize,
hash: MessageDigest, hash: MessageDigest,
key: &mut [u8]) key: &mut [u8],
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
assert!(pass.len() <= c_int::max_value() as usize); assert!(pass.len() <= c_int::max_value() as usize);
assert!(salt.len() <= c_int::max_value() as usize); assert!(salt.len() <= c_int::max_value() as usize);
assert!(key.len() <= c_int::max_value() as usize); assert!(key.len() <= c_int::max_value() as usize);
ffi::init(); ffi::init();
cvt(ffi::PKCS5_PBKDF2_HMAC(pass.as_ptr() as *const _, cvt(ffi::PKCS5_PBKDF2_HMAC(
pass.as_ptr() as *const _,
pass.len() as c_int, pass.len() as c_int,
salt.as_ptr(), salt.as_ptr(),
salt.len() as c_int, salt.len() as c_int,
iter as c_int, iter as c_int,
hash.as_ptr(), hash.as_ptr(),
key.len() as c_int, key.len() as c_int,
key.as_mut_ptr())) key.as_mut_ptr(),
.map(|_| ()) )).map(|_| ())
} }
} }
@ -100,17 +109,19 @@ pub fn pbkdf2_hmac(pass: &[u8],
/// ///
/// Requires the `v110` feature and OpenSSL 1.1.0. /// Requires the `v110` feature and OpenSSL 1.1.0.
#[cfg(all(feature = "v110", ossl110))] #[cfg(all(feature = "v110", ossl110))]
pub fn scrypt(pass: &[u8], pub fn scrypt(
pass: &[u8],
salt: &[u8], salt: &[u8],
n: u64, n: u64,
r: u64, r: u64,
p: u64, p: u64,
maxmem: u64, maxmem: u64,
key: &mut [u8]) key: &mut [u8],
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
unsafe { unsafe {
ffi::init(); ffi::init();
cvt(ffi::EVP_PBE_scrypt(pass.as_ptr() as *const _, cvt(ffi::EVP_PBE_scrypt(
pass.as_ptr() as *const _,
pass.len(), pass.len(),
salt.as_ptr() as *const _, salt.as_ptr() as *const _,
salt.len(), salt.len(),
@ -119,8 +130,8 @@ pub fn scrypt(pass: &[u8],
p, p,
maxmem, maxmem,
key.as_mut_ptr() as *mut _, key.as_mut_ptr() as *mut _,
key.len())) key.len(),
.map(|_| ()) )).map(|_| ())
} }
} }
@ -136,21 +147,58 @@ mod tests {
let mut buf = [0; 16]; let mut buf = [0; 16];
super::pbkdf2_hmac(b"passwd", b"salt", 1, MessageDigest::sha256(), &mut buf).unwrap(); super::pbkdf2_hmac(b"passwd", b"salt", 1, MessageDigest::sha256(), &mut buf).unwrap();
assert_eq!(buf, assert_eq!(
&[0x55_u8, 0xac_u8, 0x04_u8, 0x6e_u8, 0x56_u8, 0xe3_u8, 0x08_u8, 0x9f_u8, buf,
0xec_u8, 0x16_u8, 0x91_u8, 0xc2_u8, 0x25_u8, 0x44_u8, 0xb6_u8, 0x05_u8] &[
[..]); 0x55_u8,
0xac_u8,
0x04_u8,
0x6e_u8,
0x56_u8,
0xe3_u8,
0x08_u8,
0x9f_u8,
0xec_u8,
0x16_u8,
0x91_u8,
0xc2_u8,
0x25_u8,
0x44_u8,
0xb6_u8,
0x05_u8,
]
[..]
);
super::pbkdf2_hmac(b"Password", super::pbkdf2_hmac(
b"Password",
b"NaCl", b"NaCl",
80000, 80000,
MessageDigest::sha256(), MessageDigest::sha256(),
&mut buf) &mut buf,
.unwrap(); ).unwrap();
assert_eq!(buf, assert_eq!(
&[0x4d_u8, 0xdc_u8, 0xd8_u8, 0xf6_u8, 0x0b_u8, 0x98_u8, 0xbe_u8, 0x21_u8, buf,
0x83_u8, 0x0c_u8, 0xee_u8, 0x5e_u8, 0xf2_u8, 0x27_u8, 0x01_u8, 0xf9_u8] &[
[..]); 0x4d_u8,
0xdc_u8,
0xd8_u8,
0xf6_u8,
0x0b_u8,
0x98_u8,
0xbe_u8,
0x21_u8,
0x83_u8,
0x0c_u8,
0xee_u8,
0x5e_u8,
0xf2_u8,
0x27_u8,
0x01_u8,
0xf9_u8,
]
[..]
);
} }
// Test vectors from // Test vectors from
@ -160,80 +208,341 @@ mod tests {
let mut buf = [0; 64]; let mut buf = [0; 64];
super::pbkdf2_hmac(b"password", b"NaCL", 1, MessageDigest::sha512(), &mut buf).unwrap(); super::pbkdf2_hmac(b"password", b"NaCL", 1, MessageDigest::sha512(), &mut buf).unwrap();
assert_eq!(&buf[..], assert_eq!(
&[0x73_u8, 0xde_u8, 0xcf_u8, 0xa5_u8, 0x8a_u8, 0xa2_u8, 0xe8_u8, 0x4f_u8, &buf[..],
0x94_u8, 0x77_u8, 0x1a_u8, 0x75_u8, 0x73_u8, 0x6b_u8, 0xb8_u8, 0x8b_u8, &[
0xd3_u8, 0xc7_u8, 0xb3_u8, 0x82_u8, 0x70_u8, 0xcf_u8, 0xb5_u8, 0x0c_u8, 0x73_u8,
0xb3_u8, 0x90_u8, 0xed_u8, 0x78_u8, 0xb3_u8, 0x05_u8, 0x65_u8, 0x6a_u8, 0xde_u8,
0xf8_u8, 0x14_u8, 0x8e_u8, 0x52_u8, 0x45_u8, 0x2b_u8, 0x22_u8, 0x16_u8, 0xcf_u8,
0xb2_u8, 0xb8_u8, 0x09_u8, 0x8b_u8, 0x76_u8, 0x1f_u8, 0xc6_u8, 0x33_u8, 0xa5_u8,
0x60_u8, 0x60_u8, 0xa0_u8, 0x9f_u8, 0x76_u8, 0x41_u8, 0x5e_u8, 0x9f_u8, 0x8a_u8,
0x71_u8, 0xea_u8, 0x47_u8, 0xf9_u8, 0xe9_u8, 0x06_u8, 0x43_u8, 0x06_u8] 0xa2_u8,
[..]); 0xe8_u8,
0x4f_u8,
0x94_u8,
0x77_u8,
0x1a_u8,
0x75_u8,
0x73_u8,
0x6b_u8,
0xb8_u8,
0x8b_u8,
0xd3_u8,
0xc7_u8,
0xb3_u8,
0x82_u8,
0x70_u8,
0xcf_u8,
0xb5_u8,
0x0c_u8,
0xb3_u8,
0x90_u8,
0xed_u8,
0x78_u8,
0xb3_u8,
0x05_u8,
0x65_u8,
0x6a_u8,
0xf8_u8,
0x14_u8,
0x8e_u8,
0x52_u8,
0x45_u8,
0x2b_u8,
0x22_u8,
0x16_u8,
0xb2_u8,
0xb8_u8,
0x09_u8,
0x8b_u8,
0x76_u8,
0x1f_u8,
0xc6_u8,
0x33_u8,
0x60_u8,
0x60_u8,
0xa0_u8,
0x9f_u8,
0x76_u8,
0x41_u8,
0x5e_u8,
0x9f_u8,
0x71_u8,
0xea_u8,
0x47_u8,
0xf9_u8,
0xe9_u8,
0x06_u8,
0x43_u8,
0x06_u8,
]
[..]
);
super::pbkdf2_hmac(b"pass\0word", super::pbkdf2_hmac(
b"pass\0word",
b"sa\0lt", b"sa\0lt",
1, 1,
MessageDigest::sha512(), MessageDigest::sha512(),
&mut buf) &mut buf,
.unwrap(); ).unwrap();
assert_eq!(&buf[..], assert_eq!(
&[0x71_u8, 0xa0_u8, 0xec_u8, 0x84_u8, 0x2a_u8, 0xbd_u8, 0x5c_u8, 0x67_u8, &buf[..],
0x8b_u8, 0xcf_u8, 0xd1_u8, 0x45_u8, 0xf0_u8, 0x9d_u8, 0x83_u8, 0x52_u8, &[
0x2f_u8, 0x93_u8, 0x36_u8, 0x15_u8, 0x60_u8, 0x56_u8, 0x3c_u8, 0x4d_u8, 0x71_u8,
0x0d_u8, 0x63_u8, 0xb8_u8, 0x83_u8, 0x29_u8, 0x87_u8, 0x10_u8, 0x90_u8, 0xa0_u8,
0xe7_u8, 0x66_u8, 0x04_u8, 0xa4_u8, 0x9a_u8, 0xf0_u8, 0x8f_u8, 0xe7_u8, 0xec_u8,
0xc9_u8, 0xf5_u8, 0x71_u8, 0x56_u8, 0xc8_u8, 0x79_u8, 0x09_u8, 0x96_u8, 0x84_u8,
0xb2_u8, 0x0f_u8, 0x06_u8, 0xbc_u8, 0x53_u8, 0x5e_u8, 0x5a_u8, 0xb5_u8, 0x2a_u8,
0x44_u8, 0x0d_u8, 0xf7_u8, 0xe8_u8, 0x78_u8, 0x29_u8, 0x6f_u8, 0xa7_u8] 0xbd_u8,
[..]); 0x5c_u8,
0x67_u8,
0x8b_u8,
0xcf_u8,
0xd1_u8,
0x45_u8,
0xf0_u8,
0x9d_u8,
0x83_u8,
0x52_u8,
0x2f_u8,
0x93_u8,
0x36_u8,
0x15_u8,
0x60_u8,
0x56_u8,
0x3c_u8,
0x4d_u8,
0x0d_u8,
0x63_u8,
0xb8_u8,
0x83_u8,
0x29_u8,
0x87_u8,
0x10_u8,
0x90_u8,
0xe7_u8,
0x66_u8,
0x04_u8,
0xa4_u8,
0x9a_u8,
0xf0_u8,
0x8f_u8,
0xe7_u8,
0xc9_u8,
0xf5_u8,
0x71_u8,
0x56_u8,
0xc8_u8,
0x79_u8,
0x09_u8,
0x96_u8,
0xb2_u8,
0x0f_u8,
0x06_u8,
0xbc_u8,
0x53_u8,
0x5e_u8,
0x5a_u8,
0xb5_u8,
0x44_u8,
0x0d_u8,
0xf7_u8,
0xe8_u8,
0x78_u8,
0x29_u8,
0x6f_u8,
0xa7_u8,
]
[..]
);
super::pbkdf2_hmac(b"passwordPASSWORDpassword", super::pbkdf2_hmac(
b"passwordPASSWORDpassword",
b"salt\0\0\0", b"salt\0\0\0",
50, 50,
MessageDigest::sha512(), MessageDigest::sha512(),
&mut buf) &mut buf,
.unwrap(); ).unwrap();
assert_eq!(&buf[..], assert_eq!(
&[0x01_u8, 0x68_u8, 0x71_u8, 0xa4_u8, 0xc4_u8, 0xb7_u8, 0x5f_u8, 0x96_u8, &buf[..],
0x85_u8, 0x7f_u8, 0xd2_u8, 0xb9_u8, 0xf8_u8, 0xca_u8, 0x28_u8, 0x02_u8, &[
0x3b_u8, 0x30_u8, 0xee_u8, 0x2a_u8, 0x39_u8, 0xf5_u8, 0xad_u8, 0xca_u8, 0x01_u8,
0xc8_u8, 0xc9_u8, 0x37_u8, 0x5f_u8, 0x9b_u8, 0xda_u8, 0x1c_u8, 0xcd_u8, 0x68_u8,
0x1b_u8, 0x6f_u8, 0x0b_u8, 0x2f_u8, 0xc3_u8, 0xad_u8, 0xda_u8, 0x50_u8, 0x71_u8,
0x54_u8, 0x12_u8, 0xe7_u8, 0x9d_u8, 0x89_u8, 0x00_u8, 0x56_u8, 0xc6_u8, 0xa4_u8,
0x2e_u8, 0x52_u8, 0x4c_u8, 0x7d_u8, 0x51_u8, 0x15_u8, 0x4b_u8, 0x1a_u8, 0xc4_u8,
0x85_u8, 0x34_u8, 0x57_u8, 0x5b_u8, 0xd0_u8, 0x2d_u8, 0xee_u8, 0x39_u8] 0xb7_u8,
[..]); 0x5f_u8,
0x96_u8,
0x85_u8,
0x7f_u8,
0xd2_u8,
0xb9_u8,
0xf8_u8,
0xca_u8,
0x28_u8,
0x02_u8,
0x3b_u8,
0x30_u8,
0xee_u8,
0x2a_u8,
0x39_u8,
0xf5_u8,
0xad_u8,
0xca_u8,
0xc8_u8,
0xc9_u8,
0x37_u8,
0x5f_u8,
0x9b_u8,
0xda_u8,
0x1c_u8,
0xcd_u8,
0x1b_u8,
0x6f_u8,
0x0b_u8,
0x2f_u8,
0xc3_u8,
0xad_u8,
0xda_u8,
0x50_u8,
0x54_u8,
0x12_u8,
0xe7_u8,
0x9d_u8,
0x89_u8,
0x00_u8,
0x56_u8,
0xc6_u8,
0x2e_u8,
0x52_u8,
0x4c_u8,
0x7d_u8,
0x51_u8,
0x15_u8,
0x4b_u8,
0x1a_u8,
0x85_u8,
0x34_u8,
0x57_u8,
0x5b_u8,
0xd0_u8,
0x2d_u8,
0xee_u8,
0x39_u8,
]
[..]
);
} }
#[test] #[test]
fn bytes_to_key() { fn bytes_to_key() {
let salt = [16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8]; let salt = [16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8];
let data = [143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, let data = [
154_u8, 56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, 143_u8,
55_u8, 119_u8, 233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, 210_u8,
65_u8, 207_u8]; 75_u8,
63_u8,
214_u8,
179_u8,
155_u8,
241_u8,
242_u8,
31_u8,
154_u8,
56_u8,
198_u8,
145_u8,
192_u8,
64_u8,
2_u8,
245_u8,
167_u8,
220_u8,
55_u8,
119_u8,
233_u8,
136_u8,
139_u8,
27_u8,
71_u8,
242_u8,
119_u8,
175_u8,
65_u8,
207_u8,
];
let expected_key = vec![249_u8, 115_u8, 114_u8, 97_u8, 32_u8, 213_u8, 165_u8, 146_u8, let expected_key = vec![
58_u8, 87_u8, 234_u8, 3_u8, 43_u8, 250_u8, 97_u8, 114_u8, 26_u8, 249_u8,
98_u8, 245_u8, 246_u8, 238_u8, 177_u8, 229_u8, 161_u8, 183_u8, 115_u8,
224_u8, 174_u8, 3_u8, 6_u8, 244_u8, 236_u8, 255_u8]; 114_u8,
let expected_iv = vec![4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, 97_u8,
69_u8, 98_u8, 107_u8, 208_u8, 14_u8, 236_u8, 60_u8]; 32_u8,
213_u8,
165_u8,
146_u8,
58_u8,
87_u8,
234_u8,
3_u8,
43_u8,
250_u8,
97_u8,
114_u8,
26_u8,
98_u8,
245_u8,
246_u8,
238_u8,
177_u8,
229_u8,
161_u8,
183_u8,
224_u8,
174_u8,
3_u8,
6_u8,
244_u8,
236_u8,
255_u8,
];
let expected_iv = vec![
4_u8,
223_u8,
153_u8,
219_u8,
28_u8,
142_u8,
234_u8,
68_u8,
227_u8,
69_u8,
98_u8,
107_u8,
208_u8,
14_u8,
236_u8,
60_u8,
];
assert_eq!(super::bytes_to_key(Cipher::aes_256_cbc(), assert_eq!(
super::bytes_to_key(
Cipher::aes_256_cbc(),
MessageDigest::sha1(), MessageDigest::sha1(),
&data, &data,
Some(&salt), Some(&salt),
1) 1,
.unwrap(), ).unwrap(),
super::KeyIvPair { super::KeyIvPair {
key: expected_key, key: expected_key,
iv: Some(expected_iv), iv: Some(expected_iv),
}); }
);
} }
#[test] #[test]
@ -247,7 +556,15 @@ mod tests {
f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887"; f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887";
let mut actual = [0; 64]; let mut actual = [0; 64];
super::scrypt(pass.as_bytes(), salt.as_bytes(), 16384, 8, 1, 0, &mut actual).unwrap(); super::scrypt(
pass.as_bytes(),
salt.as_bytes(),
16384,
8,
1,
0,
&mut actual,
).unwrap();
assert_eq!((&actual[..]).to_hex(), expected); assert_eq!((&actual[..]).to_hex(), expected);
} }
} }

View File

@ -84,7 +84,11 @@ impl PKey {
unsafe { unsafe {
let evp = try!(cvt_p(ffi::EVP_PKEY_new())); let evp = try!(cvt_p(ffi::EVP_PKEY_new()));
let pkey = PKey(evp); let pkey = PKey(evp);
try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_RSA, rsa.as_ptr() as *mut _))); try!(cvt(ffi::EVP_PKEY_assign(
pkey.0,
ffi::EVP_PKEY_RSA,
rsa.as_ptr() as *mut _,
)));
mem::forget(rsa); mem::forget(rsa);
Ok(pkey) Ok(pkey)
} }
@ -95,7 +99,11 @@ impl PKey {
unsafe { unsafe {
let evp = try!(cvt_p(ffi::EVP_PKEY_new())); let evp = try!(cvt_p(ffi::EVP_PKEY_new()));
let pkey = PKey(evp); let pkey = PKey(evp);
try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_DSA, dsa.as_ptr() as *mut _))); try!(cvt(ffi::EVP_PKEY_assign(
pkey.0,
ffi::EVP_PKEY_DSA,
dsa.as_ptr() as *mut _,
)));
mem::forget(dsa); mem::forget(dsa);
Ok(pkey) Ok(pkey)
} }
@ -106,7 +114,11 @@ impl PKey {
unsafe { unsafe {
let evp = try!(cvt_p(ffi::EVP_PKEY_new())); let evp = try!(cvt_p(ffi::EVP_PKEY_new()));
let pkey = PKey(evp); let pkey = PKey(evp);
try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_DH, dh.as_ptr() as *mut _))); try!(cvt(ffi::EVP_PKEY_assign(
pkey.0,
ffi::EVP_PKEY_DH,
dh.as_ptr() as *mut _,
)));
mem::forget(dh); mem::forget(dh);
Ok(pkey) Ok(pkey)
} }
@ -117,7 +129,11 @@ impl PKey {
unsafe { unsafe {
let evp = try!(cvt_p(ffi::EVP_PKEY_new())); let evp = try!(cvt_p(ffi::EVP_PKEY_new()));
let pkey = PKey(evp); let pkey = PKey(evp);
try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_EC, ec_key.as_ptr() as *mut _))); try!(cvt(ffi::EVP_PKEY_assign(
pkey.0,
ffi::EVP_PKEY_EC,
ec_key.as_ptr() as *mut _,
)));
mem::forget(ec_key); mem::forget(ec_key);
Ok(pkey) Ok(pkey)
} }
@ -130,10 +146,12 @@ impl PKey {
pub fn hmac(key: &[u8]) -> Result<PKey, ErrorStack> { pub fn hmac(key: &[u8]) -> Result<PKey, ErrorStack> {
unsafe { unsafe {
assert!(key.len() <= c_int::max_value() as usize); assert!(key.len() <= c_int::max_value() as usize);
let key = try!(cvt_p(ffi::EVP_PKEY_new_mac_key(ffi::EVP_PKEY_HMAC, let key = try!(cvt_p(ffi::EVP_PKEY_new_mac_key(
ffi::EVP_PKEY_HMAC,
ptr::null_mut(), ptr::null_mut(),
key.as_ptr() as *const _, key.as_ptr() as *const _,
key.len() as c_int))); key.len() as c_int,
)));
Ok(PKey(key)) Ok(PKey(key))
} }
} }
@ -149,17 +167,19 @@ impl PKey {
/// The callback should copy the password into the provided buffer and return the number of /// The callback should copy the password into the provided buffer and return the number of
/// bytes written. /// bytes written.
pub fn private_key_from_pkcs8_callback<F>(der: &[u8], callback: F) -> Result<PKey, ErrorStack> pub fn private_key_from_pkcs8_callback<F>(der: &[u8], callback: F) -> Result<PKey, ErrorStack>
where F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack> where
F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
{ {
unsafe { unsafe {
ffi::init(); ffi::init();
let mut cb = CallbackState::new(callback); let mut cb = CallbackState::new(callback);
let bio = try!(MemBioSlice::new(der)); let bio = try!(MemBioSlice::new(der));
cvt_p(ffi::d2i_PKCS8PrivateKey_bio(bio.as_ptr(), cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
bio.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
Some(invoke_passwd_cb::<F>), Some(invoke_passwd_cb::<F>),
&mut cb as *mut _ as *mut _)) &mut cb as *mut _ as *mut _,
.map(PKey) )).map(PKey)
} }
} }
@ -169,33 +189,38 @@ impl PKey {
/// # Panics /// # Panics
/// ///
/// Panics if `passphrase` contains an embedded null. /// Panics if `passphrase` contains an embedded null.
pub fn private_key_from_pkcs8_passphrase(der: &[u8], pub fn private_key_from_pkcs8_passphrase(
passphrase: &[u8]) der: &[u8],
-> Result<PKey, ErrorStack> { passphrase: &[u8],
) -> Result<PKey, ErrorStack> {
unsafe { unsafe {
ffi::init(); ffi::init();
let bio = try!(MemBioSlice::new(der)); let bio = try!(MemBioSlice::new(der));
let passphrase = CString::new(passphrase).unwrap(); let passphrase = CString::new(passphrase).unwrap();
cvt_p(ffi::d2i_PKCS8PrivateKey_bio(bio.as_ptr(), cvt_p(ffi::d2i_PKCS8PrivateKey_bio(
bio.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
None, None,
passphrase.as_ptr() as *const _ as *mut _)) passphrase.as_ptr() as *const _ as *mut _,
.map(PKey) )).map(PKey)
} }
} }
#[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")] #[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")]
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<PKey, ErrorStack> pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<PKey, ErrorStack>
where F: FnOnce(&mut [c_char]) -> usize where
F: FnOnce(&mut [c_char]) -> usize,
{ {
ffi::init(); ffi::init();
let mut cb = CallbackState::new(pass_cb); let mut cb = CallbackState::new(pass_cb);
let mem_bio = try!(MemBioSlice::new(buf)); let mem_bio = try!(MemBioSlice::new(buf));
unsafe { unsafe {
let evp = try!(cvt_p(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(), let evp = try!(cvt_p(ffi::PEM_read_bio_PrivateKey(
mem_bio.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
Some(invoke_passwd_cb_old::<F>), Some(invoke_passwd_cb_old::<F>),
&mut cb as *mut _ as *mut c_void))); &mut cb as *mut _ as *mut c_void,
)));
Ok(PKey::from_ptr(evp)) Ok(PKey::from_ptr(evp))
} }
} }
@ -224,7 +249,10 @@ impl PKeyCtx {
impl PKeyCtxRef { impl PKeyCtxRef {
pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> { pub fn set_rsa_padding(&mut self, pad: Padding) -> Result<(), ErrorStack> {
unsafe { unsafe {
try!(cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(self.as_ptr(), pad.as_raw()))); try!(cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
self.as_ptr(),
pad.as_raw(),
)));
} }
Ok(()) Ok(())
} }
@ -232,7 +260,9 @@ impl PKeyCtxRef {
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
let mut pad: c_int = 0; let mut pad: c_int = 0;
unsafe { unsafe {
try!(cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))); try!(cvt(
ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad),
));
}; };
Ok(Padding::from_raw(pad)) Ok(Padding::from_raw(pad))
} }
@ -246,17 +276,31 @@ impl PKeyCtxRef {
pub fn derive_set_peer(&mut self, peer: &PKeyRef) -> Result<(), ErrorStack> { pub fn derive_set_peer(&mut self, peer: &PKeyRef) -> Result<(), ErrorStack> {
unsafe { unsafe {
try!(cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), peer.as_ptr()))); try!(cvt(
ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), peer.as_ptr()),
));
} }
Ok(()) Ok(())
} }
pub fn derive(&mut self) -> Result<Vec<u8>, ErrorStack> { pub fn derive(&mut self) -> Result<Vec<u8>, ErrorStack> {
let mut len: size_t = 0; let mut len: size_t = 0;
unsafe { try!(cvt(ffi::EVP_PKEY_derive(self.as_ptr(), ptr::null_mut(), &mut len))); } unsafe {
try!(cvt(ffi::EVP_PKEY_derive(
self.as_ptr(),
ptr::null_mut(),
&mut len,
)));
}
let mut key = vec![0u8; len]; let mut key = vec![0u8; len];
unsafe { try!(cvt(ffi::EVP_PKEY_derive(self.as_ptr(), key.as_mut_ptr(), &mut len))); } unsafe {
try!(cvt(ffi::EVP_PKEY_derive(
self.as_ptr(),
key.as_mut_ptr(),
&mut len,
)));
}
Ok(key) Ok(key)
} }
} }
@ -276,7 +320,8 @@ mod tests {
fn test_to_password() { fn test_to_password() {
let rsa = Rsa::generate(2048).unwrap(); let rsa = Rsa::generate(2048).unwrap();
let pkey = PKey::from_rsa(rsa).unwrap(); let pkey = PKey::from_rsa(rsa).unwrap();
let pem = pkey.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar").unwrap(); let pem = pkey.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
.unwrap();
PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap(); PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err()); assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
} }
@ -295,8 +340,7 @@ mod tests {
password_queried = true; password_queried = true;
password[..6].copy_from_slice(b"mypass"); password[..6].copy_from_slice(b"mypass");
Ok(6) Ok(6)
}) }).unwrap();
.unwrap();
assert!(password_queried); assert!(password_queried);
} }

View File

@ -45,8 +45,11 @@ impl RsaRef {
private_key_to_der!(ffi::i2d_RSAPrivateKey); private_key_to_der!(ffi::i2d_RSAPrivateKey);
public_key_to_der!(ffi::i2d_RSA_PUBKEY); public_key_to_der!(ffi::i2d_RSA_PUBKEY);
to_der_inner!(/// Serializes the public key to DER-encoded PKCS#1. to_der_inner!(
public_key_to_der_pkcs1, ffi::i2d_RSAPublicKey); /// Serializes the public key to DER-encoded PKCS#1.
public_key_to_der_pkcs1,
ffi::i2d_RSAPublicKey
);
// FIXME should return u32 // FIXME should return u32
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
@ -63,21 +66,24 @@ impl RsaRef {
/// ///
/// Panics if `self` has no private components, or if `to` is smaller /// Panics if `self` has no private components, or if `to` is smaller
/// than `self.size()`. /// than `self.size()`.
pub fn private_decrypt(&self, pub fn private_decrypt(
&self,
from: &[u8], from: &[u8],
to: &mut [u8], to: &mut [u8],
padding: Padding) padding: Padding,
-> Result<usize, ErrorStack> { ) -> Result<usize, ErrorStack> {
assert!(self.d().is_some(), "private components missing"); assert!(self.d().is_some(), "private components missing");
assert!(from.len() <= i32::max_value() as usize); assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size()); assert!(to.len() >= self.size());
unsafe { unsafe {
let len = try!(cvt_n(ffi::RSA_private_decrypt(from.len() as c_int, let len = try!(cvt_n(ffi::RSA_private_decrypt(
from.len() as c_int,
from.as_ptr(), from.as_ptr(),
to.as_mut_ptr(), to.as_mut_ptr(),
self.as_ptr(), self.as_ptr(),
padding.0))); padding.0,
)));
Ok(len as usize) Ok(len as usize)
} }
} }
@ -88,21 +94,24 @@ impl RsaRef {
/// ///
/// Panics if `self` has no private components, or if `to` is smaller /// Panics if `self` has no private components, or if `to` is smaller
/// than `self.size()`. /// than `self.size()`.
pub fn private_encrypt(&self, pub fn private_encrypt(
&self,
from: &[u8], from: &[u8],
to: &mut [u8], to: &mut [u8],
padding: Padding) padding: Padding,
-> Result<usize, ErrorStack> { ) -> Result<usize, ErrorStack> {
assert!(self.d().is_some(), "private components missing"); assert!(self.d().is_some(), "private components missing");
assert!(from.len() <= i32::max_value() as usize); assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size()); assert!(to.len() >= self.size());
unsafe { unsafe {
let len = try!(cvt_n(ffi::RSA_private_encrypt(from.len() as c_int, let len = try!(cvt_n(ffi::RSA_private_encrypt(
from.len() as c_int,
from.as_ptr(), from.as_ptr(),
to.as_mut_ptr(), to.as_mut_ptr(),
self.as_ptr(), self.as_ptr(),
padding.0))); padding.0,
)));
Ok(len as usize) Ok(len as usize)
} }
} }
@ -112,20 +121,23 @@ impl RsaRef {
/// # Panics /// # Panics
/// ///
/// Panics if `to` is smaller than `self.size()`. /// Panics if `to` is smaller than `self.size()`.
pub fn public_decrypt(&self, pub fn public_decrypt(
&self,
from: &[u8], from: &[u8],
to: &mut [u8], to: &mut [u8],
padding: Padding) padding: Padding,
-> Result<usize, ErrorStack> { ) -> Result<usize, ErrorStack> {
assert!(from.len() <= i32::max_value() as usize); assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size()); assert!(to.len() >= self.size());
unsafe { unsafe {
let len = try!(cvt_n(ffi::RSA_public_decrypt(from.len() as c_int, let len = try!(cvt_n(ffi::RSA_public_decrypt(
from.len() as c_int,
from.as_ptr(), from.as_ptr(),
to.as_mut_ptr(), to.as_mut_ptr(),
self.as_ptr(), self.as_ptr(),
padding.0))); padding.0,
)));
Ok(len as usize) Ok(len as usize)
} }
} }
@ -135,20 +147,23 @@ impl RsaRef {
/// # Panics /// # Panics
/// ///
/// Panics if `to` is smaller than `self.size()`. /// Panics if `to` is smaller than `self.size()`.
pub fn public_encrypt(&self, pub fn public_encrypt(
&self,
from: &[u8], from: &[u8],
to: &mut [u8], to: &mut [u8],
padding: Padding) padding: Padding,
-> Result<usize, ErrorStack> { ) -> Result<usize, ErrorStack> {
assert!(from.len() <= i32::max_value() as usize); assert!(from.len() <= i32::max_value() as usize);
assert!(to.len() >= self.size()); assert!(to.len() >= self.size());
unsafe { unsafe {
let len = try!(cvt_n(ffi::RSA_public_encrypt(from.len() as c_int, let len = try!(cvt_n(ffi::RSA_public_encrypt(
from.len() as c_int,
from.as_ptr(), from.as_ptr(),
to.as_mut_ptr(), to.as_mut_ptr(),
self.as_ptr(), self.as_ptr(),
padding.0))); padding.0,
)));
Ok(len as usize) Ok(len as usize)
} }
} }
@ -215,32 +230,41 @@ impl Rsa {
pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa, ErrorStack> { pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa, ErrorStack> {
unsafe { unsafe {
let rsa = Rsa(try!(cvt_p(ffi::RSA_new()))); let rsa = Rsa(try!(cvt_p(ffi::RSA_new())));
try!(cvt(compat::set_key(rsa.0, try!(cvt(compat::set_key(
rsa.0,
n.as_ptr(), n.as_ptr(),
e.as_ptr(), e.as_ptr(),
ptr::null_mut()))); ptr::null_mut(),
)));
mem::forget((n, e)); mem::forget((n, e));
Ok(rsa) Ok(rsa)
} }
} }
pub fn from_private_components(n: BigNum, pub fn from_private_components(
n: BigNum,
e: BigNum, e: BigNum,
d: BigNum, d: BigNum,
p: BigNum, p: BigNum,
q: BigNum, q: BigNum,
dp: BigNum, dp: BigNum,
dq: BigNum, dq: BigNum,
qi: BigNum) qi: BigNum,
-> Result<Rsa, ErrorStack> { ) -> Result<Rsa, ErrorStack> {
unsafe { unsafe {
let rsa = Rsa(try!(cvt_p(ffi::RSA_new()))); let rsa = Rsa(try!(cvt_p(ffi::RSA_new())));
try!(cvt(compat::set_key(rsa.0, n.as_ptr(), e.as_ptr(), d.as_ptr()))); try!(cvt(
compat::set_key(rsa.0, n.as_ptr(), e.as_ptr(), d.as_ptr()),
));
mem::forget((n, e, d)); mem::forget((n, e, d));
try!(cvt(compat::set_factors(rsa.0, p.as_ptr(), q.as_ptr()))); try!(cvt(compat::set_factors(rsa.0, p.as_ptr(), q.as_ptr())));
mem::forget((p, q)); mem::forget((p, q));
try!(cvt(compat::set_crt_params(rsa.0, dp.as_ptr(), dq.as_ptr(), try!(cvt(compat::set_crt_params(
qi.as_ptr()))); rsa.0,
dp.as_ptr(),
dq.as_ptr(),
qi.as_ptr(),
)));
mem::forget((dp, dq, qi)); mem::forget((dp, dq, qi));
Ok(rsa) Ok(rsa)
} }
@ -254,7 +278,12 @@ impl Rsa {
unsafe { unsafe {
let rsa = Rsa(try!(cvt_p(ffi::RSA_new()))); let rsa = Rsa(try!(cvt_p(ffi::RSA_new())));
let e = try!(BigNum::from_u32(ffi::RSA_F4 as u32)); let e = try!(BigNum::from_u32(ffi::RSA_F4 as u32));
try!(cvt(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.as_ptr(), ptr::null_mut()))); try!(cvt(ffi::RSA_generate_key_ex(
rsa.0,
bits as c_int,
e.as_ptr(),
ptr::null_mut(),
)));
Ok(rsa) Ok(rsa)
} }
} }
@ -265,12 +294,17 @@ impl Rsa {
public_key_from_pem!(Rsa, ffi::PEM_read_bio_RSA_PUBKEY); public_key_from_pem!(Rsa, ffi::PEM_read_bio_RSA_PUBKEY);
public_key_from_der!(Rsa, ffi::d2i_RSA_PUBKEY); public_key_from_der!(Rsa, ffi::d2i_RSA_PUBKEY);
from_der_inner!(/// Deserializes a public key from DER-encoded PKCS#1 data. from_der_inner!(
public_key_from_der_pkcs1, Rsa, ffi::d2i_RSAPublicKey); /// Deserializes a public key from DER-encoded PKCS#1 data.
public_key_from_der_pkcs1,
Rsa,
ffi::d2i_RSAPublicKey
);
#[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")] #[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")]
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<Rsa, ErrorStack> pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<Rsa, ErrorStack>
where F: FnOnce(&mut [c_char]) -> usize where
F: FnOnce(&mut [c_char]) -> usize,
{ {
ffi::init(); ffi::init();
let mut cb = CallbackState::new(pass_cb); let mut cb = CallbackState::new(pass_cb);
@ -278,10 +312,12 @@ impl Rsa {
unsafe { unsafe {
let cb_ptr = &mut cb as *mut _ as *mut c_void; let cb_ptr = &mut cb as *mut _ as *mut c_void;
let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(), let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(
mem_bio.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
Some(invoke_passwd_cb_old::<F>), Some(invoke_passwd_cb_old::<F>),
cb_ptr))); cb_ptr,
)));
Ok(Rsa(rsa)) Ok(Rsa(rsa))
} }
} }
@ -320,11 +356,12 @@ mod compat {
ffi::RSA_set0_factors(r, p, q) ffi::RSA_set0_factors(r, p, q)
} }
pub unsafe fn set_crt_params(r: *mut RSA, pub unsafe fn set_crt_params(
r: *mut RSA,
dmp1: *mut BIGNUM, dmp1: *mut BIGNUM,
dmq1: *mut BIGNUM, dmq1: *mut BIGNUM,
iqmp: *mut BIGNUM) iqmp: *mut BIGNUM,
-> c_int { ) -> c_int {
ffi::RSA_set0_crt_params(r, dmp1, dmq1, iqmp) ffi::RSA_set0_crt_params(r, dmp1, dmq1, iqmp)
} }
} }
@ -355,11 +392,12 @@ mod compat {
1 // TODO: is this right? should it be 0? what's success? 1 // TODO: is this right? should it be 0? what's success?
} }
pub unsafe fn set_crt_params(r: *mut RSA, pub unsafe fn set_crt_params(
r: *mut RSA,
dmp1: *mut BIGNUM, dmp1: *mut BIGNUM,
dmq1: *mut BIGNUM, dmq1: *mut BIGNUM,
iqmp: *mut BIGNUM) iqmp: *mut BIGNUM,
-> c_int { ) -> c_int {
(*r).dmp1 = dmp1; (*r).dmp1 = dmp1;
(*r).dmq1 = dmq1; (*r).dmq1 = dmq1;
(*r).iqmp = iqmp; (*r).iqmp = iqmp;
@ -387,8 +425,7 @@ mod test {
password_queried = true; password_queried = true;
password[..6].copy_from_slice(b"mypass"); password[..6].copy_from_slice(b"mypass");
Ok(6) Ok(6)
}) }).unwrap();
.unwrap();
assert!(password_queried); assert!(password_queried);
} }
@ -396,7 +433,8 @@ mod test {
#[test] #[test]
fn test_to_password() { fn test_to_password() {
let key = Rsa::generate(2048).unwrap(); let key = Rsa::generate(2048).unwrap();
let pem = key.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar").unwrap(); let pem = key.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
.unwrap();
Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap(); Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err()); assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
} }
@ -408,13 +446,17 @@ mod test {
let mut result = vec![0; public_key.size()]; let mut result = vec![0; public_key.size()];
let original_data = b"This is test"; let original_data = b"This is test";
let len = public_key.public_encrypt(original_data, &mut result, PKCS1_PADDING).unwrap(); let len = public_key
.public_encrypt(original_data, &mut result, PKCS1_PADDING)
.unwrap();
assert_eq!(len, 256); assert_eq!(len, 256);
let pkey = include_bytes!("../test/rsa.pem"); let pkey = include_bytes!("../test/rsa.pem");
let private_key = Rsa::private_key_from_pem(pkey).unwrap(); let private_key = Rsa::private_key_from_pem(pkey).unwrap();
let mut dec_result = vec![0; private_key.size()]; let mut dec_result = vec![0; private_key.size()];
let len = private_key.private_decrypt(&result, &mut dec_result, PKCS1_PADDING).unwrap(); let len = private_key
.private_decrypt(&result, &mut dec_result, PKCS1_PADDING)
.unwrap();
assert_eq!(&dec_result[..len], original_data); assert_eq!(&dec_result[..len], original_data);
} }
@ -430,7 +472,8 @@ mod test {
let mut emesg = vec![0; k0.size()]; let mut emesg = vec![0; k0.size()];
k0.private_encrypt(&msg, &mut emesg, PKCS1_PADDING).unwrap(); k0.private_encrypt(&msg, &mut emesg, PKCS1_PADDING).unwrap();
let mut dmesg = vec![0; k1.size()]; let mut dmesg = vec![0; k1.size()];
let len = k1.public_decrypt(&emesg, &mut dmesg, PKCS1_PADDING).unwrap(); let len = k1.public_decrypt(&emesg, &mut dmesg, PKCS1_PADDING)
.unwrap();
assert_eq!(msg, &dmesg[..len]); assert_eq!(msg, &dmesg[..len]);
} }
@ -445,7 +488,8 @@ mod test {
let mut emesg = vec![0; k0.size()]; let mut emesg = vec![0; k0.size()];
k0.public_encrypt(&msg, &mut emesg, PKCS1_PADDING).unwrap(); k0.public_encrypt(&msg, &mut emesg, PKCS1_PADDING).unwrap();
let mut dmesg = vec![0; k1.size()]; let mut dmesg = vec![0; k1.size()];
let len = k1.private_decrypt(&emesg, &mut dmesg, PKCS1_PADDING).unwrap(); let len = k1.private_decrypt(&emesg, &mut dmesg, PKCS1_PADDING)
.unwrap();
assert_eq!(msg, &dmesg[..len]); assert_eq!(msg, &dmesg[..len]);
} }
} }

View File

@ -99,11 +99,13 @@ impl<'a> Signer<'a> {
let ctx = try!(cvt_p(EVP_MD_CTX_new())); let ctx = try!(cvt_p(EVP_MD_CTX_new()));
let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut(); let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut();
let r = ffi::EVP_DigestSignInit(ctx, let r = ffi::EVP_DigestSignInit(
ctx,
&mut pctx, &mut pctx,
type_.as_ptr(), type_.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
pkey.as_ptr()); pkey.as_ptr(),
);
if r != 1 { if r != 1 {
EVP_MD_CTX_free(ctx); EVP_MD_CTX_free(ctx);
return Err(ErrorStack::get()); return Err(ErrorStack::get());
@ -129,16 +131,28 @@ impl<'a> Signer<'a> {
pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EVP_DigestUpdate(self.md_ctx, 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<Vec<u8>, ErrorStack> { pub fn finish(&self) -> Result<Vec<u8>, ErrorStack> {
unsafe { unsafe {
let mut len = 0; let mut len = 0;
try!(cvt(ffi::EVP_DigestSignFinal(self.md_ctx, ptr::null_mut(), &mut len))); try!(cvt(ffi::EVP_DigestSignFinal(
self.md_ctx,
ptr::null_mut(),
&mut len,
)));
let mut buf = vec![0; len]; let mut buf = vec![0; len];
try!(cvt(ffi::EVP_DigestSignFinal(self.md_ctx, 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 // The advertised length is not always equal to the real length for things like DSA
buf.truncate(len); buf.truncate(len);
Ok(buf) Ok(buf)
@ -179,11 +193,13 @@ impl<'a> Verifier<'a> {
let ctx = try!(cvt_p(EVP_MD_CTX_new())); let ctx = try!(cvt_p(EVP_MD_CTX_new()));
let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut(); let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut();
let r = ffi::EVP_DigestVerifyInit(ctx, let r = ffi::EVP_DigestVerifyInit(
ctx,
&mut pctx, &mut pctx,
type_.as_ptr(), type_.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
pkey.as_ptr()); pkey.as_ptr(),
);
if r != 1 { if r != 1 {
EVP_MD_CTX_free(ctx); EVP_MD_CTX_free(ctx);
return Err(ErrorStack::get()); return Err(ErrorStack::get());
@ -209,13 +225,18 @@ impl<'a> Verifier<'a> {
pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::EVP_DigestUpdate(self.md_ctx, 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<bool, ErrorStack> { pub fn finish(&self, signature: &[u8]) -> Result<bool, ErrorStack> {
unsafe { unsafe {
let r = EVP_DigestVerifyFinal(self.md_ctx, signature.as_ptr() as *const _, signature.len()); let r =
EVP_DigestVerifyFinal(self.md_ctx, signature.as_ptr() as *const _, signature.len());
match r { match r {
1 => Ok(true), 1 => Ok(true),
0 => { 0 => {
@ -244,10 +265,11 @@ use ffi::EVP_DigestVerifyFinal;
#[cfg(ossl101)] #[cfg(ossl101)]
#[allow(bad_style)] #[allow(bad_style)]
unsafe fn EVP_DigestVerifyFinal(ctx: *mut ffi::EVP_MD_CTX, unsafe fn EVP_DigestVerifyFinal(
ctx: *mut ffi::EVP_MD_CTX,
sigret: *const ::libc::c_uchar, sigret: *const ::libc::c_uchar,
siglen: ::libc::size_t) siglen: ::libc::size_t,
-> ::libc::c_int { ) -> ::libc::c_int {
ffi::EVP_DigestVerifyFinal(ctx, sigret as *mut _, siglen) ffi::EVP_DigestVerifyFinal(ctx, sigret as *mut _, siglen)
} }
@ -264,29 +286,382 @@ mod test {
use dsa::Dsa; use dsa::Dsa;
use pkey::PKey; use pkey::PKey;
static INPUT: &'static [u8] = static INPUT: &'static [u8] = &[
&[101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 83, 85, 122, 73, 49, 78, 105, 74, 57, 101,
46, 101, 121, 74, 112, 99, 51, 77, 105, 79, 105, 74, 113, 98, 50, 85, 105, 76, 65, 48, 121,
75, 73, 67, 74, 108, 101, 72, 65, 105, 79, 106, 69, 122, 77, 68, 65, 52, 77, 84, 107, 74,
122, 79, 68, 65, 115, 68, 81, 111, 103, 73, 109, 104, 48, 100, 72, 65, 54, 76, 121, 57, 104,
108, 101, 71, 70, 116, 99, 71, 120, 108, 76, 109, 78, 118, 98, 83, 57, 112, 99, 49, 57, 98,
121, 98, 50, 57, 48, 73, 106, 112, 48, 99, 110, 86, 108, 102, 81]; 71,
99,
105,
79,
105,
74,
83,
85,
122,
73,
49,
78,
105,
74,
57,
46,
101,
121,
74,
112,
99,
51,
77,
105,
79,
105,
74,
113,
98,
50,
85,
105,
76,
65,
48,
75,
73,
67,
74,
108,
101,
72,
65,
105,
79,
106,
69,
122,
77,
68,
65,
52,
77,
84,
107,
122,
79,
68,
65,
115,
68,
81,
111,
103,
73,
109,
104,
48,
100,
72,
65,
54,
76,
121,
57,
108,
101,
71,
70,
116,
99,
71,
120,
108,
76,
109,
78,
118,
98,
83,
57,
112,
99,
49,
57,
121,
98,
50,
57,
48,
73,
106,
112,
48,
99,
110,
86,
108,
102,
81,
];
static SIGNATURE: &'static [u8] = static SIGNATURE: &'static [u8] = &[
&[112, 46, 33, 137, 67, 232, 143, 209, 30, 181, 216, 45, 191, 120, 69, 243, 65, 6, 174, 112,
27, 129, 255, 247, 115, 17, 22, 173, 209, 113, 125, 131, 101, 109, 66, 10, 253, 60, 150, 46,
238, 221, 115, 162, 102, 62, 81, 102, 104, 123, 0, 11, 135, 34, 110, 1, 135, 237, 16, 33,
115, 249, 69, 229, 130, 173, 252, 239, 22, 216, 90, 121, 142, 232, 198, 109, 219, 61, 137,
184, 151, 91, 23, 208, 148, 2, 190, 237, 213, 217, 217, 112, 7, 16, 141, 178, 129, 96, 67,
213, 248, 4, 12, 167, 68, 87, 98, 184, 31, 190, 127, 249, 217, 46, 10, 231, 111, 36, 232,
242, 91, 51, 187, 230, 244, 74, 230, 30, 177, 4, 10, 203, 32, 4, 77, 62, 249, 18, 142, 143,
212, 1, 48, 121, 91, 212, 189, 59, 65, 238, 202, 208, 102, 171, 101, 25, 129, 253, 228, 209,
141, 247, 127, 55, 45, 195, 139, 159, 175, 221, 59, 239, 177, 139, 93, 163, 204, 60, 46, 30,
176, 47, 158, 58, 65, 214, 18, 202, 173, 21, 145, 18, 115, 160, 95, 35, 185, 232, 56, 181,
250, 175, 132, 157, 105, 132, 41, 239, 90, 30, 136, 121, 130, 54, 195, 212, 14, 96, 69, 216,
34, 165, 68, 200, 242, 122, 122, 45, 184, 6, 99, 209, 108, 247, 202, 234, 86, 222, 64, 45,
92, 178, 33, 90, 69, 178, 194, 85, 102, 181, 90, 193, 167, 72, 160, 112, 223, 200, 163, 191,
42, 70, 149, 67, 208, 25, 238, 251, 71]; 120,
69,
243,
65,
6,
174,
27,
129,
255,
247,
115,
17,
22,
173,
209,
113,
125,
131,
101,
109,
66,
10,
253,
60,
150,
238,
221,
115,
162,
102,
62,
81,
102,
104,
123,
0,
11,
135,
34,
110,
1,
135,
237,
16,
115,
249,
69,
229,
130,
173,
252,
239,
22,
216,
90,
121,
142,
232,
198,
109,
219,
61,
184,
151,
91,
23,
208,
148,
2,
190,
237,
213,
217,
217,
112,
7,
16,
141,
178,
129,
96,
213,
248,
4,
12,
167,
68,
87,
98,
184,
31,
190,
127,
249,
217,
46,
10,
231,
111,
36,
242,
91,
51,
187,
230,
244,
74,
230,
30,
177,
4,
10,
203,
32,
4,
77,
62,
249,
18,
142,
212,
1,
48,
121,
91,
212,
189,
59,
65,
238,
202,
208,
102,
171,
101,
25,
129,
253,
228,
141,
247,
127,
55,
45,
195,
139,
159,
175,
221,
59,
239,
177,
139,
93,
163,
204,
60,
46,
176,
47,
158,
58,
65,
214,
18,
202,
173,
21,
145,
18,
115,
160,
95,
35,
185,
232,
56,
250,
175,
132,
157,
105,
132,
41,
239,
90,
30,
136,
121,
130,
54,
195,
212,
14,
96,
69,
34,
165,
68,
200,
242,
122,
122,
45,
184,
6,
99,
209,
108,
247,
202,
234,
86,
222,
64,
92,
178,
33,
90,
69,
178,
194,
85,
102,
181,
90,
193,
167,
72,
160,
112,
223,
200,
163,
42,
70,
149,
67,
208,
25,
238,
251,
71,
];
#[test] #[test]
fn rsa_sign() { fn rsa_sign() {
@ -296,7 +671,10 @@ mod test {
let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap(); let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap();
assert_eq!(signer.pkey_ctx_mut().rsa_padding().unwrap(), PKCS1_PADDING); assert_eq!(signer.pkey_ctx_mut().rsa_padding().unwrap(), PKCS1_PADDING);
signer.pkey_ctx_mut().set_rsa_padding(PKCS1_PADDING).unwrap(); signer
.pkey_ctx_mut()
.set_rsa_padding(PKCS1_PADDING)
.unwrap();
signer.update(INPUT).unwrap(); signer.update(INPUT).unwrap();
let result = signer.finish().unwrap(); let result = signer.finish().unwrap();
@ -310,7 +688,10 @@ mod test {
let pkey = PKey::from_rsa(private_key).unwrap(); let pkey = PKey::from_rsa(private_key).unwrap();
let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
assert_eq!(verifier.pkey_ctx_mut().rsa_padding().unwrap(), PKCS1_PADDING); assert_eq!(
verifier.pkey_ctx_mut().rsa_padding().unwrap(),
PKCS1_PADDING
);
verifier.update(INPUT).unwrap(); verifier.update(INPUT).unwrap();
assert!(verifier.finish(SIGNATURE).unwrap()); assert!(verifier.finish(SIGNATURE).unwrap());
} }
@ -390,29 +771,45 @@ mod test {
fn hmac_md5() { fn hmac_md5() {
// test vectors from RFC 2202 // test vectors from RFC 2202
let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] = let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] =
[(iter::repeat(0x0b_u8).take(16).collect(), [
(
iter::repeat(0x0b_u8).take(16).collect(),
b"Hi There".to_vec(), b"Hi There".to_vec(),
Vec::from_hex("9294727a3638bb1c13f48ef8158bfc9d").unwrap()), Vec::from_hex("9294727a3638bb1c13f48ef8158bfc9d").unwrap(),
(b"Jefe".to_vec(), ),
(
b"Jefe".to_vec(),
b"what do ya want for nothing?".to_vec(), b"what do ya want for nothing?".to_vec(),
Vec::from_hex("750c783e6ab0b503eaa86e310a5db738").unwrap()), Vec::from_hex("750c783e6ab0b503eaa86e310a5db738").unwrap(),
(iter::repeat(0xaa_u8).take(16).collect(), ),
(
iter::repeat(0xaa_u8).take(16).collect(),
iter::repeat(0xdd_u8).take(50).collect(), iter::repeat(0xdd_u8).take(50).collect(),
Vec::from_hex("56be34521d144c88dbb8c733f0e8b3f6").unwrap()), Vec::from_hex("56be34521d144c88dbb8c733f0e8b3f6").unwrap(),
(Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819").unwrap(), ),
(
Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819").unwrap(),
iter::repeat(0xcd_u8).take(50).collect(), iter::repeat(0xcd_u8).take(50).collect(),
Vec::from_hex("697eaf0aca3a3aea3a75164746ffaa79").unwrap()), Vec::from_hex("697eaf0aca3a3aea3a75164746ffaa79").unwrap(),
(iter::repeat(0x0c_u8).take(16).collect(), ),
(
iter::repeat(0x0c_u8).take(16).collect(),
b"Test With Truncation".to_vec(), b"Test With Truncation".to_vec(),
Vec::from_hex("56461ef2342edc00f9bab995690efd4c").unwrap()), Vec::from_hex("56461ef2342edc00f9bab995690efd4c").unwrap(),
(iter::repeat(0xaa_u8).take(80).collect(), ),
(
iter::repeat(0xaa_u8).take(80).collect(),
b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(),
Vec::from_hex("6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd").unwrap()), Vec::from_hex("6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd").unwrap(),
(iter::repeat(0xaa_u8).take(80).collect(), ),
(
iter::repeat(0xaa_u8).take(80).collect(),
b"Test Using Larger Than Block-Size Key \ b"Test Using Larger Than Block-Size Key \
and Larger Than One Block-Size Data" and Larger Than One Block-Size Data"
.to_vec(), .to_vec(),
Vec::from_hex("6f630fad67cda0ee1fb1f562db3aa53e").unwrap())]; Vec::from_hex("6f630fad67cda0ee1fb1f562db3aa53e").unwrap(),
),
];
test_hmac(MessageDigest::md5(), &tests); test_hmac(MessageDigest::md5(), &tests);
} }
@ -421,29 +818,45 @@ mod test {
fn hmac_sha1() { fn hmac_sha1() {
// test vectors from RFC 2202 // test vectors from RFC 2202
let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] = let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] =
[(iter::repeat(0x0b_u8).take(20).collect(), [
(
iter::repeat(0x0b_u8).take(20).collect(),
b"Hi There".to_vec(), b"Hi There".to_vec(),
Vec::from_hex("b617318655057264e28bc0b6fb378c8ef146be00").unwrap()), Vec::from_hex("b617318655057264e28bc0b6fb378c8ef146be00").unwrap(),
(b"Jefe".to_vec(), ),
(
b"Jefe".to_vec(),
b"what do ya want for nothing?".to_vec(), b"what do ya want for nothing?".to_vec(),
Vec::from_hex("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79").unwrap()), Vec::from_hex("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79").unwrap(),
(iter::repeat(0xaa_u8).take(20).collect(), ),
(
iter::repeat(0xaa_u8).take(20).collect(),
iter::repeat(0xdd_u8).take(50).collect(), iter::repeat(0xdd_u8).take(50).collect(),
Vec::from_hex("125d7342b9ac11cd91a39af48aa17b4f63f175d3").unwrap()), Vec::from_hex("125d7342b9ac11cd91a39af48aa17b4f63f175d3").unwrap(),
(Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819").unwrap(), ),
(
Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819").unwrap(),
iter::repeat(0xcd_u8).take(50).collect(), iter::repeat(0xcd_u8).take(50).collect(),
Vec::from_hex("4c9007f4026250c6bc8414f9bf50c86c2d7235da").unwrap()), Vec::from_hex("4c9007f4026250c6bc8414f9bf50c86c2d7235da").unwrap(),
(iter::repeat(0x0c_u8).take(20).collect(), ),
(
iter::repeat(0x0c_u8).take(20).collect(),
b"Test With Truncation".to_vec(), b"Test With Truncation".to_vec(),
Vec::from_hex("4c1a03424b55e07fe7f27be1d58bb9324a9a5a04").unwrap()), Vec::from_hex("4c1a03424b55e07fe7f27be1d58bb9324a9a5a04").unwrap(),
(iter::repeat(0xaa_u8).take(80).collect(), ),
(
iter::repeat(0xaa_u8).take(80).collect(),
b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(),
Vec::from_hex("aa4ae5e15272d00e95705637ce8a3b55ed402112").unwrap()), Vec::from_hex("aa4ae5e15272d00e95705637ce8a3b55ed402112").unwrap(),
(iter::repeat(0xaa_u8).take(80).collect(), ),
(
iter::repeat(0xaa_u8).take(80).collect(),
b"Test Using Larger Than Block-Size Key \ b"Test Using Larger Than Block-Size Key \
and Larger Than One Block-Size Data" and Larger Than One Block-Size Data"
.to_vec(), .to_vec(),
Vec::from_hex("e8e99d0f45237d786d6bbaa7965c7808bbff1a91").unwrap())]; Vec::from_hex("e8e99d0f45237d786d6bbaa7965c7808bbff1a91").unwrap(),
),
];
test_hmac(MessageDigest::sha1(), &tests); test_hmac(MessageDigest::sha1(), &tests);
} }

View File

@ -71,7 +71,7 @@ unsafe fn state<'a, S: 'a>(bio: *mut BIO) -> &'a mut StreamState<S> {
&mut *(compat::BIO_get_data(bio) as *mut _) &mut *(compat::BIO_get_data(bio) as *mut _)
} }
unsafe extern fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int { unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int {
BIO_clear_retry_flags(bio); BIO_clear_retry_flags(bio);
let state = state::<S>(bio); let state = state::<S>(bio);
@ -93,7 +93,7 @@ unsafe extern fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int)
} }
} }
unsafe extern fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int { unsafe extern "C" fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int {
BIO_clear_retry_flags(bio); BIO_clear_retry_flags(bio);
let state = state::<S>(bio); let state = state::<S>(bio);
@ -123,15 +123,16 @@ fn retriable_error(err: &io::Error) -> bool {
} }
} }
unsafe extern fn bputs<S: Write>(bio: *mut BIO, s: *const c_char) -> c_int { unsafe extern "C" fn bputs<S: Write>(bio: *mut BIO, s: *const c_char) -> c_int {
bwrite::<S>(bio, s, strlen(s) as c_int) bwrite::<S>(bio, s, strlen(s) as c_int)
} }
unsafe extern fn ctrl<S: Write>(bio: *mut BIO, unsafe extern "C" fn ctrl<S: Write>(
bio: *mut BIO,
cmd: c_int, cmd: c_int,
_num: c_long, _num: c_long,
_ptr: *mut c_void) _ptr: *mut c_void,
-> c_long { ) -> c_long {
if cmd == BIO_CTRL_FLUSH { if cmd == BIO_CTRL_FLUSH {
let state = state::<S>(bio); let state = state::<S>(bio);
@ -151,7 +152,7 @@ unsafe extern fn ctrl<S: Write>(bio: *mut BIO,
} }
} }
unsafe extern fn create(bio: *mut BIO) -> c_int { unsafe extern "C" fn create(bio: *mut BIO) -> c_int {
compat::BIO_set_init(bio, 0); compat::BIO_set_init(bio, 0);
compat::BIO_set_num(bio, 0); compat::BIO_set_num(bio, 0);
compat::BIO_set_data(bio, ptr::null_mut()); compat::BIO_set_data(bio, ptr::null_mut());
@ -159,7 +160,7 @@ unsafe extern fn create(bio: *mut BIO) -> c_int {
1 1
} }
unsafe extern fn destroy<S>(bio: *mut BIO) -> c_int { unsafe extern "C" fn destroy<S>(bio: *mut BIO) -> c_int {
if bio.is_null() { if bio.is_null() {
return 0; return 0;
} }

View File

@ -57,9 +57,11 @@ impl SslConnectorBuilder {
let mut ctx = try!(ctx(method)); let mut ctx = try!(ctx(method));
try!(ctx.set_default_verify_paths()); try!(ctx.set_default_verify_paths());
// From https://github.com/python/cpython/blob/c30098c8c6014f3340a369a31df9c74bdbacc269/Lib/ssl.py#L191 // From https://github.com/python/cpython/blob/c30098c8c6014f3340a369a31df9c74bdbacc269/Lib/ssl.py#L191
try!(ctx.set_cipher_list("ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:\ try!(ctx.set_cipher_list(
"ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:\
DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:\ DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:\
RSA+AES:RSA+HIGH:!aNULL:!eNULL:!MD5:!3DES")); RSA+AES:RSA+HIGH:!aNULL:!eNULL:!MD5:!3DES",
));
setup_verify(&mut ctx); setup_verify(&mut ctx);
Ok(SslConnectorBuilder(ctx)) Ok(SslConnectorBuilder(ctx))
@ -96,7 +98,8 @@ impl SslConnector {
/// ///
/// The domain is used for SNI and hostname verification. /// The domain is used for SNI and hostname verification.
pub fn connect<S>(&self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>> pub fn connect<S>(&self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where S: Read + Write where
S: Read + Write,
{ {
try!(self.configure()).connect(domain, stream) try!(self.configure()).connect(domain, stream)
} }
@ -140,7 +143,8 @@ impl ConnectConfiguration {
/// ///
/// The domain is used for SNI and hostname verification. /// The domain is used for SNI and hostname verification.
pub fn connect<S>(mut self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>> pub fn connect<S>(mut self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where S: Read + Write where
S: Read + Write,
{ {
try!(self.0.set_hostname(domain)); try!(self.0.set_hostname(domain));
try!(setup_verify_hostname(&mut self.0, domain)); try!(setup_verify_hostname(&mut self.0, domain));
@ -176,13 +180,15 @@ impl SslAcceptorBuilder {
/// recommendations. See its [documentation][docs] for more details on specifics. /// recommendations. See its [documentation][docs] for more details on specifics.
/// ///
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS /// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
pub fn mozilla_intermediate<I>(method: SslMethod, pub fn mozilla_intermediate<I>(
method: SslMethod,
private_key: &PKeyRef, private_key: &PKeyRef,
certificate: &X509Ref, certificate: &X509Ref,
chain: I) chain: I,
-> Result<SslAcceptorBuilder, ErrorStack> ) -> Result<SslAcceptorBuilder, ErrorStack>
where I: IntoIterator, where
I::Item: AsRef<X509Ref> I: IntoIterator,
I::Item: AsRef<X509Ref>,
{ {
let builder = try!(SslAcceptorBuilder::mozilla_intermediate_raw(method)); let builder = try!(SslAcceptorBuilder::mozilla_intermediate_raw(method));
builder.finish_setup(private_key, certificate, chain) builder.finish_setup(private_key, certificate, chain)
@ -194,13 +200,15 @@ impl SslAcceptorBuilder {
/// See its [documentation][docs] for more details on specifics. /// See its [documentation][docs] for more details on specifics.
/// ///
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS /// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
pub fn mozilla_modern<I>(method: SslMethod, pub fn mozilla_modern<I>(
method: SslMethod,
private_key: &PKeyRef, private_key: &PKeyRef,
certificate: &X509Ref, certificate: &X509Ref,
chain: I) chain: I,
-> Result<SslAcceptorBuilder, ErrorStack> ) -> Result<SslAcceptorBuilder, ErrorStack>
where I: IntoIterator, where
I::Item: AsRef<X509Ref> I: IntoIterator,
I::Item: AsRef<X509Ref>,
{ {
let builder = try!(SslAcceptorBuilder::mozilla_modern_raw(method)); let builder = try!(SslAcceptorBuilder::mozilla_modern_raw(method));
builder.finish_setup(private_key, certificate, chain) builder.finish_setup(private_key, certificate, chain)
@ -212,7 +220,8 @@ impl SslAcceptorBuilder {
let dh = try!(Dh::from_pem(DHPARAM_PEM.as_bytes())); let dh = try!(Dh::from_pem(DHPARAM_PEM.as_bytes()));
try!(ctx.set_tmp_dh(&dh)); try!(ctx.set_tmp_dh(&dh));
try!(setup_curves(&mut ctx)); try!(setup_curves(&mut ctx));
try!(ctx.set_cipher_list("ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\ try!(ctx.set_cipher_list(
"ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\ ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\
DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:\ DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:\
@ -225,7 +234,8 @@ impl SslAcceptorBuilder {
ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:\ ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:\
EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:\ EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:\
AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:\ AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:\
DES-CBC3-SHA:!DSS")); DES-CBC3-SHA:!DSS",
));
Ok(SslAcceptorBuilder(ctx)) Ok(SslAcceptorBuilder(ctx))
} }
@ -233,21 +243,25 @@ impl SslAcceptorBuilder {
pub fn mozilla_modern_raw(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> { pub fn mozilla_modern_raw(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
let mut ctx = try!(ctx(method)); let mut ctx = try!(ctx(method));
try!(setup_curves(&mut ctx)); try!(setup_curves(&mut ctx));
try!(ctx.set_cipher_list("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\ try!(ctx.set_cipher_list(
"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\
ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\ ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\ ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\
ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:\ ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:\
ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256")); ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256",
));
Ok(SslAcceptorBuilder(ctx)) Ok(SslAcceptorBuilder(ctx))
} }
fn finish_setup<I>(mut self, fn finish_setup<I>(
mut self,
private_key: &PKeyRef, private_key: &PKeyRef,
certificate: &X509Ref, certificate: &X509Ref,
chain: I) chain: I,
-> Result<SslAcceptorBuilder, ErrorStack> ) -> Result<SslAcceptorBuilder, ErrorStack>
where I: IntoIterator, where
I::Item: AsRef<X509Ref> I: IntoIterator,
I::Item: AsRef<X509Ref>,
{ {
try!(self.0.set_private_key(private_key)); try!(self.0.set_private_key(private_key));
try!(self.0.set_certificate(certificate)); try!(self.0.set_certificate(certificate));
@ -303,7 +317,8 @@ pub struct SslAcceptor(SslContext);
impl SslAcceptor { impl SslAcceptor {
/// Initiates a server-side TLS session on a stream. /// Initiates a server-side TLS session on a stream.
pub fn accept<S>(&self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> pub fn accept<S>(&self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where S: Read + Write where
S: Read + Write,
{ {
let ssl = try!(Ssl::new(&self.0)); let ssl = try!(Ssl::new(&self.0));
ssl.accept(stream) ssl.accept(stream)
@ -320,7 +335,7 @@ fn setup_verify(ctx: &mut SslContextBuilder) {
ctx.set_verify_callback(SSL_VERIFY_PEER, |p, x509| { ctx.set_verify_callback(SSL_VERIFY_PEER, |p, x509| {
let hostname = match x509.ssl() { let hostname = match x509.ssl() {
Ok(Some(ssl)) => ssl.ex_data(*HOSTNAME_IDX), Ok(Some(ssl)) => ssl.ex_data(*HOSTNAME_IDX),
_ => None _ => None,
}; };
match hostname { match hostname {
Some(hostname) => verify::verify_callback(hostname, p, x509), Some(hostname) => verify::verify_callback(hostname, p, x509),
@ -352,10 +367,11 @@ mod verify {
use x509::{X509StoreContextRef, X509Ref, X509NameRef, GeneralName}; use x509::{X509StoreContextRef, X509Ref, X509NameRef, GeneralName};
use stack::Stack; use stack::Stack;
pub fn verify_callback(domain: &str, pub fn verify_callback(
domain: &str,
preverify_ok: bool, preverify_ok: bool,
x509_ctx: &X509StoreContextRef) x509_ctx: &X509StoreContextRef,
-> bool { ) -> bool {
if !preverify_ok || x509_ctx.error_depth() != 0 { if !preverify_ok || x509_ctx.error_depth() != 0 {
return preverify_ok; return preverify_ok;
} }
@ -497,14 +513,16 @@ mod verify {
match (expected, actual.len()) { match (expected, actual.len()) {
(&IpAddr::V4(ref addr), 4) => actual == addr.octets(), (&IpAddr::V4(ref addr), 4) => actual == addr.octets(),
(&IpAddr::V6(ref addr), 16) => { (&IpAddr::V6(ref addr), 16) => {
let segments = [((actual[0] as u16) << 8) | actual[1] as u16, let segments = [
((actual[0] as u16) << 8) | actual[1] as u16,
((actual[2] as u16) << 8) | actual[3] as u16, ((actual[2] as u16) << 8) | actual[3] as u16,
((actual[4] as u16) << 8) | actual[5] as u16, ((actual[4] as u16) << 8) | actual[5] as u16,
((actual[6] as u16) << 8) | actual[7] as u16, ((actual[6] as u16) << 8) | actual[7] as u16,
((actual[8] as u16) << 8) | actual[9] as u16, ((actual[8] as u16) << 8) | actual[9] as u16,
((actual[10] as u16) << 8) | actual[11] as u16, ((actual[10] as u16) << 8) | actual[11] as u16,
((actual[12] as u16) << 8) | actual[13] as u16, ((actual[12] as u16) << 8) | actual[13] as u16,
((actual[14] as u16) << 8) | actual[15] as u16]; ((actual[14] as u16) << 8) | actual[15] as u16,
];
segments == addr.segments() segments == addr.segments()
} }
_ => false, _ => false,

View File

@ -274,12 +274,14 @@ lazy_static! {
static ref ALPN_PROTOS_IDX: c_int = get_new_idx::<Vec<u8>>(); static ref ALPN_PROTOS_IDX: c_int = get_new_idx::<Vec<u8>>();
} }
unsafe extern "C" fn free_data_box<T>(_parent: *mut c_void, unsafe extern "C" fn free_data_box<T>(
_parent: *mut c_void,
ptr: *mut c_void, ptr: *mut c_void,
_ad: *mut ffi::CRYPTO_EX_DATA, _ad: *mut ffi::CRYPTO_EX_DATA,
_idx: c_int, _idx: c_int,
_argl: c_long, _argl: c_long,
_argp: *mut c_void) { _argp: *mut c_void,
) {
if !ptr.is_null() { if !ptr.is_null() {
Box::<T>::from_raw(ptr as *mut T); Box::<T>::from_raw(ptr as *mut T);
} }
@ -366,13 +368,16 @@ impl SslContextBuilder {
/// Configures the certificate verification method for new connections and /// Configures the certificate verification method for new connections and
/// registers a verification callback. /// registers a verification callback.
pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F) pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
where F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send where
F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send,
{ {
unsafe { unsafe {
let verify = Box::new(verify); let verify = Box::new(verify);
ffi::SSL_CTX_set_ex_data(self.as_ptr(), ffi::SSL_CTX_set_ex_data(
self.as_ptr(),
get_callback_idx::<F>(), get_callback_idx::<F>(),
mem::transmute(verify)); mem::transmute(verify),
);
ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::<F>)); ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::<F>));
} }
} }
@ -382,13 +387,16 @@ impl SslContextBuilder {
/// Obtain the server name with `servername` then set the corresponding context /// Obtain the server name with `servername` then set the corresponding context
/// with `set_ssl_context` /// with `set_ssl_context`
pub fn set_servername_callback<F>(&mut self, callback: F) pub fn set_servername_callback<F>(&mut self, callback: F)
where F: Fn(&mut SslRef) -> Result<(), SniError> + Any + 'static + Sync + Send where
F: Fn(&mut SslRef) -> Result<(), SniError> + Any + 'static + Sync + Send,
{ {
unsafe { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
ffi::SSL_CTX_set_ex_data(self.as_ptr(), ffi::SSL_CTX_set_ex_data(
self.as_ptr(),
get_callback_idx::<F>(), get_callback_idx::<F>(),
mem::transmute(callback)); mem::transmute(callback),
);
let f: extern "C" fn(_, _, _) -> _ = raw_sni::<F>; let f: extern "C" fn(_, _, _) -> _ = raw_sni::<F>;
let f: extern "C" fn() = mem::transmute(f); let f: extern "C" fn() = mem::transmute(f);
ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(f)); ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(f));
@ -409,7 +417,10 @@ impl SslContextBuilder {
pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
unsafe { unsafe {
let ptr = cert_store.as_ptr(); let ptr = cert_store.as_ptr();
try!(cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)); try!(cvt(
ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as
c_int,
));
mem::forget(cert_store); mem::forget(cert_store);
Ok(()) Ok(())
@ -434,32 +445,41 @@ impl SslContextBuilder {
} }
pub fn set_tmp_dh_callback<F>(&mut self, callback: F) pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
where F: Fn(&mut SslRef, bool, u32) -> Result<Dh, ErrorStack> + Any + 'static + Sync + Send where
F: Fn(&mut SslRef, bool, u32) -> Result<Dh, ErrorStack> + Any + 'static + Sync + Send,
{ {
unsafe { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
ffi::SSL_CTX_set_ex_data(self.as_ptr(), ffi::SSL_CTX_set_ex_data(
self.as_ptr(),
get_callback_idx::<F>(), get_callback_idx::<F>(),
Box::into_raw(callback) as *mut c_void); Box::into_raw(callback) as *mut c_void,
);
let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_dh::<F>; let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_dh::<F>;
ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), f); ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), f);
} }
} }
pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef) -> Result<(), ErrorStack> { pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) } unsafe {
cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as
c_int).map(|_| ())
}
} }
/// Requires the `v101` feature and OpenSSL 1.0.1, or the `v102` feature and OpenSSL 1.0.2. /// Requires the `v101` feature and OpenSSL 1.0.1, or the `v102` feature and OpenSSL 1.0.2.
#[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))] #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))]
pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
where F: Fn(&mut SslRef, bool, u32) -> Result<EcKey, ErrorStack> + Any + 'static + Sync + Send where
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey, ErrorStack> + Any + 'static + Sync + Send,
{ {
unsafe { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
ffi::SSL_CTX_set_ex_data(self.as_ptr(), ffi::SSL_CTX_set_ex_data(
self.as_ptr(),
get_callback_idx::<F>(), get_callback_idx::<F>(),
Box::into_raw(callback) as *mut c_void); Box::into_raw(callback) as *mut c_void,
);
let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_ecdh::<F>; let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_ecdh::<F>;
ffi::SSL_CTX_set_tmp_ecdh_callback(self.as_ptr(), f); ffi::SSL_CTX_set_tmp_ecdh_callback(self.as_ptr(), f);
} }
@ -478,10 +498,11 @@ impl SslContextBuilder {
pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> { pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
unsafe { unsafe {
cvt(ffi::SSL_CTX_load_verify_locations(self.as_ptr(), cvt(ffi::SSL_CTX_load_verify_locations(
self.as_ptr(),
file.as_ptr() as *const _, file.as_ptr() as *const _,
ptr::null())) ptr::null(),
.map(|_| ()) )).map(|_| ())
} }
} }
@ -506,24 +527,27 @@ impl SslContextBuilder {
pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> { pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
unsafe { unsafe {
assert!(sid_ctx.len() <= c_uint::max_value() as usize); assert!(sid_ctx.len() <= c_uint::max_value() as usize);
cvt(ffi::SSL_CTX_set_session_id_context(self.as_ptr(), cvt(ffi::SSL_CTX_set_session_id_context(
self.as_ptr(),
sid_ctx.as_ptr(), sid_ctx.as_ptr(),
sid_ctx.len() as c_uint)) sid_ctx.len() as c_uint,
.map(|_| ()) )).map(|_| ())
} }
} }
/// Loads a certificate from a file. /// Loads a certificate from a file.
pub fn set_certificate_file<P: AsRef<Path>>(&mut self, pub fn set_certificate_file<P: AsRef<Path>>(
&mut self,
file: P, file: P,
file_type: X509FileType) file_type: X509FileType,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
unsafe { unsafe {
cvt(ffi::SSL_CTX_use_certificate_file(self.as_ptr(), cvt(ffi::SSL_CTX_use_certificate_file(
self.as_ptr(),
file.as_ptr() as *const _, file.as_ptr() as *const _,
file_type.as_raw())) file_type.as_raw(),
.map(|_| ()) )).map(|_| ())
} }
} }
@ -532,13 +556,16 @@ impl SslContextBuilder {
/// The file should contain a sequence of PEM-formatted certificates, the first being the leaf /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf
/// certificate, and the remainder forming the chain of certificates up to and including the /// certificate, and the remainder forming the chain of certificates up to and including the
/// trusted root certificate. /// trusted root certificate.
pub fn set_certificate_chain_file<P: AsRef<Path>>(&mut self, pub fn set_certificate_chain_file<P: AsRef<Path>>(
file: P) &mut self,
-> Result<(), ErrorStack> { file: P,
) -> Result<(), ErrorStack> {
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
unsafe { unsafe {
cvt(ffi::SSL_CTX_use_certificate_chain_file(self.as_ptr(), file.as_ptr() as *const _)) cvt(ffi::SSL_CTX_use_certificate_chain_file(
.map(|_| ()) self.as_ptr(),
file.as_ptr() as *const _,
)).map(|_| ())
} }
} }
@ -553,23 +580,28 @@ impl SslContextBuilder {
/// `set_certificate` to a trusted root. /// `set_certificate` to a trusted root.
pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> { pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
unsafe { unsafe {
try!(cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)); try!(cvt(ffi::SSL_CTX_add_extra_chain_cert(
self.as_ptr(),
cert.as_ptr(),
) as c_int));
mem::forget(cert); mem::forget(cert);
Ok(()) Ok(())
} }
} }
/// Loads the private key from a file. /// Loads the private key from a file.
pub fn set_private_key_file<P: AsRef<Path>>(&mut self, pub fn set_private_key_file<P: AsRef<Path>>(
&mut self,
file: P, file: P,
file_type: X509FileType) file_type: X509FileType,
-> Result<(), ErrorStack> { ) -> Result<(), ErrorStack> {
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
unsafe { unsafe {
cvt(ffi::SSL_CTX_use_PrivateKey_file(self.as_ptr(), cvt(ffi::SSL_CTX_use_PrivateKey_file(
self.as_ptr(),
file.as_ptr() as *const _, file.as_ptr() as *const _,
file_type.as_raw())) file_type.as_raw(),
.map(|_| ()) )).map(|_| ())
} }
} }
@ -584,8 +616,10 @@ impl SslContextBuilder {
pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
let cipher_list = CString::new(cipher_list).unwrap(); let cipher_list = CString::new(cipher_list).unwrap();
unsafe { unsafe {
cvt(ffi::SSL_CTX_set_cipher_list(self.as_ptr(), cipher_list.as_ptr() as *const _)) cvt(ffi::SSL_CTX_set_cipher_list(
.map(|_| ()) self.as_ptr(),
cipher_list.as_ptr() as *const _,
)).map(|_| ())
} }
} }
@ -627,20 +661,26 @@ impl SslContextBuilder {
unsafe { unsafe {
// Attach the protocol list to the OpenSSL context structure, // Attach the protocol list to the OpenSSL context structure,
// so that we can refer to it within the callback. // so that we can refer to it within the callback.
try!(cvt(ffi::SSL_CTX_set_ex_data(self.as_ptr(), try!(cvt(ffi::SSL_CTX_set_ex_data(
self.as_ptr(),
*NPN_PROTOS_IDX, *NPN_PROTOS_IDX,
Box::into_raw(protocols) as *mut c_void))); Box::into_raw(protocols) as *mut c_void,
)));
// Now register the callback that performs the default protocol // Now register the callback that performs the default protocol
// matching based on the client-supported list of protocols that // matching based on the client-supported list of protocols that
// has been saved. // has been saved.
ffi::SSL_CTX_set_next_proto_select_cb(self.as_ptr(), ffi::SSL_CTX_set_next_proto_select_cb(
self.as_ptr(),
raw_next_proto_select_cb, raw_next_proto_select_cb,
ptr::null_mut()); ptr::null_mut(),
);
// Also register the callback to advertise these protocols, if a server socket is // Also register the callback to advertise these protocols, if a server socket is
// created with the context. // created with the context.
ffi::SSL_CTX_set_next_protos_advertised_cb(self.as_ptr(), ffi::SSL_CTX_set_next_protos_advertised_cb(
self.as_ptr(),
raw_next_protos_advertise_cb, raw_next_protos_advertise_cb,
ptr::null_mut()); ptr::null_mut(),
);
Ok(()) Ok(())
} }
} }
@ -658,9 +698,11 @@ impl SslContextBuilder {
let protocols: Box<Vec<u8>> = Box::new(ssl_encode_byte_strings(protocols)); let protocols: Box<Vec<u8>> = Box::new(ssl_encode_byte_strings(protocols));
unsafe { unsafe {
// Set the context's internal protocol list for use if we are a server // Set the context's internal protocol list for use if we are a server
let r = ffi::SSL_CTX_set_alpn_protos(self.as_ptr(), let r = ffi::SSL_CTX_set_alpn_protos(
self.as_ptr(),
protocols.as_ptr(), protocols.as_ptr(),
protocols.len() as c_uint); protocols.len() as c_uint,
);
// fun fact, SSL_CTX_set_alpn_protos has a reversed return code D: // fun fact, SSL_CTX_set_alpn_protos has a reversed return code D:
if r != 0 { if r != 0 {
return Err(ErrorStack::get()); return Err(ErrorStack::get());
@ -670,9 +712,11 @@ impl SslContextBuilder {
// ssl ctx's ex_data so that we can configure a function to free it later. In the // ssl ctx's ex_data so that we can configure a function to free it later. In the
// future, it might make sense to pull this into our internal struct Ssl instead of // future, it might make sense to pull this into our internal struct Ssl instead of
// leaning on openssl and using function pointers. // leaning on openssl and using function pointers.
try!(cvt(ffi::SSL_CTX_set_ex_data(self.as_ptr(), try!(cvt(ffi::SSL_CTX_set_ex_data(
self.as_ptr(),
*ALPN_PROTOS_IDX, *ALPN_PROTOS_IDX,
Box::into_raw(protocols) as *mut c_void))); Box::into_raw(protocols) as *mut c_void,
)));
// Now register the callback that performs the default protocol // Now register the callback that performs the default protocol
// matching based on the client-supported list of protocols that // matching based on the client-supported list of protocols that
@ -711,15 +755,21 @@ impl SslContextBuilder {
/// response of `Ok(true)` indicates that the OCSP status should be returned to the client, and /// response of `Ok(true)` indicates that the OCSP status should be returned to the client, and
/// `Ok(false)` indicates that the status should not be returned to the client. /// `Ok(false)` indicates that the status should not be returned to the client.
pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack> pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
where F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + Any + 'static + Sync + Send where
F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + Any + 'static + Sync + Send,
{ {
unsafe { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
ffi::SSL_CTX_set_ex_data(self.as_ptr(), ffi::SSL_CTX_set_ex_data(
self.as_ptr(),
get_callback_idx::<F>(), get_callback_idx::<F>(),
Box::into_raw(callback) as *mut c_void); Box::into_raw(callback) as *mut c_void,
);
let f: unsafe extern "C" fn(_, _) -> _ = raw_tlsext_status::<F>; let f: unsafe extern "C" fn(_, _) -> _ = raw_tlsext_status::<F>;
cvt(ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(f)) as c_int).map(|_| ()) cvt(ffi::SSL_CTX_set_tlsext_status_cb(
self.as_ptr(),
Some(f),
) as c_int).map(|_| ())
} }
} }
@ -730,13 +780,20 @@ impl SslContextBuilder {
/// must be written as a null-terminated C string. /// must be written as a null-terminated C string.
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))] #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
pub fn set_psk_callback<F>(&mut self, callback: F) pub fn set_psk_callback<F>(&mut self, callback: F)
where F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> + Any + 'static + Sync + Send where
F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
+ Any
+ 'static
+ Sync
+ Send,
{ {
unsafe { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
ffi::SSL_CTX_set_ex_data(self.as_ptr(), ffi::SSL_CTX_set_ex_data(
self.as_ptr(),
get_callback_idx::<F>(), get_callback_idx::<F>(),
mem::transmute(callback)); mem::transmute(callback),
);
ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_psk::<F>)) ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_psk::<F>))
} }
} }
@ -745,7 +802,11 @@ impl SslContextBuilder {
pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) { pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
unsafe { unsafe {
let data = Box::new(data); let data = Box::new(data);
ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), Box::into_raw(data) as *mut c_void); ffi::SSL_CTX_set_ex_data(
self.as_ptr(),
index.as_raw(),
Box::into_raw(data) as *mut c_void,
);
} }
} }
@ -794,7 +855,7 @@ impl SslContext {
/// index. /// index.
pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack> pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
where where
T: 'static + Sync + Send T: 'static + Sync + Send,
{ {
unsafe { unsafe {
ffi::init(); ffi::init();
@ -1023,7 +1084,7 @@ impl Ssl {
/// index. /// index.
pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack> pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
where where
T: 'static + Sync + Send T: 'static + Sync + Send,
{ {
unsafe { unsafe {
ffi::init(); ffi::init();
@ -1078,13 +1139,16 @@ impl SslRef {
/// to the certificate chain. It should return `true` if the certificate /// to the certificate chain. It should return `true` if the certificate
/// chain is valid and `false` otherwise. /// chain is valid and `false` otherwise.
pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F) pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
where F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send where
F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send,
{ {
unsafe { unsafe {
let verify = Box::new(verify); let verify = Box::new(verify);
ffi::SSL_set_ex_data(self.as_ptr(), ffi::SSL_set_ex_data(
self.as_ptr(),
get_ssl_callback_idx::<F>(), get_ssl_callback_idx::<F>(),
mem::transmute(verify)); mem::transmute(verify),
);
ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, Some(ssl_raw_verify::<F>)); ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, Some(ssl_raw_verify::<F>));
} }
} }
@ -1094,13 +1158,16 @@ impl SslRef {
} }
pub fn set_tmp_dh_callback<F>(&mut self, callback: F) pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
where F: Fn(&mut SslRef, bool, u32) -> Result<Dh, ErrorStack> + Any + 'static + Sync + Send where
F: Fn(&mut SslRef, bool, u32) -> Result<Dh, ErrorStack> + Any + 'static + Sync + Send,
{ {
unsafe { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
ffi::SSL_set_ex_data(self.as_ptr(), ffi::SSL_set_ex_data(
self.as_ptr(),
get_ssl_callback_idx::<F>(), get_ssl_callback_idx::<F>(),
Box::into_raw(callback) as *mut c_void); Box::into_raw(callback) as *mut c_void,
);
let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_dh_ssl::<F>; let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_dh_ssl::<F>;
ffi::SSL_set_tmp_dh_callback(self.as_ptr(), f); ffi::SSL_set_tmp_dh_callback(self.as_ptr(), f);
} }
@ -1113,13 +1180,16 @@ impl SslRef {
/// Requires the `v101` feature and OpenSSL 1.0.1, or the `v102` feature and OpenSSL 1.0.2. /// Requires the `v101` feature and OpenSSL 1.0.1, or the `v102` feature and OpenSSL 1.0.2.
#[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))] #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))]
pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
where F: Fn(&mut SslRef, bool, u32) -> Result<EcKey, ErrorStack> + Any + 'static + Sync + Send where
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey, ErrorStack> + Any + 'static + Sync + Send,
{ {
unsafe { unsafe {
let callback = Box::new(callback); let callback = Box::new(callback);
ffi::SSL_set_ex_data(self.as_ptr(), ffi::SSL_set_ex_data(
self.as_ptr(),
get_ssl_callback_idx::<F>(), get_ssl_callback_idx::<F>(),
Box::into_raw(callback) as *mut c_void); Box::into_raw(callback) as *mut c_void,
);
let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_ecdh_ssl::<F>; let f: unsafe extern "C" fn(_, _, _) -> _ = raw_tmp_ecdh_ssl::<F>;
ffi::SSL_set_tmp_ecdh_callback(self.as_ptr(), f); ffi::SSL_set_tmp_ecdh_callback(self.as_ptr(), f);
} }
@ -1169,8 +1239,10 @@ impl SslRef {
pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> { pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
let cstr = CString::new(hostname).unwrap(); let cstr = CString::new(hostname).unwrap();
unsafe { unsafe {
cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int) cvt(ffi::SSL_set_tlsext_host_name(
.map(|_| ()) self.as_ptr(),
cstr.as_ptr() as *mut _,
) as c_int).map(|_| ())
} }
} }
@ -1285,7 +1357,9 @@ impl SslRef {
return None; return None;
} }
let meth = ffi::SSL_COMP_get_name(ptr); let meth = ffi::SSL_COMP_get_name(ptr);
Some(str::from_utf8(CStr::from_ptr(meth as *const _).to_bytes()).unwrap()) Some(
str::from_utf8(CStr::from_ptr(meth as *const _).to_bytes()).unwrap(),
)
} }
} }
@ -1302,7 +1376,9 @@ impl SslRef {
return None; return None;
} }
Some(str::from_utf8(CStr::from_ptr(name as *const _).to_bytes()).unwrap()) Some(
str::from_utf8(CStr::from_ptr(name as *const _).to_bytes()).unwrap(),
)
} }
} }
@ -1367,7 +1443,10 @@ impl SslRef {
/// Sets the status response a client wishes the server to reply with. /// Sets the status response a client wishes the server to reply with.
pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> { pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ()) cvt(ffi::SSL_set_tlsext_status_type(
self.as_ptr(),
type_.as_raw(),
) as c_int).map(|_| ())
} }
} }
@ -1389,15 +1468,17 @@ impl SslRef {
pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> { pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
unsafe { unsafe {
assert!(response.len() <= c_int::max_value() as usize); assert!(response.len() <= c_int::max_value() as usize);
let p = try!(cvt_p(ffi::CRYPTO_malloc(response.len() as _, let p = try!(cvt_p(ffi::CRYPTO_malloc(
response.len() as _,
concat!(file!(), "\0").as_ptr() as *const _, concat!(file!(), "\0").as_ptr() as *const _,
line!() as c_int))); line!() as c_int,
)));
ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len()); ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
cvt(ffi::SSL_set_tlsext_status_ocsp_resp(self.as_ptr(), cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
self.as_ptr(),
p as *mut c_uchar, p as *mut c_uchar,
response.len() as c_long) as response.len() as c_long,
c_int) ) as c_int).map(|_| ())
.map(|_| ())
} }
} }
@ -1410,7 +1491,11 @@ impl SslRef {
pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) { pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
unsafe { unsafe {
let data = Box::new(data); let data = Box::new(data);
ffi::SSL_set_ex_data(self.as_ptr(), index.as_raw(), Box::into_raw(data) as *mut c_void); ffi::SSL_set_ex_data(
self.as_ptr(),
index.as_raw(),
Box::into_raw(data) as *mut c_void,
);
} }
} }
@ -1451,7 +1536,8 @@ impl Ssl {
/// OpenSSL's default configuration is insecure. It is highly recommended to use /// OpenSSL's default configuration is insecure. It is highly recommended to use
/// `SslConnector` rather than `Ssl` directly, as it manages that configuration. /// `SslConnector` rather than `Ssl` directly, as it manages that configuration.
pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where S: Read + Write where
S: Read + Write,
{ {
let mut stream = SslStream::new_base(self, stream); let mut stream = SslStream::new_base(self, stream);
let ret = unsafe { ffi::SSL_connect(stream.ssl.as_ptr()) }; let ret = unsafe { ffi::SSL_connect(stream.ssl.as_ptr()) };
@ -1483,7 +1569,8 @@ impl Ssl {
/// OpenSSL's default configuration is insecure. It is highly recommended to use /// OpenSSL's default configuration is insecure. It is highly recommended to use
/// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
where S: Read + Write where
S: Read + Write,
{ {
let mut stream = SslStream::new_base(self, stream); let mut stream = SslStream::new_base(self, stream);
let ret = unsafe { ffi::SSL_accept(stream.ssl.as_ptr()) }; let ret = unsafe { ffi::SSL_accept(stream.ssl.as_ptr()) };
@ -1571,7 +1658,8 @@ pub struct SslStream<S> {
} }
impl<S> fmt::Debug for SslStream<S> impl<S> fmt::Debug for SslStream<S>
where S: fmt::Debug where
S: fmt::Debug,
{ {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("SslStream") fmt.debug_struct("SslStream")
@ -1672,8 +1760,10 @@ impl<S> SslStream<S> {
match self.get_bio_error() { match self.get_bio_error() {
Some(err) => Error::Stream(err), Some(err) => Error::Stream(err),
None => { None => {
Error::Stream(io::Error::new(io::ErrorKind::ConnectionAborted, Error::Stream(io::Error::new(
"unexpected EOF observed")) io::ErrorKind::ConnectionAborted,
"unexpected EOF observed",
))
} }
} }
} else { } else {
@ -1685,8 +1775,10 @@ impl<S> SslStream<S> {
let err = match self.get_bio_error() { let err = match self.get_bio_error() {
Some(err) => err, Some(err) => err,
None => { None => {
io::Error::new(io::ErrorKind::Other, io::Error::new(
"BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO") io::ErrorKind::Other,
"BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO",
)
} }
}; };
Error::WantWrite(err) Error::WantWrite(err)
@ -1695,15 +1787,19 @@ impl<S> SslStream<S> {
let err = match self.get_bio_error() { let err = match self.get_bio_error() {
Some(err) => err, Some(err) => err,
None => { None => {
io::Error::new(io::ErrorKind::Other, io::Error::new(
"BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO") io::ErrorKind::Other,
"BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO",
)
} }
}; };
Error::WantRead(err) Error::WantRead(err)
} }
err => { err => {
Error::Stream(io::Error::new(io::ErrorKind::InvalidData, Error::Stream(io::Error::new(
format!("unexpected error {}", err))) io::ErrorKind::InvalidData,
format!("unexpected error {}", err),
))
} }
} }
} }
@ -1760,8 +1856,7 @@ impl<S: Read + Write> Read for SslStream<S> {
impl<S: Read + Write> Write for SslStream<S> { impl<S: Read + Write> Write for SslStream<S> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.ssl_write(buf) self.ssl_write(buf).map_err(|e| match e {
.map_err(|e| match e {
Error::Stream(e) => e, Error::Stream(e) => e,
Error::WantRead(e) => e, Error::WantRead(e) => e,
Error::WantWrite(e) => e, Error::WantWrite(e) => e,
@ -1795,21 +1890,25 @@ mod compat {
SSL_SESSION_get_master_key, SSL_is_server, SSL_SESSION_up_ref}; SSL_SESSION_get_master_key, SSL_is_server, SSL_SESSION_up_ref};
pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
ffi::CRYPTO_get_ex_new_index(ffi::CRYPTO_EX_INDEX_SSL_CTX, ffi::CRYPTO_get_ex_new_index(
ffi::CRYPTO_EX_INDEX_SSL_CTX,
0, 0,
ptr::null_mut(), ptr::null_mut(),
None, None,
None, None,
Some(f)) Some(f),
)
} }
pub unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { pub unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
ffi::CRYPTO_get_ex_new_index(ffi::CRYPTO_EX_INDEX_SSL, ffi::CRYPTO_get_ex_new_index(
ffi::CRYPTO_EX_INDEX_SSL,
0, 0,
ptr::null_mut(), ptr::null_mut(),
None, None,
None, None,
Some(f)) Some(f),
)
} }
pub fn tls_method() -> *const ffi::SSL_METHOD { pub fn tls_method() -> *const ffi::SSL_METHOD {
@ -1834,17 +1933,21 @@ mod compat {
} }
pub unsafe fn SSL_CTX_set_options(ctx: *const ffi::SSL_CTX, op: c_ulong) -> c_ulong { pub unsafe fn SSL_CTX_set_options(ctx: *const ffi::SSL_CTX, op: c_ulong) -> c_ulong {
ffi::SSL_CTX_ctrl(ctx as *mut _, ffi::SSL_CTX_ctrl(
ctx as *mut _,
ffi::SSL_CTRL_OPTIONS, ffi::SSL_CTRL_OPTIONS,
op as c_long, op as c_long,
ptr::null_mut()) as c_ulong ptr::null_mut(),
) as c_ulong
} }
pub unsafe fn SSL_CTX_clear_options(ctx: *const ffi::SSL_CTX, op: c_ulong) -> c_ulong { pub unsafe fn SSL_CTX_clear_options(ctx: *const ffi::SSL_CTX, op: c_ulong) -> c_ulong {
ffi::SSL_CTX_ctrl(ctx as *mut _, ffi::SSL_CTX_ctrl(
ctx as *mut _,
ffi::SSL_CTRL_CLEAR_OPTIONS, ffi::SSL_CTRL_CLEAR_OPTIONS,
op as c_long, op as c_long,
ptr::null_mut()) as c_ulong ptr::null_mut(),
) as c_ulong
} }
pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
@ -1856,18 +1959,21 @@ mod compat {
} }
pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> libc::c_int { pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> libc::c_int {
ffi::CRYPTO_add_lock(&mut (*ssl).references, ffi::CRYPTO_add_lock(
&mut (*ssl).references,
1, 1,
ffi::CRYPTO_LOCK_SSL_CTX, ffi::CRYPTO_LOCK_SSL_CTX,
"mod.rs\0".as_ptr() as *const _, "mod.rs\0".as_ptr() as *const _,
line!() as libc::c_int); line!() as libc::c_int,
);
0 0
} }
pub unsafe fn SSL_SESSION_get_master_key(session: *const ffi::SSL_SESSION, pub unsafe fn SSL_SESSION_get_master_key(
session: *const ffi::SSL_SESSION,
out: *mut c_uchar, out: *mut c_uchar,
mut outlen: size_t) mut outlen: size_t,
-> size_t { ) -> size_t {
if outlen == 0 { if outlen == 0 {
return (*session).master_key_length as size_t; return (*session).master_key_length as size_t;
} }
@ -1891,11 +1997,13 @@ mod compat {
} }
pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int { pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
ffi::CRYPTO_add_lock(&mut (*ses).references, ffi::CRYPTO_add_lock(
&mut (*ses).references,
1, 1,
ffi::CRYPTO_LOCK_SSL_CTX, ffi::CRYPTO_LOCK_SSL_CTX,
"mod.rs\0".as_ptr() as *const _, "mod.rs\0".as_ptr() as *const _,
line!() as libc::c_int); line!() as libc::c_int,
);
0 0
} }
} }

View File

@ -75,11 +75,13 @@ impl Server {
if let Some(mut input) = input { if let Some(mut input) = input {
thread::spawn(move || input(stdin)); thread::spawn(move || input(stdin));
} }
(Server { (
Server {
p: child, p: child,
_temp: td, _temp: td,
}, },
addr) addr,
)
} }
fn new_tcp(args: &[&str]) -> (Server, TcpStream) { fn new_tcp(args: &[&str]) -> (Server, TcpStream) {
@ -102,26 +104,31 @@ impl Server {
#[allow(dead_code)] #[allow(dead_code)]
fn new_alpn() -> (Server, TcpStream) { fn new_alpn() -> (Server, TcpStream) {
Server::new_tcp(&["-www", Server::new_tcp(
&[
"-www",
"-nextprotoneg", "-nextprotoneg",
"http/1.1,spdy/3.1", "http/1.1,spdy/3.1",
"-alpn", "-alpn",
"http/1.1,spdy/3.1"]) "http/1.1,spdy/3.1",
],
)
} }
fn new_dtlsv1<I>(input: I) -> (Server, UdpConnected) fn new_dtlsv1<I>(input: I) -> (Server, UdpConnected)
where I: IntoIterator<Item = &'static str>, where
I::IntoIter: Send + 'static I: IntoIterator<Item = &'static str>,
I::IntoIter: Send + 'static,
{ {
let mut input = input.into_iter(); let mut input = input.into_iter();
let (s, addr) = Server::spawn(&["-dtls1"], let (s, addr) = Server::spawn(
Some(Box::new(move |mut io| { &["-dtls1"],
for s in input.by_ref() { Some(Box::new(move |mut io| for s in input.by_ref() {
if io.write_all(s.as_bytes()).is_err() { if io.write_all(s.as_bytes()).is_err() {
break; break;
} }
} })),
}))); );
// Need to wait for the UDP socket to get bound in our child process, // Need to wait for the UDP socket to get bound in our child process,
// but don't currently have a great way to do that so just wait for a // but don't currently have a great way to do that so just wait for a
// bit. // bit.
@ -199,9 +206,10 @@ macro_rules! run_test(
); );
); );
run_test!(new_ctx, |method, _| { run_test!(
SslContext::builder(method).unwrap(); new_ctx,
}); |method, _| { SslContext::builder(method).unwrap(); }
);
run_test!(verify_untrusted, |method, stream| { run_test!(verify_untrusted, |method, stream| {
let mut ctx = SslContext::builder(method).unwrap(); let mut ctx = SslContext::builder(method).unwrap();
@ -395,8 +403,10 @@ fn test_write_hits_stream() {
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_verify(SSL_VERIFY_PEER); ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); .unwrap();
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap();
let stream = listener.accept().unwrap().0; let stream = listener.accept().unwrap().0;
let mut stream = Ssl::new(&ctx.build()).unwrap().accept(stream).unwrap(); let mut stream = Ssl::new(&ctx.build()).unwrap().accept(stream).unwrap();
@ -488,7 +498,9 @@ fn test_read() {
let mut stream = Ssl::new(&ctx.build()).unwrap().connect(tcp).unwrap(); let mut stream = Ssl::new(&ctx.build()).unwrap().connect(tcp).unwrap();
stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap();
stream.flush().unwrap(); stream.flush().unwrap();
io::copy(&mut stream, &mut io::sink()).ok().expect("read error"); io::copy(&mut stream, &mut io::sink()).ok().expect(
"read error",
);
} }
#[test] #[test]
@ -521,8 +533,10 @@ fn test_state() {
let ctx = SslContext::builder(SslMethod::tls()).unwrap(); let ctx = SslContext::builder(SslMethod::tls()).unwrap();
let stream = Ssl::new(&ctx.build()).unwrap().connect(tcp).unwrap(); let stream = Ssl::new(&ctx.build()).unwrap().connect(tcp).unwrap();
assert_eq!(stream.ssl().state_string(), "SSLOK "); assert_eq!(stream.ssl().state_string(), "SSLOK ");
assert_eq!(stream.ssl().state_string_long(), assert_eq!(
"SSL negotiation finished successfully"); stream.ssl().state_string_long(),
"SSL negotiation finished successfully"
);
} }
/// Tests that connecting with the client using ALPN, but the server not does not /// Tests that connecting with the client using ALPN, but the server not does not
@ -670,8 +684,10 @@ fn test_npn_server_advertise_multiple() {
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_verify(SSL_VERIFY_PEER); ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap();
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) assert!(
.is_ok()); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
.is_ok()
);
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap(); .unwrap();
ctx.build() ctx.build()
@ -711,8 +727,10 @@ fn test_alpn_server_advertise_multiple() {
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_verify(SSL_VERIFY_PEER); ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap();
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) assert!(
.is_ok()); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
.is_ok()
);
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap(); .unwrap();
ctx.build() ctx.build()
@ -752,8 +770,10 @@ fn test_alpn_server_select_none() {
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_verify(SSL_VERIFY_PEER); ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap();
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) assert!(
.is_ok()); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
.is_ok()
);
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap(); .unwrap();
ctx.build() ctx.build()
@ -990,7 +1010,11 @@ fn flush_panic() {
let stream = ExplodingStream(stream); let stream = ExplodingStream(stream);
let ctx = SslContext::builder(SslMethod::tls()).unwrap(); let ctx = SslContext::builder(SslMethod::tls()).unwrap();
let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).ok().unwrap(); let mut stream = Ssl::new(&ctx.build())
.unwrap()
.connect(stream)
.ok()
.unwrap();
let _ = stream.flush(); let _ = stream.flush();
} }
@ -1040,7 +1064,9 @@ fn verify_valid_hostname() {
ctx.set_verify(SSL_VERIFY_PEER); ctx.set_verify(SSL_VERIFY_PEER);
let mut ssl = Ssl::new(&ctx.build()).unwrap(); let mut ssl = Ssl::new(&ctx.build()).unwrap();
ssl.param_mut().set_hostflags(X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); ssl.param_mut().set_hostflags(
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS,
);
ssl.param_mut().set_host("google.com").unwrap(); ssl.param_mut().set_host("google.com").unwrap();
let s = TcpStream::connect("google.com:443").unwrap(); let s = TcpStream::connect("google.com:443").unwrap();
@ -1063,7 +1089,9 @@ fn verify_invalid_hostname() {
ctx.set_verify(SSL_VERIFY_PEER); ctx.set_verify(SSL_VERIFY_PEER);
let mut ssl = Ssl::new(&ctx.build()).unwrap(); let mut ssl = Ssl::new(&ctx.build()).unwrap();
ssl.param_mut().set_hostflags(X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); ssl.param_mut().set_hostflags(
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS,
);
ssl.param_mut().set_host("foobar.com").unwrap(); ssl.param_mut().set_host("foobar.com").unwrap();
let s = TcpStream::connect("google.com:443").unwrap(); let s = TcpStream::connect("google.com:443").unwrap();
@ -1143,7 +1171,10 @@ fn connector_client_server_mozilla_intermediate() {
}); });
let mut connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); let mut connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
connector.builder_mut().set_ca_file("test/root-ca.pem").unwrap(); connector
.builder_mut()
.set_ca_file("test/root-ca.pem")
.unwrap();
let connector = connector.build(); let connector = connector.build();
let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); let stream = TcpStream::connect(("127.0.0.1", port)).unwrap();
@ -1175,7 +1206,10 @@ fn connector_client_server_mozilla_modern() {
}); });
let mut connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); let mut connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
connector.builder_mut().set_ca_file("test/root-ca.pem").unwrap(); connector
.builder_mut()
.set_ca_file("test/root-ca.pem")
.unwrap();
let connector = connector.build(); let connector = connector.build();
let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); let stream = TcpStream::connect(("127.0.0.1", port)).unwrap();
@ -1196,8 +1230,10 @@ fn shutdown() {
thread::spawn(move || { thread::spawn(move || {
let stream = listener.accept().unwrap().0; let stream = listener.accept().unwrap().0;
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); .unwrap();
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap();
let ssl = Ssl::new(&ctx.build()).unwrap(); let ssl = Ssl::new(&ctx.build()).unwrap();
let mut stream = ssl.accept(stream).unwrap(); let mut stream = ssl.accept(stream).unwrap();
@ -1252,8 +1288,10 @@ fn tmp_dh_callback() {
thread::spawn(move || { thread::spawn(move || {
let stream = listener.accept().unwrap().0; let stream = listener.accept().unwrap().0;
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); .unwrap();
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap();
ctx.set_tmp_dh_callback(|_, _, _| { ctx.set_tmp_dh_callback(|_, _, _| {
CALLED_BACK.store(true, Ordering::SeqCst); CALLED_BACK.store(true, Ordering::SeqCst);
let dh = include_bytes!("../../../test/dhparams.pem"); let dh = include_bytes!("../../../test/dhparams.pem");
@ -1286,8 +1324,10 @@ fn tmp_ecdh_callback() {
thread::spawn(move || { thread::spawn(move || {
let stream = listener.accept().unwrap().0; let stream = listener.accept().unwrap().0;
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); .unwrap();
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap();
ctx.set_tmp_ecdh_callback(|_, _, _| { ctx.set_tmp_ecdh_callback(|_, _, _| {
CALLED_BACK.store(true, Ordering::SeqCst); CALLED_BACK.store(true, Ordering::SeqCst);
EcKey::new_by_curve_name(nid::X9_62_PRIME256V1) EcKey::new_by_curve_name(nid::X9_62_PRIME256V1)
@ -1315,8 +1355,10 @@ fn tmp_dh_callback_ssl() {
thread::spawn(move || { thread::spawn(move || {
let stream = listener.accept().unwrap().0; let stream = listener.accept().unwrap().0;
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); .unwrap();
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap();
let mut ssl = Ssl::new(&ctx.build()).unwrap(); let mut ssl = Ssl::new(&ctx.build()).unwrap();
ssl.set_tmp_dh_callback(|_, _, _| { ssl.set_tmp_dh_callback(|_, _, _| {
CALLED_BACK.store(true, Ordering::SeqCst); CALLED_BACK.store(true, Ordering::SeqCst);
@ -1349,8 +1391,10 @@ fn tmp_ecdh_callback_ssl() {
thread::spawn(move || { thread::spawn(move || {
let stream = listener.accept().unwrap().0; let stream = listener.accept().unwrap().0;
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); .unwrap();
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap();
let mut ssl = Ssl::new(&ctx.build()).unwrap(); let mut ssl = Ssl::new(&ctx.build()).unwrap();
ssl.set_tmp_ecdh_callback(|_, _, _| { ssl.set_tmp_ecdh_callback(|_, _, _| {
CALLED_BACK.store(true, Ordering::SeqCst); CALLED_BACK.store(true, Ordering::SeqCst);
@ -1402,8 +1446,10 @@ fn status_callbacks() {
let guard = thread::spawn(move || { let guard = thread::spawn(move || {
let stream = listener.accept().unwrap().0; let stream = listener.accept().unwrap().0;
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM)
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); .unwrap();
ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM)
.unwrap();
ctx.set_status_callback(|ssl| { ctx.set_status_callback(|ssl| {
CALLED_BACK_SERVER.store(true, Ordering::SeqCst); CALLED_BACK_SERVER.store(true, Ordering::SeqCst);
let response = OcspResponse::create(RESPONSE_STATUS_UNAUTHORIZED, None).unwrap(); let response = OcspResponse::create(RESPONSE_STATUS_UNAUTHORIZED, None).unwrap();

View File

@ -15,12 +15,13 @@ mod imp {
} }
} }
pub unsafe fn select<F: AsRawFd>(max: &F, pub unsafe fn select<F: AsRawFd>(
max: &F,
read: *mut fd_set, read: *mut fd_set,
write: *mut fd_set, write: *mut fd_set,
error: *mut fd_set, error: *mut fd_set,
timeout_ms: u32) timeout_ms: u32,
-> io::Result<bool> { ) -> io::Result<bool> {
let mut timeout = libc::timeval { let mut timeout = libc::timeval {
tv_sec: (timeout_ms / 1000) as libc::time_t, tv_sec: (timeout_ms / 1000) as libc::time_t,
tv_usec: (timeout_ms % 1000 * 1000) as libc::suseconds_t, tv_usec: (timeout_ms % 1000 * 1000) as libc::suseconds_t,
@ -52,12 +53,13 @@ mod imp {
set.fd_count += 1; set.fd_count += 1;
} }
pub unsafe fn select<F: AsRawSocket>(_max: &F, pub unsafe fn select<F: AsRawSocket>(
_max: &F,
read: *mut fd_set, read: *mut fd_set,
write: *mut fd_set, write: *mut fd_set,
error: *mut fd_set, error: *mut fd_set,
timeout_ms: u32) timeout_ms: u32,
-> io::Result<bool> { ) -> io::Result<bool> {
let mut timeout = winsock2::timeval { let mut timeout = winsock2::timeval {
tv_sec: (timeout_ms / 1000) as c_long, tv_sec: (timeout_ms / 1000) as c_long,
tv_usec: (timeout_ms % 1000 * 1000) as c_long, tv_usec: (timeout_ms % 1000 * 1000) as c_long,

View File

@ -86,8 +86,11 @@ impl<T: Stackable> ForeignType for Stack<T> {
#[inline] #[inline]
unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack<T> { unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack<T> {
assert!(!ptr.is_null(), "Must not instantiate a Stack from a null-ptr - use Stack::new() in \ assert!(
that case"); !ptr.is_null(),
"Must not instantiate a Stack from a null-ptr - use Stack::new() in \
that case"
);
Stack(ptr) Stack(ptr)
} }
@ -217,7 +220,9 @@ impl<T: Stackable> StackRef<T> {
/// Pushes a value onto the top of the stack. /// Pushes a value onto the top of the stack.
pub fn push(&mut self, data: T) -> Result<(), ErrorStack> { pub fn push(&mut self, data: T) -> Result<(), ErrorStack> {
unsafe { unsafe {
try!(cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _))); try!(cvt(
OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _),
));
mem::forget(data); mem::forget(data);
Ok(()) Ok(())
} }
@ -292,7 +297,8 @@ impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack<T> {
/// An iterator over the stack's contents. /// An iterator over the stack's contents.
pub struct Iter<'a, T: Stackable> pub struct Iter<'a, T: Stackable>
where T: 'a where
T: 'a,
{ {
stack: &'a StackRef<T>, stack: &'a StackRef<T>,
pos: usize, pos: usize,

View File

@ -74,7 +74,9 @@ unsafe fn free(buf: *mut c_char) {
#[cfg(ossl110)] #[cfg(ossl110)]
unsafe fn free(buf: *mut c_char) { unsafe fn free(buf: *mut c_char) {
::ffi::CRYPTO_free(buf as *mut c_void, ::ffi::CRYPTO_free(
buf as *mut c_void,
concat!(file!(), "\0").as_ptr() as *const c_char, concat!(file!(), "\0").as_ptr() as *const c_char,
line!() as ::libc::c_int); line!() as ::libc::c_int,
);
} }

View File

@ -164,11 +164,12 @@ impl Crypter {
/// # Panics /// # Panics
/// ///
/// Panics if an IV is required by the cipher but not provided. /// Panics if an IV is required by the cipher but not provided.
pub fn new(t: Cipher, pub fn new(
t: Cipher,
mode: Mode, mode: Mode,
key: &[u8], key: &[u8],
iv: Option<&[u8]>) iv: Option<&[u8]>,
-> Result<Crypter, ErrorStack> { ) -> Result<Crypter, ErrorStack> {
ffi::init(); ffi::init();
unsafe { unsafe {
@ -183,37 +184,46 @@ impl Crypter {
Mode::Decrypt => 0, Mode::Decrypt => 0,
}; };
try!(cvt(ffi::EVP_CipherInit_ex(crypter.ctx, try!(cvt(ffi::EVP_CipherInit_ex(
crypter.ctx,
t.as_ptr(), t.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
mode))); mode,
)));
assert!(key.len() <= c_int::max_value() as usize); assert!(key.len() <= c_int::max_value() as usize);
try!(cvt(ffi::EVP_CIPHER_CTX_set_key_length(crypter.ctx, key.len() as c_int))); try!(cvt(ffi::EVP_CIPHER_CTX_set_key_length(
crypter.ctx,
key.len() as c_int,
)));
let key = key.as_ptr() as *mut _; let key = key.as_ptr() as *mut _;
let iv = match (iv, t.iv_len()) { let iv = match (iv, t.iv_len()) {
(Some(iv), Some(len)) => { (Some(iv), Some(len)) => {
if iv.len() != len { if iv.len() != len {
assert!(iv.len() <= c_int::max_value() as usize); assert!(iv.len() <= c_int::max_value() as usize);
try!(cvt(ffi::EVP_CIPHER_CTX_ctrl(crypter.ctx, try!(cvt(ffi::EVP_CIPHER_CTX_ctrl(
crypter.ctx,
ffi::EVP_CTRL_GCM_SET_IVLEN, ffi::EVP_CTRL_GCM_SET_IVLEN,
iv.len() as c_int, iv.len() as c_int,
ptr::null_mut()))); ptr::null_mut(),
)));
} }
iv.as_ptr() as *mut _ iv.as_ptr() as *mut _
} }
(Some(_), None) | (None, None) => ptr::null_mut(), (Some(_), None) | (None, None) => ptr::null_mut(),
(None, Some(_)) => panic!("an IV is required for this cipher"), (None, Some(_)) => panic!("an IV is required for this cipher"),
}; };
try!(cvt(ffi::EVP_CipherInit_ex(crypter.ctx, try!(cvt(ffi::EVP_CipherInit_ex(
crypter.ctx,
ptr::null(), ptr::null(),
ptr::null_mut(), ptr::null_mut(),
key, key,
iv, iv,
mode))); mode,
)));
Ok(crypter) Ok(crypter)
} }
@ -236,11 +246,12 @@ impl Crypter {
unsafe { unsafe {
assert!(tag.len() <= c_int::max_value() as usize); assert!(tag.len() <= c_int::max_value() as usize);
// NB: this constant is actually more general than just GCM. // NB: this constant is actually more general than just GCM.
cvt(ffi::EVP_CIPHER_CTX_ctrl(self.ctx, cvt(ffi::EVP_CIPHER_CTX_ctrl(
self.ctx,
ffi::EVP_CTRL_GCM_SET_TAG, ffi::EVP_CTRL_GCM_SET_TAG,
tag.len() as c_int, tag.len() as c_int,
tag.as_ptr() as *mut _)) tag.as_ptr() as *mut _,
.map(|_| ()) )).map(|_| ())
} }
} }
@ -253,12 +264,13 @@ impl Crypter {
unsafe { unsafe {
assert!(input.len() <= c_int::max_value() as usize); assert!(input.len() <= c_int::max_value() as usize);
let mut len = 0; let mut len = 0;
cvt(ffi::EVP_CipherUpdate(self.ctx, cvt(ffi::EVP_CipherUpdate(
self.ctx,
ptr::null_mut(), ptr::null_mut(),
&mut len, &mut len,
input.as_ptr(), input.as_ptr(),
input.len() as c_int)) input.len() as c_int,
.map(|_| ()) )).map(|_| ())
} }
} }
@ -280,11 +292,13 @@ impl Crypter {
let mut outl = output.len() as c_int; let mut outl = output.len() as c_int;
let inl = input.len() as c_int; let inl = input.len() as c_int;
try!(cvt(ffi::EVP_CipherUpdate(self.ctx, try!(cvt(ffi::EVP_CipherUpdate(
self.ctx,
output.as_mut_ptr(), output.as_mut_ptr(),
&mut outl, &mut outl,
input.as_ptr(), input.as_ptr(),
inl))); inl,
)));
Ok(outl as usize) Ok(outl as usize)
} }
@ -305,7 +319,11 @@ impl Crypter {
assert!(output.len() >= self.block_size); assert!(output.len() >= self.block_size);
let mut outl = cmp::min(output.len(), c_int::max_value() as usize) as c_int; let mut outl = cmp::min(output.len(), c_int::max_value() as usize) as c_int;
try!(cvt(ffi::EVP_CipherFinal(self.ctx, output.as_mut_ptr(), &mut outl))); try!(cvt(ffi::EVP_CipherFinal(
self.ctx,
output.as_mut_ptr(),
&mut outl,
)));
Ok(outl as usize) Ok(outl as usize)
} }
@ -322,11 +340,12 @@ impl Crypter {
pub fn get_tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> { pub fn get_tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> {
unsafe { unsafe {
assert!(tag.len() <= c_int::max_value() as usize); assert!(tag.len() <= c_int::max_value() as usize);
cvt(ffi::EVP_CIPHER_CTX_ctrl(self.ctx, cvt(ffi::EVP_CIPHER_CTX_ctrl(
self.ctx,
ffi::EVP_CTRL_GCM_GET_TAG, ffi::EVP_CTRL_GCM_GET_TAG,
tag.len() as c_int, tag.len() as c_int,
tag.as_mut_ptr() as *mut _)) tag.as_mut_ptr() as *mut _,
.map(|_| ()) )).map(|_| ())
} }
} }
} }
@ -339,36 +358,39 @@ impl Drop for Crypter {
} }
} }
/** #[doc = /**
* Encrypts data, using the specified crypter type in encrypt mode with the * Encrypts data, using the specified crypter type in encrypt mode with the
* specified key and iv; returns the resulting (encrypted) data. * specified key and iv; returns the resulting (encrypted) data.
*/ */]
pub fn encrypt(t: Cipher, pub fn encrypt(
t: Cipher,
key: &[u8], key: &[u8],
iv: Option<&[u8]>, iv: Option<&[u8]>,
data: &[u8]) data: &[u8],
-> Result<Vec<u8>, ErrorStack> { ) -> Result<Vec<u8>, ErrorStack> {
cipher(t, Mode::Encrypt, key, iv, data) cipher(t, Mode::Encrypt, key, iv, data)
} }
/** #[doc = /**
* Decrypts data, using the specified crypter type in decrypt mode with the * Decrypts data, using the specified crypter type in decrypt mode with the
* specified key and iv; returns the resulting (decrypted) data. * specified key and iv; returns the resulting (decrypted) data.
*/ */]
pub fn decrypt(t: Cipher, pub fn decrypt(
t: Cipher,
key: &[u8], key: &[u8],
iv: Option<&[u8]>, iv: Option<&[u8]>,
data: &[u8]) data: &[u8],
-> Result<Vec<u8>, ErrorStack> { ) -> Result<Vec<u8>, ErrorStack> {
cipher(t, Mode::Decrypt, key, iv, data) cipher(t, Mode::Decrypt, key, iv, data)
} }
fn cipher(t: Cipher, fn cipher(
t: Cipher,
mode: Mode, mode: Mode,
key: &[u8], key: &[u8],
iv: Option<&[u8]>, iv: Option<&[u8]>,
data: &[u8]) data: &[u8],
-> Result<Vec<u8>, ErrorStack> { ) -> Result<Vec<u8>, ErrorStack> {
let mut c = try!(Crypter::new(t, mode, key, iv)); let mut c = try!(Crypter::new(t, mode, key, iv));
let mut out = vec![0; data.len() + t.block_size()]; let mut out = vec![0; data.len() + t.block_size()];
let count = try!(c.update(data, &mut out)); let count = try!(c.update(data, &mut out));
@ -385,13 +407,14 @@ fn cipher(t: Cipher,
/// The size of the `tag` buffer indicates the required size of the tag. While some ciphers support /// The size of the `tag` buffer indicates the required size of the tag. While some ciphers support
/// a range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16 bytes, /// a range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16 bytes,
/// for example. /// for example.
pub fn encrypt_aead(t: Cipher, pub fn encrypt_aead(
t: Cipher,
key: &[u8], key: &[u8],
iv: Option<&[u8]>, iv: Option<&[u8]>,
aad: &[u8], aad: &[u8],
data: &[u8], data: &[u8],
tag: &mut [u8]) tag: &mut [u8],
-> Result<Vec<u8>, ErrorStack> { ) -> Result<Vec<u8>, ErrorStack> {
let mut c = try!(Crypter::new(t, Mode::Encrypt, key, iv)); let mut c = try!(Crypter::new(t, Mode::Encrypt, key, iv));
let mut out = vec![0; data.len() + t.block_size()]; let mut out = vec![0; data.len() + t.block_size()];
try!(c.aad_update(aad)); try!(c.aad_update(aad));
@ -406,13 +429,14 @@ pub fn encrypt_aead(t: Cipher,
/// ///
/// Additional Authenticated Data can be provided in the `aad` field, and the authentication tag /// Additional Authenticated Data can be provided in the `aad` field, and the authentication tag
/// should be provided in the `tag` field. /// should be provided in the `tag` field.
pub fn decrypt_aead(t: Cipher, pub fn decrypt_aead(
t: Cipher,
key: &[u8], key: &[u8],
iv: Option<&[u8]>, iv: Option<&[u8]>,
aad: &[u8], aad: &[u8],
data: &[u8], data: &[u8],
tag: &[u8]) tag: &[u8],
-> Result<Vec<u8>, ErrorStack> { ) -> Result<Vec<u8>, ErrorStack> {
let mut c = try!(Crypter::new(t, Mode::Decrypt, key, iv)); let mut c = try!(Crypter::new(t, Mode::Decrypt, key, iv));
let mut out = vec![0; data.len() + t.block_size()]; let mut out = vec![0; data.len() + t.block_size()];
try!(c.aad_update(aad)); try!(c.aad_update(aad));
@ -456,19 +480,82 @@ mod tests {
// http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf // http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
#[test] #[test]
fn test_aes_256_ecb() { fn test_aes_256_ecb() {
let k0 = [0x00u8, 0x01u8, 0x02u8, 0x03u8, 0x04u8, 0x05u8, 0x06u8, 0x07u8, 0x08u8, 0x09u8, let k0 = [
0x0au8, 0x0bu8, 0x0cu8, 0x0du8, 0x0eu8, 0x0fu8, 0x10u8, 0x11u8, 0x12u8, 0x13u8, 0x00u8,
0x14u8, 0x15u8, 0x16u8, 0x17u8, 0x18u8, 0x19u8, 0x1au8, 0x1bu8, 0x1cu8, 0x1du8, 0x01u8,
0x1eu8, 0x1fu8]; 0x02u8,
let p0 = [0x00u8, 0x11u8, 0x22u8, 0x33u8, 0x44u8, 0x55u8, 0x66u8, 0x77u8, 0x88u8, 0x99u8, 0x03u8,
0xaau8, 0xbbu8, 0xccu8, 0xddu8, 0xeeu8, 0xffu8]; 0x04u8,
let c0 = [0x8eu8, 0xa2u8, 0xb7u8, 0xcau8, 0x51u8, 0x67u8, 0x45u8, 0xbfu8, 0xeau8, 0xfcu8, 0x05u8,
0x49u8, 0x90u8, 0x4bu8, 0x49u8, 0x60u8, 0x89u8]; 0x06u8,
let mut c = super::Crypter::new(super::Cipher::aes_256_ecb(), 0x07u8,
0x08u8,
0x09u8,
0x0au8,
0x0bu8,
0x0cu8,
0x0du8,
0x0eu8,
0x0fu8,
0x10u8,
0x11u8,
0x12u8,
0x13u8,
0x14u8,
0x15u8,
0x16u8,
0x17u8,
0x18u8,
0x19u8,
0x1au8,
0x1bu8,
0x1cu8,
0x1du8,
0x1eu8,
0x1fu8,
];
let p0 = [
0x00u8,
0x11u8,
0x22u8,
0x33u8,
0x44u8,
0x55u8,
0x66u8,
0x77u8,
0x88u8,
0x99u8,
0xaau8,
0xbbu8,
0xccu8,
0xddu8,
0xeeu8,
0xffu8,
];
let c0 = [
0x8eu8,
0xa2u8,
0xb7u8,
0xcau8,
0x51u8,
0x67u8,
0x45u8,
0xbfu8,
0xeau8,
0xfcu8,
0x49u8,
0x90u8,
0x4bu8,
0x49u8,
0x60u8,
0x89u8,
];
let mut c = super::Crypter::new(
super::Cipher::aes_256_ecb(),
super::Mode::Encrypt, super::Mode::Encrypt,
&k0, &k0,
None) None,
.unwrap(); ).unwrap();
c.pad(false); c.pad(false);
let mut r0 = vec![0; c0.len() + super::Cipher::aes_256_ecb().block_size()]; let mut r0 = vec![0; c0.len() + super::Cipher::aes_256_ecb().block_size()];
let count = c.update(&p0, &mut r0).unwrap(); let count = c.update(&p0, &mut r0).unwrap();
@ -476,11 +563,12 @@ mod tests {
r0.truncate(count + rest); r0.truncate(count + rest);
assert_eq!(r0.to_hex(), c0.to_hex()); assert_eq!(r0.to_hex(), c0.to_hex());
let mut c = super::Crypter::new(super::Cipher::aes_256_ecb(), let mut c = super::Crypter::new(
super::Cipher::aes_256_ecb(),
super::Mode::Decrypt, super::Mode::Decrypt,
&k0, &k0,
None) None,
.unwrap(); ).unwrap();
c.pad(false); c.pad(false);
let mut p1 = vec![0; r0.len() + super::Cipher::aes_256_ecb().block_size()]; let mut p1 = vec![0; r0.len() + super::Cipher::aes_256_ecb().block_size()];
let count = c.update(&r0, &mut p1).unwrap(); let count = c.update(&r0, &mut p1).unwrap();
@ -491,20 +579,82 @@ mod tests {
#[test] #[test]
fn test_aes_256_cbc_decrypt() { fn test_aes_256_cbc_decrypt() {
let iv = [4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, 69_u8, let iv = [
98_u8, 107_u8, 208_u8, 14_u8, 236_u8, 60_u8]; 4_u8,
let data = [143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, 223_u8,
154_u8, 56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, 153_u8,
55_u8, 119_u8, 233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, 219_u8,
65_u8, 207_u8]; 28_u8,
let ciphered_data = [0x4a_u8, 0x2e_u8, 0xe5_u8, 0x6_u8, 0xbf_u8, 0xcf_u8, 0xf2_u8, 142_u8,
0xd7_u8, 0xea_u8, 0x2d_u8, 0xb1_u8, 0x85_u8, 0x6c_u8, 0x93_u8, 234_u8,
0x65_u8, 0x6f_u8]; 68_u8,
let mut cr = super::Crypter::new(super::Cipher::aes_256_cbc(), 227_u8,
69_u8,
98_u8,
107_u8,
208_u8,
14_u8,
236_u8,
60_u8,
];
let data = [
143_u8,
210_u8,
75_u8,
63_u8,
214_u8,
179_u8,
155_u8,
241_u8,
242_u8,
31_u8,
154_u8,
56_u8,
198_u8,
145_u8,
192_u8,
64_u8,
2_u8,
245_u8,
167_u8,
220_u8,
55_u8,
119_u8,
233_u8,
136_u8,
139_u8,
27_u8,
71_u8,
242_u8,
119_u8,
175_u8,
65_u8,
207_u8,
];
let ciphered_data = [
0x4a_u8,
0x2e_u8,
0xe5_u8,
0x6_u8,
0xbf_u8,
0xcf_u8,
0xf2_u8,
0xd7_u8,
0xea_u8,
0x2d_u8,
0xb1_u8,
0x85_u8,
0x6c_u8,
0x93_u8,
0x65_u8,
0x6f_u8,
];
let mut cr = super::Crypter::new(
super::Cipher::aes_256_cbc(),
super::Mode::Decrypt, super::Mode::Decrypt,
&data, &data,
Some(&iv)) Some(&iv),
.unwrap(); ).unwrap();
cr.pad(false); cr.pad(false);
let mut unciphered_data = vec![0; data.len() + super::Cipher::aes_256_cbc().block_size()]; let mut unciphered_data = vec![0; data.len() + super::Cipher::aes_256_cbc().block_size()];
let count = cr.update(&ciphered_data, &mut unciphered_data).unwrap(); let count = cr.update(&ciphered_data, &mut unciphered_data).unwrap();
@ -529,9 +679,11 @@ mod tests {
println!("Computed: {}", computed.to_hex()); println!("Computed: {}", computed.to_hex());
println!("Expected: {}", expected.to_hex()); println!("Expected: {}", expected.to_hex());
if computed.len() != expected.len() { if computed.len() != expected.len() {
println!("Lengths differ: {} in computed vs {} expected", println!(
"Lengths differ: {} in computed vs {} expected",
computed.len(), computed.len(),
expected.len()); expected.len()
);
} }
panic!("test failure"); panic!("test failure");
} }
@ -558,9 +710,11 @@ mod tests {
println!("Computed: {}", computed.to_hex()); println!("Computed: {}", computed.to_hex());
println!("Expected: {}", expected.to_hex()); println!("Expected: {}", expected.to_hex());
if computed.len() != expected.len() { if computed.len() != expected.len() {
println!("Lengths differ: {} in computed vs {} expected", println!(
"Lengths differ: {} in computed vs {} expected",
computed.len(), computed.len(),
expected.len()); expected.len()
);
} }
panic!("test failure"); panic!("test failure");
} }
@ -742,41 +896,40 @@ mod tests {
#[test] #[test]
fn test_aes128_gcm() { fn test_aes128_gcm() {
let key = "0e00c76561d2bd9b40c3c15427e2b08f"; let key = "0e00c76561d2bd9b40c3c15427e2b08f";
let iv = let iv = "492cadaccd3ca3fbc9cf9f06eb3325c4e159850b0dbe98199b89b7af528806610b6f63998e1eae80c348e7\
"492cadaccd3ca3fbc9cf9f06eb3325c4e159850b0dbe98199b89b7af528806610b6f63998e1eae80c348e7\
4cbb921d8326631631fc6a5d304f39166daf7ea15fa1977f101819adb510b50fe9932e12c5a85aa3fd1e73\ 4cbb921d8326631631fc6a5d304f39166daf7ea15fa1977f101819adb510b50fe9932e12c5a85aa3fd1e73\
d8d760af218be829903a77c63359d75edd91b4f6ed5465a72662f5055999e059e7654a8edc921aa0d496"; d8d760af218be829903a77c63359d75edd91b4f6ed5465a72662f5055999e059e7654a8edc921aa0d496";
let pt = let pt = "fef03c2d7fb15bf0d2df18007d99f967c878ad59359034f7bb2c19af120685d78e32f6b8b83b032019956c\
"fef03c2d7fb15bf0d2df18007d99f967c878ad59359034f7bb2c19af120685d78e32f6b8b83b032019956c\
a9c0195721476b85"; a9c0195721476b85";
let aad = let aad = "d8f1163d8c840292a2b2dacf4ac7c36aff8733f18fabb4fa5594544125e03d1e6e5d6d0fd61656c8d8f327\
"d8f1163d8c840292a2b2dacf4ac7c36aff8733f18fabb4fa5594544125e03d1e6e5d6d0fd61656c8d8f327\
c92839ae5539bb469c9257f109ebff85aad7bd220fdaa95c022dbd0c7bb2d878ad504122c943045d3c5eba\ c92839ae5539bb469c9257f109ebff85aad7bd220fdaa95c022dbd0c7bb2d878ad504122c943045d3c5eba\
8f1f56c0"; 8f1f56c0";
let ct = let ct = "4f6cf471be7cbd2575cd5a1747aea8fe9dea83e51936beac3e68f66206922060c697ffa7af80ad6bb68f2c\
"4f6cf471be7cbd2575cd5a1747aea8fe9dea83e51936beac3e68f66206922060c697ffa7af80ad6bb68f2c\
f4fc97416ee52abe"; f4fc97416ee52abe";
let tag = "e20b6655"; let tag = "e20b6655";
// this tag is smaller than you'd normally want, but I pulled this test from the part of // this tag is smaller than you'd normally want, but I pulled this test from the part of
// the NIST test vectors that cover 4 byte tags. // the NIST test vectors that cover 4 byte tags.
let mut actual_tag = [0; 4]; let mut actual_tag = [0; 4];
let out = encrypt_aead(Cipher::aes_128_gcm(), let out = encrypt_aead(
Cipher::aes_128_gcm(),
&Vec::from_hex(key).unwrap(), &Vec::from_hex(key).unwrap(),
Some(&Vec::from_hex(iv).unwrap()), Some(&Vec::from_hex(iv).unwrap()),
&Vec::from_hex(aad).unwrap(), &Vec::from_hex(aad).unwrap(),
&Vec::from_hex(pt).unwrap(), &Vec::from_hex(pt).unwrap(),
&mut actual_tag) &mut actual_tag,
.unwrap(); ).unwrap();
assert_eq!(ct, out.to_hex()); assert_eq!(ct, out.to_hex());
assert_eq!(tag, actual_tag.to_hex()); assert_eq!(tag, actual_tag.to_hex());
let out = decrypt_aead(Cipher::aes_128_gcm(), let out = decrypt_aead(
Cipher::aes_128_gcm(),
&Vec::from_hex(key).unwrap(), &Vec::from_hex(key).unwrap(),
Some(&Vec::from_hex(iv).unwrap()), Some(&Vec::from_hex(iv).unwrap()),
&Vec::from_hex(aad).unwrap(), &Vec::from_hex(aad).unwrap(),
&Vec::from_hex(ct).unwrap(), &Vec::from_hex(ct).unwrap(),
&Vec::from_hex(tag).unwrap()).unwrap(); &Vec::from_hex(tag).unwrap(),
).unwrap();
assert_eq!(pt, out.to_hex()); assert_eq!(pt, out.to_hex());
} }
@ -808,23 +961,25 @@ mod tests {
let tag = "1ae10b594f09e26a7e902ecbd0600691"; let tag = "1ae10b594f09e26a7e902ecbd0600691";
let mut actual_tag = [0; 16]; let mut actual_tag = [0; 16];
let out = encrypt_aead(Cipher::chacha20_poly1305(), let out = encrypt_aead(
Cipher::chacha20_poly1305(),
&Vec::from_hex(key).unwrap(), &Vec::from_hex(key).unwrap(),
Some(&Vec::from_hex(iv).unwrap()), Some(&Vec::from_hex(iv).unwrap()),
&Vec::from_hex(aad).unwrap(), &Vec::from_hex(aad).unwrap(),
&Vec::from_hex(pt).unwrap(), &Vec::from_hex(pt).unwrap(),
&mut actual_tag) &mut actual_tag,
.unwrap(); ).unwrap();
assert_eq!(ct, out.to_hex()); assert_eq!(ct, out.to_hex());
assert_eq!(tag, actual_tag.to_hex()); assert_eq!(tag, actual_tag.to_hex());
let out = decrypt_aead(Cipher::chacha20_poly1305(), let out = decrypt_aead(
Cipher::chacha20_poly1305(),
&Vec::from_hex(key).unwrap(), &Vec::from_hex(key).unwrap(),
Some(&Vec::from_hex(iv).unwrap()), Some(&Vec::from_hex(iv).unwrap()),
&Vec::from_hex(aad).unwrap(), &Vec::from_hex(aad).unwrap(),
&Vec::from_hex(ct).unwrap(), &Vec::from_hex(ct).unwrap(),
&Vec::from_hex(tag).unwrap()) &Vec::from_hex(tag).unwrap(),
.unwrap(); ).unwrap();
assert_eq!(pt, out.to_hex()); assert_eq!(pt, out.to_hex());
} }
} }

View File

@ -35,12 +35,14 @@ impl<F> Drop for CallbackState<F> {
} }
} }
pub unsafe extern fn invoke_passwd_cb_old<F>(buf: *mut c_char, pub unsafe extern "C" fn invoke_passwd_cb_old<F>(
buf: *mut c_char,
size: c_int, size: c_int,
_rwflag: c_int, _rwflag: c_int,
cb_state: *mut c_void) cb_state: *mut c_void,
-> c_int ) -> c_int
where F: FnOnce(&mut [c_char]) -> usize where
F: FnOnce(&mut [c_char]) -> usize,
{ {
let callback = &mut *(cb_state as *mut CallbackState<F>); let callback = &mut *(cb_state as *mut CallbackState<F>);
@ -61,12 +63,14 @@ pub unsafe extern fn invoke_passwd_cb_old<F>(buf: *mut c_char,
/// Password callback function, passed to private key loading functions. /// Password callback function, passed to private key loading functions.
/// ///
/// `cb_state` is expected to be a pointer to a `CallbackState`. /// `cb_state` is expected to be a pointer to a `CallbackState`.
pub unsafe extern fn invoke_passwd_cb<F>(buf: *mut c_char, pub unsafe extern "C" fn invoke_passwd_cb<F>(
buf: *mut c_char,
size: c_int, size: c_int,
_rwflag: c_int, _rwflag: c_int,
cb_state: *mut c_void) cb_state: *mut c_void,
-> c_int ) -> c_int
where F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack> where
F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
{ {
let callback = &mut *(cb_state as *mut CallbackState<F>); let callback = &mut *(cb_state as *mut CallbackState<F>);

View File

@ -36,10 +36,11 @@ impl X509VerifyParamRef {
pub fn set_host(&mut self, host: &str) -> Result<(), ErrorStack> { pub fn set_host(&mut self, host: &str) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::X509_VERIFY_PARAM_set1_host(self.as_ptr(), cvt(ffi::X509_VERIFY_PARAM_set1_host(
self.as_ptr(),
host.as_ptr() as *const _, host.as_ptr() as *const _,
host.len())) host.len(),
.map(|_| ()) )).map(|_| ())
} }
} }
} }

View File

@ -54,28 +54,48 @@ pub fn number() -> i64 {
/// The text variant of the version number and the release date. For example, "OpenSSL 0.9.5a 1 Apr 2000". /// The text variant of the version number and the release date. For example, "OpenSSL 0.9.5a 1 Apr 2000".
pub fn version() -> &'static str { pub fn version() -> &'static str {
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_VERSION)).to_str().unwrap() } unsafe {
CStr::from_ptr(OpenSSL_version(OPENSSL_VERSION))
.to_str()
.unwrap()
}
} }
/// The compiler flags set for the compilation process in the form "compiler: ..." if available or /// The compiler flags set for the compilation process in the form "compiler: ..." if available or
/// "compiler: information not available" otherwise. /// "compiler: information not available" otherwise.
pub fn c_flags() -> &'static str { pub fn c_flags() -> &'static str {
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_CFLAGS)).to_str().unwrap() } unsafe {
CStr::from_ptr(OpenSSL_version(OPENSSL_CFLAGS))
.to_str()
.unwrap()
}
} }
/// The date of the build process in the form "built on: ..." if available or "built on: date not available" otherwise. /// The date of the build process in the form "built on: ..." if available or "built on: date not available" otherwise.
pub fn built_on() -> &'static str { pub fn built_on() -> &'static str {
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_BUILT_ON)).to_str().unwrap() } unsafe {
CStr::from_ptr(OpenSSL_version(OPENSSL_BUILT_ON))
.to_str()
.unwrap()
}
} }
/// The "Configure" target of the library build in the form "platform: ..." if available or "platform: information not available" otherwise. /// The "Configure" target of the library build in the form "platform: ..." if available or "platform: information not available" otherwise.
pub fn platform() -> &'static str { pub fn platform() -> &'static str {
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_PLATFORM)).to_str().unwrap() } unsafe {
CStr::from_ptr(OpenSSL_version(OPENSSL_PLATFORM))
.to_str()
.unwrap()
}
} }
/// The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "..."" if available or "OPENSSLDIR: N/A" otherwise. /// The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "..."" if available or "OPENSSLDIR: N/A" otherwise.
pub fn dir() -> &'static str { pub fn dir() -> &'static str {
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_DIR)).to_str().unwrap() } unsafe {
CStr::from_ptr(OpenSSL_version(OPENSSL_DIR))
.to_str()
.unwrap()
}
} }
/// This test ensures that we do not segfault when calling the functions of this module /// This test ensures that we do not segfault when calling the functions of this module
@ -90,9 +110,13 @@ fn test_versions() {
println!("Dir: '{}'", dir()); println!("Dir: '{}'", dir());
#[cfg(not(libressl))] #[cfg(not(libressl))]
fn expected_name() -> &'static str { "OpenSSL" } fn expected_name() -> &'static str {
"OpenSSL"
}
#[cfg(libressl)] #[cfg(libressl)]
fn expected_name() -> &'static str { "LibreSSL" } fn expected_name() -> &'static str {
"LibreSSL"
}
assert!(number() > 0); assert!(number() > 0);
assert!(version().starts_with(expected_name())); assert!(version().starts_with(expected_name()));

View File

@ -113,12 +113,20 @@ impl ToString for Extension {
&Extension::KeyUsage(ref purposes) => join(purposes.iter(), ","), &Extension::KeyUsage(ref purposes) => join(purposes.iter(), ","),
&Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(), ","), &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(), ","),
&Extension::SubjectAltName(ref names) => { &Extension::SubjectAltName(ref names) => {
join(names.iter().map(|&(ref opt, ref val)| opt.to_string() + ":" + &val), join(
",") names.iter().map(|&(ref opt, ref val)| {
opt.to_string() + ":" + &val
}),
",",
)
} }
&Extension::IssuerAltName(ref names) => { &Extension::IssuerAltName(ref names) => {
join(names.iter().map(|&(ref opt, ref val)| opt.to_string() + ":" + &val), join(
",") names.iter().map(|&(ref opt, ref val)| {
opt.to_string() + ":" + &val
}),
",",
)
} }
&Extension::OtherNid(_, ref value) => value.clone(), &Extension::OtherNid(_, ref value) => value.clone(),
&Extension::OtherStr(_, ref value) => value.clone(), &Extension::OtherStr(_, ref value) => value.clone(),
@ -361,10 +369,30 @@ impl KeyUsage {
let mut value = String::new(); let mut value = String::new();
let mut first = true; let mut first = true;
append(&mut value, &mut first, self.critical, "critical"); append(&mut value, &mut first, self.critical, "critical");
append(&mut value, &mut first, self.digital_signature, "digitalSignature"); append(
append(&mut value, &mut first, self.non_repudiation, "nonRepudiation"); &mut value,
append(&mut value, &mut first, self.key_encipherment, "keyEncipherment"); &mut first,
append(&mut value, &mut first, self.data_encipherment, "dataEncipherment"); self.digital_signature,
"digitalSignature",
);
append(
&mut value,
&mut first,
self.non_repudiation,
"nonRepudiation",
);
append(
&mut value,
&mut first,
self.key_encipherment,
"keyEncipherment",
);
append(
&mut value,
&mut first,
self.data_encipherment,
"dataEncipherment",
);
append(&mut value, &mut first, self.key_agreement, "keyAgreement"); append(&mut value, &mut first, self.key_agreement, "keyAgreement");
append(&mut value, &mut first, self.key_cert_sign, "keyCertSign"); append(&mut value, &mut first, self.key_cert_sign, "keyCertSign");
append(&mut value, &mut first, self.crl_sign, "cRLSign"); append(&mut value, &mut first, self.crl_sign, "cRLSign");
@ -476,7 +504,12 @@ impl ExtendedKeyUsage {
append(&mut value, &mut first, self.server_auth, "serverAuth"); append(&mut value, &mut first, self.server_auth, "serverAuth");
append(&mut value, &mut first, self.client_auth, "clientAuth"); append(&mut value, &mut first, self.client_auth, "clientAuth");
append(&mut value, &mut first, self.code_signing, "codeSigning"); append(&mut value, &mut first, self.code_signing, "codeSigning");
append(&mut value, &mut first, self.email_protection, "emailProtection"); append(
&mut value,
&mut first,
self.email_protection,
"emailProtection",
);
append(&mut value, &mut first, self.time_stamping, "timeStamping"); append(&mut value, &mut first, self.time_stamping, "timeStamping");
append(&mut value, &mut first, self.ms_code_ind, "msCodeInd"); append(&mut value, &mut first, self.ms_code_ind, "msCodeInd");
append(&mut value, &mut first, self.ms_code_com, "msCodeCom"); append(&mut value, &mut first, self.ms_code_com, "msCodeCom");
@ -497,9 +530,7 @@ pub struct SubjectKeyIdentifier {
impl SubjectKeyIdentifier { impl SubjectKeyIdentifier {
pub fn new() -> SubjectKeyIdentifier { pub fn new() -> SubjectKeyIdentifier {
SubjectKeyIdentifier { SubjectKeyIdentifier { critical: false }
critical: false,
}
} }
pub fn critical(&mut self) -> &mut SubjectKeyIdentifier { pub fn critical(&mut self) -> &mut SubjectKeyIdentifier {

View File

@ -165,7 +165,8 @@ impl X509Generator {
/// ``` /// ```
#[deprecated(since = "0.9.7", note = "use X509Builder and X509ReqBuilder instead")] #[deprecated(since = "0.9.7", note = "use X509Builder and X509ReqBuilder instead")]
pub fn add_names<I>(mut self, attrs: I) -> X509Generator pub fn add_names<I>(mut self, attrs: I) -> X509Generator
where I: IntoIterator<Item = (String, String)> where
I: IntoIterator<Item = (String, String)>,
{ {
self.names.extend(attrs); self.names.extend(attrs);
self self
@ -201,7 +202,8 @@ impl X509Generator {
/// ``` /// ```
#[deprecated(since = "0.9.7", note = "use X509Builder and X509ReqBuilder instead")] #[deprecated(since = "0.9.7", note = "use X509Builder and X509ReqBuilder instead")]
pub fn add_extensions<I>(mut self, exts: I) -> X509Generator pub fn add_extensions<I>(mut self, exts: I) -> X509Generator
where I: IntoIterator<Item = extension::Extension> where
I: IntoIterator<Item = extension::Extension>,
{ {
for ext in exts { for ext in exts {
self.extensions.add(ext); self.extensions.add(ext);
@ -251,14 +253,21 @@ impl X509Generator {
let extension = match exttype.get_nid() { let extension = match exttype.get_nid() {
Some(nid) => { Some(nid) => {
let ctx = builder.x509v3_context(None, None); let ctx = builder.x509v3_context(None, None);
try!(X509Extension::new_nid(None, Some(&ctx), nid, &ext.to_string())) try!(X509Extension::new_nid(
None,
Some(&ctx),
nid,
&ext.to_string(),
))
} }
None => { None => {
let ctx = builder.x509v3_context(None, None); let ctx = builder.x509v3_context(None, None);
try!(X509Extension::new(None, try!(X509Extension::new(
None,
Some(&ctx), Some(&ctx),
&exttype.get_name().unwrap(), &exttype.get_name().unwrap(),
&ext.to_string())) &ext.to_string(),
))
} }
}; };
try!(builder.append_extension(extension)); try!(builder.append_extension(extension));
@ -277,18 +286,24 @@ impl X509Generator {
}; };
unsafe { unsafe {
let req = try!(cvt_p(ffi::X509_to_X509_REQ(cert.as_ptr(), let req = try!(cvt_p(ffi::X509_to_X509_REQ(
cert.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
ptr::null()))); ptr::null(),
)));
let req = X509Req::from_ptr(req); let req = X509Req::from_ptr(req);
let exts = compat::X509_get0_extensions(cert.as_ptr()); let exts = compat::X509_get0_extensions(cert.as_ptr());
if exts != ptr::null_mut() { if exts != ptr::null_mut() {
try!(cvt(ffi::X509_REQ_add_extensions(req.as_ptr(), exts as *mut _))); try!(cvt(
ffi::X509_REQ_add_extensions(req.as_ptr(), exts as *mut _),
));
} }
let hash_fn = self.hash_type.as_ptr(); let hash_fn = self.hash_type.as_ptr();
try!(cvt(ffi::X509_REQ_sign(req.as_ptr(), p_key.as_ptr(), hash_fn))); try!(cvt(
ffi::X509_REQ_sign(req.as_ptr(), p_key.as_ptr(), hash_fn),
));
Ok(req) Ok(req)
} }
@ -326,17 +341,23 @@ impl X509Builder {
} }
/// Sets the serial number of the certificate. /// Sets the serial number of the certificate.
pub fn set_serial_number(&mut self, pub fn set_serial_number(&mut self, serial_number: &Asn1IntegerRef) -> Result<(), ErrorStack> {
serial_number: &Asn1IntegerRef)
-> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::X509_set_serialNumber(self.0.as_ptr(), serial_number.as_ptr())).map(|_| ()) cvt(ffi::X509_set_serialNumber(
self.0.as_ptr(),
serial_number.as_ptr(),
)).map(|_| ())
} }
} }
/// Sets the issuer name of the certificate. /// Sets the issuer name of the certificate.
pub fn set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack> { pub fn set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::X509_set_issuer_name(self.0.as_ptr(), issuer_name.as_ptr())).map(|_| ()) } unsafe {
cvt(ffi::X509_set_issuer_name(
self.0.as_ptr(),
issuer_name.as_ptr(),
)).map(|_| ())
}
} }
/// Sets the subject name of the certificate. /// Sets the subject name of the certificate.
@ -359,7 +380,10 @@ impl X509Builder {
/// ``` /// ```
pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> { pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::X509_set_subject_name(self.0.as_ptr(), subject_name.as_ptr())).map(|_| ()) cvt(ffi::X509_set_subject_name(
self.0.as_ptr(),
subject_name.as_ptr(),
)).map(|_| ())
} }
} }
@ -371,10 +395,11 @@ impl X509Builder {
/// Returns a context object which is needed to create certain X509 extension values. /// Returns a context object which is needed to create certain X509 extension values.
/// ///
/// Set `issuer` to `None` if the certificate will be self-signed. /// Set `issuer` to `None` if the certificate will be self-signed.
pub fn x509v3_context<'a>(&'a self, pub fn x509v3_context<'a>(
&'a self,
issuer: Option<&'a X509Ref>, issuer: Option<&'a X509Ref>,
conf: Option<&'a ConfRef>) conf: Option<&'a ConfRef>,
-> X509v3Context<'a> { ) -> X509v3Context<'a> {
unsafe { unsafe {
let mut ctx = mem::zeroed(); let mut ctx = mem::zeroed();
@ -383,7 +408,14 @@ impl X509Builder {
None => self.0.as_ptr(), None => self.0.as_ptr(),
}; };
let subject = self.0.as_ptr(); let subject = self.0.as_ptr();
ffi::X509V3_set_ctx(&mut ctx, issuer, subject, ptr::null_mut(), ptr::null_mut(), 0); ffi::X509V3_set_ctx(
&mut ctx,
issuer,
subject,
ptr::null_mut(),
ptr::null_mut(),
0,
);
// nodb case taken care of since we zeroed ctx above // nodb case taken care of since we zeroed ctx above
if let Some(conf) = conf { if let Some(conf) = conf {
@ -397,7 +429,9 @@ impl X509Builder {
/// Adds an X509 extension value to the certificate. /// Adds an X509 extension value to the certificate.
pub fn append_extension(&mut self, extension: X509Extension) -> Result<(), ErrorStack> { pub fn append_extension(&mut self, extension: X509Extension) -> Result<(), ErrorStack> {
unsafe { unsafe {
try!(cvt(ffi::X509_add_ext(self.0.as_ptr(), extension.as_ptr(), -1))); try!(cvt(
ffi::X509_add_ext(self.0.as_ptr(), extension.as_ptr(), -1),
));
mem::forget(extension); mem::forget(extension);
Ok(()) Ok(())
} }
@ -433,10 +467,12 @@ impl X509Ref {
/// Returns this certificate's SAN entries, if they exist. /// Returns this certificate's SAN entries, if they exist.
pub fn subject_alt_names(&self) -> Option<Stack<GeneralName>> { pub fn subject_alt_names(&self) -> Option<Stack<GeneralName>> {
unsafe { unsafe {
let stack = ffi::X509_get_ext_d2i(self.as_ptr(), let stack = ffi::X509_get_ext_d2i(
self.as_ptr(),
ffi::NID_subject_alt_name, ffi::NID_subject_alt_name,
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut()); ptr::null_mut(),
);
if stack.is_null() { if stack.is_null() {
return None; return None;
} }
@ -458,7 +494,12 @@ impl X509Ref {
let evp = hash_type.as_ptr(); let evp = hash_type.as_ptr();
let mut len = ffi::EVP_MAX_MD_SIZE; let mut len = ffi::EVP_MAX_MD_SIZE;
let mut buf = vec![0u8; len as usize]; let mut buf = vec![0u8; len as usize];
try!(cvt(ffi::X509_digest(self.as_ptr(), evp, buf.as_mut_ptr() as *mut _, &mut len))); try!(cvt(ffi::X509_digest(
self.as_ptr(),
evp,
buf.as_mut_ptr() as *mut _,
&mut len,
)));
buf.truncate(len as usize); buf.truncate(len as usize);
Ok(buf) Ok(buf)
} }
@ -505,9 +546,7 @@ impl X509Ref {
/// Returns the list of OCSP responder URLs specified in the certificate's Authority Information /// Returns the list of OCSP responder URLs specified in the certificate's Authority Information
/// Access field. /// Access field.
pub fn ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack> { pub fn ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack> {
unsafe { unsafe { cvt_p(ffi::X509_get1_ocsp(self.as_ptr())).map(|p| Stack::from_ptr(p)) }
cvt_p(ffi::X509_get1_ocsp(self.as_ptr())).map(|p| Stack::from_ptr(p))
}
} }
/// Checks that this certificate issued `subject`. /// Checks that this certificate issued `subject`.
@ -553,14 +592,13 @@ impl X509 {
let mut certs = vec![]; let mut certs = vec![];
loop { loop {
let r = ffi::PEM_read_bio_X509(bio.as_ptr(), let r =
ptr::null_mut(), ffi::PEM_read_bio_X509(bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut());
None,
ptr::null_mut());
if r.is_null() { if r.is_null() {
let err = ffi::ERR_peek_last_error(); let err = ffi::ERR_peek_last_error();
if ffi::ERR_GET_LIB(err) == ffi::ERR_LIB_PEM if ffi::ERR_GET_LIB(err) == ffi::ERR_LIB_PEM &&
&& ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE { ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE
{
ffi::ERR_clear_error(); ffi::ERR_clear_error();
break; break;
} }
@ -633,11 +671,12 @@ impl X509Extension {
/// provided. /// provided.
/// ///
/// See the extension module for builder types which will construct certain common extensions. /// See the extension module for builder types which will construct certain common extensions.
pub fn new(conf: Option<&ConfRef>, pub fn new(
conf: Option<&ConfRef>,
context: Option<&X509v3Context>, context: Option<&X509v3Context>,
name: &str, name: &str,
value: &str) value: &str,
-> Result<X509Extension, ErrorStack> { ) -> Result<X509Extension, ErrorStack> {
let name = CString::new(name).unwrap(); let name = CString::new(name).unwrap();
let value = CString::new(value).unwrap(); let value = CString::new(value).unwrap();
unsafe { unsafe {
@ -658,11 +697,12 @@ impl X509Extension {
/// be provided. /// be provided.
/// ///
/// See the extension module for builder types which will construct certain common extensions. /// See the extension module for builder types which will construct certain common extensions.
pub fn new_nid(conf: Option<&ConfRef>, pub fn new_nid(
conf: Option<&ConfRef>,
context: Option<&X509v3Context>, context: Option<&X509v3Context>,
name: Nid, name: Nid,
value: &str) value: &str,
-> Result<X509Extension, ErrorStack> { ) -> Result<X509Extension, ErrorStack> {
let value = CString::new(value).unwrap(); let value = CString::new(value).unwrap();
unsafe { unsafe {
ffi::init(); ffi::init();
@ -690,28 +730,30 @@ impl X509NameBuilder {
unsafe { unsafe {
let field = CString::new(field).unwrap(); let field = CString::new(field).unwrap();
assert!(value.len() <= c_int::max_value() as usize); assert!(value.len() <= c_int::max_value() as usize);
cvt(ffi::X509_NAME_add_entry_by_txt(self.0.as_ptr(), cvt(ffi::X509_NAME_add_entry_by_txt(
self.0.as_ptr(),
field.as_ptr() as *mut _, field.as_ptr() as *mut _,
ffi::MBSTRING_UTF8, ffi::MBSTRING_UTF8,
value.as_ptr(), value.as_ptr(),
value.len() as c_int, value.len() as c_int,
-1, -1,
0)) 0,
.map(|_| ()) )).map(|_| ())
} }
} }
pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> { pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> {
unsafe { unsafe {
assert!(value.len() <= c_int::max_value() as usize); assert!(value.len() <= c_int::max_value() as usize);
cvt(ffi::X509_NAME_add_entry_by_NID(self.0.as_ptr(), cvt(ffi::X509_NAME_add_entry_by_NID(
self.0.as_ptr(),
field.as_raw(), field.as_raw(),
ffi::MBSTRING_UTF8, ffi::MBSTRING_UTF8,
value.as_ptr() as *mut _, value.as_ptr() as *mut _,
value.len() as c_int, value.len() as c_int,
-1, -1,
0)) 0,
.map(|_| ()) )).map(|_| ())
} }
} }
@ -739,9 +781,7 @@ impl X509Name {
/// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`. /// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`.
pub fn load_client_ca_file<P: AsRef<Path>>(file: P) -> Result<Stack<X509Name>, ErrorStack> { pub fn load_client_ca_file<P: AsRef<Path>>(file: P) -> Result<Stack<X509Name>, ErrorStack> {
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
unsafe { unsafe { cvt_p(ffi::SSL_load_client_CA_file(file.as_ptr())).map(|p| Stack::from_ptr(p)) }
cvt_p(ffi::SSL_load_client_CA_file(file.as_ptr())).map(|p| Stack::from_ptr(p))
}
} }
} }
@ -819,7 +859,10 @@ impl X509ReqBuilder {
pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> { pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::X509_REQ_set_subject_name(self.0.as_ptr(), subject_name.as_ptr())).map(|_| ()) cvt(ffi::X509_REQ_set_subject_name(
self.0.as_ptr(),
subject_name.as_ptr(),
)).map(|_| ())
} }
} }
@ -827,18 +870,18 @@ impl X509ReqBuilder {
unsafe { cvt(ffi::X509_REQ_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) } unsafe { cvt(ffi::X509_REQ_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) }
} }
pub fn x509v3_context<'a>(&'a self, pub fn x509v3_context<'a>(&'a self, conf: Option<&'a ConfRef>) -> X509v3Context<'a> {
conf: Option<&'a ConfRef>)
-> X509v3Context<'a> {
unsafe { unsafe {
let mut ctx = mem::zeroed(); let mut ctx = mem::zeroed();
ffi::X509V3_set_ctx(&mut ctx, ffi::X509V3_set_ctx(
&mut ctx,
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
self.0.as_ptr(), self.0.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
0); 0,
);
// nodb case taken care of since we zeroed ctx above // nodb case taken care of since we zeroed ctx above
if let Some(conf) = conf { if let Some(conf) = conf {
@ -849,16 +892,26 @@ impl X509ReqBuilder {
} }
} }
pub fn add_extensions(&mut self, pub fn add_extensions(
extensions: &StackRef<X509Extension>) &mut self,
-> Result<(), ErrorStack> { extensions: &StackRef<X509Extension>,
) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::X509_REQ_add_extensions(self.0.as_ptr(), extensions.as_ptr())).map(|_| ()) cvt(ffi::X509_REQ_add_extensions(
self.0.as_ptr(),
extensions.as_ptr(),
)).map(|_| ())
} }
} }
pub fn sign(&mut self, key: &PKeyRef, hash: MessageDigest) -> Result<(), ErrorStack> { pub fn sign(&mut self, key: &PKeyRef, hash: MessageDigest) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::X509_REQ_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) } unsafe {
cvt(ffi::X509_REQ_sign(
self.0.as_ptr(),
key.as_ptr(),
hash.as_ptr(),
)).map(|_| ())
}
} }
pub fn build(self) -> X509Req { pub fn build(self) -> X509Req {
@ -883,10 +936,12 @@ impl X509Req {
pub fn from_pem(buf: &[u8]) -> Result<X509Req, ErrorStack> { pub fn from_pem(buf: &[u8]) -> Result<X509Req, ErrorStack> {
let mem_bio = try!(MemBioSlice::new(buf)); let mem_bio = try!(MemBioSlice::new(buf));
unsafe { unsafe {
let handle = try!(cvt_p(ffi::PEM_read_bio_X509_REQ(mem_bio.as_ptr(), let handle = try!(cvt_p(ffi::PEM_read_bio_X509_REQ(
mem_bio.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
None, None,
ptr::null_mut()))); ptr::null_mut(),
)));
Ok(X509Req::from_ptr(handle)) Ok(X509Req::from_ptr(handle))
} }
} }
@ -898,11 +953,8 @@ impl X509ReqRef {
to_pem!(ffi::PEM_write_bio_X509_REQ); to_pem!(ffi::PEM_write_bio_X509_REQ);
to_der!(ffi::i2d_X509_REQ); to_der!(ffi::i2d_X509_REQ);
pub fn version(&self) -> i32 pub fn version(&self) -> i32 {
{ unsafe { compat::X509_REQ_get_version(self.as_ptr()) as i32 }
unsafe {
compat::X509_REQ_get_version(self.as_ptr()) as i32
}
} }
pub fn subject_name(&self) -> &X509NameRef { pub fn subject_name(&self) -> &X509NameRef {
@ -1130,15 +1182,18 @@ mod compat {
} }
pub unsafe fn X509_up_ref(x: *mut ffi::X509) { pub unsafe fn X509_up_ref(x: *mut ffi::X509) {
ffi::CRYPTO_add_lock(&mut (*x).references, ffi::CRYPTO_add_lock(
&mut (*x).references,
1, 1,
ffi::CRYPTO_LOCK_X509, ffi::CRYPTO_LOCK_X509,
"mod.rs\0".as_ptr() as *const _, "mod.rs\0".as_ptr() as *const _,
line!() as c_int); line!() as c_int,
);
} }
pub unsafe fn X509_get0_extensions(cert: *const ffi::X509) pub unsafe fn X509_get0_extensions(
-> *const ffi::stack_st_X509_EXTENSION { cert: *const ffi::X509,
) -> *const ffi::stack_st_X509_EXTENSION {
let info = (*cert).cert_info; let info = (*cert).cert_info;
if info.is_null() { if info.is_null() {
0 as *mut _ 0 as *mut _
@ -1147,19 +1202,19 @@ mod compat {
} }
} }
pub unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long pub unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long {
{
::ffi::ASN1_INTEGER_get((*(*x).req_info).version) ::ffi::ASN1_INTEGER_get((*(*x).req_info).version)
} }
pub unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME pub unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME {
{
(*(*x).req_info).subject (*(*x).req_info).subject
} }
pub unsafe fn X509_get0_signature(psig: *mut *const ffi::ASN1_BIT_STRING, pub unsafe fn X509_get0_signature(
psig: *mut *const ffi::ASN1_BIT_STRING,
palg: *mut *const ffi::X509_ALGOR, palg: *mut *const ffi::X509_ALGOR,
x: *const ffi::X509) { x: *const ffi::X509,
) {
if !psig.is_null() { if !psig.is_null() {
*psig = (*x).signature; *psig = (*x).signature;
} }
@ -1168,10 +1223,12 @@ mod compat {
} }
} }
pub unsafe fn X509_ALGOR_get0(paobj: *mut *const ffi::ASN1_OBJECT, pub unsafe fn X509_ALGOR_get0(
paobj: *mut *const ffi::ASN1_OBJECT,
pptype: *mut c_int, pptype: *mut c_int,
pval: *mut *mut c_void, pval: *mut *mut c_void,
alg: *const ffi::X509_ALGOR) { alg: *const ffi::X509_ALGOR,
) {
if !paobj.is_null() { if !paobj.is_null() {
*paobj = (*alg).algorithm; *paobj = (*alg).algorithm;
} }

View File

@ -50,9 +50,7 @@ impl X509StoreBuilderRef {
/// environment variables if present, or defaults specified at OpenSSL /// environment variables if present, or defaults specified at OpenSSL
/// build time otherwise. /// build time otherwise.
pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> { pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> {
unsafe { unsafe { cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())).map(|_| ()) }
cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())).map(|_| ())
}
} }
} }

View File

@ -23,12 +23,22 @@ fn get_generator() -> X509Generator {
.add_name("CN".to_string(), "test_me".to_string()) .add_name("CN".to_string(), "test_me".to_string())
.set_sign_hash(MessageDigest::sha1()) .set_sign_hash(MessageDigest::sha1())
.add_extension(Extension::KeyUsage(vec![DigitalSignature, KeyEncipherment])) .add_extension(Extension::KeyUsage(vec![DigitalSignature, KeyEncipherment]))
.add_extension(Extension::ExtKeyUsage(vec![ClientAuth, .add_extension(Extension::ExtKeyUsage(vec![
ClientAuth,
ServerAuth, ServerAuth,
ExtKeyUsageOption::Other("2.999.1".to_owned())])) ExtKeyUsageOption::Other("2.999.1".to_owned()),
.add_extension(Extension::SubjectAltName(vec![(SAN::DNS, "example.com".to_owned())])) ]))
.add_extension(Extension::OtherNid(nid::BASIC_CONSTRAINTS, "critical,CA:TRUE".to_owned())) .add_extension(Extension::SubjectAltName(
.add_extension(Extension::OtherStr("2.999.2".to_owned(), "ASN1:UTF8:example value".to_owned())) vec![(SAN::DNS, "example.com".to_owned())],
))
.add_extension(Extension::OtherNid(
nid::BASIC_CONSTRAINTS,
"critical,CA:TRUE".to_owned(),
))
.add_extension(Extension::OtherStr(
"2.999.2".to_owned(),
"ASN1:UTF8:example value".to_owned(),
))
} }
fn pkey() -> PKey { fn pkey() -> PKey {
@ -44,8 +54,10 @@ fn test_cert_gen() {
// FIXME: check data in result to be correct, needs implementation // FIXME: check data in result to be correct, needs implementation
// of X509 getters // of X509 getters
assert_eq!(pkey.public_key_to_pem().unwrap(), assert_eq!(
cert.public_key().unwrap().public_key_to_pem().unwrap()); pkey.public_key_to_pem().unwrap(),
cert.public_key().unwrap().public_key_to_pem().unwrap()
);
} }
/// SubjectKeyIdentifier must be added before AuthorityKeyIdentifier or OpenSSL /// SubjectKeyIdentifier must be added before AuthorityKeyIdentifier or OpenSSL
@ -55,8 +67,14 @@ fn test_cert_gen() {
fn test_cert_gen_extension_ordering() { fn test_cert_gen_extension_ordering() {
let pkey = pkey(); let pkey = pkey();
get_generator() get_generator()
.add_extension(Extension::OtherNid(nid::SUBJECT_KEY_IDENTIFIER, "hash".to_owned())) .add_extension(Extension::OtherNid(
.add_extension(Extension::OtherNid(nid::AUTHORITY_KEY_IDENTIFIER, "keyid:always".to_owned())) nid::SUBJECT_KEY_IDENTIFIER,
"hash".to_owned(),
))
.add_extension(Extension::OtherNid(
nid::AUTHORITY_KEY_IDENTIFIER,
"keyid:always".to_owned(),
))
.sign(&pkey) .sign(&pkey)
.expect("Failed to generate cert with order-dependent extensions"); .expect("Failed to generate cert with order-dependent extensions");
} }
@ -67,8 +85,14 @@ fn test_cert_gen_extension_ordering() {
fn test_cert_gen_extension_bad_ordering() { fn test_cert_gen_extension_bad_ordering() {
let pkey = pkey(); let pkey = pkey();
let result = get_generator() let result = get_generator()
.add_extension(Extension::OtherNid(nid::AUTHORITY_KEY_IDENTIFIER, "keyid:always".to_owned())) .add_extension(Extension::OtherNid(
.add_extension(Extension::OtherNid(nid::SUBJECT_KEY_IDENTIFIER, "hash".to_owned())) nid::AUTHORITY_KEY_IDENTIFIER,
"keyid:always".to_owned(),
))
.add_extension(Extension::OtherNid(
nid::SUBJECT_KEY_IDENTIFIER,
"hash".to_owned(),
))
.sign(&pkey); .sign(&pkey);
assert!(result.is_err()); assert!(result.is_err());
@ -82,7 +106,11 @@ fn test_req_gen() {
let reqpem = req.to_pem().unwrap(); let reqpem = req.to_pem().unwrap();
let req = X509Req::from_pem(&reqpem).ok().expect("Failed to load PEM"); let req = X509Req::from_pem(&reqpem).ok().expect("Failed to load PEM");
let cn = (*req).subject_name().entries_by_nid(nid::COMMONNAME).next().unwrap(); let cn = (*req)
.subject_name()
.entries_by_nid(nid::COMMONNAME)
.next()
.unwrap();
assert_eq!(0, (*req).version()); assert_eq!(0, (*req).version());
assert_eq!(cn.data().as_slice(), b"test_me"); assert_eq!(cn.data().as_slice(), b"test_me");
@ -140,7 +168,10 @@ fn test_nid_values() {
let cn = subject.entries_by_nid(nid::COMMONNAME).next().unwrap(); let cn = subject.entries_by_nid(nid::COMMONNAME).next().unwrap();
assert_eq!(cn.data().as_slice(), b"example.com"); assert_eq!(cn.data().as_slice(), b"example.com");
let email = subject.entries_by_nid(nid::PKCS9_EMAILADDRESS).next().unwrap(); let email = subject
.entries_by_nid(nid::PKCS9_EMAILADDRESS)
.next()
.unwrap();
assert_eq!(email.data().as_slice(), b"test@example.com"); assert_eq!(email.data().as_slice(), b"test@example.com");
let friendly = subject.entries_by_nid(nid::FRIENDLYNAME).next().unwrap(); let friendly = subject.entries_by_nid(nid::FRIENDLYNAME).next().unwrap();
@ -165,10 +196,11 @@ fn test_subject_alt_name() {
let subject_alt_names = cert.subject_alt_names().unwrap(); let subject_alt_names = cert.subject_alt_names().unwrap();
assert_eq!(3, subject_alt_names.len()); assert_eq!(3, subject_alt_names.len());
assert_eq!(Some("foobar.com"), subject_alt_names[0].dnsname()); assert_eq!(Some("foobar.com"), subject_alt_names[0].dnsname());
assert_eq!(subject_alt_names[1].ipaddress(), assert_eq!(subject_alt_names[1].ipaddress(), Some(&[127, 0, 0, 1][..]));
Some(&[127, 0, 0, 1][..])); assert_eq!(
assert_eq!(subject_alt_names[2].ipaddress(), subject_alt_names[2].ipaddress(),
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])); Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
);
} }
#[test] #[test]
@ -178,12 +210,18 @@ fn test_subject_alt_name_iter() {
let subject_alt_names = cert.subject_alt_names().unwrap(); let subject_alt_names = cert.subject_alt_names().unwrap();
let mut subject_alt_names_iter = subject_alt_names.iter(); let mut subject_alt_names_iter = subject_alt_names.iter();
assert_eq!(subject_alt_names_iter.next().unwrap().dnsname(), assert_eq!(
Some("foobar.com")); subject_alt_names_iter.next().unwrap().dnsname(),
assert_eq!(subject_alt_names_iter.next().unwrap().ipaddress(), Some("foobar.com")
Some(&[127, 0, 0, 1][..])); );
assert_eq!(subject_alt_names_iter.next().unwrap().ipaddress(), assert_eq!(
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])); subject_alt_names_iter.next().unwrap().ipaddress(),
Some(&[127, 0, 0, 1][..])
);
assert_eq!(
subject_alt_names_iter.next().unwrap().ipaddress(),
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
);
assert!(subject_alt_names_iter.next().is_none()); assert!(subject_alt_names_iter.next().is_none());
} }
@ -192,24 +230,35 @@ fn x509_builder() {
let pkey = pkey(); let pkey = pkey();
let mut name = X509Name::builder().unwrap(); let mut name = X509Name::builder().unwrap();
name.append_entry_by_nid(nid::COMMONNAME, "foobar.com").unwrap(); name.append_entry_by_nid(nid::COMMONNAME, "foobar.com")
.unwrap();
let name = name.build(); let name = name.build();
let mut builder = X509::builder().unwrap(); let mut builder = X509::builder().unwrap();
builder.set_version(2).unwrap(); builder.set_version(2).unwrap();
builder.set_subject_name(&name).unwrap(); builder.set_subject_name(&name).unwrap();
builder.set_issuer_name(&name).unwrap(); builder.set_issuer_name(&name).unwrap();
builder.set_not_before(&Asn1Time::days_from_now(0).unwrap()).unwrap(); builder
builder.set_not_after(&Asn1Time::days_from_now(365).unwrap()).unwrap(); .set_not_before(&Asn1Time::days_from_now(0).unwrap())
.unwrap();
builder
.set_not_after(&Asn1Time::days_from_now(365).unwrap())
.unwrap();
builder.set_pubkey(&pkey).unwrap(); builder.set_pubkey(&pkey).unwrap();
let mut serial = BigNum::new().unwrap();; let mut serial = BigNum::new().unwrap();
serial.rand(128, MSB_MAYBE_ZERO, false).unwrap(); serial.rand(128, MSB_MAYBE_ZERO, false).unwrap();
builder.set_serial_number(&serial.to_asn1_integer().unwrap()).unwrap(); builder
.set_serial_number(&serial.to_asn1_integer().unwrap())
.unwrap();
let basic_constraints = BasicConstraints::new().critical().ca().build().unwrap(); let basic_constraints = BasicConstraints::new().critical().ca().build().unwrap();
builder.append_extension(basic_constraints).unwrap(); builder.append_extension(basic_constraints).unwrap();
let key_usage = KeyUsage::new().digital_signature().key_encipherment().build().unwrap(); let key_usage = KeyUsage::new()
.digital_signature()
.key_encipherment()
.build()
.unwrap();
builder.append_extension(key_usage).unwrap(); builder.append_extension(key_usage).unwrap();
let ext_key_usage = ExtendedKeyUsage::new() let ext_key_usage = ExtendedKeyUsage::new()
.client_auth() .client_auth()
@ -239,7 +288,10 @@ fn x509_builder() {
assert!(pkey.public_eq(&x509.public_key().unwrap())); assert!(pkey.public_eq(&x509.public_key().unwrap()));
let cn = x509.subject_name().entries_by_nid(nid::COMMONNAME).next().unwrap(); let cn = x509.subject_name()
.entries_by_nid(nid::COMMONNAME)
.next()
.unwrap();
assert_eq!("foobar.com".as_bytes(), cn.data().as_slice()); assert_eq!("foobar.com".as_bytes(), cn.data().as_slice());
} }
@ -248,7 +300,8 @@ fn x509_req_builder() {
let pkey = pkey(); let pkey = pkey();
let mut name = X509Name::builder().unwrap(); let mut name = X509Name::builder().unwrap();
name.append_entry_by_nid(nid::COMMONNAME, "foobar.com").unwrap(); name.append_entry_by_nid(nid::COMMONNAME, "foobar.com")
.unwrap();
let name = name.build(); let name = name.build();
let mut builder = X509Req::builder().unwrap(); let mut builder = X509Req::builder().unwrap();
@ -257,7 +310,11 @@ fn x509_req_builder() {
builder.set_pubkey(&pkey).unwrap(); builder.set_pubkey(&pkey).unwrap();
let mut extensions = Stack::new().unwrap(); let mut extensions = Stack::new().unwrap();
let key_usage = KeyUsage::new().digital_signature().key_encipherment().build().unwrap(); let key_usage = KeyUsage::new()
.digital_signature()
.key_encipherment()
.build()
.unwrap();
extensions.push(key_usage).unwrap(); extensions.push(key_usage).unwrap();
let subject_alternative_name = SubjectAlternativeName::new() let subject_alternative_name = SubjectAlternativeName::new()
.dns("example.com") .dns("example.com")
@ -275,10 +332,20 @@ fn test_stack_from_pem() {
let certs = X509::stack_from_pem(certs).unwrap(); let certs = X509::stack_from_pem(certs).unwrap();
assert_eq!(certs.len(), 2); assert_eq!(certs.len(), 2);
assert_eq!(certs[0].fingerprint(MessageDigest::sha1()).unwrap().to_hex(), assert_eq!(
"59172d9313e84459bcff27f967e79e6e9217e584"); certs[0]
assert_eq!(certs[1].fingerprint(MessageDigest::sha1()).unwrap().to_hex(), .fingerprint(MessageDigest::sha1())
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"); .unwrap()
.to_hex(),
"59172d9313e84459bcff27f967e79e6e9217e584"
);
assert_eq!(
certs[1]
.fingerprint(MessageDigest::sha1())
.unwrap()
.to_hex(),
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
);
} }
#[test] #[test]
@ -317,14 +384,16 @@ fn signature() {
let cert = include_bytes!("../../test/cert.pem"); let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap(); let cert = X509::from_pem(cert).unwrap();
let signature = cert.signature(); let signature = cert.signature();
assert_eq!(signature.as_slice().to_hex(), assert_eq!(
signature.as_slice().to_hex(),
"4af607b889790b43470442cfa551cdb8b6d0b0340d2958f76b9e3ef6ad4992230cead6842587f0ecad5\ "4af607b889790b43470442cfa551cdb8b6d0b0340d2958f76b9e3ef6ad4992230cead6842587f0ecad5\
78e6e11a221521e940187e3d6652de14e84e82f6671f097cc47932e022add3c0cb54a26bf27fa84c107\ 78e6e11a221521e940187e3d6652de14e84e82f6671f097cc47932e022add3c0cb54a26bf27fa84c107\
4971caa6bee2e42d34a5b066c427f2d452038082b8073993399548088429de034fdd589dcfb0dd33be7\ 4971caa6bee2e42d34a5b066c427f2d452038082b8073993399548088429de034fdd589dcfb0dd33be7\
ebdfdf698a28d628a89568881d658151276bde333600969502c4e62e1d3470a683364dfb241f78d310a\ ebdfdf698a28d628a89568881d658151276bde333600969502c4e62e1d3470a683364dfb241f78d310a\
89c119297df093eb36b7fd7540224f488806780305d1e79ffc938fe2275441726522ab36d88348e6c51\ 89c119297df093eb36b7fd7540224f488806780305d1e79ffc938fe2275441726522ab36d88348e6c51\
f13dcc46b5e1cdac23c974fd5ef86aa41e91c9311655090a52333bc79687c748d833595d4c5f987508f\ f13dcc46b5e1cdac23c974fd5ef86aa41e91c9311655090a52333bc79687c748d833595d4c5f987508f\
e121997410d37c"); e121997410d37c"
);
let algorithm = cert.signature_algorithm(); let algorithm = cert.signature_algorithm();
assert_eq!(algorithm.object().nid(), nid::SHA256WITHRSAENCRYPTION); assert_eq!(algorithm.object().nid(), nid::SHA256WITHRSAENCRYPTION);
assert_eq!(algorithm.object().to_string(), "sha256WithRSAEncryption"); assert_eq!(algorithm.object().to_string(), "sha256WithRSAEncryption");

View File

@ -2,4 +2,4 @@
//! //!
//! Requires the `v102` or `v110` features and OpenSSL 1.0.2 or 1.1.0. //! Requires the `v102` or `v110` features and OpenSSL 1.0.2 or 1.1.0.
pub use ::verify::*; pub use verify::*;

View File

@ -27,7 +27,12 @@ fn main() {
} else if let Ok(version) = env::var("DEP_OPENSSL_VERSION") { } else if let Ok(version) = env::var("DEP_OPENSSL_VERSION") {
cfg.cfg(&format!("ossl{}", version), None); cfg.cfg(&format!("ossl{}", version), None);
} }
if let (Ok(version), Ok(patch)) = (env::var("DEP_OPENSSL_VERSION"), env::var("DEP_OPENSSL_PATCH")) { if let (Ok(version), Ok(patch)) =
(
env::var("DEP_OPENSSL_VERSION"),
env::var("DEP_OPENSSL_PATCH"),
)
{
cfg.cfg(&format!("ossl{}{}", version, patch), None); cfg.cfg(&format!("ossl{}{}", version, patch), None);
} }
if let Ok(vars) = env::var("DEP_OPENSSL_CONF") { if let Ok(vars) = env::var("DEP_OPENSSL_CONF") {
@ -62,7 +67,9 @@ fn main() {
} else if s == "_STACK" { } else if s == "_STACK" {
format!("struct stack_st") format!("struct stack_st")
// This logic should really be cleaned up // This logic should really be cleaned up
} else if is_struct && s != "point_conversion_form_t" && s.chars().next().unwrap().is_lowercase() { } else if is_struct && s != "point_conversion_form_t" &&
s.chars().next().unwrap().is_lowercase()
{
format!("struct {}", s) format!("struct {}", s)
} else { } else {
format!("{}", s) format!("{}", s)
@ -71,13 +78,9 @@ fn main() {
cfg.skip_type(|s| { cfg.skip_type(|s| {
// function pointers are declared without a `*` in openssl so their // function pointers are declared without a `*` in openssl so their
// sizeof is 1 which isn't what we want. // sizeof is 1 which isn't what we want.
s == "PasswordCallback" || s == "PasswordCallback" || s == "bio_info_cb" || s.starts_with("CRYPTO_EX_")
s == "bio_info_cb" ||
s.starts_with("CRYPTO_EX_")
});
cfg.skip_struct(|s| {
s == "ProbeResult"
}); });
cfg.skip_struct(|s| s == "ProbeResult");
cfg.skip_fn(move |s| { cfg.skip_fn(move |s| {
s == "CRYPTO_memcmp" || // uses volatile s == "CRYPTO_memcmp" || // uses volatile
@ -94,20 +97,14 @@ fn main() {
(s == "GENERAL_NAME" && field == "d") // union (s == "GENERAL_NAME" && field == "d") // union
}); });
cfg.skip_signededness(|s| { cfg.skip_signededness(|s| {
s.ends_with("_cb") || s.ends_with("_cb") || s.ends_with("_CB") || s.ends_with("_cb_fn") ||
s.ends_with("_CB") || s.starts_with("CRYPTO_") || s == "PasswordCallback"
s.ends_with("_cb_fn") ||
s.starts_with("CRYPTO_") ||
s == "PasswordCallback"
}); });
cfg.field_name(|_s, field| { cfg.field_name(|_s, field| if field == "type_" {
if field == "type_" {
format!("type") format!("type")
} else { } else {
format!("{}", field) format!("{}", field)
}
}); });
cfg.fn_cname(|rust, link_name| link_name.unwrap_or(rust).to_string()); cfg.fn_cname(|rust, link_name| link_name.unwrap_or(rust).to_string());
cfg.generate("../openssl-sys/src/lib.rs", "all.rs"); cfg.generate("../openssl-sys/src/lib.rs", "all.rs");
} }