mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Get rid of 'read_hkd' by refactoring the 'get_verified_hkds' function. For this a new HkdLoader::load_and_verify is introduced that is a reworked version of the original code. In addition, add test cases for testing all the edge cases. Assisted-by: IBM Bob:1.0.6 Signed-off-by: Marc Hartmayer <marc@linux.ibm.com> Reviewed-by: Steffen Eiden <seiden@linux.ibm.com> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
260 lines
8.1 KiB
Rust
260 lines
8.1 KiB
Rust
// SPDX-License-Identifier: MIT
|
|
//
|
|
// Copyright IBM Corp.
|
|
|
|
//! Integration tests for malformed host key document handling
|
|
|
|
use std::fs::{self, File};
|
|
use std::io::Write;
|
|
use std::path::PathBuf;
|
|
|
|
use pv::request::NoVerifyHkd;
|
|
use utils::{AutoOrExplicit, HkdLoader, HkdVersion, TemporaryDirectory};
|
|
|
|
/// Path to test certificate assets
|
|
fn cert_asset_path(name: &str) -> PathBuf {
|
|
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.parent()
|
|
.unwrap()
|
|
.join("pv/tests/assets/cert")
|
|
.join(name)
|
|
}
|
|
|
|
#[test]
|
|
fn test_empty_hkd_file() {
|
|
let temp_dir = TemporaryDirectory::new().unwrap();
|
|
let file_path = temp_dir.path().join("empty.hkd");
|
|
File::create(&file_path).unwrap();
|
|
|
|
let result = HkdLoader::load_and_verify(&file_path, &NoVerifyHkd, AutoOrExplicit::Auto);
|
|
assert!(result.is_err(), "Empty HKD file should be rejected");
|
|
|
|
let err = result.unwrap_err();
|
|
assert!(
|
|
matches!(err, pv::Error::NoHkdInFile(_)),
|
|
"Expected NoHkdInFile error, got: {:?}",
|
|
err
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_invalid_pem_format() {
|
|
// Create a file with invalid PEM content
|
|
let temp_dir = TemporaryDirectory::new().unwrap();
|
|
let file_path = temp_dir.path().join("invalid.hkd");
|
|
let mut temp_file = File::create(&file_path).unwrap();
|
|
writeln!(temp_file, "-----BEGIN CERTIFICATE-----").unwrap();
|
|
writeln!(temp_file, "INVALID_BASE64_CONTENT!!!").unwrap();
|
|
writeln!(temp_file, "-----END CERTIFICATE-----").unwrap();
|
|
temp_file.flush().unwrap();
|
|
|
|
// Test that invalid PEM is properly rejected with HkdNotPemOrDer error
|
|
let result = HkdLoader::load_and_verify(&file_path, &NoVerifyHkd, AutoOrExplicit::Auto);
|
|
assert!(result.is_err(), "Invalid PEM format should be rejected");
|
|
|
|
let err = result.unwrap_err();
|
|
assert!(
|
|
matches!(err, pv::Error::HkdNotPemOrDer { .. }),
|
|
"Expected HkdNotPemOrDer error, got: {:?}",
|
|
err
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_wrong_number_of_certificates_v1() {
|
|
// Create a file with three valid certificates (invalid count for v1, expects 1)
|
|
let temp_dir = TemporaryDirectory::new().unwrap();
|
|
let file_path = temp_dir.path().join("wrong_count_v1.hkd");
|
|
let mut temp_file = File::create(&file_path).unwrap();
|
|
|
|
let cert1 = fs::read_to_string(cert_asset_path("host.crt")).unwrap();
|
|
let cert2 = fs::read_to_string(cert_asset_path("ibm.crt")).unwrap();
|
|
let cert3 = fs::read_to_string(cert_asset_path("root_ca.crt")).unwrap();
|
|
|
|
write!(temp_file, "{}{}{}", cert1, cert2, cert3).unwrap();
|
|
temp_file.flush().unwrap();
|
|
|
|
let result = HkdLoader::load_and_verify(
|
|
&file_path,
|
|
&NoVerifyHkd,
|
|
AutoOrExplicit::Explicit(HkdVersion::Classical),
|
|
);
|
|
assert!(
|
|
result.is_err(),
|
|
"Wrong number of certificates for v1 should be rejected"
|
|
);
|
|
|
|
let err = result.unwrap_err();
|
|
assert!(
|
|
matches!(err, pv::Error::WrongNumberOfKeys(_)),
|
|
"Expected WrongNumberOfKeys error, got: {:?}",
|
|
err
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_wrong_number_of_certificates_v2() {
|
|
// Use existing single certificate file directly (invalid count for v2, expects 2)
|
|
let file_path = cert_asset_path("host.crt");
|
|
|
|
// Test that wrong number of certificates is properly rejected with WrongNumberOfKeys error
|
|
let result = HkdLoader::load_and_verify(
|
|
&file_path,
|
|
&NoVerifyHkd,
|
|
AutoOrExplicit::Explicit(HkdVersion::Hybrid),
|
|
);
|
|
assert!(
|
|
result.is_err(),
|
|
"Wrong number of certificates for v2 should be rejected"
|
|
);
|
|
|
|
let err = result.unwrap_err();
|
|
assert!(
|
|
matches!(err, pv::Error::WrongNumberOfKeys(_)),
|
|
"Expected WrongNumberOfKeys error, got: {:?}",
|
|
err
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_corrupted_certificate() {
|
|
// Create a file with corrupted certificate data
|
|
let temp_dir = TemporaryDirectory::new().unwrap();
|
|
let file_path = temp_dir.path().join("corrupted.hkd");
|
|
let mut temp_file = File::create(&file_path).unwrap();
|
|
writeln!(temp_file, "-----BEGIN CERTIFICATE-----").unwrap();
|
|
writeln!(
|
|
temp_file,
|
|
"MIICdTCCAd6gAwIBAgIBADANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEL"
|
|
)
|
|
.unwrap();
|
|
writeln!(temp_file, "CORRUPTED_DATA_HERE").unwrap();
|
|
writeln!(temp_file, "-----END CERTIFICATE-----").unwrap();
|
|
temp_file.flush().unwrap();
|
|
|
|
let result = HkdLoader::load_and_verify(&file_path, &NoVerifyHkd, AutoOrExplicit::Auto);
|
|
assert!(result.is_err(), "Corrupted certificate should be rejected");
|
|
|
|
let err = result.unwrap_err();
|
|
assert!(
|
|
matches!(err, pv::Error::HkdNotPemOrDer { .. }),
|
|
"Expected HkdNotPemOrDer error, got: {:?}",
|
|
err
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_wrong_key_type_v1() {
|
|
// Use RSA certificate instead of EC-p521 for v1 (should fail)
|
|
let file_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.parent()
|
|
.unwrap()
|
|
.join("pv/tests/assets/keys/rsa2048.crt");
|
|
|
|
let result = HkdLoader::load_and_verify(
|
|
&file_path,
|
|
&NoVerifyHkd,
|
|
AutoOrExplicit::Explicit(HkdVersion::Classical),
|
|
);
|
|
assert!(
|
|
result.is_err(),
|
|
"RSA key should be rejected for v1 (expects EC-p521)"
|
|
);
|
|
|
|
let err = result.unwrap_err();
|
|
if let pv::Error::InvalidHkd(msg) = err {
|
|
assert_eq!(
|
|
msg, "First key must be a EC-p521 key",
|
|
"Error message should indicate EC-p521 requirement"
|
|
);
|
|
} else {
|
|
panic!(
|
|
"Expected InvalidHkd error for wrong key type, got: {:?}",
|
|
err
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_wrong_key_type_v2() {
|
|
// Create a file with two RSA certificates instead of EC-p521 + ML-KEM for v2
|
|
let temp_dir = TemporaryDirectory::new().unwrap();
|
|
let file_path = temp_dir.path().join("wrong_key_v2.hkd");
|
|
let mut temp_file = File::create(&file_path).unwrap();
|
|
|
|
// Read two RSA certificates and concatenate them
|
|
let rsa_cert_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.parent()
|
|
.unwrap()
|
|
.join("pv/tests/assets/keys/rsa2048.crt");
|
|
let rsa_cert = fs::read_to_string(&rsa_cert_path).unwrap();
|
|
|
|
write!(temp_file, "{}{}", rsa_cert, rsa_cert).unwrap();
|
|
temp_file.flush().unwrap();
|
|
|
|
// Test that wrong key types are properly rejected with InvalidHkd error
|
|
let result = HkdLoader::load_and_verify(
|
|
&file_path,
|
|
&NoVerifyHkd,
|
|
AutoOrExplicit::Explicit(HkdVersion::Hybrid),
|
|
);
|
|
assert!(
|
|
result.is_err(),
|
|
"RSA keys should be rejected for v2 (expects EC-p521 + ML-KEM)"
|
|
);
|
|
|
|
let err = result.unwrap_err();
|
|
if let pv::Error::InvalidHkd(msg) = err {
|
|
assert_eq!(
|
|
msg, "First key must be a EC-p521 key",
|
|
"Error message should indicate EC-p521 requirement"
|
|
);
|
|
} else {
|
|
panic!(
|
|
"Expected InvalidHkd error for wrong key types, got: {:?}",
|
|
err
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_wrong_second_key_type_v2() {
|
|
// Create a file with EC-p521 + EC (wrong) instead of EC-p521 + ML-KEM for v2
|
|
let temp_dir = TemporaryDirectory::new().unwrap();
|
|
let file_path = temp_dir.path().join("wrong_second_key_v2.hkd");
|
|
let mut temp_file = File::create(&file_path).unwrap();
|
|
|
|
let ec_p521_cert = fs::read_to_string(cert_asset_path("host.crt")).unwrap();
|
|
let ec_cert_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.parent()
|
|
.unwrap()
|
|
.join("pv/tests/assets/keys/host.ec.crt");
|
|
let ec_cert = fs::read_to_string(&ec_cert_path).unwrap();
|
|
|
|
write!(temp_file, "{}{}", ec_p521_cert, ec_cert).unwrap();
|
|
temp_file.flush().unwrap();
|
|
|
|
let result = HkdLoader::load_and_verify(
|
|
&file_path,
|
|
&NoVerifyHkd,
|
|
AutoOrExplicit::Explicit(HkdVersion::Hybrid),
|
|
);
|
|
assert!(
|
|
result.is_err(),
|
|
"EC key should be rejected as second key for v2 (expects ML-KEM-1024)"
|
|
);
|
|
|
|
let err = result.unwrap_err();
|
|
if let pv::Error::InvalidHkd(msg) = err {
|
|
assert_eq!(
|
|
msg, "Second key must be a ML-KEM 1024 key",
|
|
"Error message should indicate ML-KEM-1024 requirement"
|
|
);
|
|
} else {
|
|
panic!(
|
|
"Expected InvalidHkd error for wrong second key type, got: {:?}",
|
|
err
|
|
);
|
|
}
|
|
}
|