diff --git a/openssl-sys/src/handwritten/x509.rs b/openssl-sys/src/handwritten/x509.rs index 0bb682764..a3b07c180 100644 --- a/openssl-sys/src/handwritten/x509.rs +++ b/openssl-sys/src/handwritten/x509.rs @@ -779,3 +779,15 @@ const_ptr_api! { pub fn X509_ATTRIBUTE_dup(x: #[const_ptr_if(ossl300)] X509_ATTRIBUTE) -> *mut X509_ATTRIBUTE; } } +const_ptr_api! { + extern "C" { + pub fn X509_check_private_key( + cert: #[const_ptr_if(any(ossl110, libressl280, boringssl, awslc))] X509, + pkey: #[const_ptr_if(any(ossl110, libressl280, boringssl, awslc))] EVP_PKEY + ) -> c_int; + pub fn X509_REQ_check_private_key( + req: #[const_ptr_if(any(ossl320, boringssl, awslc))] X509_REQ, + pkey: #[const_ptr_if(any(boringssl, awslc))] EVP_PKEY + ) -> c_int; + } +} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 2867f91ad..7c513da2b 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -32,7 +32,7 @@ use crate::error::ErrorStack; use crate::ex_data::Index; use crate::hash::{DigestBytes, MessageDigest}; use crate::nid::Nid; -use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public}; +use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Private, Public}; use crate::ssl::SslRef; use crate::stack::{Stack, StackRef, Stackable}; use crate::string::OpensslString; @@ -666,6 +666,12 @@ impl X509Ref { } } + /// Checks for consistency between the private key and this certificate. + #[corresponds(X509_check_private_key)] + pub fn check_private_key(&self, pkey: &PKeyRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::X509_check_private_key(self.as_ptr(), pkey.as_ptr())).map(|_| ()) } + } + to_pem! { /// Serializes the certificate into a PEM-encoded X509 structure. /// @@ -1571,6 +1577,18 @@ impl X509ReqRef { Ok(Stack::from_ptr(extensions)) } } + + /// Checks for consistency between the private key and this certificate request. + #[corresponds(X509_REQ_check_private_key)] + pub fn check_private_key(&self, pkey: &PKeyRef) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::X509_REQ_check_private_key( + self.as_ptr(), + pkey.as_ptr(), + )) + .map(|_| ()) + } + } } /// The reason that a certificate was revoked. diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index e11f8bf22..0f980b2c0 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -1196,3 +1196,19 @@ fn test_store_all_certificates() { assert_eq!(store.all_certificates().len(), 1); } + +#[test] +fn test_check_private_key() { + let ca_cert = include_bytes!("../../test/root-ca.pem"); + let ca_cert = X509::from_pem(ca_cert).unwrap(); + let cert = include_bytes!("../../test/cert.pem"); + let cert = X509::from_pem(cert).unwrap(); + let csr = include_bytes!("../../test/csr.pem"); + let csr = X509Req::from_pem(csr).unwrap(); + let pkey = include_bytes!("../../test/key.pem"); + let pkey = PKey::private_key_from_pem(pkey).unwrap(); + + assert!(ca_cert.check_private_key(&pkey).is_err()); + assert!(cert.check_private_key(&pkey).is_ok()); + assert!(csr.check_private_key(&pkey).is_ok()); +}