Merge remote-tracking branch 'origin/breaks'

This commit is contained in:
Steven Fackler 2016-08-02 20:52:07 -07:00
commit c5b2ede282
23 changed files with 824 additions and 1522 deletions

View File

@ -6,7 +6,7 @@ addons:
- gcc-arm-linux-gnueabihf
rust:
- nightly
- 1.8.0
- 1.9.0
os:
- osx
- linux

View File

@ -10,8 +10,8 @@ environment:
install:
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2h.exe"
- Win%BITS%OpenSSL-1_0_2h.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.8.0-${env:TARGET}.exe"
- rust-1.8.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.9.0-${env:TARGET}.exe"
- rust-1.9.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

@ -269,6 +269,7 @@ pub type PasswordCallback = extern "C" fn(buf: *mut c_char, size: c_int,
pub const BIO_TYPE_NONE: c_int = 0;
pub const BIO_CTRL_EOF: c_int = 2;
pub const BIO_CTRL_INFO: c_int = 3;
pub const BIO_CTRL_FLUSH: c_int = 11;
pub const BIO_C_SET_BUF_MEM_EOF_RETURN: c_int = 130;
@ -453,6 +454,11 @@ fn set_id_callback() {
#[cfg(not(unix))]
fn set_id_callback() {}
// macros
pub unsafe fn BIO_get_mem_data(b: *mut BIO, pp: *mut *mut c_char) -> c_long {
BIO_ctrl(b, BIO_CTRL_INFO, 0, pp as *mut c_void)
}
// True functions
extern "C" {
pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int;
@ -466,6 +472,7 @@ extern "C" {
pub fn BIO_read(b: *mut BIO, buf: *mut c_void, len: c_int) -> c_int;
pub fn BIO_write(b: *mut BIO, buf: *const c_void, len: c_int) -> c_int;
pub fn BIO_s_mem() -> *const BIO_METHOD;
pub fn BIO_new_mem_buf(buf: *const c_void, len: c_int) -> *mut BIO;
pub fn BN_new() -> *mut BIGNUM;
pub fn BN_dup(n: *mut BIGNUM) -> *mut BIGNUM;
@ -741,6 +748,7 @@ extern "C" {
pub fn SSL_get_wbio(ssl: *mut SSL) -> *mut BIO;
pub fn SSL_accept(ssl: *mut SSL) -> c_int;
pub fn SSL_connect(ssl: *mut SSL) -> c_int;
pub fn SSL_do_handshake(ssl: *mut SSL) -> c_int;
pub fn SSL_ctrl(ssl: *mut SSL, cmd: c_int, larg: c_long,
parg: *mut c_void) -> c_long;
pub fn SSL_get_error(ssl: *mut SSL, ret: c_int) -> c_int;

View File

@ -26,9 +26,6 @@ rfc5114 = ["openssl-sys/rfc5114"]
ecdh_auto = ["openssl-sys-extras/ecdh_auto"]
pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"]
nightly = []
catch_unwind = []
[dependencies]
bitflags = ">= 0.5.0, < 0.8.0"
lazy_static = "0.2"

View File

@ -2,8 +2,7 @@ use libc::c_long;
use std::ptr;
use ffi;
use ssl::error::SslError;
use error::ErrorStack;
pub struct Asn1Time {
handle: *mut ffi::ASN1_TIME,
@ -19,7 +18,7 @@ impl Asn1Time {
}
}
fn new_with_period(period: u64) -> Result<Asn1Time, SslError> {
fn new_with_period(period: u64) -> Result<Asn1Time, ErrorStack> {
ffi::init();
let handle = unsafe {
@ -29,7 +28,7 @@ impl Asn1Time {
}
/// Creates a new time on specified interval in days from now
pub fn days_from_now(days: u32) -> Result<Asn1Time, SslError> {
pub fn days_from_now(days: u32) -> Result<Asn1Time, ErrorStack> {
Asn1Time::new_with_period(days as u64 * 60 * 60 * 24)
}

67
openssl/src/bio.rs Normal file
View File

@ -0,0 +1,67 @@
use std::marker::PhantomData;
use std::ptr;
use std::slice;
use libc::c_int;
use ffi;
use error::ErrorStack;
pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>);
impl<'a> Drop for MemBioSlice<'a> {
fn drop(&mut self) {
unsafe {
ffi::BIO_free_all(self.0);
}
}
}
impl<'a> MemBioSlice<'a> {
pub fn new(buf: &'a [u8]) -> Result<MemBioSlice<'a>, ErrorStack> {
ffi::init();
assert!(buf.len() <= c_int::max_value() as usize);
let bio = unsafe {
try_ssl_null!(ffi::BIO_new_mem_buf(buf.as_ptr() as *const _, buf.len() as c_int))
};
Ok(MemBioSlice(bio, PhantomData))
}
pub fn get_handle(&self) -> *mut ffi::BIO {
self.0
}
}
pub struct MemBio(*mut ffi::BIO);
impl Drop for MemBio {
fn drop(&mut self) {
unsafe {
ffi::BIO_free_all(self.0);
}
}
}
impl MemBio {
pub fn new() -> Result<MemBio, ErrorStack> {
ffi::init();
let bio = unsafe {
try_ssl_null!(ffi::BIO_new(ffi::BIO_s_mem()))
};
Ok(MemBio(bio))
}
pub fn get_handle(&self) -> *mut ffi::BIO {
self.0
}
pub fn get_buf(&self) -> &[u8] {
unsafe {
let mut ptr = ptr::null_mut();
let len = ffi::BIO_get_mem_data(self.0, &mut ptr);
slice::from_raw_parts(ptr as *const _ as *const _, len as usize)
}
}
}

View File

@ -1,107 +0,0 @@
use libc::{c_void, c_int};
use std::io;
use std::io::prelude::*;
use std::ptr;
use std::cmp;
use ffi;
use ffi_extras;
use ssl::error::SslError;
pub struct MemBio {
bio: *mut ffi::BIO,
owned: bool,
}
impl Drop for MemBio {
fn drop(&mut self) {
if self.owned {
unsafe {
ffi::BIO_free_all(self.bio);
}
}
}
}
impl MemBio {
/// Creates a new owned memory based BIO
pub fn new() -> Result<MemBio, SslError> {
ffi::init();
let bio = unsafe { ffi::BIO_new(ffi::BIO_s_mem()) };
try_ssl_null!(bio);
Ok(MemBio {
bio: bio,
owned: true,
})
}
/// Returns a "borrow", i.e. it has no ownership
pub fn borrowed(bio: *mut ffi::BIO) -> MemBio {
MemBio {
bio: bio,
owned: false,
}
}
/// Consumes current bio and returns wrapped value
/// Note that data ownership is lost and
/// should be managed manually
pub unsafe fn unwrap(mut self) -> *mut ffi::BIO {
self.owned = false;
self.bio
}
/// Temporarily gets wrapped value
pub unsafe fn get_handle(&self) -> *mut ffi::BIO {
self.bio
}
/// Sets the BIO's EOF state.
pub fn set_eof(&self, eof: bool) {
let v = if eof {
0
} else {
-1
};
unsafe {
ffi_extras::BIO_set_mem_eof_return(self.bio, v);
}
}
}
impl Read for MemBio {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int;
let ret = unsafe { ffi::BIO_read(self.bio, buf.as_ptr() as *mut c_void, len) };
if ret <= 0 {
let is_eof = unsafe { ffi_extras::BIO_eof(self.bio) };
if is_eof != 0 {
Ok(0)
} else {
Err(io::Error::new(io::ErrorKind::Other, SslError::get()))
}
} else {
Ok(ret as usize)
}
}
}
impl Write for MemBio {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int;
let ret = unsafe { ffi::BIO_write(self.bio, buf.as_ptr() as *const c_void, len) };
if ret < 0 {
Err(io::Error::new(io::ErrorKind::Other, SslError::get()))
} else {
Ok(ret as usize)
}
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}

View File

@ -4,7 +4,7 @@ use std::cmp::Ordering;
use std::{fmt, ptr, mem};
use ffi;
use ssl::error::SslError;
use error::ErrorStack;
/// A signed arbitrary-precision integer.
///
@ -30,7 +30,7 @@ macro_rules! with_ctx(
($name:ident, $action:block) => ({
let $name = ffi::BN_CTX_new();
if ($name).is_null() {
Err(SslError::get())
Err(ErrorStack::get())
} else {
let r = $action;
ffi::BN_CTX_free($name);
@ -47,7 +47,7 @@ macro_rules! with_bn(
if $action {
Ok($name)
} else {
Err(SslError::get())
Err(ErrorStack::get())
}
},
Err(err) => Err(err),
@ -62,13 +62,13 @@ macro_rules! with_bn_in_ctx(
Ok($name) => {
let $ctx_name = ffi::BN_CTX_new();
if ($ctx_name).is_null() {
Err(SslError::get())
Err(ErrorStack::get())
} else {
let r =
if $action {
Ok($name)
} else {
Err(SslError::get())
Err(ErrorStack::get())
};
ffi::BN_CTX_free($ctx_name);
r
@ -81,7 +81,7 @@ macro_rules! with_bn_in_ctx(
impl BigNum {
/// Creates a new `BigNum` with the value 0.
pub fn new() -> Result<BigNum, SslError> {
pub fn new() -> Result<BigNum, ErrorStack> {
unsafe {
ffi::init();
@ -91,7 +91,7 @@ impl BigNum {
}
/// Creates a new `BigNum` with the given value.
pub fn new_from(n: u64) -> Result<BigNum, SslError> {
pub fn new_from(n: u64) -> Result<BigNum, ErrorStack> {
BigNum::new().and_then(|v| unsafe {
try_ssl!(ffi::BN_set_word(v.raw(), n as c_ulong));
Ok(v)
@ -99,7 +99,7 @@ impl BigNum {
}
/// Creates a `BigNum` from a decimal string.
pub fn from_dec_str(s: &str) -> Result<BigNum, SslError> {
pub fn from_dec_str(s: &str) -> Result<BigNum, ErrorStack> {
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() as *const _));
@ -108,7 +108,7 @@ impl BigNum {
}
/// Creates a `BigNum` from a hexadecimal string.
pub fn from_hex_str(s: &str) -> Result<BigNum, SslError> {
pub fn from_hex_str(s: &str) -> Result<BigNum, ErrorStack> {
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() as *const _));
@ -116,13 +116,13 @@ impl BigNum {
})
}
pub unsafe fn new_from_ffi(orig: *mut ffi::BIGNUM) -> Result<BigNum, SslError> {
pub unsafe fn new_from_ffi(orig: *mut ffi::BIGNUM) -> Result<BigNum, ErrorStack> {
if orig.is_null() {
panic!("Null Pointer was supplied to BigNum::new_from_ffi");
}
let r = ffi::BN_dup(orig);
if r.is_null() {
Err(SslError::get())
Err(ErrorStack::get())
} else {
Ok(BigNum(r))
}
@ -136,7 +136,7 @@ impl BigNum {
///
/// assert_eq!(bignum, BigNum::new_from(0x120034).unwrap());
/// ```
pub fn new_from_slice(n: &[u8]) -> Result<BigNum, SslError> {
pub fn new_from_slice(n: &[u8]) -> Result<BigNum, ErrorStack> {
BigNum::new().and_then(|v| unsafe {
try_ssl_null!(ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, v.raw()));
Ok(v)
@ -153,7 +153,7 @@ impl BigNum {
/// assert_eq!(n.checked_sqr().unwrap(), squared);
/// assert_eq!(n * n, squared);
/// ```
pub fn checked_sqr(&self) -> Result<BigNum, SslError> {
pub fn checked_sqr(&self) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_sqr(r.raw(), self.raw(), ctx) == 1
@ -162,7 +162,7 @@ impl BigNum {
}
/// Returns the unsigned remainder of the division `self / n`.
pub fn checked_nnmod(&self, n: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_nnmod(&self, n: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_nnmod(r.raw(), self.raw(), n.raw(), ctx) == 1
@ -181,7 +181,7 @@ impl BigNum {
///
/// assert_eq!(s.checked_mod_add(a, n).unwrap(), result);
/// ```
pub fn checked_mod_add(&self, a: &BigNum, n: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_mod_add(&self, a: &BigNum, n: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_mod_add(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1
@ -190,7 +190,7 @@ impl BigNum {
}
/// Equivalent to `(self - a) mod n`.
pub fn checked_mod_sub(&self, a: &BigNum, n: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_mod_sub(&self, a: &BigNum, n: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_mod_sub(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1
@ -199,7 +199,7 @@ impl BigNum {
}
/// Equivalent to `(self * a) mod n`.
pub fn checked_mod_mul(&self, a: &BigNum, n: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_mod_mul(&self, a: &BigNum, n: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_mod_mul(r.raw(), self.raw(), a.raw(), n.raw(), ctx) == 1
@ -208,7 +208,7 @@ impl BigNum {
}
/// Equivalent to `self² mod n`.
pub fn checked_mod_sqr(&self, n: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_mod_sqr(&self, n: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_mod_sqr(r.raw(), self.raw(), n.raw(), ctx) == 1
@ -217,7 +217,7 @@ impl BigNum {
}
/// Raises `self` to the `p`th power.
pub fn checked_exp(&self, p: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_exp(&self, p: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_exp(r.raw(), self.raw(), p.raw(), ctx) == 1
@ -226,7 +226,7 @@ impl BigNum {
}
/// Equivalent to `self.checked_exp(p) mod n`.
pub fn checked_mod_exp(&self, p: &BigNum, n: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_mod_exp(&self, p: &BigNum, n: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_mod_exp(r.raw(), self.raw(), p.raw(), n.raw(), ctx) == 1
@ -236,7 +236,7 @@ impl BigNum {
/// Calculates the modular multiplicative inverse of `self` modulo `n`, that is, an integer `r`
/// such that `(self * r) % n == 1`.
pub fn checked_mod_inv(&self, n: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_mod_inv(&self, n: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
!ffi::BN_mod_inverse(r.raw(), self.raw(), n.raw(), ctx).is_null()
@ -245,60 +245,60 @@ impl BigNum {
}
/// Add an `unsigned long` to `self`. This is more efficient than adding a `BigNum`.
pub fn add_word(&mut self, w: c_ulong) -> Result<(), SslError> {
pub fn add_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> {
unsafe {
if ffi::BN_add_word(self.raw(), w) == 1 {
Ok(())
} else {
Err(SslError::get())
Err(ErrorStack::get())
}
}
}
pub fn sub_word(&mut self, w: c_ulong) -> Result<(), SslError> {
pub fn sub_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> {
unsafe {
if ffi::BN_sub_word(self.raw(), w) == 1 {
Ok(())
} else {
Err(SslError::get())
Err(ErrorStack::get())
}
}
}
pub fn mul_word(&mut self, w: c_ulong) -> Result<(), SslError> {
pub fn mul_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> {
unsafe {
if ffi::BN_mul_word(self.raw(), w) == 1 {
Ok(())
} else {
Err(SslError::get())
Err(ErrorStack::get())
}
}
}
pub fn div_word(&mut self, w: c_ulong) -> Result<c_ulong, SslError> {
pub fn div_word(&mut self, w: c_ulong) -> Result<c_ulong, ErrorStack> {
unsafe {
let result = ffi::BN_div_word(self.raw(), w);
if result != !0 as c_ulong {
Ok(result)
} else {
Err(SslError::get())
Err(ErrorStack::get())
}
}
}
pub fn mod_word(&self, w: c_ulong) -> Result<c_ulong, SslError> {
pub fn mod_word(&self, w: c_ulong) -> Result<c_ulong, ErrorStack> {
unsafe {
let result = ffi::BN_mod_word(self.raw(), w);
if result != !0 as c_ulong {
Ok(result)
} else {
Err(SslError::get())
Err(ErrorStack::get())
}
}
}
/// Computes the greatest common denominator of `self` and `a`.
pub fn checked_gcd(&self, a: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_gcd(&self, a: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_gcd(r.raw(), self.raw(), a.raw(), ctx) == 1
@ -318,7 +318,7 @@ impl BigNum {
safe: bool,
add: Option<&BigNum>,
rem: Option<&BigNum>)
-> Result<BigNum, SslError> {
-> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
let add_arg = add.map(|a| a.raw()).unwrap_or(ptr::null_mut());
@ -341,7 +341,7 @@ impl BigNum {
/// # Return Value
///
/// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
pub fn is_prime(&self, checks: i32) -> Result<bool, SslError> {
pub fn is_prime(&self, checks: i32) -> Result<bool, ErrorStack> {
unsafe {
with_ctx!(ctx, {
Ok(ffi::BN_is_prime_ex(self.raw(), checks as c_int, ctx, ptr::null()) == 1)
@ -358,7 +358,7 @@ impl BigNum {
/// # Return Value
///
/// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
pub fn is_prime_fast(&self, checks: i32, do_trial_division: bool) -> Result<bool, SslError> {
pub fn is_prime_fast(&self, checks: i32, do_trial_division: bool) -> Result<bool, ErrorStack> {
unsafe {
with_ctx!(ctx, {
Ok(ffi::BN_is_prime_fasttest_ex(self.raw(),
@ -377,7 +377,7 @@ impl BigNum {
/// * `bits`: Length of the number in bits.
/// * `prop`: The desired properties of the number.
/// * `odd`: If `true`, the generated number will be odd.
pub fn checked_new_random(bits: i32, prop: RNGProperty, odd: bool) -> Result<BigNum, SslError> {
pub fn checked_new_random(bits: i32, prop: RNGProperty, odd: bool) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1
@ -389,7 +389,7 @@ impl BigNum {
pub fn checked_new_pseudo_random(bits: i32,
prop: RNGProperty,
odd: bool)
-> Result<BigNum, SslError> {
-> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_pseudo_rand(r.raw(), bits as c_int, prop as c_int, odd as c_int) == 1
@ -399,7 +399,7 @@ impl BigNum {
/// Generates a cryptographically strong pseudo-random `BigNum` `r` in the range
/// `0 <= r < self`.
pub fn checked_rand_in_range(&self) -> Result<BigNum, SslError> {
pub fn checked_rand_in_range(&self) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_rand_range(r.raw(), self.raw()) == 1
@ -408,7 +408,7 @@ impl BigNum {
}
/// The cryptographically weak counterpart to `checked_rand_in_range`.
pub fn checked_pseudo_rand_in_range(&self) -> Result<BigNum, SslError> {
pub fn checked_pseudo_rand_in_range(&self) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_pseudo_rand_range(r.raw(), self.raw()) == 1
@ -419,12 +419,12 @@ impl BigNum {
/// Sets bit `n`. Equivalent to `self |= (1 << n)`.
///
/// When setting a bit outside of `self`, it is expanded.
pub fn set_bit(&mut self, n: i32) -> Result<(), SslError> {
pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
unsafe {
if ffi::BN_set_bit(self.raw(), n as c_int) == 1 {
Ok(())
} else {
Err(SslError::get())
Err(ErrorStack::get())
}
}
}
@ -432,12 +432,12 @@ impl BigNum {
/// Clears bit `n`, setting it to 0. Equivalent to `self &= ~(1 << n)`.
///
/// When clearing a bit outside of `self`, an error is returned.
pub fn clear_bit(&mut self, n: i32) -> Result<(), SslError> {
pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
unsafe {
if ffi::BN_clear_bit(self.raw(), n as c_int) == 1 {
Ok(())
} else {
Err(SslError::get())
Err(ErrorStack::get())
}
}
}
@ -450,12 +450,12 @@ impl BigNum {
/// Truncates `self` to the lowest `n` bits.
///
/// An error occurs if `self` is already shorter than `n` bits.
pub fn mask_bits(&mut self, n: i32) -> Result<(), SslError> {
pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> {
unsafe {
if ffi::BN_mask_bits(self.raw(), n as c_int) == 1 {
Ok(())
} else {
Err(SslError::get())
Err(ErrorStack::get())
}
}
}
@ -478,7 +478,7 @@ impl BigNum {
/// // (-8) << 1 == -16
/// assert_eq!(s.checked_shl1().unwrap(), result);
/// ```
pub fn checked_shl1(&self) -> Result<BigNum, SslError> {
pub fn checked_shl1(&self) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn!(r, {
ffi::BN_lshift1(r.raw(), self.raw()) == 1
@ -487,7 +487,7 @@ impl BigNum {
}
/// Returns `self`, shifted right by 1 bit. `self` may be negative.
pub fn checked_shr1(&self) -> Result<BigNum, SslError> {
pub fn checked_shr1(&self) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn!(r, {
ffi::BN_rshift1(r.raw(), self.raw()) == 1
@ -495,7 +495,7 @@ impl BigNum {
}
}
pub fn checked_add(&self, a: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_add(&self, a: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn!(r, {
ffi::BN_add(r.raw(), self.raw(), a.raw()) == 1
@ -503,7 +503,7 @@ impl BigNum {
}
}
pub fn checked_sub(&self, a: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_sub(&self, a: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn!(r, {
ffi::BN_sub(r.raw(), self.raw(), a.raw()) == 1
@ -511,7 +511,7 @@ impl BigNum {
}
}
pub fn checked_mul(&self, a: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_mul(&self, a: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_mul(r.raw(), self.raw(), a.raw(), ctx) == 1
@ -519,7 +519,7 @@ impl BigNum {
}
}
pub fn checked_div(&self, a: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_div(&self, a: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_div(r.raw(), ptr::null_mut(), self.raw(), a.raw(), ctx) == 1
@ -527,7 +527,7 @@ impl BigNum {
}
}
pub fn checked_mod(&self, a: &BigNum) -> Result<BigNum, SslError> {
pub fn checked_mod(&self, a: &BigNum) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn_in_ctx!(r, ctx, {
ffi::BN_div(ptr::null_mut(), r.raw(), self.raw(), a.raw(), ctx) == 1
@ -535,7 +535,7 @@ impl BigNum {
}
}
pub fn checked_shl(&self, a: &i32) -> Result<BigNum, SslError> {
pub fn checked_shl(&self, a: &i32) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn!(r, {
ffi::BN_lshift(r.raw(), self.raw(), *a as c_int) == 1
@ -543,7 +543,7 @@ impl BigNum {
}
}
pub fn checked_shr(&self, a: &i32) -> Result<BigNum, SslError> {
pub fn checked_shr(&self, a: &i32) -> Result<BigNum, ErrorStack> {
unsafe {
with_bn!(r, {
ffi::BN_rshift(r.raw(), self.raw(), *a as c_int) == 1

View File

@ -1,25 +1,21 @@
use ffi;
use std::fmt;
use ssl::error::{SslError, StreamError};
use error::ErrorStack;
use std::ptr;
use std::io::{self, Read, Write};
use libc::{c_uint, c_int};
use libc::{c_uint, c_int, c_char, c_void};
use bn::BigNum;
use bio::MemBio;
use bio::{MemBio, MemBioSlice};
use crypto::hash;
use crypto::HashTypeInternals;
#[cfg(feature = "catch_unwind")]
use libc::{c_char, c_void};
#[cfg(feature = "catch_unwind")]
use crypto::util::{CallbackState, invoke_passwd_cb};
/// Builder for upfront DSA parameter generateration
pub struct DSAParams(*mut ffi::DSA);
impl DSAParams {
pub fn with_size(size: usize) -> Result<DSAParams, SslError> {
pub fn with_size(size: usize) -> Result<DSAParams, ErrorStack> {
unsafe {
// Wrap it so that if we panic we'll call the dtor
let dsa = DSAParams(try_ssl_null!(ffi::DSA_new()));
@ -30,7 +26,7 @@ impl DSAParams {
}
/// Generate a key pair from the initialized parameters
pub fn generate(self) -> Result<DSA, SslError> {
pub fn generate(self) -> Result<DSA, ErrorStack> {
unsafe {
try_ssl!(ffi::DSA_generate_key(self.0));
let dsa = DSA(self.0);
@ -66,17 +62,15 @@ impl DSA {
/// Generate a DSA key pair
/// For more complicated key generation scenarios see the `DSAParams` type
pub fn generate(size: usize) -> Result<DSA, SslError> {
pub fn generate(size: usize) -> Result<DSA, ErrorStack> {
let params = try!(DSAParams::with_size(size));
params.generate()
}
/// Reads a DSA private key from PEM formatted data.
pub fn private_key_from_pem<R>(reader: &mut R) -> Result<DSA, SslError>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
pub fn private_key_from_pem(buf: &[u8]) -> Result<DSA, ErrorStack> {
ffi::init();
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.get_handle(),
@ -94,15 +88,12 @@ impl DSA {
///
/// The callback will be passed the password buffer and should return the number of characters
/// placed into the buffer.
///
/// Requires the `catch_unwind` feature.
#[cfg(feature = "catch_unwind")]
pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> Result<DSA, SslError>
where R: Read, F: FnOnce(&mut [c_char]) -> usize
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<DSA, ErrorStack>
where F: FnOnce(&mut [c_char]) -> usize
{
ffi::init();
let mut cb = CallbackState::new(pass_cb);
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let cb_ptr = &mut cb as *mut _ as *mut c_void;
@ -117,11 +108,10 @@ impl DSA {
}
/// Writes an DSA private key as unencrypted PEM formatted data
pub fn private_key_to_pem<W>(&self, writer: &mut W) -> Result<(), SslError>
where W: Write
pub fn private_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack>
{
assert!(self.has_private_key());
let mut mem_bio = try!(MemBio::new());
let mem_bio = try!(MemBio::new());
unsafe {
try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.get_handle(), self.0,
@ -129,18 +119,15 @@ impl DSA {
None, ptr::null_mut()))
};
try!(io::copy(&mut mem_bio, writer).map_err(StreamError));
Ok(())
Ok(mem_bio.get_buf().to_owned())
}
/// Reads an DSA public key from PEM formatted data.
pub fn public_key_from_pem<R>(reader: &mut R) -> Result<DSA, SslError>
where R: Read
pub fn public_key_from_pem(buf: &[u8]) -> Result<DSA, ErrorStack>
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
ffi::init();
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.get_handle(),
ptr::null_mut(),
@ -151,28 +138,23 @@ impl DSA {
}
/// Writes an DSA public key as PEM formatted data
pub fn public_key_to_pem<W>(&self, writer: &mut W) -> Result<(), SslError>
where W: Write
{
let mut mem_bio = try!(MemBio::new());
pub fn public_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
let mem_bio = try!(MemBio::new());
unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.get_handle(), self.0)) };
try!(io::copy(&mut mem_bio, writer).map_err(StreamError));
Ok(())
Ok(mem_bio.get_buf().to_owned())
}
pub fn size(&self) -> Result<isize, SslError> {
pub fn size(&self) -> Option<u32> {
if self.has_q() {
unsafe { Ok(ffi::DSA_size(self.0) as isize) }
unsafe { Some(ffi::DSA_size(self.0) as u32) }
} else {
Err(SslError::OpenSslErrors(vec![]))
None
}
}
pub fn sign(&self, hash: hash::Type, message: &[u8]) -> Result<Vec<u8>, SslError> {
let k_len = try!(self.size()) as c_uint;
let mut sig = vec![0;k_len as usize];
pub fn sign(&self, hash: hash::Type, message: &[u8]) -> Result<Vec<u8>, ErrorStack> {
let k_len = self.size().expect("DSA missing a q") as c_uint;
let mut sig = vec![0; k_len as usize];
let mut sig_len = k_len;
assert!(self.has_private_key());
@ -189,7 +171,7 @@ impl DSA {
}
}
pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result<bool, SslError> {
pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
unsafe {
let result = ffi::DSA_verify(hash.as_nid() as c_int,
message.as_ptr(),
@ -208,7 +190,7 @@ impl DSA {
}
// The following getters are unsafe, since BigNum::new_from_ffi fails upon null pointers
pub fn p(&self) -> Result<BigNum, SslError> {
pub fn p(&self) -> Result<BigNum, ErrorStack> {
unsafe { BigNum::new_from_ffi((*self.0).p) }
}
@ -216,7 +198,7 @@ impl DSA {
unsafe { !(*self.0).p.is_null() }
}
pub fn q(&self) -> Result<BigNum, SslError> {
pub fn q(&self) -> Result<BigNum, ErrorStack> {
unsafe { BigNum::new_from_ffi((*self.0).q) }
}
@ -224,7 +206,7 @@ impl DSA {
unsafe { !(*self.0).q.is_null() }
}
pub fn g(&self) -> Result<BigNum, SslError> {
pub fn g(&self) -> Result<BigNum, ErrorStack> {
unsafe { BigNum::new_from_ffi((*self.0).g) }
}
@ -249,19 +231,18 @@ impl fmt::Debug for DSA {
#[cfg(test)]
mod test {
use std::fs::File;
use std::io::{Write, Cursor};
use std::io::Write;
use libc::c_char;
use super::*;
use crypto::hash::*;
#[test]
pub fn test_generate() {
let key = DSA::generate(1024).unwrap();
let mut priv_buf = Cursor::new(vec![]);
let mut pub_buf = Cursor::new(vec![]);
key.public_key_to_pem(&mut pub_buf).unwrap();
key.private_key_to_pem(&mut priv_buf).unwrap();
key.public_key_to_pem().unwrap();
key.private_key_to_pem().unwrap();
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
@ -281,13 +262,13 @@ mod test {
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
let private_key = {
let mut buffer = File::open("test/dsa.pem").unwrap();
DSA::private_key_from_pem(&mut buffer).unwrap()
let key = include_bytes!("../../test/dsa.pem");
DSA::private_key_from_pem(key).unwrap()
};
let public_key = {
let mut buffer = File::open("test/dsa.pem.pub").unwrap();
DSA::public_key_from_pem(&mut buffer).unwrap()
let key = include_bytes!("../../test/dsa.pem.pub");
DSA::public_key_from_pem(key).unwrap()
};
let digest = {
@ -305,13 +286,13 @@ mod test {
pub fn test_sign_verify_fail() {
let input: Vec<u8> = (0..25).cycle().take(128).collect();
let private_key = {
let mut buffer = File::open("test/dsa.pem").unwrap();
DSA::private_key_from_pem(&mut buffer).unwrap()
let key = include_bytes!("../../test/dsa.pem");
DSA::private_key_from_pem(key).unwrap()
};
let public_key = {
let mut buffer = File::open("test/dsa.pem.pub").unwrap();
DSA::public_key_from_pem(&mut buffer).unwrap()
let key = include_bytes!("../../test/dsa.pem.pub");
DSA::public_key_from_pem(key).unwrap()
};
let digest = {
@ -331,18 +312,17 @@ mod test {
}
#[test]
#[cfg(feature = "catch_unwind")]
pub fn test_password() {
let mut password_queried = false;
let mut buffer = File::open("test/dsa-encrypted.pem").unwrap();
DSA::private_key_from_pem_cb(&mut buffer, |password| {
let key = include_bytes!("../../test/dsa-encrypted.pem");
DSA::private_key_from_pem_cb(key, |password| {
password_queried = true;
password[0] = b'm' as _;
password[1] = b'y' as _;
password[2] = b'p' as _;
password[3] = b'a' as _;
password[4] = b's' as _;
password[5] = b's' as _;
password[0] = b'm' as c_char;
password[1] = b'y' as c_char;
password[2] = b'p' as c_char;
password[3] = b'a' as c_char;
password[4] = b's' as c_char;
password[5] = b's' as c_char;
6
}).unwrap();

View File

@ -25,7 +25,6 @@ pub mod symm;
pub mod memcmp;
pub mod rsa;
pub mod dsa;
#[cfg(feature = "catch_unwind")]
mod util;
mod symm_internal;

View File

@ -1,21 +1,15 @@
use libc::{c_int, c_uint, c_ulong};
use std::io;
use std::io::prelude::*;
use libc::{c_int, c_uint, c_ulong, c_void, c_char};
use std::iter::repeat;
use std::mem;
use std::ptr;
use bio::MemBio;
use bio::{MemBio, MemBioSlice};
use crypto::HashTypeInternals;
use crypto::hash;
use crypto::hash::Type as HashType;
use ffi;
use ssl::error::{SslError, StreamError};
use crypto::rsa::RSA;
#[cfg(feature = "catch_unwind")]
use libc::{c_void, c_char};
#[cfg(feature = "catch_unwind")]
use error::ErrorStack;
use crypto::util::{CallbackState, invoke_passwd_cb};
#[derive(Copy, Clone)]
@ -80,17 +74,14 @@ impl PKey {
}
/// Reads private key from PEM, takes ownership of handle
pub fn private_key_from_pem<R>(reader: &mut R) -> Result<PKey, SslError>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
pub fn private_key_from_pem(buf: &[u8]) -> Result<PKey, ErrorStack> {
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(),
ptr::null_mut(),
None,
ptr::null_mut()));
Ok(PKey {
evp: evp as *mut ffi::EVP_PKEY,
parts: Parts::Both,
@ -103,17 +94,11 @@ impl PKey {
///
/// The callback will be passed the password buffer and should return the number of characters
/// placed into the buffer.
///
/// Requires the `catch_unwind` feature.
#[cfg(feature = "catch_unwind")]
pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> Result<PKey, SslError>
where R: Read, F: FnOnce(&mut [c_char]) -> usize
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<PKey, ErrorStack>
where F: FnOnce(&mut [c_char]) -> usize
{
let mut cb = CallbackState::new(pass_cb);
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(),
ptr::null_mut(),
@ -128,12 +113,8 @@ impl PKey {
}
/// Reads public key from PEM, takes ownership of handle
pub fn public_key_from_pem<R>(reader: &mut R) -> Result<PKey, SslError>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
pub fn public_key_from_pem(buf: &[u8]) -> Result<PKey, ErrorStack> {
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.get_handle(),
ptr::null_mut(),
@ -147,13 +128,13 @@ impl PKey {
}
/// Reads an RSA private key from PEM, takes ownership of handle
pub fn private_rsa_key_from_pem<R>(reader: &mut R) -> Result<PKey, SslError>
where R: Read
{
let rsa = try!(RSA::private_key_from_pem(reader));
pub fn private_rsa_key_from_pem(buf: &[u8]) -> Result<PKey, ErrorStack> {
let rsa = try!(RSA::private_key_from_pem(buf));
unsafe {
let evp = try_ssl_null!(ffi::EVP_PKEY_new());
try_ssl!(ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()));
if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 {
return Err(ErrorStack::get());
}
Ok(PKey {
evp: evp,
@ -163,13 +144,13 @@ impl PKey {
}
/// Reads an RSA public key from PEM, takes ownership of handle
pub fn public_rsa_key_from_pem<R>(reader: &mut R) -> Result<PKey, SslError>
where R: Read
{
let rsa = try!(RSA::public_key_from_pem(reader));
pub fn public_rsa_key_from_pem(buf: &[u8]) -> Result<PKey, ErrorStack> {
let rsa = try!(RSA::public_key_from_pem(buf));
unsafe {
let evp = try_ssl_null!(ffi::EVP_PKEY_new());
try_ssl!(ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()));
if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 {
return Err(ErrorStack::get());
}
Ok(PKey {
evp: evp,
@ -282,10 +263,8 @@ impl PKey {
/// Stores private key as a PEM
// FIXME: also add password and encryption
pub fn write_pem<W: Write>(&self,
writer: &mut W /* , password: Option<String> */)
-> Result<(), SslError> {
let mut mem_bio = try!(MemBio::new());
pub fn write_pem(&self) -> Result<Vec<u8>, ErrorStack> {
let mem_bio = try!(MemBio::new());
unsafe {
try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.get_handle(),
self.evp,
@ -296,20 +275,14 @@ impl PKey {
ptr::null_mut()));
}
let mut buf = vec![];
try!(mem_bio.read_to_end(&mut buf).map_err(StreamError));
writer.write_all(&buf).map_err(StreamError)
Ok(mem_bio.get_buf().to_owned())
}
/// Stores public key as a PEM
pub fn write_pub_pem<W: Write>(&self,
writer: &mut W /* , password: Option<String> */)
-> Result<(), SslError> {
let mut mem_bio = try!(MemBio::new());
pub fn write_pub_pem(&self) -> Result<Vec<u8>, ErrorStack> {
let mem_bio = try!(MemBio::new());
unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.get_handle(), self.evp)) }
let mut buf = vec![];
try!(mem_bio.read_to_end(&mut buf).map_err(StreamError));
writer.write_all(&buf).map_err(StreamError)
Ok(mem_bio.get_buf().to_owned())
}
/**
@ -394,7 +367,7 @@ impl PKey {
openssl_padding_code(padding));
if rv < 0 as c_int {
// println!("{:?}", SslError::get());
// println!("{:?}", ErrorStack::get());
vec![]
} else {
r.truncate(rv as usize);
@ -650,8 +623,6 @@ impl Clone for PKey {
#[cfg(test)]
mod tests {
use std::path::Path;
use std::fs::File;
use crypto::hash::Type::{MD5, SHA1};
use crypto::rsa::RSA;
@ -695,42 +666,26 @@ mod tests {
#[test]
fn test_private_key_from_pem() {
let key_path = Path::new("test/key.pem");
let mut file = File::open(&key_path)
.ok()
.expect("Failed to open `test/key.pem`");
super::PKey::private_key_from_pem(&mut file).unwrap();
let key = include_bytes!("../../test/key.pem");
super::PKey::private_key_from_pem(key).unwrap();
}
#[test]
fn test_public_key_from_pem() {
let key_path = Path::new("test/key.pem.pub");
let mut file = File::open(&key_path)
.ok()
.expect("Failed to open `test/key.pem.pub`");
super::PKey::public_key_from_pem(&mut file).unwrap();
let key = include_bytes!("../../test/key.pem.pub");
super::PKey::public_key_from_pem(key).unwrap();
}
#[test]
fn test_private_rsa_key_from_pem() {
let key_path = Path::new("test/key.pem");
let mut file = File::open(&key_path)
.ok()
.expect("Failed to open `test/key.pem`");
super::PKey::private_rsa_key_from_pem(&mut file).unwrap();
let key = include_bytes!("../../test/key.pem");
super::PKey::private_rsa_key_from_pem(key).unwrap();
}
#[test]
fn test_public_rsa_key_from_pem() {
let key_path = Path::new("test/key.pem.pub");
let mut file = File::open(&key_path)
.ok()
.expect("Failed to open `test/key.pem.pub`");
super::PKey::public_rsa_key_from_pem(&mut file).unwrap();
let key = include_bytes!("../../test/key.pem.pub");
super::PKey::public_rsa_key_from_pem(key).unwrap();
}
#[test]
@ -821,18 +776,11 @@ mod tests {
#[test]
fn test_pem() {
let key_path = Path::new("test/key.pem");
let mut file = File::open(&key_path)
.ok()
.expect("Failed to open `test/key.pem`");
let key = include_bytes!("../../test/key.pem");
let key = super::PKey::private_key_from_pem(key).unwrap();
let key = super::PKey::private_key_from_pem(&mut file).unwrap();
let mut priv_key = Vec::new();
let mut pub_key = Vec::new();
key.write_pem(&mut priv_key).unwrap();
key.write_pub_pem(&mut pub_key).unwrap();
let priv_key = key.write_pem().unwrap();
let pub_key = key.write_pub_pem().unwrap();
// As a super-simple verification, just check that the buffers contain
// the `PRIVATE KEY` or `PUBLIC KEY` strings.

View File

@ -1,18 +1,13 @@
use ffi;
use std::fmt;
use ssl::error::{SslError, StreamError};
use std::ptr;
use std::io::{self, Read, Write};
use libc::c_int;
use libc::{c_int, c_void, c_char};
use bn::BigNum;
use bio::MemBio;
use bio::{MemBio, MemBioSlice};
use error::ErrorStack;
use crypto::HashTypeInternals;
use crypto::hash;
#[cfg(feature = "catch_unwind")]
use libc::{c_void, c_char};
#[cfg(feature = "catch_unwind")]
use crypto::util::{CallbackState, invoke_passwd_cb};
pub struct RSA(*mut ffi::RSA);
@ -28,7 +23,7 @@ impl Drop for RSA {
impl RSA {
/// only useful for associating the key material directly with the key, it's safer to use
/// the supplied load and save methods for DER formatted keys.
pub fn from_public_components(n: BigNum, e: BigNum) -> Result<RSA, SslError> {
pub fn from_public_components(n: BigNum, e: BigNum) -> Result<RSA, ErrorStack> {
unsafe {
let rsa = try_ssl_null!(ffi::RSA_new());
(*rsa).n = n.into_raw();
@ -45,7 +40,7 @@ impl RSA {
dp: BigNum,
dq: BigNum,
qi: BigNum)
-> Result<RSA, SslError> {
-> Result<RSA, ErrorStack> {
unsafe {
let rsa = try_ssl_null!(ffi::RSA_new());
(*rsa).n = n.into_raw();
@ -66,12 +61,8 @@ impl RSA {
}
/// Reads an RSA private key from PEM formatted data.
pub fn private_key_from_pem<R>(reader: &mut R) -> Result<RSA, SslError>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
pub fn private_key_from_pem(buf: &[u8]) -> Result<RSA, ErrorStack> {
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.get_handle(),
ptr::null_mut(),
@ -82,16 +73,11 @@ impl RSA {
}
/// Reads an RSA private key from PEM formatted data and supplies a password callback.
///
/// Requires the `catch_unwind` feature.
#[cfg(feature = "catch_unwind")]
pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> Result<RSA, SslError>
where R: Read, F: FnOnce(&mut [c_char]) -> usize
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<RSA, ErrorStack>
where F: FnOnce(&mut [c_char]) -> usize
{
let mut cb = CallbackState::new(pass_cb);
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let cb_ptr = &mut cb as *mut _ as *mut c_void;
@ -105,10 +91,8 @@ impl RSA {
}
/// Writes an RSA private key as unencrypted PEM formatted data
pub fn private_key_to_pem<W>(&self, writer: &mut W) -> Result<(), SslError>
where W: Write
{
let mut mem_bio = try!(MemBio::new());
pub fn private_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
let mem_bio = try!(MemBio::new());
unsafe {
try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.get_handle(),
@ -119,17 +103,12 @@ impl RSA {
None,
ptr::null_mut()));
}
try!(io::copy(&mut mem_bio, writer).map_err(StreamError));
Ok(())
Ok(mem_bio.get_buf().to_owned())
}
/// Reads an RSA public key from PEM formatted data.
pub fn public_key_from_pem<R>(reader: &mut R) -> Result<RSA, SslError>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
pub fn public_key_from_pem(buf: &[u8]) -> Result<RSA, ErrorStack> {
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.get_handle(),
ptr::null_mut(),
@ -140,30 +119,27 @@ impl RSA {
}
/// Writes an RSA public key as PEM formatted data
pub fn public_key_to_pem<W>(&self, writer: &mut W) -> Result<(), SslError>
where W: Write
{
let mut mem_bio = try!(MemBio::new());
pub fn public_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
let mem_bio = try!(MemBio::new());
unsafe {
try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.get_handle(), self.0))
};
try!(io::copy(&mut mem_bio, writer).map_err(StreamError));
Ok(())
Ok(mem_bio.get_buf().to_owned())
}
pub fn size(&self) -> Result<u32, SslError> {
pub fn size(&self) -> Option<u32> {
if self.has_n() {
unsafe { Ok(ffi::RSA_size(self.0) as u32) }
unsafe { Some(ffi::RSA_size(self.0) as u32) }
} else {
Err(SslError::OpenSslErrors(vec![]))
None
}
}
pub fn sign(&self, hash: hash::Type, message: &[u8]) -> Result<Vec<u8>, SslError> {
let k_len = try!(self.size());
let mut sig = vec![0;k_len as usize];
pub fn sign(&self, hash: hash::Type, message: &[u8]) -> Result<Vec<u8>, ErrorStack> {
let k_len = self.size().expect("RSA missing an n");
let mut sig = vec![0; k_len as usize];
let mut sig_len = k_len;
unsafe {
@ -178,7 +154,7 @@ impl RSA {
}
}
pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result<bool, SslError> {
pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
unsafe {
let result = ffi::RSA_verify(hash.as_nid() as c_int,
message.as_ptr(),
@ -196,32 +172,42 @@ impl RSA {
}
// The following getters are unsafe, since BigNum::new_from_ffi fails upon null pointers
pub fn n(&self) -> Result<BigNum, SslError> {
unsafe { BigNum::new_from_ffi((*self.0).n) }
pub fn n(&self) -> Result<BigNum, ErrorStack> {
unsafe {
BigNum::new_from_ffi((*self.0).n)
}
}
pub fn has_n(&self) -> bool {
unsafe { !(*self.0).n.is_null() }
}
pub fn d(&self) -> Result<BigNum, SslError> {
unsafe { BigNum::new_from_ffi((*self.0).d) }
pub fn d(&self) -> Result<BigNum, ErrorStack> {
unsafe {
BigNum::new_from_ffi((*self.0).d)
}
}
pub fn e(&self) -> Result<BigNum, SslError> {
unsafe { BigNum::new_from_ffi((*self.0).e) }
pub fn e(&self) -> Result<BigNum, ErrorStack> {
unsafe {
BigNum::new_from_ffi((*self.0).e)
}
}
pub fn has_e(&self) -> bool {
unsafe { !(*self.0).e.is_null() }
}
pub fn p(&self) -> Result<BigNum, SslError> {
unsafe { BigNum::new_from_ffi((*self.0).p) }
pub fn p(&self) -> Result<BigNum, ErrorStack> {
unsafe {
BigNum::new_from_ffi((*self.0).p)
}
}
pub fn q(&self) -> Result<BigNum, SslError> {
unsafe { BigNum::new_from_ffi((*self.0).q) }
pub fn q(&self) -> Result<BigNum, ErrorStack> {
unsafe {
BigNum::new_from_ffi((*self.0).q)
}
}
}
@ -233,8 +219,9 @@ impl fmt::Debug for RSA {
#[cfg(test)]
mod test {
use std::fs::File;
use std::io::Write;
use libc::c_char;
use super::*;
use crypto::hash::*;
@ -266,8 +253,8 @@ mod test {
#[test]
pub fn test_sign() {
let mut buffer = File::open("test/rsa.pem").unwrap();
let private_key = RSA::private_key_from_pem(&mut buffer).unwrap();
let key = include_bytes!("../../test/rsa.pem");
let private_key = RSA::private_key_from_pem(key).unwrap();
let mut sha = Hasher::new(Type::SHA256);
sha.write_all(&signing_input_rs256()).unwrap();
@ -280,8 +267,8 @@ mod test {
#[test]
pub fn test_verify() {
let mut buffer = File::open("test/rsa.pem.pub").unwrap();
let public_key = RSA::public_key_from_pem(&mut buffer).unwrap();
let key = include_bytes!("../../test/rsa.pem.pub");
let public_key = RSA::public_key_from_pem(key).unwrap();
let mut sha = Hasher::new(Type::SHA256);
sha.write_all(&signing_input_rs256()).unwrap();
@ -293,18 +280,17 @@ mod test {
}
#[test]
#[cfg(feature = "catch_unwind")]
pub fn test_password() {
let mut password_queried = false;
let mut buffer = File::open("test/rsa-encrypted.pem").unwrap();
RSA::private_key_from_pem_cb(&mut buffer, |password| {
let key = include_bytes!("../../test/rsa-encrypted.pem");
RSA::private_key_from_pem_cb(key, |password| {
password_queried = true;
password[0] = b'm' as _;
password[1] = b'y' as _;
password[2] = b'p' as _;
password[3] = b'a' as _;
password[4] = b's' as _;
password[5] = b's' as _;
password[0] = b'm' as c_char;
password[1] = b'y' as c_char;
password[2] = b'p' as c_char;
password[3] = b'a' as c_char;
password[4] = b's' as c_char;
password[5] = b's' as c_char;
6
}).unwrap();

View File

@ -1,8 +1,6 @@
use ffi;
use std::io;
use std::io::prelude::*;
use ssl::error::{SslError, StreamError};
use bio::MemBio;
use error::ErrorStack;
use bio::MemBioSlice;
use bn::BigNum;
use std::mem;
use std::ptr;
@ -10,7 +8,7 @@ use std::ptr;
pub struct DH(*mut ffi::DH);
impl DH {
pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<DH, SslError> {
pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<DH, ErrorStack> {
let dh = try_ssl_null!(unsafe { ffi::DH_new_from_params(p.raw(), g.raw(), q.raw()) });
mem::forget(p);
mem::forget(g);
@ -18,11 +16,8 @@ impl DH {
Ok(DH(dh))
}
pub fn from_pem<R>(reader: &mut R) -> Result<DH, SslError>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
pub fn from_pem(buf: &[u8]) -> Result<DH, ErrorStack> {
let mem_bio = try!(MemBioSlice::new(buf));
let dh = unsafe {
ffi::PEM_read_bio_DHparams(mem_bio.get_handle(), ptr::null_mut(), None, ptr::null_mut())
};
@ -31,19 +26,19 @@ impl DH {
}
#[cfg(feature = "rfc5114")]
pub fn get_1024_160() -> Result<DH, SslError> {
pub fn get_1024_160() -> Result<DH, ErrorStack> {
let dh = try_ssl_null!(unsafe { ffi::DH_get_1024_160() });
Ok(DH(dh))
}
#[cfg(feature = "rfc5114")]
pub fn get_2048_224() -> Result<DH, SslError> {
pub fn get_2048_224() -> Result<DH, ErrorStack> {
let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_224() });
Ok(DH(dh))
}
#[cfg(feature = "rfc5114")]
pub fn get_2048_256() -> Result<DH, SslError> {
pub fn get_2048_256() -> Result<DH, ErrorStack> {
let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_256() });
Ok(DH(dh))
}
@ -71,8 +66,6 @@ impl Drop for DH {
#[cfg(test)]
mod tests {
use std::fs::File;
use std::path::Path;
use super::DH;
use bn::BigNum;
use ssl::SslContext;
@ -81,7 +74,7 @@ mod tests {
#[test]
#[cfg(feature = "rfc5114")]
fn test_dh_rfc5114() {
let ctx = SslContext::new(Sslv23).unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
let dh1 = DH::get_1024_160().unwrap();
ctx.set_tmp_dh(dh1).unwrap();
let dh2 = DH::get_2048_224().unwrap();
@ -92,7 +85,7 @@ mod tests {
#[test]
fn test_dh() {
let ctx = SslContext::new(Sslv23).unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435\
E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF429\
6D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C02\
@ -122,12 +115,9 @@ mod tests {
#[test]
fn test_dh_from_pem() {
let ctx = SslContext::new(Sslv23).unwrap();
let pem_path = Path::new("test/dhparams.pem");
let mut file = File::open(&pem_path)
.ok()
.expect("Failed to open `test/dhparams.pem`");
let dh = DH::from_pem(&mut file).ok().expect("Failed to load PEM");
let mut ctx = SslContext::new(Sslv23).unwrap();
let params = include_bytes!("../../test/dhparams.pem");
let dh = DH::from_pem(params).ok().expect("Failed to load PEM");
ctx.set_tmp_dh(dh).unwrap();
}
}

137
openssl/src/error.rs Normal file
View File

@ -0,0 +1,137 @@
use libc::c_ulong;
use std::fmt;
use std::error;
use std::ffi::CStr;
use std::io;
use std::str;
use ffi;
#[derive(Debug)]
pub struct ErrorStack(Vec<Error>);
impl ErrorStack {
/// Returns the contents of the OpenSSL error stack.
pub fn get() -> ErrorStack {
let mut vec = vec![];
while let Some(err) = Error::get() {
vec.push(err);
}
ErrorStack(vec)
}
}
impl ErrorStack {
/// Returns the errors in the stack.
pub fn errors(&self) -> &[Error] {
&self.0
}
}
impl fmt::Display for ErrorStack {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let mut first = true;
for err in &self.0 {
if first {
try!(fmt.write_str(", "));
first = false;
}
try!(write!(fmt, "{}", err));
}
Ok(())
}
}
impl error::Error for ErrorStack {
fn description(&self) -> &str {
"An OpenSSL error stack"
}
}
impl From<ErrorStack> for io::Error {
fn from(e: ErrorStack) -> io::Error {
io::Error::new(io::ErrorKind::Other, e)
}
}
/// An error reported from OpenSSL.
pub struct Error(c_ulong);
impl Error {
/// Returns the first error on the OpenSSL error stack.
pub fn get() -> Option<Error> {
ffi::init();
match unsafe { ffi::ERR_get_error() } {
0 => None,
err => Some((Error(err))),
}
}
/// 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 Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Error")
.field("library", &self.library())
.field("function", &self.function())
.field("reason", &self.reason())
.finish()
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(&self.reason())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"An OpenSSL error"
}
}
fn get_lib(err: c_ulong) -> &'static str {
unsafe {
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_func(err: c_ulong) -> &'static str {
unsafe {
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()
}
}

View File

@ -1,5 +1,4 @@
#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.14")]
#![cfg_attr(feature = "nightly", feature(const_fn))]
#[macro_use]
extern crate bitflags;
@ -18,11 +17,12 @@ extern crate net2;
mod macros;
pub mod asn1;
mod bio;
pub mod bn;
pub mod bio;
pub mod crypto;
pub mod dh;
pub mod ssl;
pub mod x509;
pub mod error;
pub mod nid;
pub mod ssl;
pub mod version;
pub mod x509;

View File

@ -13,7 +13,7 @@ macro_rules! try_ssl_stream {
macro_rules! try_ssl_if {
($e:expr) => (
if $e {
return Err(SslError::get())
return Err(::error::ErrorStack::get().into())
}
)
}
@ -45,7 +45,7 @@ macro_rules! try_ssl_null{
macro_rules! lift_ssl_if{
($e:expr) => ( {
if $e {
Err(SslError::get())
Err(::error::ErrorStack::get().into())
} else {
Ok(())
}

View File

@ -9,7 +9,7 @@ use std::ptr;
use std::slice;
use std::sync::Arc;
use ssl::error::SslError;
use error::ErrorStack;
pub struct StreamState<S> {
pub stream: S,
@ -39,7 +39,7 @@ impl BioMethod {
unsafe impl Send for BioMethod {}
pub fn new<S: Read + Write>(stream: S) -> Result<(*mut BIO, Arc<BioMethod>), SslError> {
pub fn new<S: Read + Write>(stream: S) -> Result<(*mut BIO, Arc<BioMethod>), ErrorStack> {
let method = Arc::new(BioMethod::new::<S>());
let state = Box::new(StreamState {

View File

@ -1,15 +1,8 @@
pub use self::SslError::*;
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;
use error::ErrorStack;
/// An SSL error.
#[derive(Debug)]
@ -27,30 +20,16 @@ pub enum Error {
/// An error reported by the underlying stream.
Stream(io::Error),
/// An error in the OpenSSL library.
Ssl(Vec<OpenSslError>),
Ssl(ErrorStack),
}
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(()),
if let Some(err) = self.cause() {
write!(fmt, ": {}", err)
} else {
Ok(())
}
}
}
@ -72,247 +51,14 @@ impl error::Error for Error {
Error::WantRead(ref err) => Some(err),
Error::WantWrite(ref err) => Some(err),
Error::Stream(ref err) => Some(err),
Error::Ssl(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 From<ErrorStack> for Error {
fn from(e: ErrorStack) -> Error {
Error::Ssl(e)
}
}
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 {
/// The underlying stream reported an error
StreamError(io::Error),
/// The SSL session has been closed by the other end
SslSessionClosed,
/// An error in the OpenSSL library
OpenSslErrors(Vec<OpensslError>),
}
/// An error on a nonblocking stream.
#[derive(Debug)]
pub enum NonblockingSslError {
/// A standard SSL error occurred.
SslError(SslError),
/// The OpenSSL library wants data from the remote socket;
/// the caller should wait for read readiness.
WantRead,
/// The OpenSSL library wants to send data to the remote socket;
/// the caller should wait for write readiness.
WantWrite,
}
impl fmt::Display for SslError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
try!(fmt.write_str(error::Error::description(self)));
if let OpenSslErrors(ref errs) = *self {
let mut first = true;
for err in errs {
if first {
try!(fmt.write_str(": "));
first = false;
} else {
try!(fmt.write_str(", "));
}
match *err {
UnknownError { ref reason, .. } => try!(fmt.write_str(reason)),
}
}
}
Ok(())
}
}
impl error::Error for SslError {
fn description(&self) -> &str {
match *self {
StreamError(_) => "The underlying stream reported an error",
SslSessionClosed => "The SSL session has been closed by the other end",
OpenSslErrors(_) => "An error in the OpenSSL library",
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
StreamError(ref err) => Some(err as &error::Error),
_ => None,
}
}
}
impl fmt::Display for NonblockingSslError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(error::Error::description(self))
}
}
impl error::Error for NonblockingSslError {
fn description(&self) -> &str {
match *self {
NonblockingSslError::SslError(ref e) => e.description(),
NonblockingSslError::WantRead => {
"The OpenSSL library wants data from the remote socket"
}
NonblockingSslError::WantWrite => {
"The OpenSSL library want to send data to the remote socket"
}
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
NonblockingSslError::SslError(ref e) => e.cause(),
_ => None,
}
}
}
impl From<SslError> for NonblockingSslError {
fn from(e: SslError) -> NonblockingSslError {
NonblockingSslError::SslError(e)
}
}
/// An error from the OpenSSL library
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OpensslError {
/// An unknown error
UnknownError {
/// The library reporting the error
library: String,
/// The function reporting the error
function: String,
/// The reason for the error
reason: String,
},
}
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_lib(err: c_ulong) -> &'static str {
unsafe {
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_func(err: c_ulong) -> &'static str {
unsafe {
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()
}
}
impl SslError {
/// Creates a new `OpenSslErrors` with the current contents of the error
/// stack.
pub fn get() -> SslError {
let mut errs = vec![];
loop {
match unsafe { ffi::ERR_get_error() } {
0 => break,
err => errs.push(OpensslError::from_error_code(err)),
}
}
OpenSslErrors(errs)
}
/// Creates an `SslError` from the raw numeric error code.
pub fn from_error(err: c_ulong) -> SslError {
OpenSslErrors(vec![OpensslError::from_error_code(err)])
}
}
#[test]
fn test_uknown_error_should_have_correct_messages() {
let errs = match SslError::from_error(336032784) {
OpenSslErrors(errs) => errs,
_ => panic!("This should always be an `OpenSslErrors` variant."),
};
let UnknownError { ref library, ref function, ref reason } = errs[0];
assert_eq!(&library[..], "SSL routines");
assert_eq!(&function[..], "SSL23_GET_SERVER_HELLO");
assert_eq!(&reason[..], "sslv3 alert handshake failure");
}

File diff suppressed because it is too large Load Diff

View File

@ -17,9 +17,9 @@ use crypto::hash::Type::SHA256;
use ssl;
use ssl::SSL_VERIFY_PEER;
use ssl::SslMethod::Sslv23;
use ssl::SslMethod;
use ssl::error::NonblockingSslError;
use ssl::{SslContext, SslStream, VerifyCallback, NonblockingSslStream};
use ssl::{SslMethod, HandshakeError};
use ssl::error::Error;
use ssl::{SslContext, SslStream};
use x509::X509StoreContext;
use x509::X509FileType;
use x509::X509;
@ -133,6 +133,7 @@ impl Drop for Server {
}
#[cfg(feature = "dtlsv1")]
#[derive(Debug)]
struct UdpConnected(UdpSocket);
#[cfg(feature = "dtlsv1")]
@ -194,9 +195,9 @@ macro_rules! run_test(
use std::net::TcpStream;
use ssl;
use ssl::SslMethod;
use ssl::{SslContext, Ssl, SslStream, VerifyCallback};
use ssl::{SslContext, Ssl, SslStream};
use ssl::SSL_VERIFY_PEER;
use crypto::hash::Type::SHA1;
use crypto::hash::Type::{SHA1, SHA256};
use x509::X509StoreContext;
use serialize::hex::FromHex;
use super::Server;
@ -222,19 +223,19 @@ run_test!(new_ctx, |method, _| {
});
run_test!(new_sslstream, |method, stream| {
SslStream::connect_generic(&SslContext::new(method).unwrap(), stream).unwrap();
SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap();
});
run_test!(get_ssl_method, |method, _| {
let ssl = Ssl::new(&SslContext::new(method).unwrap()).unwrap();
assert_eq!(ssl.get_ssl_method(), Some(method));
assert_eq!(ssl.ssl_method(), Some(method));
});
run_test!(verify_untrusted, |method, stream| {
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
match SslStream::connect_generic(&ctx, stream) {
match SslStream::connect(&ctx, stream) {
Ok(_) => panic!("expected failure"),
Err(err) => println!("error {:?}", err),
}
@ -242,127 +243,95 @@ run_test!(verify_untrusted, |method, stream| {
run_test!(verify_trusted, |method, stream| {
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
Err(err) => panic!("Unexpected error {:?}", err),
}
match SslStream::connect_generic(&ctx, stream) {
match SslStream::connect(&ctx, stream) {
Ok(_) => (),
Err(err) => panic!("Expected success, got {:?}", err),
}
});
run_test!(verify_untrusted_callback_override_ok, |method, stream| {
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
true
}
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| true);
match SslStream::connect_generic(&ctx, stream) {
match SslStream::connect(&ctx, stream) {
Ok(_) => (),
Err(err) => panic!("Expected success, got {:?}", err),
}
});
run_test!(verify_untrusted_callback_override_bad, |method, stream| {
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
false
}
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| false);
assert!(SslStream::connect_generic(&ctx, stream).is_err());
assert!(SslStream::connect(&ctx, stream).is_err());
});
run_test!(verify_trusted_callback_override_ok, |method, stream| {
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
true
}
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| true);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
Err(err) => panic!("Unexpected error {:?}", err),
}
match SslStream::connect_generic(&ctx, stream) {
match SslStream::connect(&ctx, stream) {
Ok(_) => (),
Err(err) => panic!("Expected success, got {:?}", err),
}
});
run_test!(verify_trusted_callback_override_bad, |method, stream| {
fn callback(_preverify_ok: bool, _x509_ctx: &X509StoreContext) -> bool {
false
}
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| false);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
Err(err) => panic!("Unexpected error {:?}", err),
}
assert!(SslStream::connect_generic(&ctx, stream).is_err());
assert!(SslStream::connect(&ctx, stream).is_err());
});
run_test!(verify_callback_load_certs, |method, stream| {
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool {
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| {
assert!(x509_ctx.get_current_cert().is_some());
true
}
});
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
assert!(SslStream::connect_generic(&ctx, stream).is_ok());
assert!(SslStream::connect(&ctx, stream).is_ok());
});
run_test!(verify_trusted_get_error_ok, |method, stream| {
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool {
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| {
assert!(x509_ctx.get_error().is_none());
true
}
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
});
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
Err(err) => panic!("Unexpected error {:?}", err),
}
assert!(SslStream::connect_generic(&ctx, stream).is_ok());
assert!(SslStream::connect(&ctx, stream).is_ok());
});
run_test!(verify_trusted_get_error_err, |method, stream| {
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext) -> bool {
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| {
assert!(x509_ctx.get_error().is_some());
false
}
});
let mut ctx = SslContext::new(method).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, Some(callback as VerifyCallback));
assert!(SslStream::connect_generic(&ctx, stream).is_err());
assert!(SslStream::connect(&ctx, stream).is_err());
});
run_test!(verify_callback_data, |method, stream| {
fn callback(_preverify_ok: bool, x509_ctx: &X509StoreContext, node_id: &Vec<u8>) -> bool {
let cert = x509_ctx.get_current_cert();
match cert {
None => false,
Some(cert) => {
let fingerprint = cert.fingerprint(SHA1).unwrap();
&fingerprint == node_id
}
}
}
let mut ctx = SslContext::new(method).unwrap();
// Node id was generated as SHA256 hash of certificate "test/cert.pem"
@ -371,10 +340,19 @@ run_test!(verify_callback_data, |method, stream| {
// Please update if "test/cert.pem" will ever change
let node_hash_str = "E19427DAC79FBE758394945276A6E4F15F0BEBE6";
let node_id = node_hash_str.from_hex().unwrap();
ctx.set_verify_with_data(SSL_VERIFY_PEER, callback, node_id);
ctx.set_verify_callback(SSL_VERIFY_PEER, move |_preverify_ok, x509_ctx| {
let cert = x509_ctx.get_current_cert();
match cert {
None => false,
Some(cert) => {
let fingerprint = cert.fingerprint(SHA1).unwrap();
fingerprint == node_id
}
}
});
ctx.set_verify_depth(1);
match SslStream::connect_generic(&ctx, stream) {
match SslStream::connect(&ctx, stream) {
Ok(_) => (),
Err(err) => panic!("Expected success, got {:?}", err),
}
@ -402,7 +380,7 @@ run_test!(ssl_verify_callback, |method, stream| {
}
});
match SslStream::connect_generic(ssl, stream) {
match SslStream::connect(ssl, stream) {
Ok(_) => (),
Err(err) => panic!("Expected success, got {:?}", err),
}
@ -419,14 +397,14 @@ fn test_write_hits_stream() {
let guard = thread::spawn(move || {
let ctx = SslContext::new(Sslv23).unwrap();
let stream = TcpStream::connect(addr).unwrap();
let mut stream = SslStream::connect_generic(&ctx, stream).unwrap();
let mut stream = SslStream::connect(&ctx, stream).unwrap();
stream.write_all(b"hello").unwrap();
stream
});
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM).unwrap();
ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM).unwrap();
let stream = listener.accept().unwrap().0;
@ -440,17 +418,10 @@ fn test_write_hits_stream() {
#[test]
fn test_set_certificate_and_private_key() {
let key_path = Path::new("test/key.pem");
let cert_path = Path::new("test/cert.pem");
let mut key_file = File::open(&key_path)
.ok()
.expect("Failed to open `test/key.pem`");
let mut cert_file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/cert.pem`");
let key = PKey::private_key_from_pem(&mut key_file).unwrap();
let cert = X509::from_pem(&mut cert_file).unwrap();
let key = include_bytes!("../../../test/key.pem");
let key = PKey::private_key_from_pem(key).unwrap();
let cert = include_bytes!("../../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_private_key(&key).unwrap();
@ -460,8 +431,8 @@ fn test_set_certificate_and_private_key() {
}
run_test!(get_ctx_options, |method, _| {
let mut ctx = SslContext::new(method).unwrap();
ctx.get_options();
let ctx = SslContext::new(method).unwrap();
ctx.options();
});
run_test!(set_ctx_options, |method, _| {
@ -480,7 +451,7 @@ run_test!(clear_ctx_options, |method, _| {
#[test]
fn test_write() {
let (_s, stream) = Server::new();
let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), stream).unwrap();
let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap();
stream.write_all("hello".as_bytes()).unwrap();
stream.flush().unwrap();
stream.write_all(" there".as_bytes()).unwrap();
@ -498,7 +469,7 @@ fn test_write_direct() {
}
run_test!(get_peer_certificate, |method, stream| {
let stream = SslStream::connect_generic(&SslContext::new(method).unwrap(), stream).unwrap();
let stream = SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap();
let cert = stream.ssl().peer_certificate().unwrap();
let fingerprint = cert.fingerprint(SHA1).unwrap();
let node_hash_str = "E19427DAC79FBE758394945276A6E4F15F0BEBE6";
@ -511,7 +482,7 @@ run_test!(get_peer_certificate, |method, stream| {
fn test_write_dtlsv1() {
let (_s, stream) = Server::new_dtlsv1(iter::repeat("y\n"));
let mut stream = SslStream::connect_generic(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap();
let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap();
stream.write_all(b"hello").unwrap();
stream.flush().unwrap();
stream.write_all(b" there").unwrap();
@ -521,7 +492,7 @@ fn test_write_dtlsv1() {
#[test]
fn test_read() {
let (_s, tcp) = Server::new();
let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap();
stream.flush().unwrap();
io::copy(&mut stream, &mut io::sink()).ok().expect("read error");
@ -539,7 +510,7 @@ fn test_read_direct() {
#[test]
fn test_pending() {
let (_s, tcp) = Server::new();
let mut stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap();
stream.flush().unwrap();
@ -562,7 +533,7 @@ fn test_pending() {
#[test]
fn test_state() {
let (_s, tcp) = Server::new();
let stream = SslStream::connect_generic(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
let stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
assert_eq!(stream.ssl().state_string(), "SSLOK ");
assert_eq!(stream.ssl().state_string_long(),
"SSL negotiation finished successfully");
@ -575,7 +546,7 @@ fn test_state() {
fn test_connect_with_unilateral_alpn() {
let (_s, stream) = Server::new();
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
@ -597,13 +568,13 @@ fn test_connect_with_unilateral_alpn() {
fn test_connect_with_unilateral_npn() {
let (_s, stream) = Server::new();
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
Err(err) => panic!("Unexpected error {:?}", err),
}
let stream = match SslStream::connect_generic(&ctx, stream) {
let stream = match SslStream::connect(&ctx, stream) {
Ok(stream) => stream,
Err(err) => panic!("Expected success, got {:?}", err),
};
@ -619,7 +590,7 @@ fn test_connect_with_unilateral_npn() {
fn test_connect_with_alpn_successful_multiple_matching() {
let (_s, stream) = Server::new_alpn();
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_alpn_protocols(&[b"spdy/3.1", b"http/1.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
@ -641,13 +612,13 @@ fn test_connect_with_alpn_successful_multiple_matching() {
fn test_connect_with_npn_successful_multiple_matching() {
let (_s, stream) = Server::new_alpn();
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
Err(err) => panic!("Unexpected error {:?}", err),
}
let stream = match SslStream::connect_generic(&ctx, stream) {
let stream = match SslStream::connect(&ctx, stream) {
Ok(stream) => stream,
Err(err) => panic!("Expected success, got {:?}", err),
};
@ -664,7 +635,7 @@ fn test_connect_with_npn_successful_multiple_matching() {
fn test_connect_with_alpn_successful_single_match() {
let (_s, stream) = Server::new_alpn();
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_alpn_protocols(&[b"spdy/3.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
@ -688,13 +659,13 @@ fn test_connect_with_alpn_successful_single_match() {
fn test_connect_with_npn_successful_single_match() {
let (_s, stream) = Server::new_alpn();
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_npn_protocols(&[b"spdy/3.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
Err(err) => panic!("Unexpected error {:?}", err),
}
let stream = match SslStream::connect_generic(&ctx, stream) {
let stream = match SslStream::connect(&ctx, stream) {
Ok(stream) => stream,
Err(err) => panic!("Expected success, got {:?}", err),
};
@ -713,7 +684,7 @@ fn test_npn_server_advertise_multiple() {
// We create a different context instance for the server...
let listener_ctx = {
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]);
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM)
.is_ok());
@ -728,7 +699,7 @@ fn test_npn_server_advertise_multiple() {
});
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_npn_protocols(&[b"spdy/3.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
@ -736,7 +707,7 @@ fn test_npn_server_advertise_multiple() {
}
// Now connect to the socket and make sure the protocol negotiation works...
let stream = TcpStream::connect(localhost).unwrap();
let stream = match SslStream::connect_generic(&ctx, stream) {
let stream = match SslStream::connect(&ctx, stream) {
Ok(stream) => stream,
Err(err) => panic!("Expected success, got {:?}", err),
};
@ -754,7 +725,7 @@ fn test_alpn_server_advertise_multiple() {
// We create a different context instance for the server...
let listener_ctx = {
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]);
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM)
.is_ok());
@ -769,7 +740,7 @@ fn test_alpn_server_advertise_multiple() {
});
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_alpn_protocols(&[b"spdy/3.1"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
@ -795,7 +766,7 @@ fn test_alpn_server_select_none() {
// We create a different context instance for the server...
let listener_ctx = {
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]);
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM)
.is_ok());
@ -810,7 +781,7 @@ fn test_alpn_server_select_none() {
});
let mut ctx = SslContext::new(Sslv23).unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
ctx.set_alpn_protocols(&[b"http/2"]);
match ctx.set_CA_file(&Path::new("test/cert.pem")) {
Ok(_) => {}
@ -838,7 +809,7 @@ mod dtlsv1 {
use crypto::hash::Type::SHA256;
use ssl::SslMethod;
use ssl::SslMethod::Dtlsv1;
use ssl::{SslContext, SslStream, VerifyCallback};
use ssl::{SslContext, SslStream};
use ssl::SSL_VERIFY_PEER;
use x509::X509StoreContext;
@ -855,7 +826,7 @@ mod dtlsv1 {
fn test_read_dtlsv1() {
let (_s, stream) = Server::new_dtlsv1(Some("hello"));
let mut stream = SslStream::connect_generic(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap();
let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap();
let mut buf = [0u8; 100];
assert!(stream.read(&mut buf).is_ok());
}
@ -864,15 +835,15 @@ fn test_read_dtlsv1() {
#[cfg(feature = "sslv2")]
fn test_sslv2_connect_failure() {
let (_s, tcp) = Server::new_tcp(&["-no_ssl2", "-www"]);
SslStream::connect_generic(&SslContext::new(Sslv2).unwrap(), tcp)
SslStream::connect(&SslContext::new(Sslv2).unwrap(), tcp)
.err()
.unwrap();
}
fn wait_io(stream: &NonblockingSslStream<TcpStream>, read: bool, timeout_ms: u32) -> bool {
fn wait_io(stream: &TcpStream, read: bool, timeout_ms: u32) -> bool {
unsafe {
let mut set: select::fd_set = mem::zeroed();
select::fd_set(&mut set, stream.get_ref());
select::fd_set(&mut set, stream);
let write = if read {
0 as *mut _
@ -884,7 +855,19 @@ fn wait_io(stream: &NonblockingSslStream<TcpStream>, read: bool, timeout_ms: u32
} else {
&mut set as *mut _
};
select::select(stream.get_ref(), read, write, 0 as *mut _, timeout_ms).unwrap()
select::select(stream, read, write, 0 as *mut _, timeout_ms).unwrap()
}
}
fn handshake(res: Result<SslStream<TcpStream>, HandshakeError<TcpStream>>)
-> SslStream<TcpStream> {
match res {
Ok(s) => s,
Err(HandshakeError::Interrupted(s)) => {
wait_io(s.get_ref(), true, 1_000);
handshake(s.handshake())
}
Err(err) => panic!("error on handshake {:?}", err),
}
}
@ -893,7 +876,7 @@ fn test_write_nonblocking() {
let (_s, stream) = Server::new();
stream.set_nonblocking(true).unwrap();
let cx = SslContext::new(Sslv23).unwrap();
let mut stream = NonblockingSslStream::connect(&cx, stream).unwrap();
let mut stream = handshake(SslStream::connect(&cx, stream));
let mut iterations = 0;
loop {
@ -903,16 +886,16 @@ fn test_write_nonblocking() {
// openssl.
panic!("Too many read/write round trips in handshake!!");
}
let result = stream.write(b"hello");
let result = stream.ssl_write(b"hello");
match result {
Ok(_) => {
break;
}
Err(NonblockingSslError::WantRead) => {
assert!(wait_io(&stream, true, 1000));
Err(Error::WantRead(_)) => {
assert!(wait_io(stream.get_ref(), true, 1000));
}
Err(NonblockingSslError::WantWrite) => {
assert!(wait_io(&stream, false, 1000));
Err(Error::WantWrite(_)) => {
assert!(wait_io(stream.get_ref(), false, 1000));
}
Err(other) => {
panic!("Unexpected SSL Error: {:?}", other);
@ -930,7 +913,7 @@ fn test_read_nonblocking() {
let (_s, stream) = Server::new();
stream.set_nonblocking(true).unwrap();
let cx = SslContext::new(Sslv23).unwrap();
let mut stream = NonblockingSslStream::connect(&cx, stream).unwrap();
let mut stream = handshake(SslStream::connect(&cx, stream));
let mut iterations = 0;
loop {
@ -940,17 +923,17 @@ fn test_read_nonblocking() {
// openssl.
panic!("Too many read/write round trips in handshake!!");
}
let result = stream.write(b"GET /\r\n\r\n");
let result = stream.ssl_write(b"GET /\r\n\r\n");
match result {
Ok(n) => {
assert_eq!(n, 9);
break;
}
Err(NonblockingSslError::WantRead) => {
assert!(wait_io(&stream, true, 1000));
Err(Error::WantRead(..)) => {
assert!(wait_io(stream.get_ref(), true, 1000));
}
Err(NonblockingSslError::WantWrite) => {
assert!(wait_io(&stream, false, 1000));
Err(Error::WantWrite(..)) => {
assert!(wait_io(stream.get_ref(), false, 1000));
}
Err(other) => {
panic!("Unexpected SSL Error: {:?}", other);
@ -958,7 +941,7 @@ fn test_read_nonblocking() {
}
}
let mut input_buffer = [0u8; 1500];
let result = stream.read(&mut input_buffer);
let result = stream.ssl_read(&mut input_buffer);
let bytes_read = match result {
Ok(n) => {
// This branch is unlikely, but on an overloaded VM with
@ -966,8 +949,8 @@ fn test_read_nonblocking() {
// be in the receive buffer before we issue the read() syscall...
n
}
Err(NonblockingSslError::WantRead) => {
assert!(wait_io(&stream, true, 3000));
Err(Error::WantRead(..)) => {
assert!(wait_io(stream.get_ref(), true, 3000));
// Second read should return application data.
stream.read(&mut input_buffer).unwrap()
}
@ -979,14 +962,6 @@ fn test_read_nonblocking() {
assert_eq!(&input_buffer[..5], b"HTTP/");
}
#[test]
fn broken_try_clone_doesnt_crash() {
let context = SslContext::new(SslMethod::Sslv23).unwrap();
let inner = TcpStream::connect("example.com:443").unwrap();
let stream1 = SslStream::connect(&context, inner).unwrap();
let _stream2 = stream1.try_clone().unwrap();
}
#[test]
#[should_panic(expected = "blammo")]
#[cfg(feature = "nightly")]
@ -1093,7 +1068,7 @@ fn refcount_ssl_context() {
fn default_verify_paths() {
let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap();
ctx.set_default_verify_paths().unwrap();
ctx.set_verify(SSL_VERIFY_PEER, None);
ctx.set_verify(SSL_VERIFY_PEER);
let s = TcpStream::connect("google.com:443").unwrap();
let mut socket = SslStream::connect(&ctx, s).unwrap();

View File

@ -1,6 +1,4 @@
use libc::{c_char, c_int, c_long, c_ulong, c_uint, c_void};
use std::io;
use std::io::prelude::*;
use std::cmp::Ordering;
use std::ffi::CString;
use std::iter::repeat;
@ -14,15 +12,15 @@ use std::collections::HashMap;
use std::marker::PhantomData;
use asn1::Asn1Time;
use bio::MemBio;
use bio::{MemBio, MemBioSlice};
use crypto::hash;
use crypto::hash::Type as HashType;
use crypto::pkey::{PKey, Parts};
use crypto::rand::rand_bytes;
use ffi;
use ffi_extras;
use ssl::error::{SslError, StreamError};
use nid::Nid;
use error::ErrorStack;
pub mod extension;
@ -116,13 +114,6 @@ impl X509StoreContext {
/// # Example
///
/// ```
/// # #[allow(unstable)]
/// # fn main() {
/// use std::fs;
/// use std::fs::File;
/// use std::io::prelude::*;
/// use std::path::Path;
///
/// use openssl::crypto::hash::Type;
/// use openssl::x509::X509Generator;
/// use openssl::x509::extension::{Extension, KeyUsageOption};
@ -135,17 +126,8 @@ impl X509StoreContext {
/// .add_extension(Extension::KeyUsage(vec![KeyUsageOption::DigitalSignature]));
///
/// let (cert, pkey) = gen.generate().unwrap();
///
/// let cert_path = "doc_cert.pem";
/// let mut file = File::create(cert_path).unwrap();
/// assert!(cert.write_pem(&mut file).is_ok());
/// # let _ = fs::remove_file(cert_path);
///
/// let pkey_path = "doc_key.pem";
/// let mut file = File::create(pkey_path).unwrap();
/// assert!(pkey.write_pem(&mut file).is_ok());
/// # let _ = fs::remove_file(pkey_path);
/// # }
/// let cert_pem = cert.write_pem().unwrap();
/// let pkey_pem = pkey.write_pem().unwrap();
/// ```
pub struct X509Generator {
bits: u32,
@ -256,7 +238,7 @@ impl X509Generator {
fn add_extension_internal(x509: *mut ffi::X509,
exttype: &extension::ExtensionType,
value: &str)
-> Result<(), SslError> {
-> Result<(), ErrorStack> {
unsafe {
let mut ctx: ffi::X509V3_CTX = mem::zeroed();
ffi::X509V3_set_ctx(&mut ctx, x509, x509, ptr::null_mut(), ptr::null_mut(), 0);
@ -288,7 +270,7 @@ impl X509Generator {
fn add_name_internal(name: *mut ffi::X509_NAME,
key: &str,
value: &str)
-> Result<(), SslError> {
-> Result<(), ErrorStack> {
let value_len = value.len() as c_int;
lift_ssl!(unsafe {
let key = CString::new(key.as_bytes()).unwrap();
@ -319,7 +301,7 @@ impl X509Generator {
}
/// Generates a private key and a self-signed certificate and returns them
pub fn generate<'a>(&self) -> Result<(X509<'a>, PKey), SslError> {
pub fn generate<'a>(&self) -> Result<(X509<'a>, PKey), ErrorStack> {
ffi::init();
let mut p_key = PKey::new();
@ -331,7 +313,7 @@ impl X509Generator {
/// Sets the certificate public-key, then self-sign and return it
/// Note: That the bit-length of the private key is used (set_bitlength is ignored)
pub fn sign<'a>(&self, p_key: &PKey) -> Result<X509<'a>, SslError> {
pub fn sign<'a>(&self, p_key: &PKey) -> Result<X509<'a>, ErrorStack> {
ffi::init();
unsafe {
@ -391,7 +373,7 @@ impl X509Generator {
}
/// Obtain a certificate signing request (CSR)
pub fn request(&self, p_key: &PKey) -> Result<X509Req, SslError> {
pub fn request(&self, p_key: &PKey) -> Result<X509Req, ErrorStack> {
let cert = match self.sign(p_key) {
Ok(c) => c,
Err(x) => return Err(x),
@ -444,12 +426,8 @@ impl<'ctx> X509<'ctx> {
}
/// Reads certificate from PEM, takes ownership of handle
pub fn from_pem<R>(reader: &mut R) -> Result<X509<'ctx>, SslError>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
pub fn from_pem(buf: &[u8]) -> Result<X509<'ctx>, ErrorStack> {
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(),
ptr::null_mut(),
@ -523,25 +501,21 @@ impl<'ctx> X509<'ctx> {
}
/// Writes certificate as PEM
pub fn write_pem<W>(&self, writer: &mut W) -> Result<(), SslError>
where W: Write
{
let mut mem_bio = try!(MemBio::new());
pub fn write_pem(&self) -> Result<Vec<u8>, ErrorStack> {
let mem_bio = try!(MemBio::new());
unsafe {
try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.handle));
}
io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ())
Ok(mem_bio.get_buf().to_owned())
}
/// Returns a DER serialized form of the certificate
pub fn save_der(&self) -> Result<Vec<u8>, SslError> {
let mut mem_bio = try!(MemBio::new());
pub fn save_der(&self) -> Result<Vec<u8>, ErrorStack> {
let mem_bio = try!(MemBio::new());
unsafe {
ffi::i2d_X509_bio(mem_bio.get_handle(), self.handle);
}
let mut v = Vec::new();
try!(io::copy(&mut mem_bio, &mut v).map_err(StreamError));
Ok(v)
Ok(mem_bio.get_buf().to_owned())
}
}
@ -627,12 +601,8 @@ impl X509Req {
}
/// Reads CSR from PEM
pub fn from_pem<R>(reader: &mut R) -> Result<X509Req, SslError>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
pub fn from_pem(buf: &[u8]) -> Result<X509Req, ErrorStack> {
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.get_handle(),
ptr::null_mut(),
@ -643,25 +613,21 @@ impl X509Req {
}
/// Writes CSR as PEM
pub fn write_pem<W>(&self, writer: &mut W) -> Result<(), SslError>
where W: Write
{
let mut mem_bio = try!(MemBio::new());
unsafe {
try_ssl!(ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle));
pub fn write_pem(&self) -> Result<Vec<u8>, ErrorStack> {
let mem_bio = try!(MemBio::new());
if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle) } != 1 {
return Err(ErrorStack::get());
}
io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ())
Ok(mem_bio.get_buf().to_owned())
}
/// Returns a DER serialized form of the CSR
pub fn save_der(&self) -> Result<Vec<u8>, SslError> {
let mut mem_bio = try!(MemBio::new());
pub fn save_der(&self) -> Result<Vec<u8>, ErrorStack> {
let mem_bio = try!(MemBio::new());
unsafe {
ffi::i2d_X509_REQ_bio(mem_bio.get_handle(), self.handle);
}
let mut v = Vec::new();
try!(io::copy(&mut mem_bio, &mut v).map_err(StreamError));
Ok(v)
Ok(mem_bio.get_buf().to_owned())
}
}

View File

@ -1,7 +1,4 @@
use serialize::hex::FromHex;
use std::io;
use std::path::Path;
use std::fs::File;
use crypto::hash::Type::SHA1;
use crypto::pkey::PKey;
@ -30,8 +27,8 @@ fn get_generator() -> X509Generator {
#[test]
fn test_cert_gen() {
let (cert, pkey) = get_generator().generate().unwrap();
cert.write_pem(&mut io::sink()).unwrap();
pkey.write_pem(&mut io::sink()).unwrap();
cert.write_pem().unwrap();
pkey.write_pem().unwrap();
// FIXME: check data in result to be correct, needs implementation
// of X509 getters
@ -70,7 +67,7 @@ fn test_req_gen() {
pkey.gen(512);
let req = get_generator().request(&pkey).unwrap();
req.write_pem(&mut io::sink()).unwrap();
req.write_pem().unwrap();
// FIXME: check data in result to be correct, needs implementation
// of X509_REQ getters
@ -78,12 +75,8 @@ fn test_req_gen() {
#[test]
fn test_cert_loading() {
let cert_path = Path::new("test/cert.pem");
let mut file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/cert.pem`");
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
let fingerprint = cert.fingerprint(SHA1).unwrap();
let hash_str = "E19427DAC79FBE758394945276A6E4F15F0BEBE6";
@ -94,12 +87,8 @@ fn test_cert_loading() {
#[test]
fn test_save_der() {
let cert_path = Path::new("test/cert.pem");
let mut file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/cert.pem`");
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
let der = cert.save_der().unwrap();
assert!(!der.is_empty());
@ -107,12 +96,8 @@ fn test_save_der() {
#[test]
fn test_subject_read_cn() {
let cert_path = Path::new("test/cert.pem");
let mut file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/cert.pem`");
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
let subject = cert.subject_name();
let cn = match subject.text_by_nid(Nid::CN) {
Some(x) => x,
@ -124,12 +109,8 @@ fn test_subject_read_cn() {
#[test]
fn test_nid_values() {
let cert_path = Path::new("test/nid_test_cert.pem");
let mut file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/nid_test_cert.pem`");
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
let cert = include_bytes!("../../test/nid_test_cert.pem");
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
let subject = cert.subject_name();
let cn = match subject.text_by_nid(Nid::CN) {
@ -153,12 +134,8 @@ fn test_nid_values() {
#[test]
fn test_nid_uid_value() {
let cert_path = Path::new("test/nid_uid_test_cert.pem");
let mut file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/nid_uid_test_cert.pem`");
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
let cert = include_bytes!("../../test/nid_uid_test_cert.pem");
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
let subject = cert.subject_name();
let cn = match subject.text_by_nid(Nid::UserId) {
@ -170,8 +147,8 @@ fn test_nid_uid_value() {
#[test]
fn test_subject_alt_name() {
let mut file = File::open("test/alt_name_cert.pem").unwrap();
let cert = X509::from_pem(&mut file).unwrap();
let cert = include_bytes!("../../test/alt_name_cert.pem");
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
let subject_alt_names = cert.subject_alt_names().unwrap();
assert_eq!(3, subject_alt_names.len());
@ -184,8 +161,8 @@ fn test_subject_alt_name() {
#[test]
fn test_subject_alt_name_iter() {
let mut file = File::open("test/alt_name_cert.pem").unwrap();
let cert = X509::from_pem(&mut file).unwrap();
let cert = include_bytes!("../../test/alt_name_cert.pem");
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
let subject_alt_names = cert.subject_alt_names().unwrap();
let mut subject_alt_names_iter = subject_alt_names.iter();

View File

@ -7,10 +7,6 @@ if [ "$TEST_FEATURES" == "true" ]; then
FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac"
fi
if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then
FEATURES="$FEATURES nightly catch_unwind"
fi
if [ "$TRAVIS_OS_NAME" != "osx" ]; then
export OPENSSL_LIB_DIR=$HOME/openssl/lib
export OPENSSL_INCLUDE_DIR=$HOME/openssl/include