aboutsummaryrefslogtreecommitdiff
path: root/src/x509
diff options
context:
space:
mode:
authorValerii Hiora <[email protected]>2014-09-24 19:17:17 +0300
committerValerii Hiora <[email protected]>2014-09-26 10:39:08 +0300
commit4fd169a1e5d465a10d5a815877479baa960a16eb (patch)
tree5ddc3e107274bdf72f00aeaeac67fc698b553473 /src/x509
parentMerge pull request #46 from vhbit/tls1-2-support (diff)
downloadrust-openssl-4fd169a1e5d465a10d5a815877479baa960a16eb.tar.xz
rust-openssl-4fd169a1e5d465a10d5a815877479baa960a16eb.zip
Certificate/pkey generation & PEM export
Required quite a lot of refactoring
Diffstat (limited to 'src/x509')
-rwxr-xr-xsrc/x509/mod.rs517
1 files changed, 517 insertions, 0 deletions
diff --git a/src/x509/mod.rs b/src/x509/mod.rs
new file mode 100755
index 00000000..06ae4b27
--- /dev/null
+++ b/src/x509/mod.rs
@@ -0,0 +1,517 @@
+use libc::{c_int, c_long, c_uint};
+use std::mem;
+use std::ptr;
+
+use asn1;
+use bio::{MemBio};
+use crypto::hash::{HashType, evpmd, SHA1};
+use crypto::pkey::{PKey};
+use crypto::rand::rand_bytes;
+use ssl::error::{SslError, StreamError};
+
+
+#[repr(i32)]
+pub enum X509FileType {
+ PEM = ffi::X509_FILETYPE_PEM,
+ ASN1 = ffi::X509_FILETYPE_ASN1,
+ Default = ffi::X509_FILETYPE_DEFAULT
+}
+pub struct X509StoreContext {
+ ctx: *mut ffi::X509_STORE_CTX
+}
+
+impl X509StoreContext {
+ pub fn new(ctx: *mut ffi::X509_STORE_CTX) -> X509StoreContext {
+ X509StoreContext {
+ ctx: ctx
+ }
+ }
+
+ pub fn get_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) };
+
+ if ptr.is_null() {
+ None
+ } else {
+ Some(X509 { ctx: Some(self), x509: ptr })
+ }
+ }
+}
+
+trait AsStr<'a> {
+ fn as_str(&self) -> &'a str;
+}
+
+#[deriving(Clone)]
+pub enum KeyUsage {
+ DigitalSignature,
+ NonRepudiation,
+ KeyEncipherment,
+ DataEncipherment,
+ KeyAgreement,
+ KeyCertSign,
+ CRLSign,
+ EncipherOnly,
+ DecipherOnly
+}
+
+impl AsStr<'static> for KeyUsage {
+ fn as_str(&self) -> &'static str {
+ match self {
+ &DigitalSignature => "digitalSignature",
+ &NonRepudiation => "nonRepudiation",
+ &KeyEncipherment => "keyEncipherment",
+ &DataEncipherment => "dataEncipherment",
+ &KeyAgreement => "keyAgreement",
+ &KeyCertSign => "keyCertSign",
+ &CRLSign => "cRLSign",
+ &EncipherOnly => "encipherOnly",
+ &DecipherOnly => "decipherOnly"
+ }
+ }
+}
+
+
+#[deriving(Clone)]
+pub enum ExtKeyUsage {
+ ServerAuth,
+ ClientAuth,
+ CodeSigning,
+ EmailProtection,
+ TimeStamping,
+ MsCodeInd,
+ MsCodeCom,
+ MsCtlSign,
+ MsSgc,
+ MsEfs,
+ NsSgc
+}
+
+impl AsStr<'static> for ExtKeyUsage {
+ fn as_str(&self) -> &'static str {
+ match self {
+ &ServerAuth => "serverAuth",
+ &ClientAuth => "clientAuth",
+ &CodeSigning => "codeSigning",
+ &EmailProtection => "emailProtection",
+ &TimeStamping => "timeStamping",
+ &MsCodeInd => "msCodeInd",
+ &MsCodeCom => "msCodeCom",
+ &MsCtlSign => "msCTLSign",
+ &MsSgc => "msSGC",
+ &MsEfs => "msEFS",
+ &NsSgc =>"nsSGC"
+ }
+ }
+}
+
+
+// FIXME: a dirty hack as there is no way to
+// implement ToString for Vec as both are defined
+// in another crate
+trait ToStr {
+ fn to_str(&self) -> String;
+}
+
+impl<'a, T: AsStr<'a>> ToStr for Vec<T> {
+ fn to_str(&self) -> String {
+ self.iter().enumerate().fold(String::new(), |mut acc, (idx, v)| {
+ if idx > 0 { acc.push_char(',') };
+ acc.push_str(v.as_str());
+ acc
+ })
+ }
+}
+
+#[allow(non_snake_case)]
+pub struct X509Generator {
+ bits: uint,
+ days: uint,
+ CN: String,
+ key_usage: Vec<KeyUsage>,
+ ext_key_usage: Vec<ExtKeyUsage>,
+ hash_type: HashType,
+}
+
+impl X509Generator {
+ pub fn new() -> X509Generator {
+ X509Generator {
+ bits: 1024,
+ days: 365,
+ CN: "rust-openssl".to_string(),
+ key_usage: Vec::new(),
+ ext_key_usage: Vec::new(),
+ hash_type: SHA1
+ }
+ }
+
+ pub fn set_bitlength(mut self, bits: uint) -> X509Generator {
+ self.bits = bits;
+ self
+ }
+
+ pub fn set_valid_period(mut self, days: uint) -> X509Generator {
+ self.days = days;
+ self
+ }
+
+ #[allow(non_snake_case)]
+ pub fn set_CN(mut self, CN: &str) -> X509Generator {
+ self.CN = CN.to_string();
+ self
+ }
+
+ pub fn set_usage(mut self, purposes: &[KeyUsage]) -> X509Generator {
+ self.key_usage = purposes.to_vec();
+ self
+ }
+
+ pub fn set_ext_usage(mut self, purposes: &[ExtKeyUsage]) -> X509Generator {
+ self.ext_key_usage = purposes.to_vec();
+ self
+ }
+
+ pub fn set_sign_hash(mut self, hash_type: HashType) -> X509Generator {
+ self.hash_type = hash_type;
+ self
+ }
+
+ fn add_extension(x509: *mut ffi::X509, extension: c_int, value: &str) -> Result<(), SslError> {
+ unsafe {
+ // FIXME: RAII
+ let ctx: ffi::X509V3_CTX = mem::zeroed();
+ ffi::X509V3_set_ctx(mem::transmute(&ctx), x509, x509,
+ ptr::null_mut(), ptr::null_mut(), 0);
+ let ext = value.with_c_str(|value|
+ ffi::X509V3_EXT_conf_nid(ptr::null_mut(), mem::transmute(&ctx), extension, mem::transmute(value)));
+ try_ssl_null!(ext);
+ try_ssl!(ffi::X509_add_ext(x509, ext, -1));
+ ffi::X509_EXTENSION_free(ext);
+ Ok(())
+ }
+ }
+
+ fn add_name(name: *mut ffi::X509_NAME, key: &str, value: &str) -> Result<(), SslError> {
+ let value_len = value.len() as c_int;
+ lift_ssl!(key.with_c_str(|key| {
+ value.with_c_str(|value| unsafe {
+ ffi::X509_NAME_add_entry_by_txt(name, key, asn1::ffi::MBSTRING_UTF8,
+ value, value_len, -1, 0)
+ })
+ }))
+ }
+
+ fn random_serial() -> c_long {
+ let len = mem::size_of::<c_long>();
+ let bytes = rand_bytes(len);
+ let mut res = 0;
+ for b in bytes.iter() {
+ res = res << 8;
+ res |= (*b as c_long) & 0xff;
+ }
+ res
+ }
+
+ pub fn generate<'a>(&self) -> Result<(X509<'a>, PKey), SslError> {
+ let mut p_key = PKey::new();
+ p_key.gen(self.bits);
+
+ // FIXME: all allocated resources should be correctly
+ // dropped in case of failure
+ unsafe {
+ let x509 = ffi::X509_new();
+ try_ssl_null!(x509);
+ try_ssl!(ffi::X509_set_version(x509, 2));
+ try_ssl!(asn1::ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509), X509Generator::random_serial()));
+
+ let not_before = ffi::X509_gmtime_adj(ptr::null_mut(), 0);
+ try_ssl_null!(not_before);
+
+ let not_after = ffi::X509_gmtime_adj(ptr::null_mut(), 60*60*24*self.days as i64);
+ try_ssl_null!(not_after);
+
+ try_ssl!(ffi::X509_set_notBefore(x509, mem::transmute(not_before)));
+ try_ssl!(ffi::X509_set_notAfter(x509, mem::transmute(not_after)));
+
+ try_ssl!(ffi::X509_set_pubkey(x509, p_key.get_handle()));
+
+ let name = ffi::X509_get_subject_name(x509);
+ try_ssl_null!(name);
+
+ try!(X509Generator::add_name(name, "CN", self.CN.as_slice()));
+ ffi::X509_set_issuer_name(x509, name);
+
+ if self.key_usage.len() > 0 {
+ try!(X509Generator::add_extension(x509, ffi::NID_key_usage,
+ self.key_usage.to_str().as_slice()));
+ }
+
+ if self.ext_key_usage.len() > 0 {
+ try!(X509Generator::add_extension(x509, ffi::NID_ext_key_usage,
+ self.ext_key_usage.to_str().as_slice()));
+ }
+
+ let (hash_fn, _) = evpmd(self.hash_type);
+ try_ssl!(ffi::X509_sign(x509, p_key.get_handle(), hash_fn));
+ Ok((X509 { x509: x509, ctx: None }, p_key))
+ }
+ }
+}
+
+#[allow(dead_code)]
+/// A public key certificate
+pub struct X509<'ctx> {
+ ctx: Option<&'ctx X509StoreContext>,
+ x509: *mut ffi::X509
+}
+
+impl<'ctx> X509<'ctx> {
+ pub fn subject_name<'a>(&'a self) -> X509Name<'a> {
+ let name = unsafe { ffi::X509_get_subject_name(self.x509) };
+ X509Name { x509: self, name: name }
+ }
+
+ /// Returns certificate fingerprint calculated using provided hash
+ pub fn fingerprint(&self, hash_type: HashType) -> Option<Vec<u8>> {
+ let (evp, len) = evpmd(hash_type);
+ let v: Vec<u8> = Vec::from_elem(len, 0);
+ let act_len: c_uint = 0;
+ let res = unsafe {
+ ffi::X509_digest(self.x509, evp, mem::transmute(v.as_ptr()),
+ mem::transmute(&act_len))
+ };
+
+ match res {
+ 0 => None,
+ _ => {
+ let act_len = act_len as uint;
+ match len.cmp(&act_len) {
+ Greater => None,
+ Equal => Some(v),
+ Less => fail!("Fingerprint buffer was corrupted!")
+ }
+ }
+ }
+ }
+
+ /// Writes certificate as PEM
+ pub fn write_pem(&self, writer: &mut Writer) -> Result<(), SslError> {
+ let mut mem_bio = try!(MemBio::new());
+ unsafe {
+ try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(),
+ self.x509));
+ }
+ let buf = try!(mem_bio.read_to_end().map_err(StreamError));
+ writer.write(buf.as_slice()).map_err(StreamError)
+ }
+}
+
+#[allow(dead_code)]
+pub struct X509Name<'x> {
+ x509: &'x X509<'x>,
+ name: *mut ffi::X509_NAME
+}
+
+
+pub mod ffi {
+ #![allow(non_camel_case_types)]
+ use libc::{c_void, c_int, c_char, c_ulong, c_long, c_uint};
+
+ use asn1::ffi::{ASN1_INTEGER, ASN1_TIME};
+ use bio::ffi::{BIO};
+ use crypto::hash::{EVP_MD};
+ use crypto::pkey::{EVP_PKEY};
+
+ pub type X509_STORE_CTX = c_void;
+ pub type X509 = c_void;
+ pub type X509_NAME = c_void;
+ pub type X509_CRL = c_void;
+ pub type X509_REQ = c_void;
+ pub type X509_EXTENSION = c_void;
+
+ #[repr(C)]
+ pub struct X509V3_CTX {
+ flags: c_int,
+ issuer_cert: *mut c_void,
+ subject_cert: *mut c_void,
+ subject_req: *mut c_void,
+ crl: *mut c_void,
+ db_meth: *mut c_void,
+ db: *mut c_void,
+ // I like the last comment line, it is copied from OpenSSL sources:
+ // Maybe more here
+ }
+
+ pub static X509_V_OK: c_int = 0;
+ pub static X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: c_int = 2;
+ pub static X509_V_ERR_UNABLE_TO_GET_CRL: c_int = 3;
+ pub static X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: c_int = 4;
+ pub static X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: c_int = 5;
+ pub static X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: c_int = 6;
+ pub static X509_V_ERR_CERT_SIGNATURE_FAILURE: c_int = 7;
+ pub static X509_V_ERR_CRL_SIGNATURE_FAILURE: c_int = 8;
+ pub static X509_V_ERR_CERT_NOT_YET_VALID: c_int = 9;
+ pub static X509_V_ERR_CERT_HAS_EXPIRED: c_int = 10;
+ pub static X509_V_ERR_CRL_NOT_YET_VALID: c_int = 11;
+ pub static X509_V_ERR_CRL_HAS_EXPIRED: c_int = 12;
+ pub static X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: c_int = 13;
+ pub static X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: c_int = 14;
+ pub static X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: c_int = 15;
+ pub static X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: c_int = 16;
+ pub static X509_V_ERR_OUT_OF_MEM: c_int = 17;
+ pub static X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: c_int = 18;
+ pub static X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: c_int = 19;
+ pub static X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: c_int = 20;
+ pub static X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: c_int = 21;
+ pub static X509_V_ERR_CERT_CHAIN_TOO_LONG: c_int = 22;
+ pub static X509_V_ERR_CERT_REVOKED: c_int = 23;
+ pub static X509_V_ERR_INVALID_CA: c_int = 24;
+ pub static X509_V_ERR_PATH_LENGTH_EXCEEDED: c_int = 25;
+ pub static X509_V_ERR_INVALID_PURPOSE: c_int = 26;
+ pub static X509_V_ERR_CERT_UNTRUSTED: c_int = 27;
+ pub static X509_V_ERR_CERT_REJECTED: c_int = 28;
+ pub static X509_V_ERR_SUBJECT_ISSUER_MISMATCH: c_int = 29;
+ pub static X509_V_ERR_AKID_SKID_MISMATCH: c_int = 30;
+ pub static X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: c_int = 31;
+ pub static X509_V_ERR_KEYUSAGE_NO_CERTSIGN: c_int = 32;
+ pub static X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: c_int = 33;
+ pub static X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: c_int = 34;
+ pub static X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: c_int = 35;
+ pub static X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: c_int = 36;
+ pub static X509_V_ERR_INVALID_NON_CA: c_int = 37;
+ pub static X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: c_int = 38;
+ pub static X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: c_int = 39;
+ pub static X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: c_int = 40;
+ pub static X509_V_ERR_INVALID_EXTENSION: c_int = 41;
+ pub static X509_V_ERR_INVALID_POLICY_EXTENSION: c_int = 42;
+ pub static X509_V_ERR_NO_EXPLICIT_POLICY: c_int = 43;
+ pub static X509_V_ERR_DIFFERENT_CRL_SCOPE: c_int = 44;
+ pub static X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: c_int = 45;
+ pub static X509_V_ERR_UNNESTED_RESOURCE: c_int = 46;
+ pub static X509_V_ERR_PERMITTED_VIOLATION: c_int = 47;
+ pub static X509_V_ERR_EXCLUDED_VIOLATION: c_int = 48;
+ pub static X509_V_ERR_SUBTREE_MINMAX: c_int = 49;
+ pub static X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: c_int = 51;
+ pub static X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: c_int = 52;
+ pub static X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: c_int = 53;
+ pub static X509_V_ERR_CRL_PATH_VALIDATION_ERROR: c_int = 54;
+ pub static X509_V_ERR_APPLICATION_VERIFICATION: c_int = 50;
+
+ pub static X509_FILETYPE_PEM: c_int = 1;
+ pub static X509_FILETYPE_ASN1: c_int = 2;
+ pub static X509_FILETYPE_DEFAULT: c_int = 3;
+
+ pub static NID_key_usage: c_int = 83;
+ pub static NID_ext_key_usage: c_int = 126;
+
+
+
+ extern "C" {
+ pub fn X509_STORE_CTX_get_ex_data(ctx: *mut X509_STORE_CTX, idx: c_int) -> *mut c_void;
+ pub fn X509_STORE_CTX_get_current_cert(ct: *mut X509_STORE_CTX) -> *mut X509;
+ pub fn X509_STORE_CTX_get_error(ctx: *mut X509_STORE_CTX) -> c_int;
+
+ pub fn X509_add_ext(x: *mut X509, ext: *mut X509_EXTENSION, loc: c_int) -> c_int;
+ pub fn X509_digest(x: *mut X509, digest: *const EVP_MD, buf: *mut c_char, len: *mut c_uint) -> c_int;
+ pub fn X509_get_serialNumber(x: *mut X509) -> *mut ASN1_INTEGER;
+ pub fn X509_get_subject_name(x: *mut X509) -> *mut X509_NAME;
+ pub fn X509_gmtime_adj(time: *mut ASN1_TIME, adj: c_long) -> *mut ASN1_TIME;
+ 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_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_version(x: *mut X509, version: c_ulong) -> 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_NAME_add_entry_by_txt(x: *mut X509, field: *const c_char, ty: c_int, bytes: *const c_char, len: c_int, loc: c_int, set: c_int) -> c_int;
+
+ pub fn X509V3_EXT_conf_nid(conf: *mut c_void, ctx: *mut X509V3_CTX, ext_nid: c_int, value: *mut c_char) -> *mut X509_EXTENSION;
+ pub fn X509V3_set_ctx(ctx: *mut X509V3_CTX, issuer: *mut X509, subject: *mut X509, req: *mut X509_REQ, crl: *mut X509_CRL, flags: c_int);
+
+ pub fn X509_EXTENSION_free(ext: *mut X509_EXTENSION);
+
+ pub fn PEM_write_bio_X509(bio: *mut BIO, x509: *mut X509) -> c_int;
+ }
+}
+
+macro_rules! make_validation_error(
+ ($ok_val:ident, $($name:ident = $val:ident,)+) => (
+ pub enum X509ValidationError {
+ $($name,)+
+ X509UnknownError(c_int)
+ }
+
+ impl X509ValidationError {
+ #[doc(hidden)]
+ pub fn from_raw(err: c_int) -> Option<X509ValidationError> {
+ match err {
+ self::ffi::$ok_val => None,
+ $(self::ffi::$val => Some($name),)+
+ err => Some(X509UnknownError(err))
+ }
+ }
+ }
+ )
+)
+
+make_validation_error!(X509_V_OK,
+ X509UnableToGetIssuerCert = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
+ X509UnableToGetCrl = X509_V_ERR_UNABLE_TO_GET_CRL,
+ X509UnableToDecryptCertSignature = X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
+ X509UnableToDecryptCrlSignature = X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
+ X509UnableToDecodeIssuerPublicKey = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
+ X509CertSignatureFailure = X509_V_ERR_CERT_SIGNATURE_FAILURE,
+ X509CrlSignatureFailure = X509_V_ERR_CRL_SIGNATURE_FAILURE,
+ X509CertNotYetValid = X509_V_ERR_CERT_NOT_YET_VALID,
+ X509CertHasExpired = X509_V_ERR_CERT_HAS_EXPIRED,
+ X509CrlNotYetValid = X509_V_ERR_CRL_NOT_YET_VALID,
+ X509CrlHasExpired = X509_V_ERR_CRL_HAS_EXPIRED,
+ X509ErrorInCertNotBeforeField = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD,
+ X509ErrorInCertNotAfterField = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD,
+ X509ErrorInCrlLastUpdateField = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD,
+ X509ErrorInCrlNextUpdateField = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD,
+ X509OutOfMem = X509_V_ERR_OUT_OF_MEM,
+ X509DepthZeroSelfSignedCert = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
+ X509SelfSignedCertInChain = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN,
+ X509UnableToGetIssuerCertLocally = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
+ X509UnableToVerifyLeafSignature = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE,
+ X509CertChainTooLong = X509_V_ERR_CERT_CHAIN_TOO_LONG,
+ X509CertRevoked = X509_V_ERR_CERT_REVOKED,
+ X509InvalidCA = X509_V_ERR_INVALID_CA,
+ X509PathLengthExceeded = X509_V_ERR_PATH_LENGTH_EXCEEDED,
+ X509InvalidPurpose = X509_V_ERR_INVALID_PURPOSE,
+ X509CertUntrusted = X509_V_ERR_CERT_UNTRUSTED,
+ X509CertRejected = X509_V_ERR_CERT_REJECTED,
+ X509SubjectIssuerMismatch = X509_V_ERR_SUBJECT_ISSUER_MISMATCH,
+ X509AkidSkidMismatch = X509_V_ERR_AKID_SKID_MISMATCH,
+ X509AkidIssuerSerialMismatch = X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH,
+ X509KeyusageNoCertsign = X509_V_ERR_KEYUSAGE_NO_CERTSIGN,
+ X509UnableToGetCrlIssuer = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER,
+ X509UnhandledCriticalExtension = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION,
+ X509KeyusageNoCrlSign = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN,
+ X509UnhandledCriticalCrlExtension = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION,
+ X509InvalidNonCA = X509_V_ERR_INVALID_NON_CA,
+ X509ProxyPathLengthExceeded = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED,
+ X509KeyusageNoDigitalSignature = X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE,
+ X509ProxyCertificatesNotAllowed = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED,
+ X509InvalidExtension = X509_V_ERR_INVALID_EXTENSION,
+ X509InavlidPolicyExtension = X509_V_ERR_INVALID_POLICY_EXTENSION,
+ X509NoExplicitPolicy = X509_V_ERR_NO_EXPLICIT_POLICY,
+ X509DifferentCrlScope = X509_V_ERR_DIFFERENT_CRL_SCOPE,
+ X509UnsupportedExtensionFeature = X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE,
+ X509UnnestedResource = X509_V_ERR_UNNESTED_RESOURCE,
+ X509PermittedVolation = X509_V_ERR_PERMITTED_VIOLATION,
+ X509ExcludedViolation = X509_V_ERR_EXCLUDED_VIOLATION,
+ X509SubtreeMinmax = X509_V_ERR_SUBTREE_MINMAX,
+ X509UnsupportedConstraintType = X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE,
+ X509UnsupportedConstraintSyntax = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX,
+ X509UnsupportedNameSyntax = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX,
+ X509CrlPathValidationError= X509_V_ERR_CRL_PATH_VALIDATION_ERROR,
+ X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION,
+)