rust/pv: Reorganize some tests

Use a static Mockito server instead of creating multiple on-the-fly
during testing. Add the `mockito_server_available` test to quickly
verify that the mockito server could be constructed.  Relocate the
verifier API test to the test folder as it tests the public API. Also,
make the Debug impl for CertVerifier public. The test relocation
requires this. Before, there could be a test local implementation of the
Debug impl as it was in the same crate.

While at it, get rid of the lazy_static crate in favor of the once_cell
crate. As the new std lib implementation is very near to the one from
once cell. The project will switch to the std impl when v1.70 is
available in all supported distros. See:
https://doc.rust-lang.org/std/sync/struct.OnceLock.html

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Steffen Eiden
2023-12-20 13:57:52 +01:00
committed by Jan Höppner
parent 02dded11a5
commit c0a12b29d0
6 changed files with 142 additions and 123 deletions
+3 -3
View File
@@ -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",
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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 {
+6
View File
@@ -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:
+11 -118
View File
@@ -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<Mutex<mockito::Server>> = 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");
+120
View File
@@ -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());
}