diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 039f7944..ea944a76 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -651,9 +651,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" @@ -779,9 +779,9 @@ dependencies = [ "byteorder", "clap", "curl", - "lazy_static", "log", "mockito", + "once_cell", "openssl", "openssl_extensions", "pv_core", diff --git a/rust/pv/Cargo.toml b/rust/pv/Cargo.toml index 2388ce23..3dfd7a84 100644 --- a/rust/pv/Cargo.toml +++ b/rust/pv/Cargo.toml @@ -20,5 +20,5 @@ pv_core = { path = "../pv_core" } [dev-dependencies] mockito = {version = "1", default-features = false } +once_cell = "1.19" serde_test = "1" -lazy_static = "1.1" diff --git a/rust/pv/src/lib.rs b/rust/pv/src/lib.rs index 78569712..2924e91d 100644 --- a/rust/pv/src/lib.rs +++ b/rust/pv/src/lib.rs @@ -66,7 +66,7 @@ pub mod request { pub use crate::crypto::{Aes256Key, SymKey, SymKeyType}; pub use crate::req::{Aad, Encrypt, Keyslot, ReqEncrCtx, Request}; pub use crate::secret::{Secret, Zeroize}; - pub use crate::verify::HkdVerifier; + pub use crate::verify::{CertVerifier, HkdVerifier, NoVerifyHkd}; /// Reexports some useful OpenSSL symbols pub mod openssl { diff --git a/rust/pv/src/verify.rs b/rust/pv/src/verify.rs index 54fe4357..b000f0ae 100644 --- a/rust/pv/src/verify.rs +++ b/rust/pv/src/verify.rs @@ -45,6 +45,12 @@ pub struct CertVerifier { offline: bool, } +impl std::fmt::Debug for CertVerifier { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("CertVerifier") + } +} + impl HkdVerifier for CertVerifier { /// This function verifies a host-key /// document. To do so multiple steps are required: diff --git a/rust/pv/src/verify/test.rs b/rust/pv/src/verify/test.rs index b6a57d64..da7ac1a6 100644 --- a/rust/pv/src/verify/test.rs +++ b/rust/pv/src/verify/test.rs @@ -7,46 +7,30 @@ use super::{helper, helper::*, *}; use crate::{Error, HkdVerifyErrorType::*}; use core::slice; +use once_cell::sync::OnceCell; use openssl::stack::Stack; -use std::ffi::c_int; +use std::sync::Mutex; use crate::test_utils::*; pub fn mock_endpt(res: &str) -> mockito::Mock { + static MOCK_SERVER: OnceCell> = OnceCell::new(); + let res_path = get_cert_asset_path(res); - let mut server = mockito::Server::new(); - server + MOCK_SERVER + .get_or_init(|| mockito::Server::new_with_port(1234).into()) + .lock() + .expect("COULD NOT GET THE MOCK_SERVER LOCK") .mock("GET", format!("/crl/{res}").as_str()) .with_header("content-type", "application/pkix-crl") .with_body_from_file(res_path) .create() } -#[track_caller] -fn verify_sign_error(exp_raw: c_int, obs: Error) { - verify_sign_error_slice(&[exp_raw], obs) -} -fn verify_sign_error_slice(exp_raw: &[c_int], obs: Error) { - if exp_raw - .iter() - .filter(|e| match &obs { - Error::HkdVerify(ty) => match ty { - IbmSignInvalid(err, _d) => &&err.as_raw() == e, - _ => false, - }, - e => panic!("Unexpected error type: {e:?}"), - }) - .count() - == 0 - { - panic!("Error {obs:?} did not match one of the expected {exp_raw:?}"); - } -} -impl std::fmt::Debug for CertVerifier { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("CertVerifier") - } +#[test] +fn mockito_server_available() { + let _mock = mock_endpt("ibm.crt"); } #[test] @@ -175,97 +159,6 @@ fn verify_offline() { )); } -#[test] -fn verifier_new() { - let root_chn_crt = get_cert_asset_path_string("root_ca.chained.crt"); - let root_crt = get_cert_asset_path_string("root_ca.crt"); - let inter_crt = get_cert_asset_path_string("inter_ca.crt"); - let inter_fake_crt = get_cert_asset_path_string("fake_inter_ca.crt"); - let inter_fake_crl = get_cert_asset_path_string("fake_inter_ca.crl"); - let inter_crl = get_cert_asset_path_string("inter_ca.crl"); - let ibm_crt = get_cert_asset_path_string("ibm.crt"); - let ibm_early_crt = get_cert_asset_path_string("ibm_outdated_early.crl"); - let ibm_late_crt = get_cert_asset_path_string("ibm_outdated_late.crl"); - let ibm_rev_crt = get_cert_asset_path_string("ibm_rev.crt"); - - // To many signing keys - let verifier = CertVerifier::new(&[ibm_crt.clone(), ibm_rev_crt.clone()], &[], &None, true); - assert!(matches!(verifier, Err(Error::HkdVerify(ManyIbmSignKeys)))); - - // no CRL for each X509 - let verifier = CertVerifier::new( - &[inter_crt.clone(), ibm_crt.clone()], - &[inter_crl.clone()], - &Some(root_crt), - false, - ); - verify_sign_error(3, verifier.unwrap_err()); - let verifier = CertVerifier::new( - &[inter_crt.clone(), ibm_crt.clone()], - &[], - &Some(root_chn_crt.clone()), - false, - ); - verify_sign_error(3, verifier.unwrap_err()); - - // wrong intermediate (or ibm key) - let verifier = CertVerifier::new( - &[inter_fake_crt, ibm_crt.clone()], - &[inter_fake_crl], - &Some(root_chn_crt.clone()), - true, - ); - //Depending on the OpenSSL version different error codes can appear - verify_sign_error_slice(&[20, 30], verifier.unwrap_err()); - - //wrong root ca - let verifier = CertVerifier::new( - &[inter_crt.clone(), ibm_crt.clone()], - &[inter_crl.clone()], - &None, - true, - ); - verify_sign_error(20, verifier.unwrap_err()); - - //correct signing key + intermediate cert - let _verifier = CertVerifier::new( - &[inter_crt.clone(), ibm_crt.clone()], - &[inter_crl.clone()], - &Some(root_chn_crt.clone()), - false, - ) - .unwrap(); - - // no intermediate key - let verifier = CertVerifier::new(&[ibm_crt], &[], &Some(root_chn_crt.clone()), false); - verify_sign_error(20, verifier.unwrap_err()); - - //Ibm Sign outdated - let verifier = CertVerifier::new( - &[inter_crt.clone(), ibm_early_crt], - &[inter_crl.clone()], - &Some(root_chn_crt.clone()), - false, - ); - assert!(matches!(verifier, Err(Error::HkdVerify(NoIbmSignKey)))); - let verifier = CertVerifier::new( - &[inter_crt.clone(), ibm_late_crt], - &[inter_crl.clone()], - &Some(root_chn_crt.clone()), - false, - ); - assert!(matches!(verifier, Err(Error::HkdVerify(NoIbmSignKey)))); - - // revoked - let verifier = CertVerifier::new( - &[inter_crt, ibm_rev_crt], - &[inter_crl], - &Some(root_chn_crt), - false, - ); - verify_sign_error(23, verifier.unwrap_err()); -} - #[test] fn dist_points() { let crt = load_gen_cert("ibm.crt"); diff --git a/rust/pv/tests/cert_verifier.rs b/rust/pv/tests/cert_verifier.rs new file mode 100644 index 00000000..cb2606bf --- /dev/null +++ b/rust/pv/tests/cert_verifier.rs @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MIT +// +// Copyright IBM Corp. 2023 + +use pv::request::CertVerifier; +use pv::test_utils::*; +use pv::{Error, HkdVerifyErrorType::*}; +use std::ffi::c_int; + +#[track_caller] +fn verify_sign_error(exp_raw: c_int, obs: Error) { + verify_sign_error_slice(&[exp_raw], obs) +} +fn verify_sign_error_slice(exp_raw: &[c_int], obs: Error) { + if exp_raw + .iter() + .filter(|e| match &obs { + Error::HkdVerify(ty) => match ty { + IbmSignInvalid(err, _d) => &&err.as_raw() == e, + _ => false, + }, + e => panic!("Unexpected error type: {e:?}"), + }) + .count() + == 0 + { + panic!("Error {obs:?} did not match one of the expected {exp_raw:?}"); + } +} + +#[test] +fn verifier_new() { + let root_chn_crt = get_cert_asset_path_string("root_ca.chained.crt"); + let root_crt = get_cert_asset_path_string("root_ca.crt"); + let inter_crt = get_cert_asset_path_string("inter_ca.crt"); + let inter_fake_crt = get_cert_asset_path_string("fake_inter_ca.crt"); + let inter_fake_crl = get_cert_asset_path_string("fake_inter_ca.crl"); + let inter_crl = get_cert_asset_path_string("inter_ca.crl"); + let ibm_crt = get_cert_asset_path_string("ibm.crt"); + let ibm_early_crt = get_cert_asset_path_string("ibm_outdated_early.crl"); + let ibm_late_crt = get_cert_asset_path_string("ibm_outdated_late.crl"); + let ibm_rev_crt = get_cert_asset_path_string("ibm_rev.crt"); + + // Too many signing keys + let verifier = CertVerifier::new(&[ibm_crt.clone(), ibm_rev_crt.clone()], &[], &None, true); + assert!(matches!(verifier, Err(Error::HkdVerify(ManyIbmSignKeys)))); + + // No CRL for each X509 + let verifier = CertVerifier::new( + &[inter_crt.clone(), ibm_crt.clone()], + &[inter_crl.clone()], + &Some(root_crt), + false, + ); + verify_sign_error(3, verifier.unwrap_err()); + let verifier = CertVerifier::new( + &[inter_crt.clone(), ibm_crt.clone()], + &[], + &Some(root_chn_crt.clone()), + false, + ); + verify_sign_error(3, verifier.unwrap_err()); + + // Wrong intermediate (or ibm key) + let verifier = CertVerifier::new( + &[inter_fake_crt, ibm_crt.clone()], + &[inter_fake_crl], + &Some(root_chn_crt.clone()), + true, + ); + // Depending on the OpenSSL version different error codes can appear + verify_sign_error_slice(&[20, 30], verifier.unwrap_err()); + + // Wrong root ca + let verifier = CertVerifier::new( + &[inter_crt.clone(), ibm_crt.clone()], + &[inter_crl.clone()], + &None, + true, + ); + verify_sign_error(20, verifier.unwrap_err()); + + // Correct signing key + intermediate cert + let _verifier = CertVerifier::new( + &[inter_crt.clone(), ibm_crt.clone()], + &[inter_crl.clone()], + &Some(root_chn_crt.clone()), + false, + ) + .unwrap(); + + // No intermediate key + let verifier = CertVerifier::new(&[ibm_crt], &[], &Some(root_chn_crt.clone()), false); + verify_sign_error(20, verifier.unwrap_err()); + + // IBM Sign outdated + let verifier = CertVerifier::new( + &[inter_crt.clone(), ibm_early_crt], + &[inter_crl.clone()], + &Some(root_chn_crt.clone()), + false, + ); + assert!(matches!(verifier, Err(Error::HkdVerify(NoIbmSignKey)))); + let verifier = CertVerifier::new( + &[inter_crt.clone(), ibm_late_crt], + &[inter_crl.clone()], + &Some(root_chn_crt.clone()), + false, + ); + assert!(matches!(verifier, Err(Error::HkdVerify(NoIbmSignKey)))); + + // Revoked + let verifier = CertVerifier::new( + &[inter_crt, ibm_rev_crt], + &[inter_crl], + &Some(root_chn_crt), + false, + ); + verify_sign_error(23, verifier.unwrap_err()); +}