Restructure PEM input/output methods
Dealing with byte buffers directly avoids error handling weirdness and we were loading it all into memory before anyway.
This commit is contained in:
parent
92abf49b96
commit
08e27f31ed
|
|
@ -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_TYPE_NONE: c_int = 0;
|
||||||
|
|
||||||
pub const BIO_CTRL_EOF: c_int = 2;
|
pub const BIO_CTRL_EOF: c_int = 2;
|
||||||
|
pub const BIO_CTRL_INFO: c_int = 3;
|
||||||
pub const BIO_CTRL_FLUSH: c_int = 11;
|
pub const BIO_CTRL_FLUSH: c_int = 11;
|
||||||
pub const BIO_C_SET_BUF_MEM_EOF_RETURN: c_int = 130;
|
pub const BIO_C_SET_BUF_MEM_EOF_RETURN: c_int = 130;
|
||||||
|
|
||||||
|
|
@ -453,6 +454,11 @@ fn set_id_callback() {
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
fn set_id_callback() {}
|
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
|
// True functions
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int;
|
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_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_write(b: *mut BIO, buf: *const c_void, len: c_int) -> c_int;
|
||||||
pub fn BIO_s_mem() -> *const BIO_METHOD;
|
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_new() -> *mut BIGNUM;
|
||||||
pub fn BN_dup(n: *mut BIGNUM) -> *mut BIGNUM;
|
pub fn BN_dup(n: *mut BIGNUM) -> *mut BIGNUM;
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 error::ErrorStack;
|
|
||||||
|
|
||||||
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, ErrorStack> {
|
|
||||||
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, ErrorStack::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, ErrorStack::get()))
|
|
||||||
} else {
|
|
||||||
Ok(ret as usize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,11 +2,10 @@ use ffi;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::io::{self, Read, Write};
|
|
||||||
use libc::{c_uint, c_int, c_char, c_void};
|
use libc::{c_uint, c_int, c_char, c_void};
|
||||||
|
|
||||||
use bn::BigNum;
|
use bn::BigNum;
|
||||||
use bio::MemBio;
|
use bio::{MemBio, MemBioSlice};
|
||||||
use crypto::hash;
|
use crypto::hash;
|
||||||
use crypto::HashTypeInternals;
|
use crypto::HashTypeInternals;
|
||||||
use crypto::util::{CallbackState, invoke_passwd_cb};
|
use crypto::util::{CallbackState, invoke_passwd_cb};
|
||||||
|
|
@ -69,11 +68,9 @@ impl DSA {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a DSA private key from PEM formatted data.
|
/// Reads a DSA private key from PEM formatted data.
|
||||||
pub fn private_key_from_pem<R>(reader: &mut R) -> io::Result<DSA>
|
pub fn private_key_from_pem(buf: &[u8]) -> Result<DSA, ErrorStack> {
|
||||||
where R: Read
|
ffi::init();
|
||||||
{
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.get_handle(),
|
let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.get_handle(),
|
||||||
|
|
@ -91,12 +88,12 @@ impl DSA {
|
||||||
///
|
///
|
||||||
/// The callback will be passed the password buffer and should return the number of characters
|
/// The callback will be passed the password buffer and should return the number of characters
|
||||||
/// placed into the buffer.
|
/// placed into the buffer.
|
||||||
pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> io::Result<DSA>
|
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<DSA, ErrorStack>
|
||||||
where R: Read, F: FnOnce(&mut [c_char]) -> usize
|
where F: FnOnce(&mut [c_char]) -> usize
|
||||||
{
|
{
|
||||||
|
ffi::init();
|
||||||
let mut cb = CallbackState::new(pass_cb);
|
let mut cb = CallbackState::new(pass_cb);
|
||||||
let mut mem_bio = try!(MemBio::new());
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let cb_ptr = &mut cb as *mut _ as *mut c_void;
|
let cb_ptr = &mut cb as *mut _ as *mut c_void;
|
||||||
|
|
@ -111,11 +108,10 @@ impl DSA {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes an DSA private key as unencrypted PEM formatted data
|
/// Writes an DSA private key as unencrypted PEM formatted data
|
||||||
pub fn private_key_to_pem<W>(&self, writer: &mut W) -> io::Result<()>
|
pub fn private_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack>
|
||||||
where W: Write
|
|
||||||
{
|
{
|
||||||
assert!(self.has_private_key());
|
assert!(self.has_private_key());
|
||||||
let mut mem_bio = try!(MemBio::new());
|
let mem_bio = try!(MemBio::new());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.get_handle(), self.0,
|
try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.get_handle(), self.0,
|
||||||
|
|
@ -123,18 +119,15 @@ impl DSA {
|
||||||
None, ptr::null_mut()))
|
None, ptr::null_mut()))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
try!(io::copy(&mut mem_bio, writer));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an DSA public key from PEM formatted data.
|
/// Reads an DSA public key from PEM formatted data.
|
||||||
pub fn public_key_from_pem<R>(reader: &mut R) -> io::Result<DSA>
|
pub fn public_key_from_pem(buf: &[u8]) -> Result<DSA, ErrorStack>
|
||||||
where R: Read
|
|
||||||
{
|
{
|
||||||
let mut mem_bio = try!(MemBio::new());
|
ffi::init();
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
unsafe {
|
unsafe {
|
||||||
let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.get_handle(),
|
let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.get_handle(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
|
|
@ -145,15 +138,10 @@ impl DSA {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes an DSA public key as PEM formatted data
|
/// Writes an DSA public key as PEM formatted data
|
||||||
pub fn public_key_to_pem<W>(&self, writer: &mut W) -> io::Result<()>
|
pub fn public_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
where W: Write
|
let mem_bio = try!(MemBio::new());
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
|
|
||||||
unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.get_handle(), self.0)) };
|
unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.get_handle(), self.0)) };
|
||||||
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
try!(io::copy(&mut mem_bio, writer));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> Option<u32> {
|
pub fn size(&self) -> Option<u32> {
|
||||||
|
|
@ -243,8 +231,7 @@ impl fmt::Debug for DSA {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::fs::File;
|
use std::io::Write;
|
||||||
use std::io::{Write, Cursor};
|
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -253,11 +240,9 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_generate() {
|
pub fn test_generate() {
|
||||||
let key = DSA::generate(1024).unwrap();
|
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.public_key_to_pem().unwrap();
|
||||||
key.private_key_to_pem(&mut priv_buf).unwrap();
|
key.private_key_to_pem().unwrap();
|
||||||
|
|
||||||
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
||||||
|
|
||||||
|
|
@ -277,13 +262,13 @@ mod test {
|
||||||
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
|
||||||
|
|
||||||
let private_key = {
|
let private_key = {
|
||||||
let mut buffer = File::open("test/dsa.pem").unwrap();
|
let key = include_bytes!("../../test/dsa.pem");
|
||||||
DSA::private_key_from_pem(&mut buffer).unwrap()
|
DSA::private_key_from_pem(key).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let public_key = {
|
let public_key = {
|
||||||
let mut buffer = File::open("test/dsa.pem.pub").unwrap();
|
let key = include_bytes!("../../test/dsa.pem.pub");
|
||||||
DSA::public_key_from_pem(&mut buffer).unwrap()
|
DSA::public_key_from_pem(key).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let digest = {
|
let digest = {
|
||||||
|
|
@ -301,13 +286,13 @@ mod test {
|
||||||
pub fn test_sign_verify_fail() {
|
pub fn test_sign_verify_fail() {
|
||||||
let input: Vec<u8> = (0..25).cycle().take(128).collect();
|
let input: Vec<u8> = (0..25).cycle().take(128).collect();
|
||||||
let private_key = {
|
let private_key = {
|
||||||
let mut buffer = File::open("test/dsa.pem").unwrap();
|
let key = include_bytes!("../../test/dsa.pem");
|
||||||
DSA::private_key_from_pem(&mut buffer).unwrap()
|
DSA::private_key_from_pem(key).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let public_key = {
|
let public_key = {
|
||||||
let mut buffer = File::open("test/dsa.pem.pub").unwrap();
|
let key = include_bytes!("../../test/dsa.pem.pub");
|
||||||
DSA::public_key_from_pem(&mut buffer).unwrap()
|
DSA::public_key_from_pem(key).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let digest = {
|
let digest = {
|
||||||
|
|
@ -329,8 +314,8 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_password() {
|
pub fn test_password() {
|
||||||
let mut password_queried = false;
|
let mut password_queried = false;
|
||||||
let mut buffer = File::open("test/dsa-encrypted.pem").unwrap();
|
let key = include_bytes!("../../test/dsa-encrypted.pem");
|
||||||
DSA::private_key_from_pem_cb(&mut buffer, |password| {
|
DSA::private_key_from_pem_cb(key, |password| {
|
||||||
password_queried = true;
|
password_queried = true;
|
||||||
password[0] = b'm' as c_char;
|
password[0] = b'm' as c_char;
|
||||||
password[1] = b'y' as c_char;
|
password[1] = b'y' as c_char;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
use libc::{c_int, c_uint, c_ulong, c_void, c_char};
|
use libc::{c_int, c_uint, c_ulong, c_void, c_char};
|
||||||
use std::io;
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use bio::MemBio;
|
use bio::{MemBio, MemBioSlice};
|
||||||
|
|
||||||
use crypto::HashTypeInternals;
|
use crypto::HashTypeInternals;
|
||||||
use crypto::hash;
|
use crypto::hash;
|
||||||
|
|
@ -76,12 +74,8 @@ impl PKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads private key from PEM, takes ownership of handle
|
/// Reads private key from PEM, takes ownership of handle
|
||||||
pub fn private_key_from_pem<R>(reader: &mut R) -> io::Result<PKey>
|
pub fn private_key_from_pem(buf: &[u8]) -> Result<PKey, ErrorStack> {
|
||||||
where R: Read
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(),
|
let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
|
|
@ -100,14 +94,11 @@ impl PKey {
|
||||||
///
|
///
|
||||||
/// The callback will be passed the password buffer and should return the number of characters
|
/// The callback will be passed the password buffer and should return the number of characters
|
||||||
/// placed into the buffer.
|
/// placed into the buffer.
|
||||||
pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> io::Result<PKey>
|
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<PKey, ErrorStack>
|
||||||
where R: Read, F: FnOnce(&mut [c_char]) -> usize
|
where F: FnOnce(&mut [c_char]) -> usize
|
||||||
{
|
{
|
||||||
let mut cb = CallbackState::new(pass_cb);
|
let mut cb = CallbackState::new(pass_cb);
|
||||||
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(),
|
let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
|
|
@ -122,12 +113,8 @@ impl PKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads public key from PEM, takes ownership of handle
|
/// Reads public key from PEM, takes ownership of handle
|
||||||
pub fn public_key_from_pem<R>(reader: &mut R) -> io::Result<PKey>
|
pub fn public_key_from_pem(buf: &[u8]) -> Result<PKey, ErrorStack> {
|
||||||
where R: Read
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.get_handle(),
|
let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.get_handle(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
|
|
@ -141,14 +128,12 @@ impl PKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an RSA private key from PEM, takes ownership of handle
|
/// Reads an RSA private key from PEM, takes ownership of handle
|
||||||
pub fn private_rsa_key_from_pem<R>(reader: &mut R) -> io::Result<PKey>
|
pub fn private_rsa_key_from_pem(buf: &[u8]) -> Result<PKey, ErrorStack> {
|
||||||
where R: Read
|
let rsa = try!(RSA::private_key_from_pem(buf));
|
||||||
{
|
|
||||||
let rsa = try!(RSA::private_key_from_pem(reader));
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let evp = try_ssl_null!(ffi::EVP_PKEY_new());
|
let evp = try_ssl_null!(ffi::EVP_PKEY_new());
|
||||||
if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 {
|
if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get()));
|
return Err(ErrorStack::get());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PKey {
|
Ok(PKey {
|
||||||
|
|
@ -159,14 +144,12 @@ impl PKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an RSA public key from PEM, takes ownership of handle
|
/// Reads an RSA public key from PEM, takes ownership of handle
|
||||||
pub fn public_rsa_key_from_pem<R>(reader: &mut R) -> io::Result<PKey>
|
pub fn public_rsa_key_from_pem(buf: &[u8]) -> Result<PKey, ErrorStack> {
|
||||||
where R: Read
|
let rsa = try!(RSA::public_key_from_pem(buf));
|
||||||
{
|
|
||||||
let rsa = try!(RSA::public_key_from_pem(reader));
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let evp = try_ssl_null!(ffi::EVP_PKEY_new());
|
let evp = try_ssl_null!(ffi::EVP_PKEY_new());
|
||||||
if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 {
|
if ffi::EVP_PKEY_set1_RSA(evp, rsa.as_ptr()) == 0 {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get()));
|
return Err(ErrorStack::get());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PKey {
|
Ok(PKey {
|
||||||
|
|
@ -280,10 +263,8 @@ impl PKey {
|
||||||
|
|
||||||
/// Stores private key as a PEM
|
/// Stores private key as a PEM
|
||||||
// FIXME: also add password and encryption
|
// FIXME: also add password and encryption
|
||||||
pub fn write_pem<W: Write>(&self,
|
pub fn write_pem(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
writer: &mut W /* , password: Option<String> */)
|
let mem_bio = try!(MemBio::new());
|
||||||
-> io::Result<()> {
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
unsafe {
|
unsafe {
|
||||||
try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.get_handle(),
|
try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.get_handle(),
|
||||||
self.evp,
|
self.evp,
|
||||||
|
|
@ -294,20 +275,14 @@ impl PKey {
|
||||||
ptr::null_mut()));
|
ptr::null_mut()));
|
||||||
|
|
||||||
}
|
}
|
||||||
let mut buf = vec![];
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
try!(mem_bio.read_to_end(&mut buf));
|
|
||||||
writer.write_all(&buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores public key as a PEM
|
/// Stores public key as a PEM
|
||||||
pub fn write_pub_pem<W: Write>(&self,
|
pub fn write_pub_pem(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
writer: &mut W /* , password: Option<String> */)
|
let mem_bio = try!(MemBio::new());
|
||||||
-> io::Result<()> {
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.get_handle(), self.evp)) }
|
unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.get_handle(), self.evp)) }
|
||||||
let mut buf = vec![];
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
try!(mem_bio.read_to_end(&mut buf));
|
|
||||||
writer.write_all(&buf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -648,8 +623,6 @@ impl Clone for PKey {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::path::Path;
|
|
||||||
use std::fs::File;
|
|
||||||
use crypto::hash::Type::{MD5, SHA1};
|
use crypto::hash::Type::{MD5, SHA1};
|
||||||
use crypto::rsa::RSA;
|
use crypto::rsa::RSA;
|
||||||
|
|
||||||
|
|
@ -693,42 +666,26 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_private_key_from_pem() {
|
fn test_private_key_from_pem() {
|
||||||
let key_path = Path::new("test/key.pem");
|
let key = include_bytes!("../../test/key.pem");
|
||||||
let mut file = File::open(&key_path)
|
super::PKey::private_key_from_pem(key).unwrap();
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/key.pem`");
|
|
||||||
|
|
||||||
super::PKey::private_key_from_pem(&mut file).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_public_key_from_pem() {
|
fn test_public_key_from_pem() {
|
||||||
let key_path = Path::new("test/key.pem.pub");
|
let key = include_bytes!("../../test/key.pem.pub");
|
||||||
let mut file = File::open(&key_path)
|
super::PKey::public_key_from_pem(key).unwrap();
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/key.pem.pub`");
|
|
||||||
|
|
||||||
super::PKey::public_key_from_pem(&mut file).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_private_rsa_key_from_pem() {
|
fn test_private_rsa_key_from_pem() {
|
||||||
let key_path = Path::new("test/key.pem");
|
let key = include_bytes!("../../test/key.pem");
|
||||||
let mut file = File::open(&key_path)
|
super::PKey::private_rsa_key_from_pem(key).unwrap();
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/key.pem`");
|
|
||||||
|
|
||||||
super::PKey::private_rsa_key_from_pem(&mut file).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_public_rsa_key_from_pem() {
|
fn test_public_rsa_key_from_pem() {
|
||||||
let key_path = Path::new("test/key.pem.pub");
|
let key = include_bytes!("../../test/key.pem.pub");
|
||||||
let mut file = File::open(&key_path)
|
super::PKey::public_rsa_key_from_pem(key).unwrap();
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/key.pem.pub`");
|
|
||||||
|
|
||||||
super::PKey::public_rsa_key_from_pem(&mut file).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -819,18 +776,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pem() {
|
fn test_pem() {
|
||||||
let key_path = Path::new("test/key.pem");
|
let key = include_bytes!("../../test/key.pem");
|
||||||
let mut file = File::open(&key_path)
|
let key = super::PKey::private_key_from_pem(key).unwrap();
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/key.pem`");
|
|
||||||
|
|
||||||
let key = super::PKey::private_key_from_pem(&mut file).unwrap();
|
let priv_key = key.write_pem().unwrap();
|
||||||
|
let pub_key = key.write_pub_pem().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();
|
|
||||||
|
|
||||||
// As a super-simple verification, just check that the buffers contain
|
// As a super-simple verification, just check that the buffers contain
|
||||||
// the `PRIVATE KEY` or `PUBLIC KEY` strings.
|
// the `PRIVATE KEY` or `PUBLIC KEY` strings.
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
use ffi;
|
use ffi;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::io::{self, Read, Write};
|
|
||||||
use libc::{c_int, c_void, c_char};
|
use libc::{c_int, c_void, c_char};
|
||||||
|
|
||||||
use bn::BigNum;
|
use bn::BigNum;
|
||||||
use bio::MemBio;
|
use bio::{MemBio, MemBioSlice};
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
use crypto::HashTypeInternals;
|
use crypto::HashTypeInternals;
|
||||||
use crypto::hash;
|
use crypto::hash;
|
||||||
|
|
@ -62,12 +61,8 @@ impl RSA {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an RSA private key from PEM formatted data.
|
/// Reads an RSA private key from PEM formatted data.
|
||||||
pub fn private_key_from_pem<R>(reader: &mut R) -> io::Result<RSA>
|
pub fn private_key_from_pem(buf: &[u8]) -> Result<RSA, ErrorStack> {
|
||||||
where R: Read
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.get_handle(),
|
let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.get_handle(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
|
|
@ -78,13 +73,11 @@ impl RSA {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an RSA private key from PEM formatted data and supplies a password callback.
|
/// Reads an RSA private key from PEM formatted data and supplies a password callback.
|
||||||
pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> io::Result<RSA>
|
pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<RSA, ErrorStack>
|
||||||
where R: Read, F: FnOnce(&mut [c_char]) -> usize
|
where F: FnOnce(&mut [c_char]) -> usize
|
||||||
{
|
{
|
||||||
let mut cb = CallbackState::new(pass_cb);
|
let mut cb = CallbackState::new(pass_cb);
|
||||||
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let cb_ptr = &mut cb as *mut _ as *mut c_void;
|
let cb_ptr = &mut cb as *mut _ as *mut c_void;
|
||||||
|
|
@ -98,10 +91,8 @@ impl RSA {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes an RSA private key as unencrypted PEM formatted data
|
/// Writes an RSA private key as unencrypted PEM formatted data
|
||||||
pub fn private_key_to_pem<W>(&self, writer: &mut W) -> io::Result<()>
|
pub fn private_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
where W: Write
|
let mem_bio = try!(MemBio::new());
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.get_handle(),
|
try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.get_handle(),
|
||||||
|
|
@ -112,17 +103,12 @@ impl RSA {
|
||||||
None,
|
None,
|
||||||
ptr::null_mut()));
|
ptr::null_mut()));
|
||||||
}
|
}
|
||||||
try!(io::copy(&mut mem_bio, writer));
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads an RSA public key from PEM formatted data.
|
/// Reads an RSA public key from PEM formatted data.
|
||||||
pub fn public_key_from_pem<R>(reader: &mut R) -> io::Result<RSA>
|
pub fn public_key_from_pem(buf: &[u8]) -> Result<RSA, ErrorStack> {
|
||||||
where R: Read
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.get_handle(),
|
let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.get_handle(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
|
|
@ -133,17 +119,14 @@ impl RSA {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes an RSA public key as PEM formatted data
|
/// Writes an RSA public key as PEM formatted data
|
||||||
pub fn public_key_to_pem<W>(&self, writer: &mut W) -> io::Result<()>
|
pub fn public_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
where W: Write
|
let mem_bio = try!(MemBio::new());
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.get_handle(), self.0))
|
try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.get_handle(), self.0))
|
||||||
};
|
};
|
||||||
|
|
||||||
try!(io::copy(&mut mem_bio, writer));
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> Option<u32> {
|
pub fn size(&self) -> Option<u32> {
|
||||||
|
|
@ -236,7 +219,6 @@ impl fmt::Debug for RSA {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
|
|
||||||
|
|
@ -271,8 +253,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_sign() {
|
pub fn test_sign() {
|
||||||
let mut buffer = File::open("test/rsa.pem").unwrap();
|
let key = include_bytes!("../../test/rsa.pem");
|
||||||
let private_key = RSA::private_key_from_pem(&mut buffer).unwrap();
|
let private_key = RSA::private_key_from_pem(key).unwrap();
|
||||||
|
|
||||||
let mut sha = Hasher::new(Type::SHA256);
|
let mut sha = Hasher::new(Type::SHA256);
|
||||||
sha.write_all(&signing_input_rs256()).unwrap();
|
sha.write_all(&signing_input_rs256()).unwrap();
|
||||||
|
|
@ -285,8 +267,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_verify() {
|
pub fn test_verify() {
|
||||||
let mut buffer = File::open("test/rsa.pem.pub").unwrap();
|
let key = include_bytes!("../../test/rsa.pem.pub");
|
||||||
let public_key = RSA::public_key_from_pem(&mut buffer).unwrap();
|
let public_key = RSA::public_key_from_pem(key).unwrap();
|
||||||
|
|
||||||
let mut sha = Hasher::new(Type::SHA256);
|
let mut sha = Hasher::new(Type::SHA256);
|
||||||
sha.write_all(&signing_input_rs256()).unwrap();
|
sha.write_all(&signing_input_rs256()).unwrap();
|
||||||
|
|
@ -300,8 +282,8 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_password() {
|
pub fn test_password() {
|
||||||
let mut password_queried = false;
|
let mut password_queried = false;
|
||||||
let mut buffer = File::open("test/rsa-encrypted.pem").unwrap();
|
let key = include_bytes!("../../test/rsa-encrypted.pem");
|
||||||
RSA::private_key_from_pem_cb(&mut buffer, |password| {
|
RSA::private_key_from_pem_cb(key, |password| {
|
||||||
password_queried = true;
|
password_queried = true;
|
||||||
password[0] = b'm' as c_char;
|
password[0] = b'm' as c_char;
|
||||||
password[1] = b'y' as c_char;
|
password[1] = b'y' as c_char;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
use ffi;
|
use ffi;
|
||||||
use std::io;
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
use bio::MemBio;
|
use bio::MemBioSlice;
|
||||||
use bn::BigNum;
|
use bn::BigNum;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
@ -18,11 +16,8 @@ impl DH {
|
||||||
Ok(DH(dh))
|
Ok(DH(dh))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_pem<R>(reader: &mut R) -> io::Result<DH>
|
pub fn from_pem(buf: &[u8]) -> Result<DH, ErrorStack> {
|
||||||
where R: Read
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
let dh = unsafe {
|
let dh = unsafe {
|
||||||
ffi::PEM_read_bio_DHparams(mem_bio.get_handle(), ptr::null_mut(), None, ptr::null_mut())
|
ffi::PEM_read_bio_DHparams(mem_bio.get_handle(), ptr::null_mut(), None, ptr::null_mut())
|
||||||
};
|
};
|
||||||
|
|
@ -71,8 +66,6 @@ impl Drop for DH {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::fs::File;
|
|
||||||
use std::path::Path;
|
|
||||||
use super::DH;
|
use super::DH;
|
||||||
use bn::BigNum;
|
use bn::BigNum;
|
||||||
use ssl::SslContext;
|
use ssl::SslContext;
|
||||||
|
|
@ -123,11 +116,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dh_from_pem() {
|
fn test_dh_from_pem() {
|
||||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||||
let pem_path = Path::new("test/dhparams.pem");
|
let params = include_bytes!("../../test/dhparams.pem");
|
||||||
let mut file = File::open(&pem_path)
|
let dh = DH::from_pem(params).ok().expect("Failed to load PEM");
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/dhparams.pem`");
|
|
||||||
let dh = DH::from_pem(&mut file).ok().expect("Failed to load PEM");
|
|
||||||
ctx.set_tmp_dh(dh).unwrap();
|
ctx.set_tmp_dh(dh).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ extern crate net2;
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
pub mod asn1;
|
pub mod asn1;
|
||||||
pub mod bio;
|
mod bio;
|
||||||
pub mod bn;
|
pub mod bn;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod dh;
|
pub mod dh;
|
||||||
|
|
|
||||||
|
|
@ -418,17 +418,10 @@ fn test_write_hits_stream() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_set_certificate_and_private_key() {
|
fn test_set_certificate_and_private_key() {
|
||||||
let key_path = Path::new("test/key.pem");
|
let key = include_bytes!("../../../test/key.pem");
|
||||||
let cert_path = Path::new("test/cert.pem");
|
let key = PKey::private_key_from_pem(key).unwrap();
|
||||||
let mut key_file = File::open(&key_path)
|
let cert = include_bytes!("../../../test/cert.pem");
|
||||||
.ok()
|
let cert = X509::from_pem(cert).unwrap();
|
||||||
.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 mut ctx = SslContext::new(Sslv23).unwrap();
|
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||||
ctx.set_private_key(&key).unwrap();
|
ctx.set_private_key(&key).unwrap();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
use libc::{c_char, c_int, c_long, c_ulong, c_uint, c_void};
|
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::cmp::Ordering;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
|
|
@ -14,7 +12,7 @@ use std::collections::HashMap;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use asn1::Asn1Time;
|
use asn1::Asn1Time;
|
||||||
use bio::MemBio;
|
use bio::{MemBio, MemBioSlice};
|
||||||
use crypto::hash;
|
use crypto::hash;
|
||||||
use crypto::hash::Type as HashType;
|
use crypto::hash::Type as HashType;
|
||||||
use crypto::pkey::{PKey, Parts};
|
use crypto::pkey::{PKey, Parts};
|
||||||
|
|
@ -116,13 +114,6 @@ impl X509StoreContext {
|
||||||
/// # Example
|
/// # 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::crypto::hash::Type;
|
||||||
/// use openssl::x509::X509Generator;
|
/// use openssl::x509::X509Generator;
|
||||||
/// use openssl::x509::extension::{Extension, KeyUsageOption};
|
/// use openssl::x509::extension::{Extension, KeyUsageOption};
|
||||||
|
|
@ -135,17 +126,8 @@ impl X509StoreContext {
|
||||||
/// .add_extension(Extension::KeyUsage(vec![KeyUsageOption::DigitalSignature]));
|
/// .add_extension(Extension::KeyUsage(vec![KeyUsageOption::DigitalSignature]));
|
||||||
///
|
///
|
||||||
/// let (cert, pkey) = gen.generate().unwrap();
|
/// let (cert, pkey) = gen.generate().unwrap();
|
||||||
///
|
/// let cert_pem = cert.write_pem().unwrap();
|
||||||
/// let cert_path = "doc_cert.pem";
|
/// let pkey_pem = pkey.write_pem().unwrap();
|
||||||
/// 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);
|
|
||||||
/// # }
|
|
||||||
/// ```
|
/// ```
|
||||||
pub struct X509Generator {
|
pub struct X509Generator {
|
||||||
bits: u32,
|
bits: u32,
|
||||||
|
|
@ -444,12 +426,8 @@ impl<'ctx> X509<'ctx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads certificate from PEM, takes ownership of handle
|
/// Reads certificate from PEM, takes ownership of handle
|
||||||
pub fn from_pem<R>(reader: &mut R) -> io::Result<X509<'ctx>>
|
pub fn from_pem(buf: &[u8]) -> Result<X509<'ctx>, ErrorStack> {
|
||||||
where R: Read
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(),
|
let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
|
|
@ -523,25 +501,21 @@ impl<'ctx> X509<'ctx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes certificate as PEM
|
/// Writes certificate as PEM
|
||||||
pub fn write_pem<W>(&self, writer: &mut W) -> io::Result<()>
|
pub fn write_pem(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
where W: Write
|
let mem_bio = try!(MemBio::new());
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
unsafe {
|
unsafe {
|
||||||
try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.handle));
|
try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.handle));
|
||||||
}
|
}
|
||||||
io::copy(&mut mem_bio, writer).map(|_| ())
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a DER serialized form of the certificate
|
/// Returns a DER serialized form of the certificate
|
||||||
pub fn save_der(&self) -> Result<Vec<u8>, ErrorStack> {
|
pub fn save_der(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
let mut mem_bio = try!(MemBio::new());
|
let mem_bio = try!(MemBio::new());
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::i2d_X509_bio(mem_bio.get_handle(), self.handle);
|
ffi::i2d_X509_bio(mem_bio.get_handle(), self.handle);
|
||||||
}
|
}
|
||||||
let mut v = Vec::new();
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
drop(io::copy(&mut mem_bio, &mut v));
|
|
||||||
Ok(v)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -627,12 +601,8 @@ impl X509Req {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads CSR from PEM
|
/// Reads CSR from PEM
|
||||||
pub fn from_pem<R>(reader: &mut R) -> io::Result<X509Req>
|
pub fn from_pem(buf: &[u8]) -> Result<X509Req, ErrorStack> {
|
||||||
where R: Read
|
let mem_bio = try!(MemBioSlice::new(buf));
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
try!(io::copy(reader, &mut mem_bio));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.get_handle(),
|
let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.get_handle(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
|
|
@ -643,25 +613,21 @@ impl X509Req {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes CSR as PEM
|
/// Writes CSR as PEM
|
||||||
pub fn write_pem<W>(&self, writer: &mut W) -> io::Result<()>
|
pub fn write_pem(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
where W: Write
|
let mem_bio = try!(MemBio::new());
|
||||||
{
|
|
||||||
let mut mem_bio = try!(MemBio::new());
|
|
||||||
if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle) } != 1 {
|
if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle) } != 1 {
|
||||||
return Err(io::Error::new(io::ErrorKind::Other, ErrorStack::get()));
|
return Err(ErrorStack::get());
|
||||||
}
|
}
|
||||||
io::copy(&mut mem_bio, writer).map(|_| ())
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a DER serialized form of the CSR
|
/// Returns a DER serialized form of the CSR
|
||||||
pub fn save_der(&self) -> Result<Vec<u8>, ErrorStack> {
|
pub fn save_der(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
let mut mem_bio = try!(MemBio::new());
|
let mem_bio = try!(MemBio::new());
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::i2d_X509_REQ_bio(mem_bio.get_handle(), self.handle);
|
ffi::i2d_X509_REQ_bio(mem_bio.get_handle(), self.handle);
|
||||||
}
|
}
|
||||||
let mut v = Vec::new();
|
Ok(mem_bio.get_buf().to_owned())
|
||||||
drop(io::copy(&mut mem_bio, &mut v));
|
|
||||||
Ok(v)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
use serialize::hex::FromHex;
|
use serialize::hex::FromHex;
|
||||||
use std::io;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::fs::File;
|
|
||||||
|
|
||||||
use crypto::hash::Type::SHA1;
|
use crypto::hash::Type::SHA1;
|
||||||
use crypto::pkey::PKey;
|
use crypto::pkey::PKey;
|
||||||
|
|
@ -30,8 +27,8 @@ fn get_generator() -> X509Generator {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cert_gen() {
|
fn test_cert_gen() {
|
||||||
let (cert, pkey) = get_generator().generate().unwrap();
|
let (cert, pkey) = get_generator().generate().unwrap();
|
||||||
cert.write_pem(&mut io::sink()).unwrap();
|
cert.write_pem().unwrap();
|
||||||
pkey.write_pem(&mut io::sink()).unwrap();
|
pkey.write_pem().unwrap();
|
||||||
|
|
||||||
// FIXME: check data in result to be correct, needs implementation
|
// FIXME: check data in result to be correct, needs implementation
|
||||||
// of X509 getters
|
// of X509 getters
|
||||||
|
|
@ -70,7 +67,7 @@ fn test_req_gen() {
|
||||||
pkey.gen(512);
|
pkey.gen(512);
|
||||||
|
|
||||||
let req = get_generator().request(&pkey).unwrap();
|
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
|
// FIXME: check data in result to be correct, needs implementation
|
||||||
// of X509_REQ getters
|
// of X509_REQ getters
|
||||||
|
|
@ -78,12 +75,8 @@ fn test_req_gen() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cert_loading() {
|
fn test_cert_loading() {
|
||||||
let cert_path = Path::new("test/cert.pem");
|
let cert = include_bytes!("../../test/cert.pem");
|
||||||
let mut file = File::open(&cert_path)
|
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/cert.pem`");
|
|
||||||
|
|
||||||
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
|
|
||||||
let fingerprint = cert.fingerprint(SHA1).unwrap();
|
let fingerprint = cert.fingerprint(SHA1).unwrap();
|
||||||
|
|
||||||
let hash_str = "E19427DAC79FBE758394945276A6E4F15F0BEBE6";
|
let hash_str = "E19427DAC79FBE758394945276A6E4F15F0BEBE6";
|
||||||
|
|
@ -94,12 +87,8 @@ fn test_cert_loading() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_save_der() {
|
fn test_save_der() {
|
||||||
let cert_path = Path::new("test/cert.pem");
|
let cert = include_bytes!("../../test/cert.pem");
|
||||||
let mut file = File::open(&cert_path)
|
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/cert.pem`");
|
|
||||||
|
|
||||||
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
|
|
||||||
|
|
||||||
let der = cert.save_der().unwrap();
|
let der = cert.save_der().unwrap();
|
||||||
assert!(!der.is_empty());
|
assert!(!der.is_empty());
|
||||||
|
|
@ -107,12 +96,8 @@ fn test_save_der() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_subject_read_cn() {
|
fn test_subject_read_cn() {
|
||||||
let cert_path = Path::new("test/cert.pem");
|
let cert = include_bytes!("../../test/cert.pem");
|
||||||
let mut file = File::open(&cert_path)
|
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/cert.pem`");
|
|
||||||
|
|
||||||
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
|
|
||||||
let subject = cert.subject_name();
|
let subject = cert.subject_name();
|
||||||
let cn = match subject.text_by_nid(Nid::CN) {
|
let cn = match subject.text_by_nid(Nid::CN) {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
|
|
@ -124,12 +109,8 @@ fn test_subject_read_cn() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nid_values() {
|
fn test_nid_values() {
|
||||||
let cert_path = Path::new("test/nid_test_cert.pem");
|
let cert = include_bytes!("../../test/nid_test_cert.pem");
|
||||||
let mut file = File::open(&cert_path)
|
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
|
||||||
.ok()
|
|
||||||
.expect("Failed to open `test/nid_test_cert.pem`");
|
|
||||||
|
|
||||||
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
|
|
||||||
let subject = cert.subject_name();
|
let subject = cert.subject_name();
|
||||||
|
|
||||||
let cn = match subject.text_by_nid(Nid::CN) {
|
let cn = match subject.text_by_nid(Nid::CN) {
|
||||||
|
|
@ -153,12 +134,8 @@ fn test_nid_values() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nid_uid_value() {
|
fn test_nid_uid_value() {
|
||||||
let cert_path = Path::new("test/nid_uid_test_cert.pem");
|
let cert = include_bytes!("../../test/nid_uid_test_cert.pem");
|
||||||
let mut file = File::open(&cert_path)
|
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
|
||||||
.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 subject = cert.subject_name();
|
let subject = cert.subject_name();
|
||||||
|
|
||||||
let cn = match subject.text_by_nid(Nid::UserId) {
|
let cn = match subject.text_by_nid(Nid::UserId) {
|
||||||
|
|
@ -170,8 +147,8 @@ fn test_nid_uid_value() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_subject_alt_name() {
|
fn test_subject_alt_name() {
|
||||||
let mut file = File::open("test/alt_name_cert.pem").unwrap();
|
let cert = include_bytes!("../../test/alt_name_cert.pem");
|
||||||
let cert = X509::from_pem(&mut file).unwrap();
|
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
|
||||||
|
|
||||||
let subject_alt_names = cert.subject_alt_names().unwrap();
|
let subject_alt_names = cert.subject_alt_names().unwrap();
|
||||||
assert_eq!(3, subject_alt_names.len());
|
assert_eq!(3, subject_alt_names.len());
|
||||||
|
|
@ -184,8 +161,8 @@ fn test_subject_alt_name() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_subject_alt_name_iter() {
|
fn test_subject_alt_name_iter() {
|
||||||
let mut file = File::open("test/alt_name_cert.pem").unwrap();
|
let cert = include_bytes!("../../test/alt_name_cert.pem");
|
||||||
let cert = X509::from_pem(&mut file).unwrap();
|
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
|
||||||
|
|
||||||
let subject_alt_names = cert.subject_alt_names().unwrap();
|
let subject_alt_names = cert.subject_alt_names().unwrap();
|
||||||
let mut subject_alt_names_iter = subject_alt_names.iter();
|
let mut subject_alt_names_iter = subject_alt_names.iter();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue