Implement "extensions" field in X509generator, and change existing extensions to use that
This commit is contained in:
parent
d5a4d48cab
commit
8d1abf5156
|
|
@ -1,5 +1,5 @@
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
#[repr(usize)]
|
#[repr(usize)]
|
||||||
pub enum Nid {
|
pub enum Nid {
|
||||||
Undefined,
|
Undefined,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,11 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use nid::Nid;
|
||||||
|
|
||||||
|
#[derive(Clone,Copy,Hash,PartialEq,Eq)]
|
||||||
|
pub enum ExtensionType {
|
||||||
|
KeyUsage,
|
||||||
|
ExtKeyUsage,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Extension {
|
pub enum Extension {
|
||||||
|
|
@ -6,6 +13,41 @@ pub enum Extension {
|
||||||
ExtKeyUsage(Vec<ExtKeyUsageOption>),
|
ExtKeyUsage(Vec<ExtKeyUsageOption>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Extension {
|
||||||
|
pub fn get_type(&self) -> ExtensionType {
|
||||||
|
match self {
|
||||||
|
&Extension::KeyUsage(_) => ExtensionType::KeyUsage,
|
||||||
|
&Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_nid(&self) -> Nid {
|
||||||
|
match self {
|
||||||
|
&Extension::KeyUsage(_) => Nid::KeyUsage,
|
||||||
|
&Extension::ExtKeyUsage(_) => Nid::ExtendedKeyUsage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This would be nicer as a method on Iterator<Item=ToString>. This can
|
||||||
|
// eventually be replaced by the successor to std::slice::SliceConcatExt.connect
|
||||||
|
fn join<I: Iterator<Item=T>,T: ToString>(iter: I, sep: &str) -> String {
|
||||||
|
iter.enumerate().fold(String::new(), |mut acc, (idx, v)| {
|
||||||
|
if idx > 0 { acc.push_str(sep) };
|
||||||
|
acc.push_str(&v.to_string());
|
||||||
|
acc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for Extension {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
&Extension::KeyUsage(ref purposes) => join(purposes.iter(),","),
|
||||||
|
&Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone,Copy)]
|
#[derive(Clone,Copy)]
|
||||||
pub enum KeyUsageOption {
|
pub enum KeyUsageOption {
|
||||||
DigitalSignature,
|
DigitalSignature,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use std::ptr;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use asn1::{Asn1Time};
|
use asn1::{Asn1Time};
|
||||||
use bio::{MemBio};
|
use bio::{MemBio};
|
||||||
|
|
@ -22,6 +23,8 @@ use nid;
|
||||||
|
|
||||||
mod extension;
|
mod extension;
|
||||||
|
|
||||||
|
use self::extension::{ExtensionType,Extension};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
|
@ -103,16 +106,6 @@ impl X509StoreContext {
|
||||||
pub use self::extension::KeyUsageOption as KeyUsage;
|
pub use self::extension::KeyUsageOption as KeyUsage;
|
||||||
pub use self::extension::ExtKeyUsageOption as ExtKeyUsage;
|
pub use self::extension::ExtKeyUsageOption as ExtKeyUsage;
|
||||||
|
|
||||||
// FIXME: This would be nicer as a method on Iterator<Item=ToString>. This can
|
|
||||||
// eventually be replaced by the successor to std::slice::SliceConcatExt.connect
|
|
||||||
fn join<I: Iterator<Item=T>,T: ToString>(iter: I, sep: &str) -> String {
|
|
||||||
iter.enumerate().fold(String::new(), |mut acc, (idx, v)| {
|
|
||||||
if idx > 0 { acc.push_str(sep) };
|
|
||||||
acc.push_str(&v.to_string());
|
|
||||||
acc
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
/// Generator of private key/certificate pairs
|
/// Generator of private key/certificate pairs
|
||||||
///
|
///
|
||||||
|
|
@ -153,8 +146,8 @@ pub struct X509Generator {
|
||||||
bits: u32,
|
bits: u32,
|
||||||
days: u32,
|
days: u32,
|
||||||
CN: String,
|
CN: String,
|
||||||
key_usage: Vec<KeyUsage>,
|
// RFC 3280 §4.2: A certificate MUST NOT include more than one instance of a particular extension.
|
||||||
ext_key_usage: Vec<ExtKeyUsage>,
|
extensions: HashMap<ExtensionType,Extension>,
|
||||||
hash_type: HashType,
|
hash_type: HashType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,8 +166,7 @@ impl X509Generator {
|
||||||
bits: 1024,
|
bits: 1024,
|
||||||
days: 365,
|
days: 365,
|
||||||
CN: "rust-openssl".to_string(),
|
CN: "rust-openssl".to_string(),
|
||||||
key_usage: Vec::new(),
|
extensions: HashMap::new(),
|
||||||
ext_key_usage: Vec::new(),
|
|
||||||
hash_type: HashType::SHA1
|
hash_type: HashType::SHA1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -200,13 +192,13 @@ impl X509Generator {
|
||||||
|
|
||||||
/// Sets what for certificate could be used
|
/// Sets what for certificate could be used
|
||||||
pub fn set_usage(mut self, purposes: &[KeyUsage]) -> X509Generator {
|
pub fn set_usage(mut self, purposes: &[KeyUsage]) -> X509Generator {
|
||||||
self.key_usage = purposes.to_vec();
|
self.extensions.insert(ExtensionType::KeyUsage,Extension::KeyUsage(purposes.to_owned()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets allowed extended usage of certificate
|
/// Sets allowed extended usage of certificate
|
||||||
pub fn set_ext_usage(mut self, purposes: &[ExtKeyUsage]) -> X509Generator {
|
pub fn set_ext_usage(mut self, purposes: &[ExtKeyUsage]) -> X509Generator {
|
||||||
self.ext_key_usage = purposes.to_vec();
|
self.extensions.insert(ExtensionType::ExtKeyUsage,Extension::ExtKeyUsage(purposes.to_owned()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,14 +296,8 @@ impl X509Generator {
|
||||||
try!(X509Generator::add_name(name, "CN", &self.CN));
|
try!(X509Generator::add_name(name, "CN", &self.CN));
|
||||||
ffi::X509_set_issuer_name(x509.handle, name);
|
ffi::X509_set_issuer_name(x509.handle, name);
|
||||||
|
|
||||||
if self.key_usage.len() > 0 {
|
for ext in self.extensions.values() {
|
||||||
try!(X509Generator::add_extension(x509.handle, ffi::NID_key_usage,
|
try!(X509Generator::add_extension(x509.handle, ext.get_nid() as c_int, &ext.to_string()));
|
||||||
&join(self.key_usage.iter(),",")));
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.ext_key_usage.len() > 0 {
|
|
||||||
try!(X509Generator::add_extension(x509.handle, ffi::NID_ext_key_usage,
|
|
||||||
&join(self.ext_key_usage.iter(),",")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let hash_fn = self.hash_type.evp_md();
|
let hash_fn = self.hash_type.evp_md();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue