mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Add unite tests and (binary) test asses for the hybrid key patch. Co-developed-by: Marc Hartmayer <marc@linux.ibm.com> Signed-off-by: Marc Hartmayer <marc@linux.ibm.com> Signed-off-by: Timo Keller <tkeller@linux.ibm.com> Reviewed-by: Steffen Eiden <seiden@linux.ibm.com> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
469 lines
15 KiB
Rust
469 lines
15 KiB
Rust
// SPDX-License-Identifier: MIT
|
|
//
|
|
// Copyright IBM Corp. 2023
|
|
|
|
#![allow(missing_docs)]
|
|
use openssl::ec::{EcGroup, EcKey};
|
|
use openssl::nid::Nid;
|
|
use openssl::pkey::Private;
|
|
use s390_pv::request::openssl::pkey::PKey;
|
|
use s390_pv::request::{BootHdrTags, HostKey, HybridPKey, ReqEncrCtx, Request, SymKey};
|
|
use s390_pv::secret::{
|
|
verify_asrcb_and_get_user_data, AddSecretFlags, AddSecretRequest, AddSecretVersion, ExtSecret,
|
|
GuestSecret,
|
|
};
|
|
use s390_pv::test_utils::{get_test_keys, get_test_keys_hybrid, DeterministicTestRandGuard};
|
|
use s390_pv::uv::ConfigUid;
|
|
use s390_pv::{get_test_asset, Result};
|
|
|
|
const TAGS: BootHdrTags = BootHdrTags::new([1; 64], [2; 64], [3; 64], [4; 16]);
|
|
const CUID: ConfigUid = [0x42u8; 16];
|
|
const ASSOC_SECRET: [u8; 32] = [0x11; 32];
|
|
const ASSOC_ID: &str = "add_secret_request";
|
|
|
|
fn create_asrcb(
|
|
guest_secret: GuestSecret,
|
|
ext_secret: Option<ExtSecret>,
|
|
flags: AddSecretFlags,
|
|
cuid: Option<ConfigUid>,
|
|
hkd: HostKey,
|
|
ctx: &ReqEncrCtx,
|
|
) -> Result<Vec<u8>> {
|
|
let asrcb = match hkd {
|
|
HostKey::V1(_) => AddSecretRequest::new(AddSecretVersion::One, guest_secret, TAGS, flags),
|
|
HostKey::V2(_) => AddSecretRequest::new(AddSecretVersion::Two, guest_secret, TAGS, flags),
|
|
_ => unreachable!("Unknown HostKey version"),
|
|
};
|
|
|
|
let mut asrcb = asrcb?;
|
|
if let Some(s) = ext_secret {
|
|
asrcb.set_ext_secret(s)?
|
|
};
|
|
if let Some(c) = cuid {
|
|
asrcb.set_cuid(c);
|
|
};
|
|
|
|
asrcb.add_hostkey(hkd)?;
|
|
asrcb.encrypt(ctx)
|
|
}
|
|
|
|
fn get_crypto() -> (HostKey, ReqEncrCtx) {
|
|
let (cust_key, host_key) = get_test_keys();
|
|
let host_key = HostKey::V1(host_key);
|
|
let ctx = ReqEncrCtx::new_aes_256(
|
|
Some([0x55; 12]),
|
|
Some(cust_key),
|
|
Some(SymKey::Aes256([0x17; 32].into())),
|
|
)
|
|
.unwrap();
|
|
(host_key, ctx)
|
|
}
|
|
|
|
fn get_crypto_v2() -> (HostKey, ReqEncrCtx) {
|
|
let (cust_key, host_key1, host_key2) = get_test_keys_hybrid();
|
|
let host_key = HostKey::V2(HybridPKey::new(host_key1, host_key2).unwrap());
|
|
let ctx = ReqEncrCtx::new_aes_256(
|
|
Some([0x55; 12]),
|
|
Some(cust_key),
|
|
Some(SymKey::Aes256([0x17; 32].into())),
|
|
)
|
|
.unwrap();
|
|
(host_key, ctx)
|
|
}
|
|
|
|
fn gen_asrcb<E>(
|
|
guest_secret: GuestSecret,
|
|
ext_secret: E,
|
|
flags: AddSecretFlags,
|
|
cuid: bool,
|
|
) -> Result<Vec<u8>>
|
|
where
|
|
E: Into<Option<ExtSecret>>,
|
|
{
|
|
let (host_key, ctx) = get_crypto();
|
|
let cuid = match cuid {
|
|
true => Some(CUID),
|
|
false => None,
|
|
};
|
|
create_asrcb(guest_secret, ext_secret.into(), flags, cuid, host_key, &ctx)
|
|
}
|
|
|
|
fn gen_asrcb_v2<E>(
|
|
guest_secret: GuestSecret,
|
|
ext_secret: E,
|
|
flags: AddSecretFlags,
|
|
cuid: bool,
|
|
) -> Result<Vec<u8>>
|
|
where
|
|
E: Into<Option<ExtSecret>>,
|
|
{
|
|
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
|
let (host_key, ctx) = get_crypto_v2();
|
|
let cuid = match cuid {
|
|
true => Some(CUID),
|
|
false => None,
|
|
};
|
|
create_asrcb(guest_secret, ext_secret.into(), flags, cuid, host_key, &ctx)
|
|
}
|
|
|
|
fn association() -> GuestSecret {
|
|
GuestSecret::association(ASSOC_ID, ASSOC_SECRET).unwrap()
|
|
}
|
|
|
|
fn ext_simple() -> ExtSecret {
|
|
ExtSecret::Simple([0x17; 32].into())
|
|
}
|
|
|
|
fn ext_derived() -> ExtSecret {
|
|
ExtSecret::Derived([0; 32].into())
|
|
}
|
|
|
|
fn no_flag() -> AddSecretFlags {
|
|
AddSecretFlags::default()
|
|
}
|
|
|
|
fn create_signed_asrcb(skey: PKey<Private>, user_data: Vec<u8>) -> Vec<u8> {
|
|
let (host_key, ctx) = get_crypto();
|
|
let mut asrcb =
|
|
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag())
|
|
.expect("AddSecretRequest::new failed");
|
|
|
|
asrcb.add_hostkey(host_key).unwrap();
|
|
asrcb.set_user_data(user_data, Some(skey)).unwrap();
|
|
asrcb.encrypt(&ctx).unwrap()
|
|
}
|
|
|
|
fn create_signed_asrcb_v2(skey: PKey<Private>, user_data: Vec<u8>) -> Vec<u8> {
|
|
let (host_key, ctx) = get_crypto_v2();
|
|
let mut asrcb =
|
|
AddSecretRequest::new(AddSecretVersion::Two, GuestSecret::Null, TAGS, no_flag())
|
|
.expect("AddSecretRequest::new failed");
|
|
|
|
asrcb.add_hostkey(host_key).unwrap();
|
|
asrcb.set_user_data(user_data, Some(skey)).unwrap();
|
|
asrcb.encrypt(&ctx).unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_one_user_unsgn() {
|
|
let user_data_orig = vec![0x56; 0x183];
|
|
let (host_key, ctx) = get_crypto();
|
|
let mut asrcb =
|
|
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag())
|
|
.expect("AddSecretRequest::new failed");
|
|
|
|
asrcb.add_hostkey(host_key).unwrap();
|
|
asrcb.set_user_data(user_data_orig.clone(), None).unwrap();
|
|
let asrcb = asrcb.encrypt(&ctx).unwrap();
|
|
|
|
let user_data = verify_asrcb_and_get_user_data(asrcb, None).unwrap();
|
|
|
|
assert_eq!(
|
|
user_data_orig.as_slice(),
|
|
&user_data.as_ref().unwrap()[..user_data_orig.len()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_one_user_ec() {
|
|
let (usr_sgn_key, _) = get_test_keys();
|
|
|
|
let usr_vrfy_key = usr_sgn_key.ec_key().unwrap();
|
|
let usr_vrfy_key = usr_vrfy_key.public_key();
|
|
let usr_vrfy_key = PKey::from_ec_key(
|
|
EcKey::from_public_key(
|
|
&EcGroup::from_curve_name(Nid::SECP521R1).unwrap(),
|
|
usr_vrfy_key,
|
|
)
|
|
.unwrap(),
|
|
)
|
|
.unwrap();
|
|
|
|
let user_data_orig = vec![0x56; 0x100];
|
|
let asrcb = create_signed_asrcb(usr_sgn_key, user_data_orig.clone());
|
|
|
|
let user_data = verify_asrcb_and_get_user_data(asrcb, Some(usr_vrfy_key)).unwrap();
|
|
assert_eq!(
|
|
user_data_orig.as_slice(),
|
|
&user_data.as_ref().unwrap()[..user_data_orig.len()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_one_user_rsa2048() {
|
|
let usr_sgn_key = get_test_asset!("keys/rsa2048key.pem");
|
|
let usr_sgn_key = PKey::private_key_from_pem(usr_sgn_key).unwrap();
|
|
let user_data_orig = vec![0x56; 0x100];
|
|
let asrcb = create_signed_asrcb(usr_sgn_key, user_data_orig.clone());
|
|
|
|
let usr_vrfy_key = get_test_asset!("keys/rsa2048key.pub.pem");
|
|
let usr_vrfy_key = PKey::public_key_from_pem(usr_vrfy_key).unwrap();
|
|
|
|
let user_data = verify_asrcb_and_get_user_data(asrcb, Some(usr_vrfy_key)).unwrap();
|
|
assert_eq!(
|
|
user_data_orig.as_slice(),
|
|
&user_data.as_ref().unwrap()[..user_data_orig.len()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_one_user_rsa3072() {
|
|
let usr_sgn_key = get_test_asset!("keys/rsa3072key.pem");
|
|
let usr_sgn_key = PKey::private_key_from_pem(usr_sgn_key).unwrap();
|
|
let user_data_orig = vec![0x56; 0x80];
|
|
let asrcb = create_signed_asrcb(usr_sgn_key, user_data_orig.clone());
|
|
|
|
let usr_vrfy_key = get_test_asset!("keys/rsa3072key.pub.pem");
|
|
let usr_vrfy_key = PKey::public_key_from_pem(usr_vrfy_key).unwrap();
|
|
|
|
let user_data = verify_asrcb_and_get_user_data(asrcb, Some(usr_vrfy_key)).unwrap();
|
|
assert_eq!(
|
|
user_data_orig.as_slice(),
|
|
&user_data.as_ref().unwrap()[..user_data_orig.len()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_cuid_one() {
|
|
let asrcb = gen_asrcb(GuestSecret::Null, None, no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_none_default_cuid_one");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn assoc_none_default_cuid_one() {
|
|
let asrcb = gen_asrcb(association(), None, no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/assoc_none_default_cuid_one");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_simple_default_cuid_one() {
|
|
let asrcb = gen_asrcb(GuestSecret::Null, ext_simple(), no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_simple_default_cuid_one");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn assoc_simple_default_cuid_one() {
|
|
let asrcb = gen_asrcb(association(), ext_simple(), no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/assoc_simple_default_cuid_one");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_derived_default_cuid_one() {
|
|
let asrcb = gen_asrcb(GuestSecret::Null, ext_derived(), no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_derived_default_cuid_one");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn assoc_derived_default_cuid_one() {
|
|
let asrcb = gen_asrcb(association(), ext_derived(), no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/assoc_derived_default_cuid_one");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_dump_cuid_one() {
|
|
let mut flags = no_flag();
|
|
flags.set_disable_dump();
|
|
let asrcb = gen_asrcb(GuestSecret::Null, None, flags, true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_none_dump_cuid_one");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_one() {
|
|
let asrcb = gen_asrcb(GuestSecret::Null, None, no_flag(), false).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_none_default_ncuid_one");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_cuid_seven() {
|
|
let (hkd, ctx) = get_crypto();
|
|
let mut asrcb =
|
|
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag())
|
|
.expect("AddSecretRequest::new failed");
|
|
for _ in 0..7 {
|
|
asrcb.add_hostkey(hkd.clone()).unwrap()
|
|
}
|
|
asrcb.set_cuid(CUID);
|
|
let asrcb = asrcb.encrypt(&ctx).unwrap();
|
|
|
|
let exp = get_test_asset!("exp/asrcb/null_none_default_cuid_seven");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn verify_no_user_data() {
|
|
let req = get_test_asset!("exp/asrcb/null_none_default_ncuid_one");
|
|
assert!(matches!(
|
|
verify_asrcb_and_get_user_data(req.to_vec(), None),
|
|
Ok(None)
|
|
))
|
|
}
|
|
|
|
// V2 tests (using hybrid keys)
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_two_user_unsgn() {
|
|
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
|
let user_data_orig = vec![0x56; 0x183];
|
|
let (host_key, ctx) = get_crypto_v2();
|
|
let mut asrcb =
|
|
AddSecretRequest::new(AddSecretVersion::Two, GuestSecret::Null, TAGS, no_flag())
|
|
.expect("AddSecretRequest::new failed");
|
|
|
|
asrcb.add_hostkey(host_key).unwrap();
|
|
asrcb.set_user_data(user_data_orig.clone(), None).unwrap();
|
|
let asrcb = asrcb.encrypt(&ctx).unwrap();
|
|
|
|
let user_data = verify_asrcb_and_get_user_data(asrcb, None).unwrap();
|
|
|
|
assert_eq!(
|
|
user_data_orig.as_slice(),
|
|
&user_data.as_ref().unwrap()[..user_data_orig.len()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_two_user_ec() {
|
|
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
|
let (usr_sgn_key, _) = get_test_keys();
|
|
|
|
let usr_vrfy_key = usr_sgn_key.ec_key().unwrap();
|
|
let usr_vrfy_key = usr_vrfy_key.public_key();
|
|
let usr_vrfy_key = PKey::from_ec_key(
|
|
EcKey::from_public_key(
|
|
&EcGroup::from_curve_name(Nid::SECP521R1).unwrap(),
|
|
usr_vrfy_key,
|
|
)
|
|
.unwrap(),
|
|
)
|
|
.unwrap();
|
|
|
|
let user_data_orig = vec![0x56; 0x100];
|
|
let asrcb = create_signed_asrcb_v2(usr_sgn_key, user_data_orig.clone());
|
|
|
|
let user_data = verify_asrcb_and_get_user_data(asrcb, Some(usr_vrfy_key)).unwrap();
|
|
assert_eq!(
|
|
user_data_orig.as_slice(),
|
|
&user_data.as_ref().unwrap()[..user_data_orig.len()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_two_user_rsa2048() {
|
|
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
|
let usr_sgn_key = get_test_asset!("keys/rsa2048key.pem");
|
|
let usr_sgn_key = PKey::private_key_from_pem(usr_sgn_key).unwrap();
|
|
let user_data_orig = vec![0x56; 0x100];
|
|
let asrcb = create_signed_asrcb_v2(usr_sgn_key, user_data_orig.clone());
|
|
|
|
let usr_vrfy_key = get_test_asset!("keys/rsa2048key.pub.pem");
|
|
let usr_vrfy_key = PKey::public_key_from_pem(usr_vrfy_key).unwrap();
|
|
|
|
let user_data = verify_asrcb_and_get_user_data(asrcb, Some(usr_vrfy_key)).unwrap();
|
|
assert_eq!(
|
|
user_data_orig.as_slice(),
|
|
&user_data.as_ref().unwrap()[..user_data_orig.len()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_two_user_rsa3072() {
|
|
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
|
let usr_sgn_key = get_test_asset!("keys/rsa3072key.pem");
|
|
let usr_sgn_key = PKey::private_key_from_pem(usr_sgn_key).unwrap();
|
|
let user_data_orig = vec![0x56; 0x80];
|
|
let asrcb = create_signed_asrcb_v2(usr_sgn_key, user_data_orig.clone());
|
|
|
|
let usr_vrfy_key = get_test_asset!("keys/rsa3072key.pub.pem");
|
|
let usr_vrfy_key = PKey::public_key_from_pem(usr_vrfy_key).unwrap();
|
|
|
|
let user_data = verify_asrcb_and_get_user_data(asrcb, Some(usr_vrfy_key)).unwrap();
|
|
assert_eq!(
|
|
user_data_orig.as_slice(),
|
|
&user_data.as_ref().unwrap()[..user_data_orig.len()]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_cuid_two() {
|
|
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
|
let asrcb = gen_asrcb_v2(GuestSecret::Null, None, no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_none_default_cuid_two");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn assoc_none_default_cuid_two() {
|
|
let asrcb = gen_asrcb_v2(association(), None, no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/assoc_none_default_cuid_two");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_simple_default_cuid_two() {
|
|
let asrcb = gen_asrcb_v2(GuestSecret::Null, ext_simple(), no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_simple_default_cuid_two");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn assoc_simple_default_cuid_two() {
|
|
let asrcb = gen_asrcb_v2(association(), ext_simple(), no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/assoc_simple_default_cuid_two");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_derived_default_cuid_two() {
|
|
let asrcb = gen_asrcb_v2(GuestSecret::Null, ext_derived(), no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_derived_default_cuid_two");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn assoc_derived_default_cuid_two() {
|
|
let asrcb = gen_asrcb_v2(association(), ext_derived(), no_flag(), true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/assoc_derived_default_cuid_two");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_dump_cuid_two() {
|
|
let mut flags = no_flag();
|
|
flags.set_disable_dump();
|
|
let asrcb = gen_asrcb_v2(GuestSecret::Null, None, flags, true).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_none_dump_cuid_two");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_ncuid_two() {
|
|
let asrcb = gen_asrcb_v2(GuestSecret::Null, None, no_flag(), false).unwrap();
|
|
let exp = get_test_asset!("exp/asrcb/null_none_default_ncuid_two");
|
|
assert_eq!(asrcb, exp);
|
|
}
|
|
|
|
#[test]
|
|
fn null_none_default_cuid_seven_two() {
|
|
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
|
let (hkd, ctx) = get_crypto_v2();
|
|
let mut asrcb =
|
|
AddSecretRequest::new(AddSecretVersion::Two, GuestSecret::Null, TAGS, no_flag())
|
|
.expect("AddSecretRequest::new failed");
|
|
for _ in 0..7 {
|
|
asrcb.add_hostkey(hkd.clone()).unwrap()
|
|
}
|
|
asrcb.set_cuid(CUID);
|
|
let asrcb = asrcb.encrypt(&ctx).unwrap();
|
|
|
|
let exp = get_test_asset!("exp/asrcb/null_none_default_cuid_seven_two");
|
|
assert_eq!(asrcb, exp);
|
|
}
|