Skip to content

Commit aa500d0

Browse files
Merge #172
172: Adding `Certificate::verify_with_callback` function r=jethrogb a=raoulstrackx For [Nitro attestation verification](fortanix/rust-sgx#376) we need some features introduced by `@AdrianCX` on the `acruceru/port-async-support` branch. For the rust-sgx repo, we want to avoid relying on a separate branch for rust-mbedtls. With this PR two features are added to master: * serialization and deserialization of signatures * Certificate verification with a callback function Co-authored-by: Raoul Strackx <[email protected]>
2 parents f77f80d + 851078e commit aa500d0

File tree

3 files changed

+103
-46
lines changed

3 files changed

+103
-46
lines changed

mbedtls/src/ssl/config.rs

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ use crate::private::UnsafeFrom;
2828
use crate::rng::RngCallback;
2929
use crate::ssl::context::HandshakeContext;
3030
use crate::ssl::ticket::TicketCallback;
31-
use crate::x509::Certificate;
32-
use crate::x509::Crl;
33-
use crate::x509::Profile;
34-
use crate::x509::VerifyError;
31+
use crate::x509::{self, Certificate, Crl, Profile, VerifyCallback};
3532

3633
#[allow(non_camel_case_types)]
3734
#[derive(Eq, PartialEq, PartialOrd, Ord, Debug, Copy, Clone)]
@@ -98,7 +95,6 @@ define!(
9895
}
9996
);
10097

101-
callback!(VerifyCallback: Fn(&Certificate, i32, &mut VerifyError) -> Result<()>);
10298
#[cfg(feature = "std")]
10399
callback!(DbgCallback: Fn(i32, Cow<'_, str>, i32, Cow<'_, str>) -> ());
104100
callback!(SniCallback: Fn(&mut HandshakeContext, &[u8]) -> Result<()>);
@@ -343,40 +339,8 @@ impl Config {
343339
where
344340
F: VerifyCallback + 'static,
345341
{
346-
unsafe extern "C" fn verify_callback<F>(
347-
closure: *mut c_void,
348-
crt: *mut x509_crt,
349-
depth: c_int,
350-
flags: *mut u32,
351-
) -> c_int
352-
where
353-
F: VerifyCallback + 'static,
354-
{
355-
if crt.is_null() || closure.is_null() || flags.is_null() {
356-
return ::mbedtls_sys::ERR_X509_BAD_INPUT_DATA;
357-
}
358-
359-
let cb = &mut *(closure as *mut F);
360-
let crt: &mut Certificate = UnsafeFrom::from(crt).expect("valid certificate");
361-
362-
let mut verify_error = match VerifyError::from_bits(*flags) {
363-
Some(ve) => ve,
364-
// This can only happen if mbedtls is setting flags in VerifyError that are
365-
// missing from our definition.
366-
None => return ::mbedtls_sys::ERR_X509_BAD_INPUT_DATA,
367-
};
368-
369-
let res = cb(crt, depth, &mut verify_error);
370-
*flags = verify_error.bits();
371-
match res {
372-
Ok(()) => 0,
373-
Err(e) => e.to_int(),
374-
}
375-
}
376-
377-
378342
self.verify_callback = Some(Arc::new(cb));
379-
unsafe { ssl_conf_verify(self.into(), Some(verify_callback::<F>), &**self.verify_callback.as_mut().unwrap() as *const _ as *mut c_void) }
343+
unsafe { ssl_conf_verify(self.into(), Some(x509::verify_callback::<F>), &**self.verify_callback.as_ref().unwrap() as *const _ as *mut c_void) }
380344
}
381345

382346
pub fn set_ca_callback<F>(&mut self, cb: F)

mbedtls/src/x509/certificate.rs

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use core::iter::FromIterator;
1111
use core::ptr::NonNull;
1212

1313
use mbedtls_sys::*;
14-
use mbedtls_sys::types::raw_types::c_char;
14+
use mbedtls_sys::types::raw_types::{c_char, c_void};
1515

1616
use crate::alloc::{List as MbedtlsList, Box as MbedtlsBox};
1717
#[cfg(not(feature = "std"))]
@@ -21,7 +21,7 @@ use crate::hash::Type as MdType;
2121
use crate::pk::Pk;
2222
use crate::private::UnsafeFrom;
2323
use crate::rng::Random;
24-
use crate::x509::Time;
24+
use crate::x509::{self, Time, VerifyCallback};
2525

2626
extern "C" {
2727
pub(crate) fn forward_mbedtls_calloc(n: mbedtls_sys::types::size_t, size: mbedtls_sys::types::size_t) -> *mut mbedtls_sys::types::raw_types::c_void;
@@ -221,11 +221,21 @@ impl Certificate {
221221
MdType::from(self.inner.sig_md)
222222
}
223223

224-
pub fn verify(
224+
fn verify_ex<F>(
225225
chain: &MbedtlsList<Certificate>,
226226
trust_ca: &MbedtlsList<Certificate>,
227227
err_info: Option<&mut String>,
228-
) -> Result<()> {
228+
cb: Option<F>,
229+
) -> Result<()>
230+
where
231+
F: VerifyCallback + 'static,
232+
{
233+
let (f_vrfy, p_vrfy): (Option<unsafe extern "C" fn(_, _, _, _) -> _>, _) = if let Some(cb) = cb.as_ref() {
234+
(Some(x509::verify_callback::<F>),
235+
cb as *const _ as *mut c_void)
236+
} else {
237+
(None, ::core::ptr::null_mut())
238+
};
229239
let mut flags = 0;
230240
let result = unsafe {
231241
x509_crt_verify(
@@ -234,8 +244,8 @@ impl Certificate {
234244
::core::ptr::null_mut(),
235245
::core::ptr::null(),
236246
&mut flags,
237-
None,
238-
::core::ptr::null_mut(),
247+
f_vrfy,
248+
p_vrfy,
239249
)
240250
}
241251
.into_result();
@@ -253,6 +263,26 @@ impl Certificate {
253263
}
254264
result.map(|_| ())
255265
}
266+
267+
pub fn verify(
268+
chain: &MbedtlsList<Certificate>,
269+
trust_ca: &MbedtlsList<Certificate>,
270+
err_info: Option<&mut String>,
271+
) -> Result<()> {
272+
Self::verify_ex(chain, trust_ca, err_info, None::<&dyn VerifyCallback>)
273+
}
274+
275+
pub fn verify_with_callback<F>(
276+
chain: &MbedtlsList<Certificate>,
277+
trust_ca: &MbedtlsList<Certificate>,
278+
err_info: Option<&mut String>,
279+
cb: F,
280+
) -> Result<()>
281+
where
282+
F: VerifyCallback + 'static,
283+
{
284+
Self::verify_ex(chain, trust_ca, err_info, Some(cb))
285+
}
256286
}
257287

258288
// TODO
@@ -719,10 +749,10 @@ impl Extend<MbedtlsBox::<Certificate>> for MbedtlsList<Certificate> {
719749
}
720750
}
721751

722-
723752
#[cfg(test)]
724753
mod tests {
725754
use super::*;
755+
use crate::x509::VerifyError;
726756

727757
struct Test {
728758
key1: Pk,
@@ -995,7 +1025,22 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
9951025

9961026
// try again after fixing the chain
9971027
chain.push(c_int2.clone());
1028+
1029+
1030+
let mut err_str = String::new();
1031+
1032+
let verify_callback = |_crt: &Certificate, _depth: i32, verify_flags: &mut VerifyError| {
1033+
verify_flags.remove(VerifyError::CERT_EXPIRED);
1034+
Ok(())
1035+
};
1036+
9981037
Certificate::verify(&chain, &mut c_root, None).unwrap();
1038+
let res = Certificate::verify_with_callback(&chain, &mut c_root, Some(&mut err_str), verify_callback);
1039+
1040+
match res {
1041+
Ok(()) => (),
1042+
Err(e) => assert!(false, "Failed to verify, error: {}, err_str: {}", e, err_str),
1043+
};
9991044
}
10001045

10011046
{
@@ -1005,6 +1050,19 @@ cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
10051050
chain.push(c_int2.clone());
10061051

10071052
Certificate::verify(&chain, &mut c_root, None).unwrap();
1053+
1054+
let verify_callback = |_crt: &Certificate, _depth: i32, verify_flags: &mut VerifyError| {
1055+
verify_flags.remove(VerifyError::CERT_EXPIRED);
1056+
Ok(())
1057+
};
1058+
1059+
let mut err_str = String::new();
1060+
let res = Certificate::verify_with_callback(&chain, &mut c_root, Some(&mut err_str), verify_callback);
1061+
1062+
match res {
1063+
Ok(()) => (),
1064+
Err(e) => assert!(false, "Failed to verify, error: {}, err_str: {}", e, err_str),
1065+
};
10081066
}
10091067
}
10101068

mbedtls/src/x509/mod.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ pub mod profile;
1717
// write_crt
1818
// write_csr
1919

20+
use crate::error::Error;
21+
use crate::private::UnsafeFrom;
2022
#[doc(inline)]
2123
pub use self::certificate::Certificate;
2224
pub use self::crl::Crl;
@@ -26,7 +28,7 @@ pub use self::csr::Csr;
2628
pub use self::profile::Profile;
2729

2830
use mbedtls_sys::*;
29-
use mbedtls_sys::types::raw_types::c_uint;
31+
use mbedtls_sys::types::raw_types::{c_int, c_uint, c_void};
3032
bitflags! {
3133
pub struct KeyUsage: c_uint {
3234
const DIGITAL_SIGNATURE = X509_KU_DIGITAL_SIGNATURE as c_uint;
@@ -117,6 +119,39 @@ impl VerifyError {
117119
}
118120
}
119121

122+
callback!(VerifyCallback: Fn(&Certificate, i32, &mut VerifyError) -> Result<(), Error>);
123+
124+
pub(crate) unsafe extern "C" fn verify_callback<F>(
125+
closure: *mut c_void,
126+
crt: *mut x509_crt,
127+
depth: c_int,
128+
flags: *mut u32,
129+
) -> c_int
130+
where
131+
F: VerifyCallback + 'static,
132+
{
133+
if crt.is_null() || closure.is_null() || flags.is_null() {
134+
return ::mbedtls_sys::ERR_X509_BAD_INPUT_DATA;
135+
}
136+
137+
let cb = &*(closure as *const F);
138+
let crt: &mut Certificate = UnsafeFrom::from(crt).expect("valid certificate");
139+
140+
let mut verify_error = match VerifyError::from_bits(*flags) {
141+
Some(ve) => ve,
142+
// This can only happen if mbedtls is setting flags in VerifyError that are
143+
// missing from our definition.
144+
None => return ::mbedtls_sys::ERR_X509_BAD_INPUT_DATA,
145+
};
146+
147+
let res = cb(crt, depth, &mut verify_error);
148+
*flags = verify_error.bits();
149+
match res {
150+
Ok(()) => 0,
151+
Err(e) => e.to_int(),
152+
}
153+
}
154+
120155
/// A specific moment in time in UTC
121156
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
122157
pub struct Time {

0 commit comments

Comments
 (0)