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:
Steven Fackler 2016-08-02 20:48:42 -07:00
parent 92abf49b96
commit 08e27f31ed
11 changed files with 201 additions and 391 deletions

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;

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 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(())
}
}

View File

@ -2,11 +2,10 @@ use ffi;
use std::fmt;
use error::ErrorStack;
use std::ptr;
use std::io::{self, Read, Write};
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;
use crypto::util::{CallbackState, invoke_passwd_cb};
@ -69,11 +68,9 @@ impl DSA {
}
/// Reads a DSA private key from PEM formatted data.
pub fn private_key_from_pem<R>(reader: &mut R) -> io::Result<DSA>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio));
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(),
@ -91,12 +88,12 @@ impl DSA {
///
/// The callback will be passed the password buffer and should return the number of characters
/// placed into the buffer.
pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> io::Result<DSA>
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));
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
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
pub fn private_key_to_pem<W>(&self, writer: &mut W) -> io::Result<()>
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,
@ -123,18 +119,15 @@ impl DSA {
None, ptr::null_mut()))
};
try!(io::copy(&mut mem_bio, writer));
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) -> io::Result<DSA>
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));
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(),
@ -145,15 +138,10 @@ impl DSA {
}
/// Writes an DSA public key as PEM formatted data
pub fn public_key_to_pem<W>(&self, writer: &mut W) -> io::Result<()>
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));
Ok(())
Ok(mem_bio.get_buf().to_owned())
}
pub fn size(&self) -> Option<u32> {
@ -243,8 +231,7 @@ 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::*;
@ -253,11 +240,9 @@ mod test {
#[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();
@ -277,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 = {
@ -301,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 = {
@ -329,8 +314,8 @@ mod test {
#[test]
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 c_char;
password[1] = b'y' as c_char;

View File

@ -1,10 +1,8 @@
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::mem;
use std::ptr;
use bio::MemBio;
use bio::{MemBio, MemBioSlice};
use crypto::HashTypeInternals;
use crypto::hash;
@ -76,12 +74,8 @@ impl PKey {
}
/// Reads private key from PEM, takes ownership of handle
pub fn private_key_from_pem<R>(reader: &mut R) -> io::Result<PKey>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio));
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(),
@ -100,14 +94,11 @@ impl PKey {
///
/// The callback will be passed the password buffer and should return the number of characters
/// placed into the buffer.
pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> io::Result<PKey>
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));
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(),
@ -122,12 +113,8 @@ impl PKey {
}
/// Reads public key from PEM, takes ownership of handle
pub fn public_key_from_pem<R>(reader: &mut R) -> io::Result<PKey>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio));
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(),
@ -141,14 +128,12 @@ impl PKey {
}
/// 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>
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());
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 {
@ -159,14 +144,12 @@ impl PKey {
}
/// 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>
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());
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 {
@ -280,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> */)
-> io::Result<()> {
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,
@ -294,20 +275,14 @@ impl PKey {
ptr::null_mut()));
}
let mut buf = vec![];
try!(mem_bio.read_to_end(&mut buf));
writer.write_all(&buf)
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> */)
-> io::Result<()> {
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));
writer.write_all(&buf)
Ok(mem_bio.get_buf().to_owned())
}
/**
@ -648,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;
@ -693,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]
@ -819,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,11 +1,10 @@
use ffi;
use std::fmt;
use std::ptr;
use std::io::{self, Read, Write};
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;
@ -62,12 +61,8 @@ impl RSA {
}
/// Reads an RSA private key from PEM formatted data.
pub fn private_key_from_pem<R>(reader: &mut R) -> io::Result<RSA>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio));
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(),
@ -78,13 +73,11 @@ impl RSA {
}
/// 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>
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));
let mem_bio = try!(MemBioSlice::new(buf));
unsafe {
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
pub fn private_key_to_pem<W>(&self, writer: &mut W) -> io::Result<()>
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(),
@ -112,17 +103,12 @@ impl RSA {
None,
ptr::null_mut()));
}
try!(io::copy(&mut mem_bio, writer));
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) -> io::Result<RSA>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio));
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(),
@ -133,17 +119,14 @@ impl RSA {
}
/// Writes an RSA public key as PEM formatted data
pub fn public_key_to_pem<W>(&self, writer: &mut W) -> io::Result<()>
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));
Ok(())
Ok(mem_bio.get_buf().to_owned())
}
pub fn size(&self) -> Option<u32> {
@ -236,7 +219,6 @@ impl fmt::Debug for RSA {
#[cfg(test)]
mod test {
use std::fs::File;
use std::io::Write;
use libc::c_char;
@ -271,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();
@ -285,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();
@ -300,8 +282,8 @@ mod test {
#[test]
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 c_char;
password[1] = b'y' as c_char;

View File

@ -1,8 +1,6 @@
use ffi;
use std::io;
use std::io::prelude::*;
use error::ErrorStack;
use bio::MemBio;
use bio::MemBioSlice;
use bn::BigNum;
use std::mem;
use std::ptr;
@ -18,11 +16,8 @@ impl DH {
Ok(DH(dh))
}
pub fn from_pem<R>(reader: &mut R) -> io::Result<DH>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio));
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())
};
@ -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;
@ -123,11 +116,8 @@ mod tests {
#[test]
fn test_dh_from_pem() {
let mut 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 params = include_bytes!("../../test/dhparams.pem");
let dh = DH::from_pem(params).ok().expect("Failed to load PEM");
ctx.set_tmp_dh(dh).unwrap();
}
}

View File

@ -17,7 +17,7 @@ extern crate net2;
mod macros;
pub mod asn1;
pub mod bio;
mod bio;
pub mod bn;
pub mod crypto;
pub mod dh;

View File

@ -418,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();

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,7 +12,7 @@ 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};
@ -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,
@ -444,12 +426,8 @@ impl<'ctx> X509<'ctx> {
}
/// Reads certificate from PEM, takes ownership of handle
pub fn from_pem<R>(reader: &mut R) -> io::Result<X509<'ctx>>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio));
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) -> io::Result<()>
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(|_| ())
Ok(mem_bio.get_buf().to_owned())
}
/// Returns a DER serialized form of the certificate
pub fn save_der(&self) -> Result<Vec<u8>, ErrorStack> {
let mut mem_bio = try!(MemBio::new());
let mem_bio = try!(MemBio::new());
unsafe {
ffi::i2d_X509_bio(mem_bio.get_handle(), self.handle);
}
let mut v = Vec::new();
drop(io::copy(&mut mem_bio, &mut v));
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) -> io::Result<X509Req>
where R: Read
{
let mut mem_bio = try!(MemBio::new());
try!(io::copy(reader, &mut mem_bio));
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) -> io::Result<()>
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());
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
pub fn save_der(&self) -> Result<Vec<u8>, ErrorStack> {
let mut mem_bio = try!(MemBio::new());
let mem_bio = try!(MemBio::new());
unsafe {
ffi::i2d_X509_REQ_bio(mem_bio.get_handle(), self.handle);
}
let mut v = Vec::new();
drop(io::copy(&mut mem_bio, &mut v));
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();