aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/x509
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2016-08-11 21:01:27 -0700
committerSteven Fackler <[email protected]>2016-08-11 21:01:27 -0700
commit652326003cefe215dbfc838051e6114515cc5190 (patch)
tree22dc99a726321cd8228004c34c40ca4a0648c594 /openssl/src/x509
parentMerge branch 'release-v0.7.14' into release (diff)
parentRelease openssl-sys v0.7.15, openssl v0.8.0 (diff)
downloadrust-openssl-openssl-v0.8.0.tar.xz
rust-openssl-openssl-v0.8.0.zip
Merge branch 'release-v0.7.15-sys-v0.8.0' into releaseopenssl-v0.8.0openssl-sys-v0.7.15
Diffstat (limited to 'openssl/src/x509')
-rw-r--r--openssl/src/x509/mod.rs370
-rw-r--r--openssl/src/x509/tests.rs79
2 files changed, 189 insertions, 260 deletions
diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs
index 3150cc6e..4cb4458a 100644
--- a/openssl/src/x509/mod.rs
+++ b/openssl/src/x509/mod.rs
@@ -1,9 +1,5 @@
-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 libc::{c_char, c_int, c_long, c_ulong, c_void};
use std::ffi::CString;
-use std::iter::repeat;
use std::mem;
use std::ptr;
use std::ops::Deref;
@@ -13,16 +9,16 @@ use std::slice;
use std::collections::HashMap;
use std::marker::PhantomData;
+use HashTypeInternals;
use asn1::Asn1Time;
-use bio::MemBio;
+use bio::{MemBio, MemBioSlice};
use crypto::hash;
use crypto::hash::Type as HashType;
-use crypto::pkey::{PKey, Parts};
+use crypto::pkey::PKey;
use crypto::rand::rand_bytes;
use ffi;
-use ffi_extras;
-use ssl::error::{SslError, StreamError};
use nid::Nid;
+use error::ErrorStack;
pub mod extension;
@@ -86,22 +82,20 @@ impl X509StoreContext {
X509StoreContext { ctx: ctx }
}
- pub fn get_error(&self) -> Option<X509ValidationError> {
+ pub fn error(&self) -> Option<X509ValidationError> {
let err = unsafe { ffi::X509_STORE_CTX_get_error(self.ctx) };
X509ValidationError::from_raw(err)
}
- pub fn get_current_cert<'a>(&'a self) -> Option<X509<'a>> {
- let ptr = unsafe { ffi::X509_STORE_CTX_get_current_cert(self.ctx) };
+ pub fn current_cert<'a>(&'a self) -> Option<X509Ref<'a>> {
+ unsafe {
+ let ptr = ffi::X509_STORE_CTX_get_current_cert(self.ctx);
- if ptr.is_null() {
- None
- } else {
- Some(X509 {
- ctx: Some(self),
- handle: ptr,
- owned: false,
- })
+ if ptr.is_null() {
+ None
+ } else {
+ Some(X509Ref::new(ptr))
+ }
}
}
@@ -116,39 +110,26 @@ 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::crypto::pkey::PKey;
+/// use openssl::crypto::rsa::RSA;
/// use openssl::x509::X509Generator;
/// use openssl::x509::extension::{Extension, KeyUsageOption};
///
+/// let rsa = RSA::generate(2048).unwrap();
+/// let pkey = PKey::from_rsa(rsa).unwrap();
+///
/// let gen = X509Generator::new()
-/// .set_bitlength(2048)
/// .set_valid_period(365*2)
/// .add_name("CN".to_owned(), "SuperMegaCorp Inc.".to_owned())
/// .set_sign_hash(Type::SHA256)
/// .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 = gen.sign(&pkey).unwrap();
+/// let cert_pem = cert.to_pem().unwrap();
+/// let pkey_pem = pkey.private_key_to_pem().unwrap();
/// ```
pub struct X509Generator {
- bits: u32,
days: u32,
names: Vec<(String, String)>,
extensions: Extensions,
@@ -158,8 +139,6 @@ pub struct X509Generator {
impl X509Generator {
/// Creates a new generator with the following defaults:
///
- /// bit length: 1024
- ///
/// validity period: 365 days
///
/// CN: "rust-openssl"
@@ -167,7 +146,6 @@ impl X509Generator {
/// hash: SHA1
pub fn new() -> X509Generator {
X509Generator {
- bits: 1024,
days: 365,
names: vec![],
extensions: Extensions::new(),
@@ -175,12 +153,6 @@ impl X509Generator {
}
}
- /// Sets desired bit length
- pub fn set_bitlength(mut self, bits: u32) -> X509Generator {
- self.bits = bits;
- self
- }
-
/// Sets certificate validity period in days since today
pub fn set_valid_period(mut self, days: u32) -> X509Generator {
self.days = days;
@@ -256,7 +228,7 @@ impl X509Generator {
fn add_extension_internal(x509: *mut ffi::X509,
exttype: &extension::ExtensionType,
value: &str)
- -> Result<(), SslError> {
+ -> Result<(), ErrorStack> {
unsafe {
let mut ctx: ffi::X509V3_CTX = mem::zeroed();
ffi::X509V3_set_ctx(&mut ctx, x509, x509, ptr::null_mut(), ptr::null_mut(), 0);
@@ -288,7 +260,7 @@ impl X509Generator {
fn add_name_internal(name: *mut ffi::X509_NAME,
key: &str,
value: &str)
- -> Result<(), SslError> {
+ -> Result<(), ErrorStack> {
let value_len = value.len() as c_int;
lift_ssl!(unsafe {
let key = CString::new(key.as_bytes()).unwrap();
@@ -303,9 +275,10 @@ impl X509Generator {
})
}
- fn random_serial() -> c_long {
+ fn random_serial() -> Result<c_long, ErrorStack> {
let len = mem::size_of::<c_long>();
- let bytes = rand_bytes(len);
+ let mut bytes = vec![0; len];
+ try!(rand_bytes(&mut bytes));
let mut res = 0;
for b in bytes.iter() {
res = res << 8;
@@ -315,54 +288,36 @@ impl X509Generator {
// While OpenSSL is actually OK to have negative serials
// other libraries (for example, Go crypto) can drop
// such certificates as invalid, so we clear the high bit
- ((res as c_ulong) >> 1) as c_long
- }
-
- /// Generates a private key and a self-signed certificate and returns them
- pub fn generate<'a>(&self) -> Result<(X509<'a>, PKey), SslError> {
- ffi::init();
-
- let mut p_key = PKey::new();
- p_key.gen(self.bits as usize);
-
- let x509 = try!(self.sign(&p_key));
- Ok((x509, p_key))
+ Ok(((res as c_ulong) >> 1) as c_long)
}
/// Sets the certificate public-key, then self-sign and return it
/// Note: That the bit-length of the private key is used (set_bitlength is ignored)
- pub fn sign<'a>(&self, p_key: &PKey) -> Result<X509<'a>, SslError> {
+ pub fn sign(&self, p_key: &PKey) -> Result<X509, ErrorStack> {
ffi::init();
unsafe {
- let x509 = ffi::X509_new();
- try_ssl_null!(x509);
+ let x509 = try_ssl_null!(ffi::X509_new());
+ let x509 = X509::new(x509);
- let x509 = X509 {
- handle: x509,
- ctx: None,
- owned: true,
- };
-
- try_ssl!(ffi::X509_set_version(x509.handle, 2));
- try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.handle),
- X509Generator::random_serial()));
+ try_ssl!(ffi::X509_set_version(x509.as_ptr(), 2));
+ try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.as_ptr()),
+ try!(X509Generator::random_serial())));
let not_before = try!(Asn1Time::days_from_now(0));
let not_after = try!(Asn1Time::days_from_now(self.days));
- try_ssl!(ffi::X509_set_notBefore(x509.handle, mem::transmute(not_before.get_handle())));
+ try_ssl!(ffi::X509_set_notBefore(x509.as_ptr(), not_before.as_ptr() as *const _));
// If prev line succeded - ownership should go to cert
mem::forget(not_before);
- try_ssl!(ffi::X509_set_notAfter(x509.handle, mem::transmute(not_after.get_handle())));
+ try_ssl!(ffi::X509_set_notAfter(x509.as_ptr(), not_after.as_ptr() as *const _));
// If prev line succeded - ownership should go to cert
mem::forget(not_after);
- try_ssl!(ffi::X509_set_pubkey(x509.handle, p_key.get_handle()));
+ try_ssl!(ffi::X509_set_pubkey(x509.as_ptr(), p_key.as_ptr()));
- let name = ffi::X509_get_subject_name(x509.handle);
- try_ssl_null!(name);
+ let name = try_ssl_null!(ffi::X509_get_subject_name(x509.as_ptr()));
let default = [("CN", "rust-openssl")];
let default_iter = &mut default.iter().map(|&(k, v)| (k, v));
@@ -376,105 +331,69 @@ impl X509Generator {
for (key, val) in iter {
try!(X509Generator::add_name_internal(name, &key, &val));
}
- ffi::X509_set_issuer_name(x509.handle, name);
+ try_ssl!(ffi::X509_set_issuer_name(x509.as_ptr(), name));
for (exttype, ext) in self.extensions.iter() {
- try!(X509Generator::add_extension_internal(x509.handle,
+ try!(X509Generator::add_extension_internal(x509.as_ptr(),
&exttype,
&ext.to_string()));
}
let hash_fn = self.hash_type.evp_md();
- try_ssl!(ffi::X509_sign(x509.handle, p_key.get_handle(), hash_fn));
+ try_ssl!(ffi::X509_sign(x509.as_ptr(), p_key.as_ptr(), hash_fn));
Ok(x509)
}
}
/// Obtain a certificate signing request (CSR)
- pub fn request(&self, p_key: &PKey) -> Result<X509Req, SslError> {
+ ///
+ /// Requries the `x509_generator_request` feature.
+ #[cfg(feature = "x509_generator_request")]
+ pub fn request(&self, p_key: &PKey) -> Result<X509Req, ErrorStack> {
let cert = match self.sign(p_key) {
Ok(c) => c,
Err(x) => return Err(x),
};
unsafe {
- let req = ffi::X509_to_X509_REQ(cert.handle, ptr::null_mut(), ptr::null());
+ let req = ffi::X509_to_X509_REQ(cert.as_ptr(), ptr::null_mut(), ptr::null());
try_ssl_null!(req);
- let exts = ffi_extras::X509_get_extensions(cert.handle);
+ let exts = ::c_helpers::rust_X509_get_extensions(cert.as_ptr());
if exts != ptr::null_mut() {
try_ssl!(ffi::X509_REQ_add_extensions(req, exts));
}
let hash_fn = self.hash_type.evp_md();
- try_ssl!(ffi::X509_REQ_sign(req, p_key.get_handle(), hash_fn));
+ try_ssl!(ffi::X509_REQ_sign(req, p_key.as_ptr(), hash_fn));
Ok(X509Req::new(req))
}
}
}
+/// A borrowed public key certificate.
+pub struct X509Ref<'a>(*mut ffi::X509, PhantomData<&'a ()>);
-#[allow(dead_code)]
-/// A public key certificate
-pub struct X509<'ctx> {
- ctx: Option<&'ctx X509StoreContext>,
- handle: *mut ffi::X509,
- owned: bool,
-}
-
-impl<'ctx> X509<'ctx> {
- /// Creates new from handle with desired ownership.
- pub fn new(handle: *mut ffi::X509, owned: bool) -> X509<'ctx> {
- X509 {
- ctx: None,
- handle: handle,
- owned: owned,
- }
- }
-
- /// Creates a new certificate from context. Doesn't take ownership
- /// of handle.
- pub fn new_in_ctx(handle: *mut ffi::X509, ctx: &'ctx X509StoreContext) -> X509<'ctx> {
- X509 {
- ctx: Some(ctx),
- handle: handle,
- owned: false,
- }
+impl<'a> X509Ref<'a> {
+ /// Creates a new `X509Ref` wrapping the provided handle.
+ pub unsafe fn new(handle: *mut ffi::X509) -> X509Ref<'a> {
+ X509Ref(handle, PhantomData)
}
- /// Reads certificate from PEM, takes ownership of handle
- pub fn from_pem<R>(reader: &mut R) -> Result<X509<'ctx>, SslError>
- where R: Read
- {
- let mut mem_bio = try!(MemBio::new());
- try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
-
- unsafe {
- let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(),
- ptr::null_mut(),
- None,
- ptr::null_mut()));
- Ok(X509::new(handle, true))
- }
- }
-
- pub fn get_handle(&self) -> *mut ffi::X509 {
- self.handle
+ pub fn as_ptr(&self) -> *mut ffi::X509 {
+ self.0
}
- pub fn subject_name<'a>(&'a self) -> X509Name<'a> {
- let name = unsafe { ffi::X509_get_subject_name(self.handle) };
- X509Name {
- x509: self,
- name: name,
- }
+ pub fn subject_name<'b>(&'b self) -> X509Name<'b> {
+ let name = unsafe { ffi::X509_get_subject_name(self.0) };
+ X509Name(name, PhantomData)
}
/// Returns this certificate's SAN entries, if they exist.
- pub fn subject_alt_names<'a>(&'a self) -> Option<GeneralNames<'a>> {
+ pub fn subject_alt_names<'b>(&'b self) -> Option<GeneralNames<'b>> {
unsafe {
- let stack = ffi::X509_get_ext_d2i(self.handle,
+ let stack = ffi::X509_get_ext_d2i(self.0,
Nid::SubjectAltName as c_int,
ptr::null_mut(),
ptr::null_mut());
@@ -489,94 +408,102 @@ impl<'ctx> X509<'ctx> {
}
}
- pub fn public_key(&self) -> PKey {
- let pkey = unsafe { ffi::X509_get_pubkey(self.handle) };
- assert!(!pkey.is_null());
-
- PKey::from_handle(pkey, Parts::Public)
+ pub fn public_key(&self) -> Result<PKey, ErrorStack> {
+ unsafe {
+ let pkey = try_ssl_null!(ffi::X509_get_pubkey(self.0));
+ Ok(PKey::from_ptr(pkey))
+ }
}
/// Returns certificate fingerprint calculated using provided hash
- pub fn fingerprint(&self, hash_type: hash::Type) -> Option<Vec<u8>> {
- let evp = hash_type.evp_md();
- let len = hash_type.md_len();
- let v: Vec<u8> = repeat(0).take(len as usize).collect();
- let act_len: c_uint = 0;
- let res = unsafe {
- ffi::X509_digest(self.handle,
- evp,
- mem::transmute(v.as_ptr()),
- mem::transmute(&act_len))
- };
-
- match res {
- 0 => None,
- _ => {
- let act_len = act_len as usize;
- match len.cmp(&act_len) {
- Ordering::Greater => None,
- Ordering::Equal => Some(v),
- Ordering::Less => panic!("Fingerprint buffer was corrupted!"),
- }
- }
+ pub fn fingerprint(&self, hash_type: hash::Type) -> Result<Vec<u8>, ErrorStack> {
+ unsafe {
+ let evp = hash_type.evp_md();
+ let mut len = ffi::EVP_MAX_MD_SIZE;
+ let mut buf = vec![0u8; len as usize];
+ try_ssl!(ffi::X509_digest(self.0, evp, buf.as_mut_ptr() as *mut _, &mut len));
+ buf.truncate(len as usize);
+ Ok(buf)
}
}
/// Writes certificate as PEM
- pub fn write_pem<W>(&self, writer: &mut W) -> Result<(), SslError>
- where W: Write
- {
- let mut mem_bio = try!(MemBio::new());
+ pub fn to_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));
+ try_ssl!(ffi::PEM_write_bio_X509(mem_bio.as_ptr(), self.0));
}
- io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ())
+ Ok(mem_bio.get_buf().to_owned())
+ }
+
+ /// Returns a DER serialized form of the certificate
+ pub fn to_der(&self) -> Result<Vec<u8>, ErrorStack> {
+ let mem_bio = try!(MemBio::new());
+ unsafe {
+ ffi::i2d_X509_bio(mem_bio.as_ptr(), self.0);
+ }
+ Ok(mem_bio.get_buf().to_owned())
}
}
-extern "C" {
- fn rust_X509_clone(x509: *mut ffi::X509);
+/// An owned public key certificate.
+pub struct X509(X509Ref<'static>);
+
+impl X509 {
+ /// Returns a new `X509`, taking ownership of the handle.
+ pub unsafe fn new(x509: *mut ffi::X509) -> X509 {
+ X509(X509Ref::new(x509))
+ }
+
+ /// Reads a certificate from PEM.
+ pub fn from_pem(buf: &[u8]) -> Result<X509, ErrorStack> {
+ let mem_bio = try!(MemBioSlice::new(buf));
+ unsafe {
+ let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.as_ptr(),
+ ptr::null_mut(),
+ None,
+ ptr::null_mut()));
+ Ok(X509::new(handle))
+ }
+ }
}
-impl<'ctx> Clone for X509<'ctx> {
- fn clone(&self) -> X509<'ctx> {
- unsafe { rust_X509_clone(self.handle) }
- // FIXME: given that we now have refcounting control, 'owned' should be uneeded, the 'ctx
- // is probably also uneeded. We can remove both to condense the x509 api quite a bit
- //
- X509::new(self.handle, true)
+impl Deref for X509 {
+ type Target = X509Ref<'static>;
+
+ fn deref(&self) -> &X509Ref<'static> {
+ &self.0
}
}
-impl<'ctx> Drop for X509<'ctx> {
- fn drop(&mut self) {
- if self.owned {
- unsafe { ffi::X509_free(self.handle) };
+#[cfg(feature = "x509_clone")]
+impl Clone for X509 {
+ /// Requires the `x509_clone` feature.
+ fn clone(&self) -> X509 {
+ unsafe {
+ ::c_helpers::rust_X509_clone(self.as_ptr());
+ X509::new(self.as_ptr())
}
}
}
-#[allow(dead_code)]
-pub struct X509Name<'x> {
- x509: &'x X509<'x>,
- name: *mut ffi::X509_NAME,
+impl Drop for X509 {
+ fn drop(&mut self) {
+ unsafe { ffi::X509_free(self.as_ptr()) };
+ }
}
-#[allow(dead_code)]
-pub struct X509NameEntry<'x> {
- x509_name: &'x X509Name<'x>,
- ne: *mut ffi::X509_NAME_ENTRY,
-}
+pub struct X509Name<'x>(*mut ffi::X509_NAME, PhantomData<&'x ()>);
impl<'x> X509Name<'x> {
pub fn text_by_nid(&self, nid: Nid) -> Option<SslString> {
unsafe {
- let loc = ffi::X509_NAME_get_index_by_NID(self.name, nid as c_int, -1);
+ let loc = ffi::X509_NAME_get_index_by_NID(self.0, nid as c_int, -1);
if loc == -1 {
return None;
}
- let ne = ffi::X509_NAME_get_entry(self.name, loc);
+ let ne = ffi::X509_NAME_get_entry(self.0, loc);
if ne.is_null() {
return None;
}
@@ -601,25 +528,23 @@ impl<'x> X509Name<'x> {
}
/// A certificate signing request
-pub struct X509Req {
- handle: *mut ffi::X509_REQ,
-}
+pub struct X509Req(*mut ffi::X509_REQ);
impl X509Req {
/// Creates new from handle
- pub fn new(handle: *mut ffi::X509_REQ) -> X509Req {
- X509Req { handle: handle }
+ pub unsafe fn new(handle: *mut ffi::X509_REQ) -> X509Req {
+ X509Req(handle)
}
- /// Reads CSR from PEM
- pub fn from_pem<R>(reader: &mut R) -> Result<X509Req, SslError>
- where R: Read
- {
- let mut mem_bio = try!(MemBio::new());
- try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
+ pub fn as_ptr(&self) -> *mut ffi::X509_REQ {
+ self.0
+ }
+ /// Reads CSR from PEM
+ 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(),
+ let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.as_ptr(),
ptr::null_mut(),
None,
ptr::null_mut()));
@@ -628,20 +553,27 @@ impl X509Req {
}
/// Writes CSR as PEM
- pub fn write_pem<W>(&self, writer: &mut W) -> Result<(), SslError>
- where W: Write
- {
- let mut mem_bio = try!(MemBio::new());
+ pub fn to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
+ let mem_bio = try!(MemBio::new());
+ if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.as_ptr(), self.0) } != 1 {
+ return Err(ErrorStack::get());
+ }
+ Ok(mem_bio.get_buf().to_owned())
+ }
+
+ /// Returns a DER serialized form of the CSR
+ pub fn to_der(&self) -> Result<Vec<u8>, ErrorStack> {
+ let mem_bio = try!(MemBio::new());
unsafe {
- try_ssl!(ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle));
+ ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.0);
}
- io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ())
+ Ok(mem_bio.get_buf().to_owned())
}
}
impl Drop for X509Req {
fn drop(&mut self) {
- unsafe { ffi::X509_REQ_free(self.handle) };
+ unsafe { ffi::X509_REQ_free(self.0) };
}
}
@@ -908,7 +840,7 @@ impl<'a> GeneralName<'a> {
fn test_negative_serial() {
// I guess that's enough to get a random negative number
for _ in 0..1000 {
- assert!(X509Generator::random_serial() > 0,
+ assert!(X509Generator::random_serial().unwrap() > 0,
"All serials should be positive");
}
}
diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs
index f547a982..c09b31cd 100644
--- a/openssl/src/x509/tests.rs
+++ b/openssl/src/x509/tests.rs
@@ -1,10 +1,8 @@
use serialize::hex::FromHex;
-use std::io;
-use std::path::Path;
-use std::fs::File;
use crypto::hash::Type::SHA1;
use crypto::pkey::PKey;
+use crypto::rsa::RSA;
use x509::{X509, X509Generator};
use x509::extension::Extension::{KeyUsage, ExtKeyUsage, SubjectAltName, OtherNid, OtherStr};
use x509::extension::AltNameOption as SAN;
@@ -14,7 +12,6 @@ use nid::Nid;
fn get_generator() -> X509Generator {
X509Generator::new()
- .set_bitlength(2048)
.set_valid_period(365 * 2)
.add_name("CN".to_string(), "test_me".to_string())
.set_sign_hash(SHA1)
@@ -27,16 +24,21 @@ fn get_generator() -> X509Generator {
.add_extension(OtherStr("2.999.2".to_owned(), "ASN1:UTF8:example value".to_owned()))
}
+fn pkey() -> PKey {
+ let rsa = RSA::generate(2048).unwrap();
+ PKey::from_rsa(rsa).unwrap()
+}
+
#[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();
+ let pkey = pkey();
+ let cert = get_generator().sign(&pkey).unwrap();
// FIXME: check data in result to be correct, needs implementation
// of X509 getters
- assert_eq!(pkey.save_pub(), cert.public_key().save_pub());
+ assert_eq!(pkey.public_key_to_pem().unwrap(),
+ cert.public_key().unwrap().public_key_to_pem().unwrap());
}
/// SubjectKeyIdentifier must be added before AuthorityKeyIdentifier or OpenSSL
@@ -44,10 +46,11 @@ fn test_cert_gen() {
/// for extensions is preserved when the cert is signed.
#[test]
fn test_cert_gen_extension_ordering() {
+ let pkey = pkey();
get_generator()
.add_extension(OtherNid(Nid::SubjectKeyIdentifier, "hash".to_owned()))
.add_extension(OtherNid(Nid::AuthorityKeyIdentifier, "keyid:always".to_owned()))
- .generate()
+ .sign(&pkey)
.expect("Failed to generate cert with order-dependent extensions");
}
@@ -55,22 +58,23 @@ fn test_cert_gen_extension_ordering() {
/// deterministic by reversing the order of extensions and asserting failure.
#[test]
fn test_cert_gen_extension_bad_ordering() {
+ let pkey = pkey();
let result = get_generator()
.add_extension(OtherNid(Nid::AuthorityKeyIdentifier,
"keyid:always".to_owned()))
.add_extension(OtherNid(Nid::SubjectKeyIdentifier, "hash".to_owned()))
- .generate();
+ .sign(&pkey);
assert!(result.is_err());
}
#[test]
+#[cfg(feature = "x509_generator_request")]
fn test_req_gen() {
- let mut pkey = PKey::new();
- pkey.gen(512);
+ let pkey = pkey();
let req = get_generator().request(&pkey).unwrap();
- req.write_pem(&mut io::sink()).unwrap();
+ req.to_pem().unwrap();
// FIXME: check data in result to be correct, needs implementation
// of X509_REQ getters
@@ -78,12 +82,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";
@@ -93,13 +93,18 @@ fn test_cert_loading() {
}
#[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`");
+fn test_save_der() {
+ let cert = include_bytes!("../../test/cert.pem");
+ let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
+
+ let der = cert.to_der().unwrap();
+ assert!(!der.is_empty());
+}
- let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
+#[test]
+fn test_subject_read_cn() {
+ 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,
@@ -111,12 +116,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) {
@@ -140,12 +141,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) {
@@ -157,8 +154,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());
@@ -171,8 +168,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();