Merge branch 'release-v0.7.2' into release

This commit is contained in:
Steven Fackler 2015-12-15 19:42:12 -08:00
commit cf075d8e6b
19 changed files with 1015 additions and 601 deletions

View File

@ -9,7 +9,7 @@ os:
- linux - linux
env: env:
global: global:
- FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto" - FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac"
before_install: before_install:
- (test $TRAVIS_OS_NAME == "osx" || ./openssl/test/build.sh) - (test $TRAVIS_OS_NAME == "osx" || ./openssl/test/build.sh)
script: script:

View File

@ -2,7 +2,7 @@
[![Build Status](https://travis-ci.org/sfackler/rust-openssl.svg?branch=master)](https://travis-ci.org/sfackler/rust-openssl) [![Build Status](https://travis-ci.org/sfackler/rust-openssl.svg?branch=master)](https://travis-ci.org/sfackler/rust-openssl)
[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.7.1/openssl). [Documentation](https://sfackler.github.io/rust-openssl/doc/v0.7.2/openssl).
## Building ## Building
@ -25,7 +25,9 @@ sudo pacman -S openssl
OpenSSL 0.9.8 is preinstalled on OSX. Some features are only available when OpenSSL 0.9.8 is preinstalled on OSX. Some features are only available when
linking against OpenSSL 1.0.0 or greater; see below on how to point linking against OpenSSL 1.0.0 or greater; see below on how to point
rust-openssl to a separate installation. rust-openssl to a separate installation. OSX releases starting at 10.11, "El
Capitan", no longer include OpenSSL headers which will prevent the `openssl`
crate from compiling.
### Windows ### Windows

View File

@ -8,10 +8,10 @@ environment:
- TARGET: x86_64-pc-windows-msvc - TARGET: x86_64-pc-windows-msvc
BITS: 64 BITS: 64
install: install:
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2d.exe" - ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2e.exe"
- Win%BITS%OpenSSL-1_0_2d.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL" - Win%BITS%OpenSSL-1_0_2e.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe" - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.5.0-${env:TARGET}.exe"
- rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - rust-1.5.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
- SET PATH=%PATH%;C:\MinGW\bin - SET PATH=%PATH%;C:\MinGW\bin
- rustc -V - rustc -V

View File

@ -1,13 +1,11 @@
[package] [package]
name = "openssl-sys-extras" name = "openssl-sys-extras"
version = "0.7.1" version = "0.7.2"
authors = ["Steven Fackler <sfackler@gmail.com>"] authors = ["Steven Fackler <sfackler@gmail.com>"]
license = "MIT" license = "MIT"
description = "Extra FFI bindings to OpenSSL that require a C shim" description = "Extra FFI bindings to OpenSSL that require a C shim"
repository = "https://github.com/sfackler/rust-openssl" repository = "https://github.com/sfackler/rust-openssl"
documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.1/openssl_sys_extras" documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.2/openssl_sys_extras"
links = "openssl_shim"
build = "build.rs" build = "build.rs"
[features] [features]

View File

@ -1,10 +1,10 @@
#![allow(non_upper_case_globals, non_snake_case)] #![allow(non_upper_case_globals, non_snake_case)]
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.0")] #![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.2")]
extern crate openssl_sys; extern crate openssl_sys;
extern crate libc; extern crate libc;
use libc::{c_int, c_uint, c_long, c_char}; use libc::{c_int, c_uint, c_long, c_char, c_void};
use openssl_sys::{HMAC_CTX, EVP_MD, ENGINE, SSL_CTX, BIO, X509, stack_st_X509_EXTENSION, SSL, DH}; use openssl_sys::{HMAC_CTX, EVP_MD, ENGINE, SSL_CTX, BIO, X509, stack_st_X509_EXTENSION, SSL, DH};
macro_rules! import_options { macro_rules! import_options {
@ -49,6 +49,14 @@ extern {
pub fn BIO_set_nbio(b: *mut BIO, enabled: c_long) -> c_long; pub fn BIO_set_nbio(b: *mut BIO, enabled: c_long) -> c_long;
#[link_name = "BIO_set_mem_eof_return_shim"] #[link_name = "BIO_set_mem_eof_return_shim"]
pub fn BIO_set_mem_eof_return(b: *mut BIO, v: c_int); pub fn BIO_set_mem_eof_return(b: *mut BIO, v: c_int);
#[link_name = "BIO_clear_retry_flags_shim"]
pub fn BIO_clear_retry_flags(b: *mut BIO);
#[link_name = "BIO_set_retry_read_shim"]
pub fn BIO_set_retry_read(b: *mut BIO);
#[link_name = "BIO_set_retry_write_shim"]
pub fn BIO_set_retry_write(b: *mut BIO);
#[link_name = "BIO_flush"]
pub fn BIO_flush(b: *mut BIO) -> c_long;
pub fn SSL_CTX_set_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long; pub fn SSL_CTX_set_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long;
pub fn SSL_CTX_get_options_shim(ctx: *mut SSL_CTX) -> c_long; pub fn SSL_CTX_get_options_shim(ctx: *mut SSL_CTX) -> c_long;
pub fn SSL_CTX_clear_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long; pub fn SSL_CTX_clear_options_shim(ctx: *mut SSL_CTX, options: c_long) -> c_long;
@ -65,4 +73,8 @@ extern {
pub fn SSL_CTX_set_tmp_dh(s: *mut SSL, dh: *const DH) -> c_long; pub fn SSL_CTX_set_tmp_dh(s: *mut SSL, dh: *const DH) -> c_long;
#[link_name = "X509_get_extensions_shim"] #[link_name = "X509_get_extensions_shim"]
pub fn X509_get_extensions(x: *mut X509) -> *mut stack_st_X509_EXTENSION; pub fn X509_get_extensions(x: *mut X509) -> *mut stack_st_X509_EXTENSION;
#[link_name = "SSL_CTX_set_tlsext_servername_callback_shim"]
pub fn SSL_CTX_set_tlsext_servername_callback(ssl: *mut SSL_CTX, callback: Option<extern fn()>);
#[link_name = "SSL_CTX_set_tlsext_servername_arg_shim"]
pub fn SSL_CTX_set_tlsext_servername_arg(ssl: *mut SSL_CTX, arg: *const c_void);
} }

View File

@ -91,6 +91,22 @@ void BIO_set_mem_eof_return_shim(BIO *b, int v) {
BIO_set_mem_eof_return(b, v); BIO_set_mem_eof_return(b, v);
} }
void BIO_clear_retry_flags_shim(BIO *b) {
BIO_clear_retry_flags(b);
}
void BIO_set_retry_read_shim(BIO *b) {
BIO_set_retry_read(b);
}
void BIO_set_retry_write_shim(BIO *b) {
BIO_set_retry_write(b);
}
long BIO_flush_shim(BIO *b) {
return BIO_flush(b);
}
long SSL_CTX_set_options_shim(SSL_CTX *ctx, long options) { long SSL_CTX_set_options_shim(SSL_CTX *ctx, long options) {
return SSL_CTX_set_options(ctx, options); return SSL_CTX_set_options(ctx, options);
} }
@ -115,6 +131,14 @@ long SSL_CTX_set_tmp_dh_shim(SSL_CTX *ctx, DH *dh) {
return SSL_CTX_set_tmp_dh(ctx, dh); return SSL_CTX_set_tmp_dh(ctx, dh);
} }
long SSL_CTX_set_tlsext_servername_callback_shim(SSL_CTX *ctx, int (*callback)(SSL_CTX *, int *, void*)) {
return SSL_CTX_set_tlsext_servername_callback(ctx, callback);
}
long SSL_CTX_set_tlsext_servername_arg_shim(SSL_CTX *ctx, void* arg) {
return SSL_CTX_set_tlsext_servername_arg(ctx, arg);
}
#if OPENSSL_VERSION_NUMBER >= 0x10002000L #if OPENSSL_VERSION_NUMBER >= 0x10002000L
int SSL_CTX_set_ecdh_auto_shim(SSL_CTX *ctx, int onoff) { int SSL_CTX_set_ecdh_auto_shim(SSL_CTX *ctx, int onoff) {
return SSL_CTX_set_ecdh_auto(ctx, onoff); return SSL_CTX_set_ecdh_auto(ctx, onoff);

View File

@ -1,13 +1,12 @@
[package] [package]
name = "openssl-sys" name = "openssl-sys"
version = "0.7.1" version = "0.7.2"
authors = ["Alex Crichton <alex@alexcrichton.com>", authors = ["Alex Crichton <alex@alexcrichton.com>",
"Steven Fackler <sfackler@gmail.com>"] "Steven Fackler <sfackler@gmail.com>"]
license = "MIT" license = "MIT"
description = "FFI bindings to OpenSSL" description = "FFI bindings to OpenSSL"
repository = "https://github.com/sfackler/rust-openssl" repository = "https://github.com/sfackler/rust-openssl"
documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.1/openssl_sys" documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.2/openssl_sys"
links = "openssl" links = "openssl"
build = "build.rs" build = "build.rs"
@ -23,6 +22,7 @@ aes_ctr = []
npn = [] npn = []
alpn = [] alpn = []
rfc5114 = [] rfc5114 = []
pkcs5_pbkdf2_hmac = []
[dependencies] [dependencies]
libc = "0.2" libc = "0.2"

View File

@ -1,6 +1,6 @@
#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] #![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]
#![allow(dead_code)] #![allow(dead_code)]
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.1")] #![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.2")]
extern crate libc; extern crate libc;
@ -15,11 +15,8 @@ use std::sync::{Once, ONCE_INIT};
pub type ASN1_INTEGER = c_void; pub type ASN1_INTEGER = c_void;
pub type ASN1_STRING = c_void; pub type ASN1_STRING = c_void;
pub type ASN1_TIME = c_void; pub type ASN1_TIME = c_void;
pub type BIO = c_void;
pub type BIO_METHOD = c_void;
pub type BN_CTX = c_void; pub type BN_CTX = c_void;
pub type COMP_METHOD = c_void; pub type COMP_METHOD = c_void;
pub type CRYPTO_EX_DATA = c_void;
pub type DH = c_void; pub type DH = c_void;
pub type ENGINE = c_void; pub type ENGINE = c_void;
pub type EVP_CIPHER = c_void; pub type EVP_CIPHER = c_void;
@ -39,6 +36,65 @@ pub type X509_NAME_ENTRY = c_void;
pub type X509_REQ = c_void; pub type X509_REQ = c_void;
pub type X509_STORE_CTX = c_void; pub type X509_STORE_CTX = c_void;
pub type stack_st_X509_EXTENSION = c_void; pub type stack_st_X509_EXTENSION = c_void;
pub type stack_st_void = c_void;
pub type bio_st = c_void;
pub type bio_info_cb = Option<unsafe extern "C" fn(*mut BIO,
c_int,
*const c_char,
c_int,
c_long,
c_long)>;
#[repr(C)]
#[derive(Copy, Clone)]
#[allow(raw_pointer_derive)]
pub struct BIO_METHOD {
pub type_: c_int,
pub name: *const c_char,
pub bwrite: Option<unsafe extern "C" fn(*mut BIO, *const c_char, c_int) -> c_int>,
pub bread: Option<unsafe extern "C" fn(*mut BIO, *mut c_char, c_int) -> c_int>,
pub bputs: Option<unsafe extern "C" fn(*mut BIO, *const c_char) -> c_int>,
pub bgets: Option<unsafe extern "C" fn(*mut BIO, *mut c_char, c_int) -> c_int>,
pub ctrl: Option<unsafe extern "C" fn(*mut BIO, c_int, c_long, *mut c_void) -> c_long>,
pub create: Option<unsafe extern "C" fn(*mut BIO) -> c_int>,
pub destroy: Option<unsafe extern "C" fn(*mut BIO) -> c_int>,
pub callback_ctrl: Option<unsafe extern "C" fn(*mut BIO, c_int, bio_info_cb) -> c_long>,
}
// so we can create static BIO_METHODs
unsafe impl Sync for BIO_METHOD {}
#[repr(C)]
pub struct BIO {
pub method: *mut BIO_METHOD,
pub callback: Option<unsafe extern "C" fn(*mut BIO,
c_int,
*const c_char,
c_int,
c_long,
c_long)
-> c_long>,
pub cb_arg: *mut c_char,
pub init: c_int,
pub shutdown: c_int,
pub flags: c_int,
pub retry_reason: c_int,
pub num: c_int,
pub ptr: *mut c_void,
pub next_bio: *mut BIO,
pub prev_bio: *mut BIO,
pub references: c_int,
pub num_read: c_ulong,
pub num_write: c_ulong,
pub ex_data: CRYPTO_EX_DATA,
}
#[repr(C)]
pub struct CRYPTO_EX_DATA {
pub sk: *mut stack_st_void,
pub dummy: c_int,
}
#[repr(C)] #[repr(C)]
pub struct EVP_MD_CTX { pub struct EVP_MD_CTX {
@ -116,7 +172,10 @@ pub type PasswordCallback = extern "C" fn(buf: *mut c_char, size: c_int,
rwflag: c_int, user_data: *mut c_void) rwflag: c_int, user_data: *mut c_void)
-> c_int; -> c_int;
pub const BIO_TYPE_NONE: c_int = 0;
pub const BIO_CTRL_EOF: c_int = 2; pub const BIO_CTRL_EOF: c_int = 2;
pub const BIO_CTRL_FLUSH: c_int = 11;
pub const BIO_C_SET_BUF_MEM_EOF_RETURN: c_int = 130; pub const BIO_C_SET_BUF_MEM_EOF_RETURN: c_int = 130;
pub const CRYPTO_LOCK: c_int = 1; pub const CRYPTO_LOCK: c_int = 1;
@ -135,6 +194,8 @@ pub const PKCS5_SALT_LEN: c_int = 8;
pub const SSL_CTRL_OPTIONS: c_int = 32; pub const SSL_CTRL_OPTIONS: c_int = 32;
pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77; pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77;
pub const SSL_CTRL_SET_TLSEXT_SERVERNAME_CB: c_int = 53;
pub const SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: c_int = 54;
pub const SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55; pub const SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55;
pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14;
@ -478,7 +539,11 @@ extern "C" {
salt: *const u8, saltlen: c_int, salt: *const u8, saltlen: c_int,
iter: c_int, keylen: c_int, iter: c_int, keylen: c_int,
out: *mut u8) -> c_int; out: *mut u8) -> c_int;
#[cfg(feature = "pkcs5_pbkdf2_hmac")]
pub fn PKCS5_PBKDF2_HMAC(pass: *const u8, passlen: c_int,
salt: *const u8, saltlen: c_int,
iter: c_int, digest: *const EVP_MD, keylen: c_int,
out: *mut u8) -> c_int;
pub fn RAND_bytes(buf: *mut u8, num: c_int) -> c_int; pub fn RAND_bytes(buf: *mut u8, num: c_int) -> c_int;
@ -532,12 +597,15 @@ extern "C" {
pub fn SSL_write(ssl: *mut SSL, buf: *const c_void, num: c_int) -> c_int; pub fn SSL_write(ssl: *mut SSL, buf: *const c_void, num: c_int) -> c_int;
pub fn SSL_get_ex_data_X509_STORE_CTX_idx() -> c_int; pub fn SSL_get_ex_data_X509_STORE_CTX_idx() -> c_int;
pub fn SSL_get_SSL_CTX(ssl: *mut SSL) -> *mut SSL_CTX; pub fn SSL_get_SSL_CTX(ssl: *mut SSL) -> *mut SSL_CTX;
pub fn SSL_set_SSL_CTX(ssl: *mut SSL, ctx: *mut SSL_CTX) -> *mut SSL_CTX;
pub fn SSL_get_current_compression(ssl: *mut SSL) -> *const COMP_METHOD; pub fn SSL_get_current_compression(ssl: *mut SSL) -> *const COMP_METHOD;
pub fn SSL_get_peer_certificate(ssl: *mut SSL) -> *mut X509; pub fn SSL_get_peer_certificate(ssl: *mut SSL) -> *mut X509;
pub fn SSL_get_ssl_method(ssl: *mut SSL) -> *const SSL_METHOD; pub fn SSL_get_ssl_method(ssl: *mut SSL) -> *const SSL_METHOD;
pub fn SSL_state_string(ssl: *mut SSL) -> *const c_char; pub fn SSL_state_string(ssl: *mut SSL) -> *const c_char;
pub fn SSL_state_string_long(ssl: *mut SSL) -> *const c_char; pub fn SSL_state_string_long(ssl: *mut SSL) -> *const c_char;
pub fn SSL_get_servername(ssl: *const SSL, name_type: c_long) -> *const c_char;
pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char;
pub fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX; pub fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX;
@ -566,7 +634,6 @@ extern "C" {
pub fn SSL_CTX_set_cipher_list(ssl: *mut SSL_CTX, s: *const c_char) -> c_int; pub fn SSL_CTX_set_cipher_list(ssl: *mut SSL_CTX, s: *const c_char) -> c_int;
pub fn SSL_CTX_ctrl(ssl: *mut SSL_CTX, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long;
#[cfg(feature = "npn")] #[cfg(feature = "npn")]
pub fn SSL_CTX_set_next_protos_advertised_cb(ssl: *mut SSL_CTX, pub fn SSL_CTX_set_next_protos_advertised_cb(ssl: *mut SSL_CTX,
cb: extern "C" fn(ssl: *mut SSL, cb: extern "C" fn(ssl: *mut SSL,

View File

@ -1,13 +1,14 @@
[package] [package]
name = "openssl" name = "openssl"
version = "0.7.1" version = "0.7.2"
authors = ["Steven Fackler <sfackler@gmail.com>"] authors = ["Steven Fackler <sfackler@gmail.com>"]
license = "Apache-2.0" license = "Apache-2.0"
description = "OpenSSL bindings" description = "OpenSSL bindings"
repository = "https://github.com/sfackler/rust-openssl" repository = "https://github.com/sfackler/rust-openssl"
documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.1/openssl" documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.2/openssl"
readme = "../README.md" readme = "../README.md"
keywords = ["crypto", "tls", "ssl", "dtls"] keywords = ["crypto", "tls", "ssl", "dtls"]
build = "build.rs"
[features] [features]
tlsv1_2 = ["openssl-sys/tlsv1_2"] tlsv1_2 = ["openssl-sys/tlsv1_2"]
@ -22,6 +23,7 @@ npn = ["openssl-sys/npn"]
alpn = ["openssl-sys/alpn"] alpn = ["openssl-sys/alpn"]
rfc5114 = ["openssl-sys/rfc5114"] rfc5114 = ["openssl-sys/rfc5114"]
ecdh_auto = ["openssl-sys-extras/ecdh_auto"] ecdh_auto = ["openssl-sys-extras/ecdh_auto"]
pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"]
[dependencies] [dependencies]
bitflags = ">= 0.2, < 0.4" bitflags = ">= 0.2, < 0.4"
@ -30,6 +32,9 @@ libc = "0.2"
openssl-sys = { version = "0.7.1", path = "../openssl-sys" } openssl-sys = { version = "0.7.1", path = "../openssl-sys" }
openssl-sys-extras = { version = "0.7.1", path = "../openssl-sys-extras" } openssl-sys-extras = { version = "0.7.1", path = "../openssl-sys-extras" }
[build-dependencies]
gcc = "0.3"
[dev-dependencies] [dev-dependencies]
rustc-serialize = "0.3" rustc-serialize = "0.3"
net2 = "0.2.16" net2 = "0.2.16"

16
openssl/build.rs Normal file
View File

@ -0,0 +1,16 @@
extern crate gcc;
use std::env;
use std::path::PathBuf;
fn main() {
let mut config = gcc::Config::new();
if let Some(paths) = env::var_os("DEP_OPENSSL_INCLUDE") {
for path in env::split_paths(&paths) {
config.include(PathBuf::from(path));
}
}
config.file("src/c_helpers.c").compile("libc_helpers.a");
}

View File

@ -89,7 +89,7 @@ impl BigNum {
pub fn from_dec_str(s: &str) -> Result<BigNum, SslError> { pub fn from_dec_str(s: &str) -> Result<BigNum, SslError> {
BigNum::new().and_then(|v| unsafe { BigNum::new().and_then(|v| unsafe {
let c_str = CString::new(s.as_bytes()).unwrap(); let c_str = CString::new(s.as_bytes()).unwrap();
try_ssl!(ffi::BN_dec2bn(v.raw_ptr(), c_str.as_ptr())); try_ssl!(ffi::BN_dec2bn(v.raw_ptr(), c_str.as_ptr() as *const _));
Ok(v) Ok(v)
}) })
} }
@ -97,7 +97,7 @@ impl BigNum {
pub fn from_hex_str(s: &str) -> Result<BigNum, SslError> { pub fn from_hex_str(s: &str) -> Result<BigNum, SslError> {
BigNum::new().and_then(|v| unsafe { BigNum::new().and_then(|v| unsafe {
let c_str = CString::new(s.as_bytes()).unwrap(); let c_str = CString::new(s.as_bytes()).unwrap();
try_ssl!(ffi::BN_hex2bn(v.raw_ptr(), c_str.as_ptr())); try_ssl!(ffi::BN_hex2bn(v.raw_ptr(), c_str.as_ptr() as *const _));
Ok(v) Ok(v)
}) })
} }
@ -421,7 +421,7 @@ impl BigNum {
unsafe { unsafe {
let buf = ffi::BN_bn2dec(self.raw()); let buf = ffi::BN_bn2dec(self.raw());
assert!(!buf.is_null()); assert!(!buf.is_null());
let str = String::from_utf8(CStr::from_ptr(buf).to_bytes().to_vec()).unwrap(); let str = String::from_utf8(CStr::from_ptr(buf as *const _).to_bytes().to_vec()).unwrap();
ffi::CRYPTO_free(buf as *mut c_void); ffi::CRYPTO_free(buf as *mut c_void);
str str
} }
@ -431,7 +431,7 @@ impl BigNum {
unsafe { unsafe {
let buf = ffi::BN_bn2hex(self.raw()); let buf = ffi::BN_bn2hex(self.raw());
assert!(!buf.is_null()); assert!(!buf.is_null());
let str = String::from_utf8(CStr::from_ptr(buf).to_bytes().to_vec()).unwrap(); let str = String::from_utf8(CStr::from_ptr(buf as *const _).to_bytes().to_vec()).unwrap();
ffi::CRYPTO_free(buf as *mut c_void); ffi::CRYPTO_free(buf as *mut c_void);
str str
} }

9
openssl/src/c_helpers.c Normal file
View File

@ -0,0 +1,9 @@
#include <openssl/ssl.h>
void rust_SSL_clone(SSL *ssl) {
CRYPTO_add(&ssl->references, 1, CRYPTO_LOCK_SSL);
}
void rust_SSL_CTX_clone(SSL_CTX *ctx) {
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
}

View File

@ -88,6 +88,43 @@ pub fn pbkdf2_hmac_sha1(pass: &str, salt: &[u8], iter: usize, keylen: usize) ->
} }
} }
/// Derives a key from a password and salt using the PBKDF2-HMAC-SHA256 algorithm.
#[cfg(feature = "pkcs5_pbkdf2_hmac")]
pub fn pbkdf2_hmac_sha256(pass: &str, salt: &[u8], iter: usize, keylen: usize) -> Vec<u8> {
pbkdf2_hmac_sha(pass, salt, iter, unsafe { ffi::EVP_sha256() }, keylen)
}
/// Derives a key from a password and salt using the PBKDF2-HMAC-SHA512 algorithm.
#[cfg(feature = "pkcs5_pbkdf2_hmac")]
pub fn pbkdf2_hmac_sha512(pass: &str, salt: &[u8], iter: usize, keylen: usize) -> Vec<u8> {
pbkdf2_hmac_sha(pass, salt, iter, unsafe { ffi::EVP_sha512() }, keylen)
}
/// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function.
#[cfg(feature = "pkcs5_pbkdf2_hmac")]
fn pbkdf2_hmac_sha(pass: &str, salt: &[u8], iter: usize, digest: *const ffi::EVP_MD, keylen: usize) -> Vec<u8> {
unsafe {
assert!(iter >= 1);
assert!(keylen >= 1);
let mut out = Vec::with_capacity(keylen);
ffi::init();
let r = ffi::PKCS5_PBKDF2_HMAC(
pass.as_ptr(), pass.len() as c_int,
salt.as_ptr(), salt.len() as c_int,
iter as c_int, digest, keylen as c_int,
out.as_mut_ptr());
if r != 1 { panic!(); }
out.set_len(keylen);
out
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crypto::hash; use crypto::hash;
@ -183,6 +220,108 @@ mod tests {
); );
} }
// Test vectors from
// https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
#[test]
#[cfg(feature = "pkcs5_pbkdf2_hmac")]
fn test_pbkdf2_hmac_sha256() {
assert_eq!(
super::pbkdf2_hmac_sha256(
"passwd",
"salt".as_bytes(),
1,
16
),
vec!(
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
)
);
assert_eq!(
super::pbkdf2_hmac_sha256(
"Password",
"NaCl".as_bytes(),
80000,
16
),
vec!(
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
// https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
#[test]
#[cfg(feature = "pkcs5_pbkdf2_hmac")]
fn test_pbkdf2_hmac_sha512() {
assert_eq!(
super::pbkdf2_hmac_sha512(
"password",
"NaCL".as_bytes(),
1,
64
),
vec!(
0x73_u8, 0xde_u8, 0xcf_u8, 0xa5_u8, 0x8a_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
)
);
assert_eq!(
super::pbkdf2_hmac_sha512(
"pass\0word",
"sa\0lt".as_bytes(),
1,
64
),
vec!(
0x71_u8, 0xa0_u8, 0xec_u8, 0x84_u8, 0x2a_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
)
);
assert_eq!(
super::pbkdf2_hmac_sha512(
"passwordPASSWORDpassword",
"salt\0\0\0".as_bytes(),
50,
64
),
vec!(
0x01_u8, 0x68_u8, 0x71_u8, 0xa4_u8, 0xc4_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 test_evp_bytes_to_key_pbkdf1_compatible() { fn test_evp_bytes_to_key_pbkdf1_compatible() {
let salt = [ let salt = [

View File

@ -1,4 +1,4 @@
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.1")] #![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.2")]
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;

162
openssl/src/ssl/bio.rs Normal file
View File

@ -0,0 +1,162 @@
use libc::{c_char, c_int, c_long, c_void, strlen};
use ffi::{BIO, BIO_METHOD, BIO_CTRL_FLUSH, BIO_TYPE_NONE, BIO_new};
use ffi_extras::{BIO_clear_retry_flags, BIO_set_retry_read, BIO_set_retry_write};
use std::io;
use std::io::prelude::*;
use std::mem;
use std::slice;
use std::ptr;
use ssl::error::SslError;
// "rust"
const NAME: [c_char; 5] = [114, 117, 115, 116, 0];
// we use this after removing the stream from the BIO so that we don't have to
// worry about freeing the heap allocated BIO_METHOD after freeing the BIO.
static DESTROY_METHOD: BIO_METHOD = BIO_METHOD {
type_: BIO_TYPE_NONE,
name: &NAME[0],
bwrite: None,
bread: None,
bputs: None,
bgets: None,
ctrl: None,
create: None,
destroy: Some(destroy),
callback_ctrl: None,
};
pub struct StreamState<S> {
pub stream: S,
pub error: Option<io::Error>,
}
pub fn new<S: Read + Write>(stream: S) -> Result<(*mut BIO, Box<BIO_METHOD>), SslError> {
let method = Box::new(BIO_METHOD {
type_: BIO_TYPE_NONE,
name: &NAME[0],
bwrite: Some(bwrite::<S>),
bread: Some(bread::<S>),
bputs: Some(bputs::<S>),
bgets: None,
ctrl: Some(ctrl::<S>),
create: Some(create),
destroy: None, // covered in the replacement BIO_METHOD
callback_ctrl: None,
});
let state = Box::new(StreamState {
stream: stream,
error: None,
});
unsafe {
let bio = try_ssl_null!(BIO_new(&*method));
(*bio).ptr = Box::into_raw(state) as *mut _;
(*bio).init = 1;
return Ok((bio, method));
}
}
pub unsafe fn take_error<S>(bio: *mut BIO) -> Option<io::Error> {
let state = state::<S>(bio);
state.error.take()
}
pub unsafe fn take_stream<S>(bio: *mut BIO) -> S {
let state: Box<StreamState<S>> = Box::from_raw((*bio).ptr as *mut _);
(*bio).ptr = ptr::null_mut();
(*bio).method = &DESTROY_METHOD as *const _ as *mut _;
(*bio).init = 0;
state.stream
}
pub unsafe fn get_ref<'a, S: 'a>(bio: *mut BIO) -> &'a S {
let state: &'a StreamState<S> = mem::transmute((*bio).ptr);
&state.stream
}
pub unsafe fn get_mut<'a, S: 'a>(bio: *mut BIO) -> &'a mut S {
&mut state(bio).stream
}
unsafe fn state<'a, S: 'a>(bio: *mut BIO) -> &'a mut StreamState<S> {
mem::transmute((*bio).ptr)
}
unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int {
BIO_clear_retry_flags(bio);
let state = state::<S>(bio);
let buf = slice::from_raw_parts(buf as *const _, len as usize);
match state.stream.write(buf) {
Ok(len) => len as c_int,
Err(err) => {
if err.kind() == io::ErrorKind::WouldBlock {
BIO_set_retry_write(bio);
}
state.error = Some(err);
-1
}
}
}
unsafe extern "C" fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int {
BIO_clear_retry_flags(bio);
let state = state::<S>(bio);
let buf = slice::from_raw_parts_mut(buf as *mut _, len as usize);
match state.stream.read(buf) {
Ok(len) => len as c_int,
Err(err) => {
if err.kind() == io::ErrorKind::WouldBlock {
BIO_set_retry_read(bio);
}
state.error = Some(err);
-1
}
}
}
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)
}
unsafe extern "C" fn ctrl<S: Write>(bio: *mut BIO,
cmd: c_int,
_num: c_long,
_ptr: *mut c_void)
-> c_long {
if cmd == BIO_CTRL_FLUSH {
let state = state::<S>(bio);
match state.stream.flush() {
Ok(()) => 1,
Err(err) => {
state.error = Some(err);
0
}
}
} else {
0
}
}
unsafe extern "C" fn create(bio: *mut BIO) -> c_int {
(*bio).init = 0;
(*bio).num = 0;
(*bio).ptr = ptr::null_mut();
(*bio).flags = 0;
1
}
unsafe extern "C" fn destroy(bio: *mut BIO) -> c_int {
if bio.is_null() {
return 0;
}
assert!((*bio).ptr.is_null());
1
}

View File

@ -3,12 +3,141 @@ pub use self::OpensslError::*;
use libc::c_ulong; use libc::c_ulong;
use std::error; use std::error;
use std::error::Error as StdError;
use std::fmt; use std::fmt;
use std::ffi::CStr; use std::ffi::CStr;
use std::io; use std::io;
use std::str;
use ffi; use ffi;
/// An SSL error.
#[derive(Debug)]
pub enum Error {
/// The SSL session has been closed by the other end
ZeroReturn,
/// An attempt to read data from the underlying socket returned
/// `WouldBlock`. Wait for read readiness and reattempt the operation.
WantRead(io::Error),
/// An attempt to write data from the underlying socket returned
/// `WouldBlock`. Wait for write readiness and reattempt the operation.
WantWrite(io::Error),
/// The client certificate callback requested to be called again.
WantX509Lookup,
/// An error reported by the underlying stream.
Stream(io::Error),
/// An error in the OpenSSL library.
Ssl(Vec<OpenSslError>),
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
try!(fmt.write_str(self.description()));
match *self {
Error::Stream(ref err) => write!(fmt, ": {}", err),
Error::WantRead(ref err) => write!(fmt, ": {}", err),
Error::WantWrite(ref err) => write!(fmt, ": {}", err),
Error::Ssl(ref errs) => {
let mut first = true;
for err in errs {
if first {
try!(fmt.write_str(": "));
first = false;
} else {
try!(fmt.write_str(", "));
}
try!(fmt.write_str(&err.reason()))
}
Ok(())
}
_ => Ok(())
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::ZeroReturn => "The SSL session was closed by the other end",
Error::WantRead(_) => "A read attempt returned a `WouldBlock` error",
Error::WantWrite(_) => "A write attempt returned a `WouldBlock` error",
Error::WantX509Lookup => "The client certificate callback requested to be called again",
Error::Stream(_) => "The underlying stream reported an error",
Error::Ssl(_) => "The OpenSSL library reported an error",
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::WantRead(ref err) => Some(err),
Error::WantWrite(ref err) => Some(err),
Error::Stream(ref err) => Some(err),
_ => None
}
}
}
/// An error reported from OpenSSL.
pub struct OpenSslError(c_ulong);
impl OpenSslError {
/// Returns the contents of the OpenSSL error stack.
pub fn get_stack() -> Vec<OpenSslError> {
ffi::init();
let mut errs = vec!();
loop {
match unsafe { ffi::ERR_get_error() } {
0 => break,
err => errs.push(OpenSslError(err))
}
}
errs
}
/// Returns the raw OpenSSL error code for this error.
pub fn error_code(&self) -> c_ulong {
self.0
}
/// Returns the name of the library reporting the error.
pub fn library(&self) -> &'static str {
get_lib(self.0)
}
/// Returns the name of the function reporting the error.
pub fn function(&self) -> &'static str {
get_func(self.0)
}
/// Returns the reason for the error.
pub fn reason(&self) -> &'static str {
get_reason(self.0)
}
}
impl fmt::Debug for OpenSslError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("OpenSslError")
.field("library", &self.library())
.field("function", &self.function())
.field("reason", &self.reason())
.finish()
}
}
impl fmt::Display for OpenSslError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(&self.reason())
}
}
impl error::Error for OpenSslError {
fn description(&self) -> &str {
"An OpenSSL error"
}
}
/// An SSL error /// An SSL error
#[derive(Debug)] #[derive(Debug)]
pub enum SslError { pub enum SslError {
@ -115,24 +244,38 @@ pub enum OpensslError {
} }
} }
fn get_lib(err: c_ulong) -> String { impl OpensslError {
unsafe { pub fn from_error_code(err: c_ulong) -> OpensslError {
let bytes = CStr::from_ptr(ffi::ERR_lib_error_string(err)).to_bytes().to_vec(); ffi::init();
String::from_utf8(bytes).unwrap() UnknownError {
library: get_lib(err).to_owned(),
function: get_func(err).to_owned(),
reason: get_reason(err).to_owned()
}
} }
} }
fn get_func(err: c_ulong) -> String { fn get_lib(err: c_ulong) -> &'static str {
unsafe { unsafe {
let bytes = CStr::from_ptr(ffi::ERR_func_error_string(err)).to_bytes().to_vec(); let cstr = ffi::ERR_lib_error_string(err);
String::from_utf8(bytes).unwrap() let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
str::from_utf8(bytes).unwrap()
} }
} }
fn get_reason(err: c_ulong) -> String { fn get_func(err: c_ulong) -> &'static str {
unsafe { unsafe {
let bytes = CStr::from_ptr(ffi::ERR_reason_error_string(err)).to_bytes().to_vec(); let cstr = ffi::ERR_func_error_string(err);
String::from_utf8(bytes).unwrap() let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
str::from_utf8(bytes).unwrap()
}
}
fn get_reason(err: c_ulong) -> &'static str {
unsafe {
let cstr = ffi::ERR_reason_error_string(err);
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
str::from_utf8(bytes).unwrap()
} }
} }
@ -144,7 +287,7 @@ impl SslError {
loop { loop {
match unsafe { ffi::ERR_get_error() } { match unsafe { ffi::ERR_get_error() } {
0 => break, 0 => break,
err => errs.push(SslError::from_error_code(err)) err => errs.push(OpensslError::from_error_code(err))
} }
} }
OpenSslErrors(errs) OpenSslErrors(errs)
@ -152,16 +295,7 @@ impl SslError {
/// Creates an `SslError` from the raw numeric error code. /// Creates an `SslError` from the raw numeric error code.
pub fn from_error(err: c_ulong) -> SslError { pub fn from_error(err: c_ulong) -> SslError {
OpenSslErrors(vec![SslError::from_error_code(err)]) OpenSslErrors(vec![OpensslError::from_error_code(err)])
}
fn from_error_code(err: c_ulong) -> OpensslError {
ffi::init();
UnknownError {
library: get_lib(err),
function: get_func(err),
reason: get_reason(err)
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -50,7 +50,7 @@ impl Deref for SslString {
impl SslString { impl SslString {
unsafe fn new(buf: *const c_char) -> SslString { unsafe fn new(buf: *const c_char) -> SslString {
SslString { SslString {
s: str::from_utf8(CStr::from_ptr(buf).to_bytes()).unwrap() s: str::from_utf8(CStr::from_ptr(buf as *const _).to_bytes()).unwrap()
} }
} }
} }
@ -275,8 +275,8 @@ impl X509Generator {
lift_ssl!(unsafe { lift_ssl!(unsafe {
let key = CString::new(key.as_bytes()).unwrap(); let key = CString::new(key.as_bytes()).unwrap();
let value = CString::new(value.as_bytes()).unwrap(); let value = CString::new(value.as_bytes()).unwrap();
ffi::X509_NAME_add_entry_by_txt(name, key.as_ptr(), ffi::MBSTRING_UTF8, ffi::X509_NAME_add_entry_by_txt(name, key.as_ptr() as *const _, ffi::MBSTRING_UTF8,
value.as_ptr(), value_len, -1, 0) value.as_ptr() as *const _, value_len, -1, 0)
}) })
} }

View File

@ -3,7 +3,7 @@ set -e
mkdir /tmp/openssl mkdir /tmp/openssl
cd /tmp/openssl cd /tmp/openssl
curl https://openssl.org/source/openssl-1.0.2d.tar.gz | tar --strip-components=1 -xzf - curl https://openssl.org/source/openssl-1.0.2e.tar.gz | tar --strip-components=1 -xzf -
./config --prefix=$HOME/openssl shared ./config --prefix=$HOME/openssl shared
make make
make install make install