mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
rust/pv: Add new attestation additional-data flags
Add additional data for the Attestation request. The secret store hash measures all added secrets and the state of the store (locked or not) with a single hash. The hash is computed by concatenating all add-secret request tags (16 bytes each) and a byte stating the locked state (1 for locked, 0 for not locked). The firmware state is an opaque state description of the systems firmware status to be interpreted by an IBM service. Add request flags and fields in the additional data structure. Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com> Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
This commit is contained in:
@@ -14,8 +14,10 @@ use super::arcb::AttestationFlags;
|
||||
/// Hash for additional-data stuff used for parsing [`AdditionalData`]
|
||||
pub(super) const PHKH_SIZE: u32 = 0x20;
|
||||
static_assert!(Keyslot::PHKH_SIZE == PHKH_SIZE);
|
||||
pub(super) const SECRET_STORE_HASH_SIZE: u32 = 0x40;
|
||||
pub(super) const FW_STATE_SIZE: u32 = 0x140;
|
||||
|
||||
/// Struct describing the additional-data of an Attestation Request
|
||||
/// Additional-data of an Attestation Request
|
||||
#[derive(Serialize, Debug)]
|
||||
#[serde(default)]
|
||||
pub struct AdditionalData<T>
|
||||
@@ -27,6 +29,10 @@ where
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
attestation_phkh: Option<T>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
secret_store_hash: Option<T>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
firmware_state: Option<T>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
unrecognized: Option<T>,
|
||||
}
|
||||
|
||||
@@ -51,6 +57,8 @@ where
|
||||
}
|
||||
write_field(f, "Image PHKH", &self.image_phkh)?;
|
||||
write_field(f, "Attestation PHKH", &self.attestation_phkh)?;
|
||||
write_field(f, "Secret store hash", &self.secret_store_hash)?;
|
||||
write_field(f, "Firmware state", &self.firmware_state)?;
|
||||
write_field(f, "Unrecognized", &self.unrecognized)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -71,7 +79,7 @@ fn read_value<'a>(
|
||||
}
|
||||
|
||||
impl<T: Serialize> AdditionalData<T> {
|
||||
/// Provides a reference to the image public host key hash.
|
||||
/// Provides a reference to the image public host key hash, if any.
|
||||
///
|
||||
/// This is the hash of the public host key of the corresponding private machine key that
|
||||
/// decrypted the Secure Execution guest.
|
||||
@@ -80,7 +88,7 @@ impl<T: Serialize> AdditionalData<T> {
|
||||
self.image_phkh.as_ref()
|
||||
}
|
||||
|
||||
/// Provides a reference to the attestation public host key hash.
|
||||
/// Provides a reference to the attestation public host key hash, if any.
|
||||
///
|
||||
/// This is the hash of the public host key of the corresponding private machine key that
|
||||
/// decrypted the Attestation request.
|
||||
@@ -89,6 +97,24 @@ impl<T: Serialize> AdditionalData<T> {
|
||||
self.attestation_phkh.as_ref()
|
||||
}
|
||||
|
||||
/// Provides a reference to the secret store hash, if any.
|
||||
///
|
||||
/// This is a hash over the state of the guest's UV secret store. A SHA512 hash over the
|
||||
/// concatenated request tags of all Add-secret requests and a 0 or 1 byte for the locked
|
||||
/// state.
|
||||
///
|
||||
/// SHA512 (n*[Add-secret-request]|locked?)
|
||||
pub fn secret_store_hash(&self) -> Option<&T> {
|
||||
self.secret_store_hash.as_ref()
|
||||
}
|
||||
|
||||
/// Provides a reference to the firmware state, if any.
|
||||
///
|
||||
/// This represents the state of selected firmware parts to be interpreted by an IBM service.
|
||||
pub fn firmware_state(&self) -> Option<&T> {
|
||||
self.firmware_state.as_ref()
|
||||
}
|
||||
|
||||
/// Provides a reference to the data not known by this implementation.
|
||||
pub fn unrecognized(&self) -> Option<&T> {
|
||||
self.unrecognized.as_ref()
|
||||
@@ -101,11 +127,15 @@ impl<'a, T: Serialize + From<&'a [u8]> + Sized> AdditionalData<T> {
|
||||
let AdditionalData {
|
||||
image_phkh,
|
||||
attestation_phkh,
|
||||
secret_store_hash,
|
||||
firmware_state: firmware_hash,
|
||||
unrecognized,
|
||||
} = other;
|
||||
Self {
|
||||
image_phkh: image_phkh.map(|i| i.into()),
|
||||
attestation_phkh: attestation_phkh.map(|i| i.into()),
|
||||
secret_store_hash: secret_store_hash.map(|i| i.into()),
|
||||
firmware_state: firmware_hash.map(|i| i.into()),
|
||||
unrecognized: unrecognized.map(|i| i.into()),
|
||||
}
|
||||
}
|
||||
@@ -125,11 +155,21 @@ impl<'a> AdditionalData<&'a [u8]> {
|
||||
let (image_phkh, data) = read_value(data, PHKH_SIZE, flags.image_phkh(), "Image PHKH")?;
|
||||
let (attestation_phkh, data) =
|
||||
read_value(data, PHKH_SIZE, flags.attest_phkh(), "Attestation PHKH")?;
|
||||
let (secret_store_hash, data) = read_value(
|
||||
data,
|
||||
SECRET_STORE_HASH_SIZE,
|
||||
flags.secret_store_hash(),
|
||||
"Secret store state",
|
||||
)?;
|
||||
let (firmware_state, data) =
|
||||
read_value(data, FW_STATE_SIZE, flags.firmware_state(), "Firmware hash")?;
|
||||
let unrecognized = (!data.is_empty()).then_some(data);
|
||||
|
||||
Ok(Self {
|
||||
image_phkh,
|
||||
attestation_phkh,
|
||||
secret_store_hash,
|
||||
firmware_state,
|
||||
unrecognized,
|
||||
})
|
||||
}
|
||||
@@ -145,7 +185,9 @@ mod test {
|
||||
let add = AdditionalData {
|
||||
image_phkh: 0_u8.into(),
|
||||
attestation_phkh: 1_u8.into(),
|
||||
unrecognized: 2_u8.into(),
|
||||
secret_store_hash: 2_u8.into(),
|
||||
firmware_state: 3_u8.into(),
|
||||
unrecognized: 4_u8.into(),
|
||||
};
|
||||
|
||||
serde_test::assert_ser_tokens(
|
||||
@@ -153,7 +195,7 @@ mod test {
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "AdditionalData",
|
||||
len: 3,
|
||||
len: 5,
|
||||
},
|
||||
Token::Str("image_phkh"),
|
||||
Token::Some,
|
||||
@@ -161,19 +203,27 @@ mod test {
|
||||
Token::Str("attestation_phkh"),
|
||||
Token::Some,
|
||||
Token::U8(1),
|
||||
Token::Str("unrecognized"),
|
||||
Token::Str("secret_store_hash"),
|
||||
Token::Some,
|
||||
Token::U8(2),
|
||||
Token::Str("firmware_state"),
|
||||
Token::Some,
|
||||
Token::U8(3),
|
||||
Token::Str("unrecognized"),
|
||||
Token::Some,
|
||||
Token::U8(4),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ser_no_att() {
|
||||
fn ser_no_miss() {
|
||||
let add = AdditionalData {
|
||||
image_phkh: 0_u8.into(),
|
||||
attestation_phkh: None,
|
||||
secret_store_hash: None,
|
||||
firmware_state: None,
|
||||
unrecognized: 2_u8.into(),
|
||||
};
|
||||
|
||||
@@ -200,6 +250,8 @@ mod test {
|
||||
let add = AdditionalData {
|
||||
image_phkh: 0_u8.into(),
|
||||
attestation_phkh: 1_u8.into(),
|
||||
secret_store_hash: None,
|
||||
firmware_state: None,
|
||||
unrecognized: None,
|
||||
};
|
||||
|
||||
@@ -225,6 +277,8 @@ mod test {
|
||||
let add: AdditionalData<u8> = AdditionalData {
|
||||
image_phkh: None,
|
||||
attestation_phkh: None,
|
||||
secret_store_hash: None,
|
||||
firmware_state: None,
|
||||
unrecognized: None,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright IBM Corp. 2024
|
||||
use super::{additional::PHKH_SIZE, AttNonce};
|
||||
|
||||
use openssl::pkey::{PKey, Public};
|
||||
use std::mem::size_of;
|
||||
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U32};
|
||||
|
||||
use crate::{
|
||||
assert_size,
|
||||
attest::{AttestationMagic, AttestationMeasAlg},
|
||||
@@ -13,9 +17,11 @@ use crate::{
|
||||
uv::UvFlags,
|
||||
Error, Result,
|
||||
};
|
||||
use openssl::pkey::{PKey, Public};
|
||||
use std::mem::size_of;
|
||||
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U32};
|
||||
|
||||
use super::{
|
||||
additional::{FW_STATE_SIZE, PHKH_SIZE, SECRET_STORE_HASH_SIZE},
|
||||
AttNonce,
|
||||
};
|
||||
|
||||
#[cfg(doc)]
|
||||
use crate::{
|
||||
@@ -310,7 +316,14 @@ static_assert!(AttestationFlags::FLAG_TO_ADD_SIZE.len() < 64);
|
||||
|
||||
impl AttestationFlags {
|
||||
/// Maps the flag to the (maximum) required size for the additional data
|
||||
pub(crate) const FLAG_TO_ADD_SIZE: [u32; 4] = [0, 0, PHKH_SIZE, PHKH_SIZE];
|
||||
pub(crate) const FLAG_TO_ADD_SIZE: [u32; 6] = [
|
||||
0,
|
||||
0,
|
||||
PHKH_SIZE,
|
||||
PHKH_SIZE,
|
||||
SECRET_STORE_HASH_SIZE,
|
||||
FW_STATE_SIZE,
|
||||
];
|
||||
|
||||
/// Returns the maximum size this flag requires for additional data
|
||||
pub fn expected_additional_size(&self) -> u32 {
|
||||
@@ -353,6 +366,30 @@ impl AttestationFlags {
|
||||
pub fn attest_phkh(&self) -> bool {
|
||||
self.0.is_set(3)
|
||||
}
|
||||
|
||||
/// Flag 4 - request the state of the secret store
|
||||
///
|
||||
/// Asks the Ultravisor to provide the hash of the added secret requests. Requires 64 bytes.
|
||||
pub fn set_secret_store_hash(&mut self) {
|
||||
self.0.set_bit(4);
|
||||
}
|
||||
|
||||
/// Check weather the hash of the added secret requests flag is on
|
||||
pub fn secret_store_hash(&self) -> bool {
|
||||
self.0.is_set(4)
|
||||
}
|
||||
|
||||
/// Flag 5 - request the firmware hash
|
||||
///
|
||||
/// Asks the Ultravisor to provide the hash of the firmware. Requires 320 bytes.
|
||||
pub fn set_firmware_state(&mut self) {
|
||||
self.0.set_bit(5);
|
||||
}
|
||||
|
||||
/// Check weather the hash of the added secret requests flag is on
|
||||
pub fn firmware_state(&self) -> bool {
|
||||
self.0.is_set(5)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
||||
Reference in New Issue
Block a user