Start on an X509Builder
This commit is contained in:
parent
1edb6f682e
commit
b83edbad0d
|
|
@ -1259,6 +1259,7 @@ extern {
|
||||||
pub fn ASN1_STRING_type_new(ty: c_int) -> *mut ASN1_STRING;
|
pub fn ASN1_STRING_type_new(ty: c_int) -> *mut ASN1_STRING;
|
||||||
pub fn ASN1_TIME_free(tm: *mut ASN1_TIME);
|
pub fn ASN1_TIME_free(tm: *mut ASN1_TIME);
|
||||||
pub fn ASN1_TIME_print(b: *mut BIO, tm: *const ASN1_TIME) -> c_int;
|
pub fn ASN1_TIME_print(b: *mut BIO, tm: *const ASN1_TIME) -> c_int;
|
||||||
|
pub fn ASN1_INTEGER_free(x: *mut ASN1_INTEGER);
|
||||||
|
|
||||||
pub fn BIO_ctrl(b: *mut BIO, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long;
|
pub fn BIO_ctrl(b: *mut BIO, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long;
|
||||||
pub fn BIO_free_all(b: *mut BIO);
|
pub fn BIO_free_all(b: *mut BIO);
|
||||||
|
|
@ -1273,20 +1274,17 @@ extern {
|
||||||
pub fn BIO_set_flags(b: *mut BIO, flags: c_int);
|
pub fn BIO_set_flags(b: *mut BIO, flags: c_int);
|
||||||
pub fn BIO_clear_flags(b: *mut BIO, flags: c_int);
|
pub fn BIO_clear_flags(b: *mut BIO, flags: c_int);
|
||||||
|
|
||||||
|
pub fn BN_CTX_new() -> *mut BN_CTX;
|
||||||
|
pub fn BN_CTX_free(ctx: *mut BN_CTX);
|
||||||
|
|
||||||
pub fn BN_new() -> *mut BIGNUM;
|
pub fn BN_new() -> *mut BIGNUM;
|
||||||
pub fn BN_dup(n: *const BIGNUM) -> *mut BIGNUM;
|
pub fn BN_dup(n: *const BIGNUM) -> *mut BIGNUM;
|
||||||
pub fn BN_clear(bn: *mut BIGNUM);
|
pub fn BN_clear(bn: *mut BIGNUM);
|
||||||
pub fn BN_free(bn: *mut BIGNUM);
|
pub fn BN_free(bn: *mut BIGNUM);
|
||||||
pub fn BN_clear_free(bn: *mut BIGNUM);
|
pub fn BN_clear_free(bn: *mut BIGNUM);
|
||||||
|
|
||||||
pub fn BN_CTX_new() -> *mut BN_CTX;
|
|
||||||
pub fn BN_CTX_free(ctx: *mut BN_CTX);
|
|
||||||
|
|
||||||
pub fn BN_num_bits(bn: *const BIGNUM) -> c_int;
|
pub fn BN_num_bits(bn: *const BIGNUM) -> c_int;
|
||||||
pub fn BN_set_negative(bn: *mut BIGNUM, n: c_int);
|
pub fn BN_set_negative(bn: *mut BIGNUM, n: c_int);
|
||||||
pub fn BN_set_word(bn: *mut BIGNUM, n: BN_ULONG) -> c_int;
|
pub fn BN_set_word(bn: *mut BIGNUM, n: BN_ULONG) -> c_int;
|
||||||
|
|
||||||
/* Arithmetic operations on BIGNUMs */
|
|
||||||
pub fn BN_add(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
pub fn BN_add(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
||||||
pub fn BN_div(dv: *mut BIGNUM, rem: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM, ctx: *mut BN_CTX) -> c_int;
|
pub fn BN_div(dv: *mut BIGNUM, rem: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM, ctx: *mut BN_CTX) -> c_int;
|
||||||
pub fn BN_exp(r: *mut BIGNUM, a: *const BIGNUM, p: *const BIGNUM, ctx: *mut BN_CTX) -> c_int;
|
pub fn BN_exp(r: *mut BIGNUM, a: *const BIGNUM, p: *const BIGNUM, ctx: *mut BN_CTX) -> c_int;
|
||||||
|
|
@ -1306,8 +1304,6 @@ extern {
|
||||||
pub fn BN_mod_word(r: *const BIGNUM, w: BN_ULONG) -> BN_ULONG;
|
pub fn BN_mod_word(r: *const BIGNUM, w: BN_ULONG) -> BN_ULONG;
|
||||||
pub fn BN_sqr(r: *mut BIGNUM, a: *const BIGNUM, ctx: *mut BN_CTX) -> c_int;
|
pub fn BN_sqr(r: *mut BIGNUM, a: *const BIGNUM, ctx: *mut BN_CTX) -> c_int;
|
||||||
pub fn BN_sub(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
pub fn BN_sub(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
||||||
|
|
||||||
/* Bit operations on BIGNUMs */
|
|
||||||
pub fn BN_clear_bit(a: *mut BIGNUM, n: c_int) -> c_int;
|
pub fn BN_clear_bit(a: *mut BIGNUM, n: c_int) -> c_int;
|
||||||
pub fn BN_is_bit_set(a: *const BIGNUM, n: c_int) -> c_int;
|
pub fn BN_is_bit_set(a: *const BIGNUM, n: c_int) -> c_int;
|
||||||
pub fn BN_lshift(r: *mut BIGNUM, a: *const BIGNUM, n: c_int) -> c_int;
|
pub fn BN_lshift(r: *mut BIGNUM, a: *const BIGNUM, n: c_int) -> c_int;
|
||||||
|
|
@ -1316,33 +1312,22 @@ extern {
|
||||||
pub fn BN_rshift(r: *mut BIGNUM, a: *const BIGNUM, n: c_int) -> c_int;
|
pub fn BN_rshift(r: *mut BIGNUM, a: *const BIGNUM, n: c_int) -> c_int;
|
||||||
pub fn BN_set_bit(a: *mut BIGNUM, n: c_int) -> c_int;
|
pub fn BN_set_bit(a: *mut BIGNUM, n: c_int) -> c_int;
|
||||||
pub fn BN_rshift1(r: *mut BIGNUM, a: *const BIGNUM) -> c_int;
|
pub fn BN_rshift1(r: *mut BIGNUM, a: *const BIGNUM) -> c_int;
|
||||||
|
|
||||||
/* Comparisons on BIGNUMs */
|
|
||||||
pub fn BN_cmp(a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
pub fn BN_cmp(a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
||||||
pub fn BN_ucmp(a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
pub fn BN_ucmp(a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
||||||
|
|
||||||
/* Prime handling */
|
|
||||||
pub fn BN_generate_prime_ex(r: *mut BIGNUM, bits: c_int, safe: c_int, add: *const BIGNUM, rem: *const BIGNUM, cb: *mut BN_GENCB) -> c_int;
|
pub fn BN_generate_prime_ex(r: *mut BIGNUM, bits: c_int, safe: c_int, add: *const BIGNUM, rem: *const BIGNUM, cb: *mut BN_GENCB) -> c_int;
|
||||||
pub fn BN_is_prime_ex(p: *const BIGNUM, checks: c_int, ctx: *mut BN_CTX, cb: *mut BN_GENCB) -> c_int;
|
pub fn BN_is_prime_ex(p: *const BIGNUM, checks: c_int, ctx: *mut BN_CTX, cb: *mut BN_GENCB) -> c_int;
|
||||||
pub fn BN_is_prime_fasttest_ex(p: *const BIGNUM, checks: c_int, ctx: *mut BN_CTX, do_trial_division: c_int, cb: *mut BN_GENCB) -> c_int;
|
pub fn BN_is_prime_fasttest_ex(p: *const BIGNUM, checks: c_int, ctx: *mut BN_CTX, do_trial_division: c_int, cb: *mut BN_GENCB) -> c_int;
|
||||||
|
|
||||||
/* Random number handling */
|
|
||||||
pub fn BN_rand(r: *mut BIGNUM, bits: c_int, top: c_int, bottom: c_int) -> c_int;
|
pub fn BN_rand(r: *mut BIGNUM, bits: c_int, top: c_int, bottom: c_int) -> c_int;
|
||||||
pub fn BN_pseudo_rand(r: *mut BIGNUM, bits: c_int, top: c_int, bottom: c_int) -> c_int;
|
pub fn BN_pseudo_rand(r: *mut BIGNUM, bits: c_int, top: c_int, bottom: c_int) -> c_int;
|
||||||
pub fn BN_rand_range(r: *mut BIGNUM, range: *const BIGNUM) -> c_int;
|
pub fn BN_rand_range(r: *mut BIGNUM, range: *const BIGNUM) -> c_int;
|
||||||
pub fn BN_pseudo_rand_range(r: *mut BIGNUM, range: *const BIGNUM) -> c_int;
|
pub fn BN_pseudo_rand_range(r: *mut BIGNUM, range: *const BIGNUM) -> c_int;
|
||||||
|
|
||||||
/* Conversion from/to binary representation */
|
|
||||||
pub fn BN_bin2bn(s: *const u8, size: c_int, ret: *mut BIGNUM) -> *mut BIGNUM;
|
pub fn BN_bin2bn(s: *const u8, size: c_int, ret: *mut BIGNUM) -> *mut BIGNUM;
|
||||||
pub fn BN_bn2bin(a: *const BIGNUM, to: *mut u8) -> c_int;
|
pub fn BN_bn2bin(a: *const BIGNUM, to: *mut u8) -> c_int;
|
||||||
|
|
||||||
/* Conversion from/to decimal string representation */
|
|
||||||
pub fn BN_dec2bn(a: *mut *mut BIGNUM, s: *const c_char) -> c_int;
|
pub fn BN_dec2bn(a: *mut *mut BIGNUM, s: *const c_char) -> c_int;
|
||||||
pub fn BN_bn2dec(a: *const BIGNUM) -> *mut c_char;
|
pub fn BN_bn2dec(a: *const BIGNUM) -> *mut c_char;
|
||||||
|
|
||||||
/* Conversion from/to hexidecimal string representation */
|
|
||||||
pub fn BN_hex2bn(a: *mut *mut BIGNUM, s: *const c_char) -> c_int;
|
pub fn BN_hex2bn(a: *mut *mut BIGNUM, s: *const c_char) -> c_int;
|
||||||
pub fn BN_bn2hex(a: *const BIGNUM) -> *mut c_char;
|
pub fn BN_bn2hex(a: *const BIGNUM) -> *mut c_char;
|
||||||
|
pub fn BN_to_ASN1_INTEGER(bn: *const BIGNUM, ai: *mut ASN1_INTEGER) -> *mut ASN1_INTEGER;
|
||||||
|
|
||||||
pub fn CRYPTO_memcmp(a: *const c_void, b: *const c_void,
|
pub fn CRYPTO_memcmp(a: *const c_void, b: *const c_void,
|
||||||
len: size_t) -> c_int;
|
len: size_t) -> c_int;
|
||||||
|
|
@ -1665,6 +1650,8 @@ extern {
|
||||||
pub fn X509_gmtime_adj(time: *mut ASN1_TIME, adj: c_long) -> *mut ASN1_TIME;
|
pub fn X509_gmtime_adj(time: *mut ASN1_TIME, adj: c_long) -> *mut ASN1_TIME;
|
||||||
pub fn X509_new() -> *mut X509;
|
pub fn X509_new() -> *mut X509;
|
||||||
pub fn X509_set_issuer_name(x: *mut X509, name: *mut X509_NAME) -> c_int;
|
pub fn X509_set_issuer_name(x: *mut X509, name: *mut X509_NAME) -> c_int;
|
||||||
|
pub fn X509_set_subject_name(x: *mut X509, name: *mut X509_NAME) -> c_int;
|
||||||
|
pub fn X509_set_serialNumber(x: *mut X509, sn: *mut ASN1_INTEGER) -> c_int;
|
||||||
pub fn X509_set_version(x: *mut X509, version: c_long) -> c_int;
|
pub fn X509_set_version(x: *mut X509, version: c_long) -> c_int;
|
||||||
pub fn X509_set_pubkey(x: *mut X509, pkey: *mut EVP_PKEY) -> c_int;
|
pub fn X509_set_pubkey(x: *mut X509, pkey: *mut EVP_PKEY) -> c_int;
|
||||||
pub fn X509_sign(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int;
|
pub fn X509_sign(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int;
|
||||||
|
|
@ -1674,6 +1661,7 @@ extern {
|
||||||
|
|
||||||
pub fn X509_EXTENSION_free(ext: *mut X509_EXTENSION);
|
pub fn X509_EXTENSION_free(ext: *mut X509_EXTENSION);
|
||||||
|
|
||||||
|
pub fn X509_NAME_new() -> *mut X509_NAME;
|
||||||
pub fn X509_NAME_free(x: *mut X509_NAME);
|
pub fn X509_NAME_free(x: *mut X509_NAME);
|
||||||
pub fn X509_NAME_add_entry_by_txt(x: *mut X509_NAME, field: *const c_char, ty: c_int, bytes: *const c_uchar, len: c_int, loc: c_int, set: c_int) -> c_int;
|
pub fn X509_NAME_add_entry_by_txt(x: *mut X509_NAME, field: *const c_char, ty: c_int, bytes: *const c_uchar, len: c_int, loc: c_int, set: c_int) -> c_int;
|
||||||
pub fn X509_NAME_get_index_by_NID(n: *mut X509_NAME, nid: c_int, last_pos: c_int) -> c_int;
|
pub fn X509_NAME_get_index_by_NID(n: *mut X509_NAME, nid: c_int, last_pos: c_int) -> c_int;
|
||||||
|
|
|
||||||
|
|
@ -586,6 +586,7 @@ extern {
|
||||||
pub fn X509_set_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
pub fn X509_set_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
||||||
pub fn X509_set_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
pub fn X509_set_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
||||||
pub fn X509_get_ext_d2i(x: *mut ::X509, nid: c_int, crit: *mut c_int, idx: *mut c_int) -> *mut c_void;
|
pub fn X509_get_ext_d2i(x: *mut ::X509, nid: c_int, crit: *mut c_int, idx: *mut c_int) -> *mut c_void;
|
||||||
|
pub fn X509_NAME_add_entry_by_NID(x: *mut ::X509_NAME, field: c_int, ty: c_int, bytes: *mut c_uchar, len: c_int, loc: c_int, set: c_int) -> c_int;
|
||||||
pub fn X509_NAME_get_entry(n: *mut ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY;
|
pub fn X509_NAME_get_entry(n: *mut ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY;
|
||||||
pub fn X509_NAME_ENTRY_get_data(ne: *mut ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING;
|
pub fn X509_NAME_ENTRY_get_data(ne: *mut ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING;
|
||||||
pub fn X509_STORE_CTX_get_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509;
|
pub fn X509_STORE_CTX_get_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509;
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ extern {
|
||||||
pub fn X509_set1_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
pub fn X509_set1_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
||||||
pub fn X509_set1_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
pub fn X509_set1_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
||||||
pub fn X509_get_ext_d2i(x: *const ::X509, nid: c_int, crit: *mut c_int, idx: *mut c_int) -> *mut c_void;
|
pub fn X509_get_ext_d2i(x: *const ::X509, nid: c_int, crit: *mut c_int, idx: *mut c_int) -> *mut c_void;
|
||||||
|
pub fn X509_NAME_add_entry_by_NID(x: *mut ::X509_NAME, field: c_int, ty: c_int, bytes: *const c_uchar, len: c_int, loc: c_int, set: c_int) -> c_int;
|
||||||
pub fn X509_NAME_get_entry(n: *const ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY;
|
pub fn X509_NAME_get_entry(n: *const ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY;
|
||||||
pub fn X509_NAME_ENTRY_get_data(ne: *const ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING;
|
pub fn X509_NAME_ENTRY_get_data(ne: *const ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING;
|
||||||
pub fn X509V3_EXT_nconf_nid(conf: *mut ::CONF, ctx: *mut ::X509V3_CTX, ext_nid: c_int, value: *const c_char) -> *mut ::X509_EXTENSION;
|
pub fn X509V3_EXT_nconf_nid(conf: *mut ::CONF, ctx: *mut ::X509V3_CTX, ext_nid: c_int, value: *const c_char) -> *mut ::X509_EXTENSION;
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ impl Asn1StringRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type_!(Asn1Integer, Asn1IntegerRef, ffi::ASN1_INTEGER, ffi::ASN1_INTEGER_free);
|
||||||
|
|
||||||
#[cfg(any(ossl101, ossl102))]
|
#[cfg(any(ossl101, ossl102))]
|
||||||
use ffi::ASN1_STRING_data;
|
use ffi::ASN1_STRING_data;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use std::{fmt, ptr};
|
||||||
use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref};
|
use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref};
|
||||||
|
|
||||||
use {cvt, cvt_p, cvt_n};
|
use {cvt, cvt_p, cvt_n};
|
||||||
|
use asn1::Asn1Integer;
|
||||||
use crypto::CryptoString;
|
use crypto::CryptoString;
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
use types::{OpenSslType, OpenSslTypeRef};
|
use types::{OpenSslType, OpenSslTypeRef};
|
||||||
|
|
@ -492,6 +493,14 @@ impl BigNumRef {
|
||||||
Ok(CryptoString::from_null_terminated(buf))
|
Ok(CryptoString::from_null_terminated(buf))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an `Asn1Integer` containing the value of `self`.
|
||||||
|
pub fn to_asn1_integer(&self) -> Result<Asn1Integer, ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
cvt_p(ffi::BN_to_ASN1_INTEGER(self.as_ptr(), ptr::null_mut()))
|
||||||
|
.map(|p| Asn1Integer::from_ptr(p))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type_!(BigNum, BigNumRef, ffi::BIGNUM, ffi::BN_free);
|
type_!(BigNum, BigNumRef, ffi::BIGNUM, ffi::BN_free);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use std::slice;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use {cvt, cvt_p};
|
use {cvt, cvt_p};
|
||||||
use asn1::{Asn1StringRef, Asn1Time, Asn1TimeRef};
|
use asn1::{Asn1StringRef, Asn1Time, Asn1TimeRef, Asn1IntegerRef};
|
||||||
use bio::{MemBio, MemBioSlice};
|
use bio::{MemBio, MemBioSlice};
|
||||||
use hash::MessageDigest;
|
use hash::MessageDigest;
|
||||||
use pkey::{PKey, PKeyRef};
|
use pkey::{PKey, PKeyRef};
|
||||||
|
|
@ -353,6 +353,58 @@ impl X509Generator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct X509Builder(X509);
|
||||||
|
|
||||||
|
impl X509Builder {
|
||||||
|
pub fn new() -> Result<X509Builder, ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
cvt_p(ffi::X509_new()).map(|p| X509Builder(X509(p)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> {
|
||||||
|
unsafe { cvt(X509_set_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> {
|
||||||
|
unsafe { cvt(X509_set_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
|
||||||
|
unsafe { cvt(ffi::X509_set_version(self.0.as_ptr(), version.into())).map(|_| ()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_serial_number(&mut self,
|
||||||
|
serial_number: &Asn1IntegerRef)
|
||||||
|
-> Result<(), ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
cvt(ffi::X509_set_serialNumber(self.0.as_ptr(), serial_number.as_ptr())).map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack> {
|
||||||
|
unsafe { cvt(ffi::X509_set_issuer_name(self.0.as_ptr(), issuer_name.as_ptr())).map(|_| ()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
cvt(ffi::X509_set_subject_name(self.0.as_ptr(), subject_name.as_ptr())).map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_pubkey(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> {
|
||||||
|
unsafe { cvt(ffi::X509_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sign(&mut self, key: &PKeyRef, hash: MessageDigest) -> Result<(), ErrorStack> {
|
||||||
|
unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> X509 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type_!(X509, X509Ref, ffi::X509, ffi::X509_free);
|
type_!(X509, X509Ref, ffi::X509, ffi::X509_free);
|
||||||
|
|
||||||
impl X509Ref {
|
impl X509Ref {
|
||||||
|
|
@ -446,6 +498,11 @@ impl ToOwned for X509Ref {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl X509 {
|
impl X509 {
|
||||||
|
/// Returns a new builder.
|
||||||
|
pub fn builder() -> Result<X509Builder, ErrorStack> {
|
||||||
|
X509Builder::new()
|
||||||
|
}
|
||||||
|
|
||||||
/// Reads a certificate from DER.
|
/// Reads a certificate from DER.
|
||||||
pub fn from_der(buf: &[u8]) -> Result<X509, ErrorStack> {
|
pub fn from_der(buf: &[u8]) -> Result<X509, ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -497,9 +554,55 @@ impl Stackable for X509 {
|
||||||
type StackType = ffi::stack_st_X509;
|
type StackType = ffi::stack_st_X509;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct X509NameBuilder(X509Name);
|
||||||
|
|
||||||
|
impl X509NameBuilder {
|
||||||
|
pub fn new() -> Result<X509NameBuilder, ErrorStack> {
|
||||||
|
unsafe { cvt_p(ffi::X509_NAME_new()).map(|p| X509NameBuilder(X509Name(p))) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
let field = CString::new(field).unwrap();
|
||||||
|
assert!(value.len() <= c_int::max_value() as usize);
|
||||||
|
cvt(ffi::X509_NAME_add_entry_by_txt(self.0.as_ptr(),
|
||||||
|
field.as_ptr() as *mut _,
|
||||||
|
ffi::MBSTRING_UTF8,
|
||||||
|
value.as_ptr(),
|
||||||
|
value.len() as c_int,
|
||||||
|
-1,
|
||||||
|
0))
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
assert!(value.len() <= c_int::max_value() as usize);
|
||||||
|
cvt(ffi::X509_NAME_add_entry_by_NID(self.0.as_ptr(),
|
||||||
|
field.as_raw(),
|
||||||
|
ffi::MBSTRING_UTF8,
|
||||||
|
value.as_ptr() as *mut _,
|
||||||
|
value.len() as c_int,
|
||||||
|
-1,
|
||||||
|
0))
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> X509Name {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type_!(X509Name, X509NameRef, ffi::X509_NAME, ffi::X509_NAME_free);
|
type_!(X509Name, X509NameRef, ffi::X509_NAME, ffi::X509_NAME_free);
|
||||||
|
|
||||||
impl X509Name {
|
impl X509Name {
|
||||||
|
/// Returns a new builder.
|
||||||
|
pub fn builder() -> Result<X509NameBuilder, ErrorStack> {
|
||||||
|
X509NameBuilder::new()
|
||||||
|
}
|
||||||
|
|
||||||
/// Loads subject names from a file containing PEM-formatted certificates.
|
/// Loads subject names from a file containing PEM-formatted certificates.
|
||||||
///
|
///
|
||||||
/// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`.
|
/// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`.
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
use serialize::hex::FromHex;
|
use serialize::hex::FromHex;
|
||||||
|
|
||||||
|
use asn1::Asn1Time;
|
||||||
|
use bn::{BigNum, MSB_MAYBE_ZERO};
|
||||||
use hash::MessageDigest;
|
use hash::MessageDigest;
|
||||||
use pkey::PKey;
|
use pkey::PKey;
|
||||||
use rsa::Rsa;
|
use rsa::Rsa;
|
||||||
use x509::{X509, X509Generator};
|
use x509::{X509, X509Generator, X509Name};
|
||||||
use x509::extension::Extension::{KeyUsage, ExtKeyUsage, SubjectAltName, OtherNid, OtherStr};
|
use x509::extension::Extension::{KeyUsage, ExtKeyUsage, SubjectAltName, OtherNid, OtherStr};
|
||||||
use x509::extension::AltNameOption as SAN;
|
use x509::extension::AltNameOption as SAN;
|
||||||
use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment};
|
use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment};
|
||||||
|
|
@ -174,3 +176,32 @@ fn test_subject_alt_name_iter() {
|
||||||
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..]));
|
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..]));
|
||||||
assert!(subject_alt_names_iter.next().is_none());
|
assert!(subject_alt_names_iter.next().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_x509_builder() {
|
||||||
|
let pkey = pkey();
|
||||||
|
|
||||||
|
let mut name = X509Name::builder().unwrap();
|
||||||
|
name.append_entry_by_nid(nid::COMMONNAME, "foobar.com").unwrap();
|
||||||
|
let name = name.build();
|
||||||
|
|
||||||
|
let mut builder = X509::builder().unwrap();
|
||||||
|
builder.set_subject_name(&name).unwrap();
|
||||||
|
builder.set_issuer_name(&name).unwrap();
|
||||||
|
builder.set_not_before(&Asn1Time::days_from_now(0).unwrap()).unwrap();
|
||||||
|
builder.set_not_after(&Asn1Time::days_from_now(365).unwrap()).unwrap();
|
||||||
|
builder.set_pubkey(&pkey).unwrap();
|
||||||
|
|
||||||
|
let mut serial = BigNum::new().unwrap();;
|
||||||
|
serial.rand(128, MSB_MAYBE_ZERO, false).unwrap();
|
||||||
|
builder.set_serial_number(&serial.to_asn1_integer().unwrap()).unwrap();
|
||||||
|
|
||||||
|
builder.sign(&pkey, MessageDigest::sha256()).unwrap();
|
||||||
|
|
||||||
|
let x509 = builder.build();
|
||||||
|
|
||||||
|
assert!(pkey.public_eq(&x509.public_key().unwrap()));
|
||||||
|
|
||||||
|
let cn = x509.subject_name().entries_by_nid(nid::COMMONNAME).next().unwrap();
|
||||||
|
assert_eq!("foobar.com".as_bytes(), cn.data().as_slice());
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue