diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 63714b7e..517707c3 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1761,10 +1761,14 @@ extern { pub fn d2i_X509(a: *mut *mut X509, pp: *mut *const c_uchar, length: c_long) -> *mut X509; pub fn i2d_X509_bio(b: *mut BIO, x: *mut X509) -> c_int; + pub fn i2d_X509(x: *mut X509, buf: *mut *mut u8) -> c_int; pub fn i2d_X509_REQ_bio(b: *mut BIO, x: *mut X509_REQ) -> c_int; + pub fn i2d_X509_REQ(x: *mut X509_REQ, buf: *mut *mut u8) -> c_int; pub fn i2d_PUBKEY_bio(b: *mut BIO, x: *mut EVP_PKEY) -> c_int; pub fn i2d_PrivateKey_bio(b: *mut BIO, x: *mut EVP_PKEY) -> c_int; + pub fn i2d_PUBKEY(k: *mut EVP_PKEY, buf: *mut *mut u8) -> c_int; + pub fn i2d_PrivateKey(k: *mut EVP_PKEY, buf: *mut *mut u8) -> c_int; pub fn i2d_RSA_PUBKEY(k: *mut RSA, buf: *mut *mut u8) -> c_int; pub fn d2i_RSA_PUBKEY(k: *mut *mut RSA, buf: *mut *const u8, len: c_long) -> *mut RSA; diff --git a/openssl/src/dh.rs b/openssl/src/dh.rs index ad1ebf9f..2b0a1508 100644 --- a/openssl/src/dh.rs +++ b/openssl/src/dh.rs @@ -22,15 +22,7 @@ impl DhRef { Ok(mem_bio.get_buf().to_owned()) } - /// Encodes the parameters to DER. - pub fn to_der(&self) -> Result, ErrorStack> { - unsafe { - let len = try!(cvt(ffi::i2d_DHparams(self.as_ptr(), ptr::null_mut()))); - let mut buf = vec![0; len as usize]; - try!(cvt(ffi::i2d_DHparams(self.as_ptr(), &mut buf.as_mut_ptr()))); - Ok(buf) - } - } + to_der!(ffi::i2d_DHparams); } impl Dh { diff --git a/openssl/src/dsa.rs b/openssl/src/dsa.rs index 9afb952e..0444ed9f 100644 --- a/openssl/src/dsa.rs +++ b/openssl/src/dsa.rs @@ -25,25 +25,8 @@ impl DsaRef { Ok(mem_bio.get_buf().to_owned()) } - /// Encodes a DSA private key as unencrypted DER formatted data. - pub fn private_key_to_der(&self) -> Result, ErrorStack> { - unsafe { - let len = try!(cvt(ffi::i2d_DSAPrivateKey(self.as_ptr(), ptr::null_mut()))); - let mut buf = vec![0; len as usize]; - try!(cvt(ffi::i2d_DSAPrivateKey(self.as_ptr(), &mut buf.as_mut_ptr()))); - Ok(buf) - } - } - - /// Encodes a DSA public key as DER formatted data. - pub fn public_key_to_der(&self) -> Result, ErrorStack> { - unsafe { - let len = try!(cvt(ffi::i2d_DSAPublicKey(self.as_ptr(), ptr::null_mut()))); - let mut buf = vec![0; len as usize]; - try!(cvt(ffi::i2d_DSAPublicKey(self.as_ptr(), &mut buf.as_mut_ptr()))); - Ok(buf) - } - } + private_key_to_der!(ffi::i2d_DSAPrivateKey); + public_key_to_der!(ffi::i2d_DSAPublicKey); // FIXME should return u32 pub fn size(&self) -> Option { diff --git a/openssl/src/ec_key.rs b/openssl/src/ec_key.rs index 7406572a..706265ef 100644 --- a/openssl/src/ec_key.rs +++ b/openssl/src/ec_key.rs @@ -12,16 +12,7 @@ type_!(EcKey, EcKeyRef, ffi::EC_KEY, ffi::EC_KEY_free); impl EcKeyRef { private_key_to_pem!(ffi::PEM_write_bio_ECPrivateKey); - - /// Serializes the private key components to DER. - pub fn private_key_to_der(&self) -> Result, ErrorStack> { - unsafe { - let len = try!(cvt(ffi::i2d_ECPrivateKey(self.as_ptr(), ptr::null_mut()))); - let mut buf = vec![0; len as usize]; - try!(cvt(ffi::i2d_ECPrivateKey(self.as_ptr(), &mut buf.as_mut_ptr()))); - Ok(buf) - } - } + private_key_to_der!(ffi::i2d_ECPrivateKey); } impl EcKey { @@ -31,6 +22,7 @@ impl EcKey { cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(EcKey) } } + /// Deserializes a DER-encoded private key. pub fn private_key_from_der(der: &[u8]) -> Result { unsafe { diff --git a/openssl/src/macros.rs b/openssl/src/macros.rs index 0be5ff17..7fa15d1f 100644 --- a/openssl/src/macros.rs +++ b/openssl/src/macros.rs @@ -135,3 +135,38 @@ macro_rules! private_key_to_pem { } } } + +macro_rules! to_der_inner { + (#[$m:meta] $n:ident, $f:path) => { + #[$m] + pub fn $n(&self) -> Result, ::error::ErrorStack> { + unsafe { + let len = try!(::cvt($f(::types::OpenSslTypeRef::as_ptr(self), ptr::null_mut()))); + let mut buf = vec![0; len as usize]; + try!(::cvt($f(::types::OpenSslTypeRef::as_ptr(self), &mut buf.as_mut_ptr()))); + Ok(buf) + } + } + }; +} + +macro_rules! to_der { + ($f:path) => { + to_der_inner!(/// Serializes this value to DER. + to_der, $f); + } +} + +macro_rules! private_key_to_der { + ($f:path) => { + to_der_inner!(/// Serializes the private key to DER. + private_key_to_der, $f); + } +} + +macro_rules! public_key_to_der { + ($f:path) => { + to_der_inner!(/// Serializes the public key to DER. + public_key_to_der, $f); + } +} diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index 079a04cc..05df2f4b 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -50,6 +50,9 @@ impl PKeyRef { private_key_to_pem!(ffi::PEM_write_bio_PKCS8PrivateKey); + private_key_to_der!(ffi::i2d_PrivateKey); + public_key_to_der!(ffi::i2d_PUBKEY); + /// Encodes the public key in the PEM format. pub fn public_key_to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); @@ -59,24 +62,6 @@ impl PKeyRef { Ok(mem_bio.get_buf().to_owned()) } - /// Encodes the public key in the DER format. - pub fn public_key_to_der(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { - try!(cvt(ffi::i2d_PUBKEY_bio(mem_bio.as_ptr(), self.as_ptr()))); - } - Ok(mem_bio.get_buf().to_owned()) - } - - /// Encodes the private key in the DER format - pub fn private_key_to_der(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { - try!(cvt(ffi::i2d_PrivateKey_bio(mem_bio.as_ptr(), self.as_ptr()))); - } - Ok(mem_bio.get_buf().to_owned()) - } - /// Returns the size of the key. /// /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index f2dd8d00..89c0bb85 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -36,25 +36,8 @@ impl RsaRef { Ok(mem_bio.get_buf().to_owned()) } - /// Encodes an RSA private key as unencrypted DER formatted data. - pub fn private_key_to_der(&self) -> Result, ErrorStack> { - unsafe { - let len = try!(cvt(ffi::i2d_RSAPrivateKey(self.as_ptr(), ptr::null_mut()))); - let mut buf = vec![0; len as usize]; - try!(cvt(ffi::i2d_RSAPrivateKey(self.as_ptr(), &mut buf.as_mut_ptr()))); - Ok(buf) - } - } - - /// Encodes an RSA public key as DER formatted data. - pub fn public_key_to_der(&self) -> Result, ErrorStack> { - unsafe { - let len = try!(cvt(ffi::i2d_RSA_PUBKEY(self.as_ptr(), ptr::null_mut()))); - let mut buf = vec![0; len as usize]; - try!(cvt(ffi::i2d_RSA_PUBKEY(self.as_ptr(), &mut buf.as_mut_ptr()))); - Ok(buf) - } - } + private_key_to_der!(ffi::i2d_RSAPrivateKey); + public_key_to_der!(ffi::i2d_RSA_PUBKEY); // FIXME should return u32 pub fn size(&self) -> usize { diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index e7c633d0..74f586c2 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -425,14 +425,7 @@ impl X509Ref { Ok(mem_bio.get_buf().to_owned()) } - /// Returns a DER serialized form of the certificate - pub fn to_der(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { - ffi::i2d_X509_bio(mem_bio.as_ptr(), self.as_ptr()); - } - Ok(mem_bio.get_buf().to_owned()) - } + to_der!(ffi::i2d_X509); } impl ToOwned for X509Ref { @@ -575,14 +568,7 @@ impl X509ReqRef { Ok(mem_bio.get_buf().to_owned()) } - /// Returns a DER serialized form of the CSR - pub fn to_der(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { - ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.as_ptr()); - } - Ok(mem_bio.get_buf().to_owned()) - } + to_der!(ffi::i2d_X509_REQ); } impl X509Req {