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
env:
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:
- (test $TRAVIS_OS_NAME == "osx" || ./openssl/test/build.sh)
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)
[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
@ -25,7 +25,9 @@ sudo pacman -S openssl
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
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

View File

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

View File

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

View File

@ -1,10 +1,10 @@
#![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 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};
macro_rules! import_options {
@ -49,6 +49,14 @@ extern {
pub fn BIO_set_nbio(b: *mut BIO, enabled: c_long) -> c_long;
#[link_name = "BIO_set_mem_eof_return_shim"]
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_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;
@ -65,4 +73,8 @@ extern {
pub fn SSL_CTX_set_tmp_dh(s: *mut SSL, dh: *const DH) -> c_long;
#[link_name = "X509_get_extensions_shim"]
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);
}
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) {
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);
}
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
int SSL_CTX_set_ecdh_auto_shim(SSL_CTX *ctx, int onoff) {
return SSL_CTX_set_ecdh_auto(ctx, onoff);

View File

@ -1,13 +1,12 @@
[package]
name = "openssl-sys"
version = "0.7.1"
version = "0.7.2"
authors = ["Alex Crichton <alex@alexcrichton.com>",
"Steven Fackler <sfackler@gmail.com>"]
license = "MIT"
description = "FFI bindings to 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"
build = "build.rs"
@ -23,6 +22,7 @@ aes_ctr = []
npn = []
alpn = []
rfc5114 = []
pkcs5_pbkdf2_hmac = []
[dependencies]
libc = "0.2"

View File

@ -1,6 +1,6 @@
#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]
#![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;
@ -15,11 +15,8 @@ use std::sync::{Once, ONCE_INIT};
pub type ASN1_INTEGER = c_void;
pub type ASN1_STRING = 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 COMP_METHOD = c_void;
pub type CRYPTO_EX_DATA = c_void;
pub type DH = c_void;
pub type ENGINE = 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_STORE_CTX = 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)]
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)
-> c_int;
pub const BIO_TYPE_NONE: c_int = 0;
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 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_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_EXTRA_CHAIN_CERT: c_int = 14;
@ -478,7 +539,11 @@ extern "C" {
salt: *const u8, saltlen: c_int,
iter: c_int, keylen: 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;
@ -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_get_ex_data_X509_STORE_CTX_idx() -> c_int;
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_peer_certificate(ssl: *mut SSL) -> *mut X509;
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_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_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_ctrl(ssl: *mut SSL_CTX, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long;
#[cfg(feature = "npn")]
pub fn SSL_CTX_set_next_protos_advertised_cb(ssl: *mut SSL_CTX,
cb: extern "C" fn(ssl: *mut SSL,

View File

@ -1,13 +1,14 @@
[package]
name = "openssl"
version = "0.7.1"
version = "0.7.2"
authors = ["Steven Fackler <sfackler@gmail.com>"]
license = "Apache-2.0"
description = "OpenSSL bindings"
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"
keywords = ["crypto", "tls", "ssl", "dtls"]
build = "build.rs"
[features]
tlsv1_2 = ["openssl-sys/tlsv1_2"]
@ -22,6 +23,7 @@ npn = ["openssl-sys/npn"]
alpn = ["openssl-sys/alpn"]
rfc5114 = ["openssl-sys/rfc5114"]
ecdh_auto = ["openssl-sys-extras/ecdh_auto"]
pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"]
[dependencies]
bitflags = ">= 0.2, < 0.4"
@ -30,6 +32,9 @@ libc = "0.2"
openssl-sys = { version = "0.7.1", path = "../openssl-sys" }
openssl-sys-extras = { version = "0.7.1", path = "../openssl-sys-extras" }
[build-dependencies]
gcc = "0.3"
[dev-dependencies]
rustc-serialize = "0.3"
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> {
BigNum::new().and_then(|v| unsafe {
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)
})
}
@ -97,7 +97,7 @@ impl BigNum {
pub fn from_hex_str(s: &str) -> Result<BigNum, SslError> {
BigNum::new().and_then(|v| unsafe {
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)
})
}
@ -421,7 +421,7 @@ impl BigNum {
unsafe {
let buf = ffi::BN_bn2dec(self.raw());
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);
str
}
@ -431,7 +431,7 @@ impl BigNum {
unsafe {
let buf = ffi::BN_bn2hex(self.raw());
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);
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)]
mod tests {
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]
fn test_evp_bytes_to_key_pbkdf1_compatible() {
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]
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 std::error;
use std::error::Error as StdError;
use std::fmt;
use std::ffi::CStr;
use std::io;
use std::str;
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
#[derive(Debug)]
pub enum SslError {
@ -115,24 +244,38 @@ pub enum OpensslError {
}
}
fn get_lib(err: c_ulong) -> String {
unsafe {
let bytes = CStr::from_ptr(ffi::ERR_lib_error_string(err)).to_bytes().to_vec();
String::from_utf8(bytes).unwrap()
impl OpensslError {
pub fn from_error_code(err: c_ulong) -> OpensslError {
ffi::init();
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 {
let bytes = CStr::from_ptr(ffi::ERR_func_error_string(err)).to_bytes().to_vec();
String::from_utf8(bytes).unwrap()
let cstr = ffi::ERR_lib_error_string(err);
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 {
let bytes = CStr::from_ptr(ffi::ERR_reason_error_string(err)).to_bytes().to_vec();
String::from_utf8(bytes).unwrap()
let cstr = ffi::ERR_func_error_string(err);
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 {
match unsafe { ffi::ERR_get_error() } {
0 => break,
err => errs.push(SslError::from_error_code(err))
err => errs.push(OpensslError::from_error_code(err))
}
}
OpenSslErrors(errs)
@ -152,16 +295,7 @@ impl SslError {
/// Creates an `SslError` from the raw numeric error code.
pub fn from_error(err: c_ulong) -> SslError {
OpenSslErrors(vec![SslError::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)
}
OpenSslErrors(vec![OpensslError::from_error_code(err)])
}
}

File diff suppressed because it is too large Load Diff

View File

@ -50,7 +50,7 @@ impl Deref for SslString {
impl SslString {
unsafe fn new(buf: *const c_char) -> 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 {
let key = CString::new(key.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,
value.as_ptr(), value_len, -1, 0)
ffi::X509_NAME_add_entry_by_txt(name, key.as_ptr() as *const _, ffi::MBSTRING_UTF8,
value.as_ptr() as *const _, value_len, -1, 0)
})
}

View File

@ -3,7 +3,7 @@ set -e
mkdir /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
make
make install