diff options
Diffstat (limited to 'openssl/src/rsa.rs')
| -rw-r--r-- | openssl/src/rsa.rs | 121 |
1 files changed, 54 insertions, 67 deletions
diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index bd1d16d3..792f7070 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -3,52 +3,48 @@ use std::fmt; use std::ptr; use std::mem; use libc::{c_int, c_void, c_char}; +use foreign_types::ForeignTypeRef; use {cvt, cvt_p, cvt_n}; use bn::{BigNum, BigNumRef}; -use bio::{MemBio, MemBioSlice}; +use bio::MemBioSlice; use error::ErrorStack; -use util::{CallbackState, invoke_passwd_cb}; -use types::OpenSslTypeRef; +use util::{CallbackState, invoke_passwd_cb_old}; /// Type of encryption padding to use. -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct Padding(c_int); +impl Padding { + pub fn from_raw(value: c_int) -> Padding { + Padding(value) + } + + pub fn as_raw(&self) -> c_int { + self.0 + } +} + pub const NO_PADDING: Padding = Padding(ffi::RSA_NO_PADDING); pub const PKCS1_PADDING: Padding = Padding(ffi::RSA_PKCS1_PADDING); pub const PKCS1_OAEP_PADDING: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING); -type_!(Rsa, RsaRef, ffi::RSA, ffi::RSA_free); +foreign_type! { + type CType = ffi::RSA; + fn drop = ffi::RSA_free; -impl RsaRef { - /// Writes an RSA private key as unencrypted PEM formatted data - pub fn private_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> { - let mem_bio = try!(MemBio::new()); - - unsafe { - try!(cvt(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.as_ptr(), - self.as_ptr(), - ptr::null(), - ptr::null_mut(), - 0, - None, - ptr::null_mut()))); - } - Ok(mem_bio.get_buf().to_owned()) - } + pub struct Rsa; + pub struct RsaRef; +} - /// Writes an RSA public key as PEM formatted data - pub fn public_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> { - let mem_bio = try!(MemBio::new()); +impl RsaRef { + private_key_to_pem!(ffi::PEM_write_bio_RSAPrivateKey); + public_key_to_pem!(ffi::PEM_write_bio_RSA_PUBKEY); - unsafe { - try!(cvt(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.as_ptr(), self.as_ptr()))); - } - - Ok(mem_bio.get_buf().to_owned()) - } + private_key_to_der!(ffi::i2d_RSAPrivateKey); + public_key_to_der!(ffi::i2d_RSA_PUBKEY); + // FIXME should return u32 pub fn size(&self) -> usize { unsafe { assert!(self.n().is_some()); @@ -250,6 +246,7 @@ impl Rsa { /// /// The public exponent will be 65537. pub fn generate(bits: u32) -> Result<Rsa, ErrorStack> { + ffi::init(); unsafe { let rsa = Rsa(try!(cvt_p(ffi::RSA_new()))); let e = try!(BigNum::from_u32(ffi::RSA_F4 as u32)); @@ -258,22 +255,16 @@ impl Rsa { } } - /// Reads an RSA private key from PEM formatted data. - pub fn private_key_from_pem(buf: &[u8]) -> Result<Rsa, ErrorStack> { - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut()))); - Ok(Rsa(rsa)) - } - } + private_key_from_pem!(Rsa, ffi::PEM_read_bio_RSAPrivateKey); + private_key_from_der!(Rsa, ffi::d2i_RSAPrivateKey); + public_key_from_pem!(Rsa, ffi::PEM_read_bio_RSA_PUBKEY); + public_key_from_der!(Rsa, ffi::d2i_RSA_PUBKEY); - /// Reads an RSA private key from PEM formatted data and supplies a password callback. + #[deprecated(since = "0.9.2", note = "use private_key_from_pem_callback")] pub fn private_key_from_pem_cb<F>(buf: &[u8], pass_cb: F) -> Result<Rsa, ErrorStack> where F: FnOnce(&mut [c_char]) -> usize { + ffi::init(); let mut cb = CallbackState::new(pass_cb); let mem_bio = try!(MemBioSlice::new(buf)); @@ -281,23 +272,11 @@ impl Rsa { let cb_ptr = &mut cb as *mut _ as *mut c_void; let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(), ptr::null_mut(), - Some(invoke_passwd_cb::<F>), + Some(invoke_passwd_cb_old::<F>), cb_ptr))); Ok(Rsa(rsa)) } } - - /// Reads an RSA public key from PEM formatted data. - pub fn public_key_from_pem(buf: &[u8]) -> Result<Rsa, ErrorStack> { - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let rsa = try!(cvt_p(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut()))); - Ok(Rsa(rsa)) - } - } } impl fmt::Debug for Rsa { @@ -380,26 +359,26 @@ mod compat { } } - #[cfg(test)] mod test { - use libc::c_char; + use symm::Cipher; use super::*; #[test] - pub fn test_password() { + fn test_from_password() { + let key = include_bytes!("../test/rsa-encrypted.pem"); + Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap(); + } + + #[test] + fn test_from_password_callback() { let mut password_queried = false; let key = include_bytes!("../test/rsa-encrypted.pem"); - Rsa::private_key_from_pem_cb(key, |password| { + Rsa::private_key_from_pem_callback(key, |password| { password_queried = true; - 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 + password[..6].copy_from_slice(b"mypass"); + Ok(6) }) .unwrap(); @@ -407,7 +386,15 @@ mod test { } #[test] - pub fn test_public_encrypt_private_decrypt_with_padding() { + fn test_to_password() { + let key = Rsa::generate(2048).unwrap(); + let pem = key.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar").unwrap(); + Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap(); + assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err()); + } + + #[test] + fn test_public_encrypt_private_decrypt_with_padding() { let key = include_bytes!("../test/rsa.pem.pub"); let public_key = Rsa::public_key_from_pem(key).unwrap(); |