diff --git a/openssl-sys/src/handwritten/x509.rs b/openssl-sys/src/handwritten/x509.rs index 0bb682764..a3f0c26f8 100644 --- a/openssl-sys/src/handwritten/x509.rs +++ b/openssl-sys/src/handwritten/x509.rs @@ -285,6 +285,16 @@ extern "C" { pub fn X509_NAME_new() -> *mut X509_NAME; pub fn X509_NAME_cmp(x: *const X509_NAME, y: *const X509_NAME) -> c_int; + #[cfg(ossl300)] + pub fn X509_NAME_hash_ex( + x: *const X509_NAME, + ctx: *mut OSSL_LIB_CTX, + propq: *const c_char, + ok: *mut c_int, + ) -> c_ulong; + + #[cfg(not(ossl300))] + pub fn X509_NAME_hash(x: *mut X509_NAME) -> c_ulong; pub fn X509_NAME_free(x: *mut X509_NAME); pub fn X509_new() -> *mut X509; diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 67c86ee3d..c91cc1b0b 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -31,6 +31,8 @@ use crate::conf::ConfRef; use crate::error::ErrorStack; use crate::ex_data::Index; use crate::hash::{DigestBytes, MessageDigest}; +#[cfg(ossl300)] +use crate::lib_ctx::LibCtxRef; use crate::nid::Nid; use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public}; use crate::ssl::SslRef; @@ -1218,6 +1220,51 @@ impl Stackable for X509Name { } impl X509NameRef { + /// Returns the hash of the X509 name + #[cfg(ossl300)] + #[corresponds(X509_NAME_hash_ex)] + pub fn hash_ex(&self, ctx: Option, propq: Option<&str>) -> Result { + let ctx_ref = ctx.map_or(ptr::null_mut(), |ctx| ctx.as_ptr()); + + let cstr; + let propq = if let Some(propq) = propq { + cstr = CString::new(propq).unwrap(); + cstr.as_ptr() + } else { + ptr::null() + }; + + let mut ok: c_int = 0; + let hash; + + #[allow(clippy::unnecessary_cast)] + unsafe { + hash = ffi::X509_NAME_hash_ex(self.as_ptr(), ctx_ref, propq, &mut ok) as u32; + } + + if ok != 1 { + return Err(ErrorStack::get()); + } + + Ok(hash) + } + + /// Returns the hash of the X509 name + #[cfg(ossl300)] + #[corresponds(X509_NAME_hash)] + pub fn hash(&self) -> u32 { + self.hash_ex(None, None).unwrap_or(0) + } + + #[cfg(not(ossl300))] + #[corresponds(X509_NAME_hash)] + pub fn hash(&self) -> u32 { + #[allow(clippy::unnecessary_cast)] + unsafe { + ffi::X509_NAME_hash(self.as_ptr()) as u32 + } + } + /// Returns the name entries by the nid. pub fn entries_by_nid(&self, nid: Nid) -> X509NameEntries<'_> { X509NameEntries { diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 25c2da012..da047b26b 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -680,6 +680,8 @@ fn test_load_crl() { let crl = include_bytes!("../../test/test.crl"); let crl = X509Crl::from_der(crl).unwrap(); assert!(crl.verify(&ca.public_key().unwrap()).unwrap()); + let issuer = crl.issuer_name(); + assert_eq!(format!("{:08x}", issuer.hash()), "f88ed8fa"); let cert = include_bytes!("../../test/subca.crt"); let cert = X509::from_pem(cert).unwrap();