Skip to content

Commit

Permalink
Add support for X509_VERIFY_PARAM_set_time and X509_VERIFY_PARAM_set_…
Browse files Browse the repository at this point in the history
…depth
  • Loading branch information
alexanderjordanbaker committed Oct 27, 2022
1 parent bbdcaf7 commit 969f955
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 4 deletions.
14 changes: 14 additions & 0 deletions openssl-sys/src/handwritten/x509_vfy.rs
Expand Up @@ -47,6 +47,12 @@ extern "C" {
pub fn X509_STORE_set_flags(store: *mut X509_STORE, flags: c_ulong) -> c_int;
}

const_ptr_api! {
extern "C" {
pub fn X509_STORE_set1_param(store: *mut X509_STORE, pm: #[const_ptr_if(ossl300)] X509_VERIFY_PARAM) -> c_int;
}
}

const_ptr_api! {
extern "C" {
pub fn X509_STORE_CTX_get_ex_data(ctx: #[const_ptr_if(ossl300)] X509_STORE_CTX, idx: c_int) -> *mut c_void;
Expand All @@ -73,13 +79,21 @@ cfg_if! {
}

extern "C" {
#[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_new() -> *mut X509_VERIFY_PARAM;
#[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_free(param: *mut X509_VERIFY_PARAM);

#[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_set_flags(param: *mut X509_VERIFY_PARAM, flags: c_ulong) -> c_int;
#[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_clear_flags(param: *mut X509_VERIFY_PARAM, flags: c_ulong) -> c_int;

#[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_set_time(param: *mut X509_VERIFY_PARAM, t: time_t);

#[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_set_depth(param: *mut X509_VERIFY_PARAM, depth: c_int);
}
const_ptr_api! {
extern "C" {
Expand Down
9 changes: 8 additions & 1 deletion openssl/src/x509/store.rs
Expand Up @@ -50,7 +50,7 @@ use crate::error::ErrorStack;
use crate::ssl::SslFiletype;
use crate::stack::StackRef;
#[cfg(any(ossl102, libressl261))]
use crate::x509::verify::X509VerifyFlags;
use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef};
use crate::x509::{X509Object, X509};
use crate::{cvt, cvt_p};
use openssl_macros::corresponds;
Expand Down Expand Up @@ -122,6 +122,13 @@ impl X509StoreBuilderRef {
pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) }
}

/// Sets certificate chain validation related parameters.
#[corresponds[X509_STORE_set1_param]]
#[cfg(any(ossl102, libressl261))]
pub fn set_param(&mut self, param: &X509VerifyParamRef) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::X509_STORE_set1_param(self.as_ptr(), param.as_ptr())).map(|_| ()) }
}
}

