mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
pvattest: Verify hybrid keys
Allow pvattest verify to verify hybrid keys. The hybrid key is represented by a sha512 hash truncated to 32 bytes. Signed-off-by: Steffen Eiden <seiden@linux.ibm.com> Reviewed-by: Marc Hartmayer <marc@linux.ibm.com> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
//! IBM Z Host key-slot implementations.
|
||||
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::hash::{DigestBytes, MessageDigest};
|
||||
use openssl::pkey::{PKey, PKeyRef, Private, Public};
|
||||
|
||||
use crate::crypto::{derive_aes256_gcm_key, derive_aes256_gcm_key_hybrid, encrypt_aead, hash};
|
||||
@@ -101,6 +101,19 @@ impl KeyslotV2 {
|
||||
}
|
||||
}
|
||||
|
||||
/// calculates the sha512 of this hybrid key
|
||||
pub fn sha512(&self) -> Result<DigestBytes> {
|
||||
let mut phk_buf = Vec::<u8>::with_capacity(160 + 1568);
|
||||
let ec_phk: EcPubKeyCoord = self.ec_hostkey.as_ref().try_into()?;
|
||||
phk_buf.extend_from_slice(ec_phk.as_ref());
|
||||
phk_buf.extend_from_slice(&self.mlkem_hostkey.raw_public_key()?);
|
||||
assert_eq!(phk_buf.len(), 160 + 1568);
|
||||
|
||||
let hash = hash(MessageDigest::sha512(), &phk_buf)?;
|
||||
assert_eq!(hash.len(), 64);
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
/// Encrypts `secret` using `self` and `priv_key` the encryption.
|
||||
///
|
||||
/// # Returns
|
||||
@@ -132,12 +145,6 @@ impl KeyslotV2 {
|
||||
priv_key: &PKeyRef<Private>,
|
||||
to: &mut Vec<u8>,
|
||||
) -> Result<()> {
|
||||
let mut phk_buf = Vec::<u8>::with_capacity(160 + 1568);
|
||||
let ec_phk: EcPubKeyCoord = self.ec_hostkey.as_ref().try_into()?;
|
||||
phk_buf.extend_from_slice(ec_phk.as_ref());
|
||||
phk_buf.extend_from_slice(&self.mlkem_hostkey.raw_public_key()?);
|
||||
assert_eq!(phk_buf.len(), 160 + 1568);
|
||||
|
||||
let (derived_key, ciphertext) =
|
||||
derive_aes256_gcm_key_hybrid(priv_key, &self.ec_hostkey, &self.mlkem_hostkey)?;
|
||||
let mut wrpk_and_kst =
|
||||
@@ -145,7 +152,7 @@ impl KeyslotV2 {
|
||||
assert_eq!(wrpk_and_kst.len(), 48);
|
||||
|
||||
to.reserve(1680);
|
||||
let hash = hash(MessageDigest::sha512(), &phk_buf)?;
|
||||
let hash = self.sha512()?;
|
||||
assert_eq!(hash.len(), 64);
|
||||
to.extend_from_slice(&hash);
|
||||
to.append(&mut wrpk_and_kst);
|
||||
|
||||
@@ -6,8 +6,8 @@ use std::path::PathBuf;
|
||||
|
||||
use clap::{Args, Parser, Subcommand, ValueEnum, ValueHint};
|
||||
use utils::{
|
||||
AutoOrExplicit, AutoOrExplicitParser, CertificateOptions, DeprecatedVerbosityOptions,
|
||||
HkdVersion, ValueEnumDisplay, ValueEnumFromStr,
|
||||
AutoOrExplicit, CertificateOptions, DeprecatedVerbosityOptions, HkdVersion, ValueEnumDisplay,
|
||||
ValueEnumFromStr,
|
||||
};
|
||||
|
||||
/// create, perform, and verify attestation measurements
|
||||
@@ -82,7 +82,6 @@ pub enum AttVersion {
|
||||
}
|
||||
|
||||
pub type AttVersionSelection = AutoOrExplicit<AttVersion>;
|
||||
pub type AttVersionSelectionParser = AutoOrExplicitParser<AttVersion>;
|
||||
|
||||
impl From<AttVersion> for HkdVersion {
|
||||
fn from(val: AttVersion) -> Self {
|
||||
@@ -122,8 +121,8 @@ pub struct CreateAttOpt {
|
||||
pub add_data: Vec<AttAddFlags>,
|
||||
|
||||
/// Specify the Attestation Request version to use.
|
||||
#[arg(long = "att-version", value_name = "VERSION", default_value_t = AttVersionSelection::Explicit(AttVersion::V1), value_parser = AttVersionSelectionParser::default())]
|
||||
pub att_version: AttVersionSelection,
|
||||
#[arg(long = "att-version", value_name = "VERSION", default_value_t = AttVersion::V1)]
|
||||
pub att_version: AttVersion,
|
||||
}
|
||||
|
||||
#[derive(Debug, ValueEnum, Clone, Copy)]
|
||||
|
||||
@@ -6,10 +6,9 @@ use std::fmt::Display;
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use log::{debug, info};
|
||||
use log::{debug, info, warn};
|
||||
use pv::misc::{read_certs, read_file};
|
||||
use pv::request::openssl::DigestBytes;
|
||||
use pv::request::EcPubKeyCoord;
|
||||
use pv::request::{EcPubKeyCoord, HybridPKey, KeyslotV2};
|
||||
use serde::Serialize;
|
||||
use utils::HexSlice;
|
||||
|
||||
@@ -36,7 +35,7 @@ impl Display for HkCheck {
|
||||
}
|
||||
}
|
||||
|
||||
fn load_host_keys<A: AsRef<Path>>(hkds: &[A]) -> Result<Vec<(&Path, DigestBytes)>> {
|
||||
fn load_host_keys<A: AsRef<Path>>(hkds: &[A]) -> Result<Vec<(&Path, Vec<u8>)>> {
|
||||
let mut hkd_hash = Vec::with_capacity(hkds.len());
|
||||
for hkd in hkds {
|
||||
let hkd = hkd.as_ref();
|
||||
@@ -45,21 +44,41 @@ fn load_host_keys<A: AsRef<Path>>(hkds: &[A]) -> Result<Vec<(&Path, DigestBytes)
|
||||
hkd: hkd.display().to_string(),
|
||||
source,
|
||||
})?;
|
||||
let ec_coord: EcPubKeyCoord = certs.first().unwrap().public_key()?.as_ref().try_into()?;
|
||||
hkd_hash.push((hkd, ec_coord.sha256()?));
|
||||
|
||||
let ec_key = certs.first().unwrap().public_key()?;
|
||||
|
||||
match certs.len() {
|
||||
1 => {
|
||||
let ec_coord: EcPubKeyCoord = ec_key.as_ref().try_into()?;
|
||||
hkd_hash.push((hkd, ec_coord.sha256()?.as_ref().to_vec()));
|
||||
}
|
||||
2 => {
|
||||
let mlkem_key = certs[1].public_key()?;
|
||||
let ks = KeyslotV2::new(HybridPKey::new(ec_key, mlkem_key)?);
|
||||
let hash = ks.sha512()?;
|
||||
hkd_hash.push((hkd, hash[..32].to_vec()));
|
||||
}
|
||||
_ => {
|
||||
warn!(
|
||||
"The host-key document in '{}' contains more than two certificates!",
|
||||
hkd.display()
|
||||
);
|
||||
Err(pv::Error::WrongNumberOfKeys(hkd.display().to_string()))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(hkd_hash)
|
||||
}
|
||||
|
||||
fn contains_phkh<'a>(
|
||||
hkd_hashes: &[(&'a Path, DigestBytes)],
|
||||
hkd_hashes: &[(&'a Path, Vec<u8>)],
|
||||
phkh: &HexSlice<'_>,
|
||||
mode: HkCheck,
|
||||
check_enforced: bool,
|
||||
) -> CheckState<HostKeyCheck<'a>> {
|
||||
let hk: Vec<_> = hkd_hashes
|
||||
.iter()
|
||||
.filter_map(|(path, hash)| match hash.as_ref() == phkh.as_ref() {
|
||||
.filter_map(|(path, hash)| match hash == phkh.as_ref() {
|
||||
true => Some(*path),
|
||||
false => None,
|
||||
})
|
||||
|
||||
@@ -62,11 +62,12 @@ fn determine_version(
|
||||
}
|
||||
|
||||
pub fn create(opt: &CreateAttOpt) -> Result<ExitCode> {
|
||||
let hkds = opt
|
||||
.certificate_args
|
||||
.get_verified_hkds_new("attestation request", opt.att_version.map(|v| v.into()))?;
|
||||
let hkds = opt.certificate_args.get_verified_hkds_new(
|
||||
"attestation request",
|
||||
AttVersionSelection::Explicit(opt.att_version).map(|v| v.into()),
|
||||
)?;
|
||||
|
||||
let att_version = determine_version(opt.att_version, &hkds);
|
||||
let att_version = determine_version(AttVersionSelection::Explicit(opt.att_version), &hkds);
|
||||
let meas_alg = AttestationMeasAlg::HmacSha512;
|
||||
|
||||
let mut arcb = AttestationRequest::new(att_version, meas_alg, flags(&opt.add_data))?;
|
||||
|
||||
Reference in New Issue
Block a user