generic_foreign_type_and_impl_send_sync! {
Expand Down
93 changes: 92 additions & 1 deletion openssl/src/x509/tests.rs
Expand Up @@ -13,11 +13,13 @@ use crate::x509::extension::{
};
use crate::x509::store::X509StoreBuilder;
#[cfg(any(ossl102, libressl261))]
use crate::x509::verify::X509VerifyFlags;
use crate::x509::verify::{X509VerifyFlags, X509VerifyParam};
#[cfg(ossl110)]
use crate::x509::X509Builder;
use crate::x509::{X509Name, X509Req, X509StoreContext, X509VerifyResult, X509};
use hex::{self, FromHex};
#[cfg(any(ossl102, libressl261))]
use libc::time_t;

fn pkey() -> PKey<Private> {
let rsa = Rsa::generate(2048).unwrap();
Expand Down Expand Up @@ -543,3 +545,92 @@ fn test_name_cmp() {
assert_eq!(Ordering::Equal, subject.try_cmp(subject).unwrap());
assert_eq!(Ordering::Greater, subject.try_cmp(issuer).unwrap());
}

#[test]
#[cfg(any(ossl102, libressl261))]
fn test_verify_param_set_time_fails_verification() {
const TEST_T_2030: time_t = 1893456000;

let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let chain = Stack::new().unwrap();

let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
let mut verify_params = X509VerifyParam::new().unwrap();
verify_params.set_time(TEST_T_2030);
store_bldr.set_param(&verify_params).unwrap();
let store = store_bldr.build();

let mut context = X509StoreContext::new().unwrap();
assert_eq!(
context
.init(&store, &cert, &chain, |c| {
c.verify_cert()?;
Ok(c.error())
})
.unwrap()
.error_string(),
"certificate has expired"
)
}

#[test]
#[cfg(any(ossl102, libressl261))]
fn test_verify_param_set_time() {
const TEST_T_2020: time_t = 1577836800;

let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let chain = Stack::new().unwrap();

let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
let mut verify_params = X509VerifyParam::new().unwrap();
verify_params.set_time(TEST_T_2020);
store_bldr.set_param(&verify_params).unwrap();
let store = store_bldr.build();

let mut context = X509StoreContext::new().unwrap();
assert!(context
.init(&store, &cert, &chain, |c| c.verify_cert())
.unwrap());
assert!(context
.init(&store, &cert, &chain, |c| c.verify_cert())
.unwrap());
}

#[test]
#[cfg(any(ossl102, libressl261))]
fn test_verify_param_set_depth() {
let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let chain = Stack::new().unwrap();

let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
let mut verify_params = X509VerifyParam::new().unwrap();
// OpenSSL 1.1.0+ considers the root certificate to not be part of the chain, while 1.0.2 does
let expected_depth = if cfg!(any(ossl110, libressl261)) {
0
} else {
1
};
verify_params.set_depth(expected_depth);
store_bldr.set_param(&verify_params).unwrap();
let store = store_bldr.build();

let mut context = X509StoreContext::new().unwrap();
assert!(context
.init(&store, &cert, &chain, |c| c.verify_cert())
.unwrap());
assert!(context
.init(&store, &cert, &chain, |c| c.verify_cert())
.unwrap());
}
27 changes: 25 additions & 2 deletions openssl/src/x509/verify.rs
@@ -1,10 +1,10 @@
use bitflags::bitflags;
use foreign_types::ForeignTypeRef;
use libc::{c_uint, c_ulong};
use libc::{c_int, c_uint, c_ulong, time_t};
use std::net::IpAddr;

use crate::cvt;
use crate::error::ErrorStack;
use crate::{cvt, cvt_p};
use openssl_macros::corresponds;

bitflags! {
Expand Down Expand Up @@ -69,6 +69,17 @@ foreign_type_and_impl_send_sync! {
pub struct X509VerifyParamRef;
}

impl X509VerifyParam {
/// Create an X509VerifyParam
#[corresponds(X509_VERIFY_PARAM_new)]
pub fn new() -> Result<X509VerifyParam, ErrorStack> {
unsafe {
ffi::init();
cvt_p(ffi::X509_VERIFY_PARAM_new()).map(X509VerifyParam)
}
}
}

impl X509VerifyParamRef {
/// Set the host flags.
#[corresponds(X509_VERIFY_PARAM_set_hostflags)]
Expand Down Expand Up @@ -139,4 +150,16 @@ impl X509VerifyParamRef {
.map(|_| ())
}
}

/// Set the verification time, where time is of type time_t, traditionaly defined as seconds since the epoch
#[corresponds(X509_VERIFY_PARAM_set_time)]
pub fn set_time(&mut self, time: time_t) {
unsafe { ffi::X509_VERIFY_PARAM_set_time(self.as_ptr(), time) }
}

/// Set the verification depth
#[corresponds(X509_VERIFY_PARAM_set_depth)]
pub fn set_depth(&mut self, depth: c_int) {
unsafe { ffi::X509_VERIFY_PARAM_set_depth(self.as_ptr(), depth) }
}
}

0 comments on commit 969f955

Please sign in to comment.