/// A `u32` that is always equal to zero #[derive(
Clone, Copy, Debug, Default, Eq, FromZeros, IntoBytes, Immutable, KnownLayout, PartialEq,
)] #[repr(u32)] pubenum AlignedZeroU32 { /// The sole enum #[default]
Zero = 0,
}
/// Abstract the interface to the TPM/GSC so submodules can implement RPCs. pubtrait TpmInterface { /// An abstraction of the Error type returned by TPM RPCs. type Error;
/// Transmit a TPM request message and get back a TPM response message. fn transmit<Req: TpmvRequest, Rsp: FromBytes + KnownLayout + Immutable>(
&self,
request: Req,
) -> Result<Rsp, Self::Error>;
/// Transmit a TPM request message and get back a TPM response message. fn transmit_into< 'a,
Req: TpmvRequestBuild + ?Sized,
Rsp: FromBytes + IntoBytes + KnownLayout + Immutable + Unaligned + ?Sized,
>(
&self,
request: &TpmRequestMessage<Req>,
buffer: &'a mut Vec<u8>,
) -> Result<&'a mut Rsp, Self::Error>;
}
/// Defines the constants required by each type of TPM vendor request. /// /// All TPMV requests are required to implement this trait. pubtrait TpmvRequest: IntoBytes + Immutable + Unaligned { /// The first 4 bytes of every TPM request and response. /// Used to indicate if the request requires a session to be run const TAG: U16<BE>;
/// A code that is unique to each request type that the TPM will recognize /// and know how to process const COMMAND_CODE: U16<BE>;
/// The ordinal associated with the request type. const ORDINAL: U32<BE>;
/// Each request type has an associated response type used to deserialize /// bytes received from the TPM after a request is processed. type TpmvResponse: TryFromBytes + ?Sized + Unaligned;
}
/// Operations to build a dynamically-sized request type. /// /// See [`TpmRequestMessage::new_in_vec`]. pubtrait TpmvRequestBuild: TpmvRequest + FromZeros + IntoBytes + KnownLayout { /// Parameters to build an self-consistent instance of this request from zeros. /// /// This does not need to fill every field of the request, only those that should /// be static for every instance of this message. type BuildParams;
/// Error in initialization or size calculation. type Err;
/// The expected size for the request in bytes, excluding the TPM header. /// /// If `Self: Sized` this should be `size_of::<Self>()`. fn expected_size(params: &Self::BuildParams) -> Result<u32, Self::Err>;
/// Initializes a zeroed `self` to an internally consistent state. /// /// This is where data length fields should be initialized, for example. fn init(&mutself, params: Self::BuildParams) -> Result<(), Self::Err>;
}
/// Represents a complete TPM request. Contains both the request header and any /// additional fields required by the request type #[derive(Debug, Eq, TryFromBytes, IntoBytes, Immutable, PartialEq, KnownLayout, Unaligned)] #[repr(C)] pubstruct TpmRequestMessage<T: TpmvRequest + ?Sized> { /// The request header
header: TpmRequestHeader,
/// Contains fields specific to the type of request being sent pub request: T,
}
impl<T: TpmvRequest> TpmRequestMessage<T> { /// Generates a new `TpmvRequest` for the provided type `T`. pubfn new(request: T) -> Self { Self { header: TpmRequestHeader::for_request::<T>(), request }
}
}
/// An error while building a TPM Request from a buffer. #[derive(thiserror::Error)] pubenum TpmRequestBuildError<Req: ?Sized + TpmvRequestBuild> { /// Failed to allocate enough space for the request. #[error("failed to allocate enough space for the request")]
Alloc,
/// The size returned by the request was invalid. #[error("the request code gave an invalid size")]
Size,
/// `init` or `expected_size` in [`TpmvRequestBuild`] failed. #[error("internal request build error: {0}")]
Internal(Req::Err),
}
impl<T: ?Sized + TpmvRequestBuild> TpmRequestMessage<T> { /// Builds a request message using the given `Vec` as backing memory. pubfn new_in_vec(
buf: &mut Vec<u8>,
params: <T as TpmvRequestBuild>::BuildParams,
) -> Result<&mutSelf, TpmRequestBuildError<T>> { let data_size: usize = T::expected_size(¶ms)
.map_err(TpmRequestBuildError::Internal)?
.try_into()
.map_err(|_| TpmRequestBuildError::Size)?; let total_size = data_size
.checked_add(size_of::<TpmRequestHeader>())
.ok_or(TpmRequestBuildError::Size)?; let total_size_u32: u32 = total_size.try_into().map_err(|_| TpmRequestBuildError::Size)?; iflet Some(additional) = total_size.checked_sub(buf.len()) {
buf.try_reserve(additional)?;
}
buf.clear();
buf.resize(total_size, 0); let out = matchSelf::try_mut_from_bytes(&mut buf[..]).map_err(TryReadError::from) {
Ok(m) if size_of_val(m) == total_size => Ok(m),
Ok(_) | Err(ConvertError::Size(_)) => Err(TpmRequestBuildError::Size),
Err(ConvertError::Validity(_)) => unreachable!("T: FromZeros"),
}?;
out.header = TpmRequestHeader::for_request_with_total_size::<T>(total_size_u32);
out.request.init(params).map_err(TpmRequestBuildError::Internal)?;
Ok(out)
}
}
/// Represents the initial bytes of every TPM request. #[derive(Debug, Eq, FromBytes, IntoBytes, Immutable, PartialEq, Unaligned)] #[repr(C)] pubstruct TpmRequestHeader { /// The first 4 bytes of every TPM request pub tag: U16<BE>,
/// The total number of bytes in the request /// /// Rust usually calls this term a "size" - `[u32; 3]` has a size of 12, but a length of 3. pub length: U32<BE>,
/// The request's ordinal pub ordinal: U32<BE>,
/// A code that is unique to each request type that the TPM will recognize /// and know how to process pub command_code: U16<BE>,
}
impl TpmRequestHeader { /// Constructs a `TpmRequestHeader` for the given request and total message size in bytes. pubfn for_request_with_total_size<T: TpmvRequest + ?Sized>(size: u32) -> Self {
TpmRequestHeader {
tag: T::TAG,
length: U32::new(size),
ordinal: T::ORDINAL,
command_code: T::COMMAND_CODE,
}
}
/// Constructs a `TpmRequestHeader` for the given fixed-size request. pubfn for_request<T: TpmvRequest>() -> Self { const { assert!(size_of::<TpmRequestMessage<T>>() as u64 <= u32::MAX as u64) } Self::for_request_with_total_size::<T>(size_of::<TpmRequestMessage<T>>() as u32)
}
}
/// Represents a complete TPM response. Contains both the response header and any /// additional fields required by the response type #[derive(Debug, Eq, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned, PartialEq)] #[repr(C)] pubstruct TpmResponseMessage<T: ?Sized> { /// The response header pub header: TpmResponseHeader,
/// Contains fields specific to the type of response being sent pub response: T,
}
/// Represents the initial bytes of every TPM response. #[derive(Debug, Eq, FromBytes, IntoBytes, Immutable, KnownLayout, Unaligned, PartialEq)] #[repr(C)] pubstruct TpmResponseHeader { /// The first 4 bytes of every TPM response /// Used to indicate if the request requires a session to be run pub tag: U16<BE>,
/// The total number of bytes in the response pub length: U32<BE>,
/// Used to indicate if an error occurred while processing the request pub error_code: U32<BE>,
/// The same command code present in the initial request pub command_code: U16<BE>,
}
/// A module containing the requests and responses used to retrieve console /// logs from ths GSC pubmod get_console_log { usesuper::*; /// Used to retrieve the oldest (2048 - header size) bytes worth of console logs from the device. /// Repeated calls can be used to consume all previously unread console logs. /// Returns an empty string when there are no more logs to read #[derive(Debug, Eq, IntoBytes, Immutable, PartialEq, Unaligned)] #[repr(C)] pubstruct Request;
/// Represents a response from a [`Request`] #[derive(Debug, Eq, FromBytes, Immutable, KnownLayout, PartialEq, Unaligned)] #[repr(C)] pubstruct Response { /// A dynamically sized slice containing ASCII characters pub data: [u8],
}
}
/// A module containing the requests and responses used to retrieve version /// info from ths GSC pubmod get_version_info { usesuper::*; /// Requests version info from the device #[derive(Default, IntoBytes, Immutable, Unaligned)] #[repr(C)] pubstruct Request { /// The block digest. Always equal to zero when getting version info pub digest: ZeroU32, /// The destination address. Always equal to zero when getting version info pub address: ZeroU32,
}
/// Represents a response from a [`Request`] /// TODO: b/394187914 - Add support for older protocols #[derive(Debug, FromBytes, Immutable, KnownLayout, PartialEq, Unaligned)] #[repr(C)] pubstruct Response { /// Indicates what error (if any) occurred while fetching version info pub return_value: UpdateStatus, /// The update protocol currently being used by the GSC. Mostly used to /// indicate which fields will be present in the response pub protocol_version: U32<BE>, /// The offset at which the RO section of the GSC image begins pub backup_ro_offset: U32<BE>, /// The offset at which the RW section of the GSC image begins pub backup_rw_offset: U32<BE>, /// The RO minor version pub ro_minor: U32<BE>, /// The RO major version pub ro_major: U32<BE>, /// The RO epoch pub ro_epoch: U32<BE>, /// The RW minor version pub rw_minor: U32<BE>, /// The RW major version pub rw_major: U32<BE>, /// The RW epoch pub rw_epoch: U32<BE>, /// The key id of the currently active RO section pub ro_keyid: U32<BE>, /// The key id of the currently active RW section pub rw_keyid: U32<BE>,
}
}
pubmod pinweaver;
/// Contains the requests and responses used to access superblock mac /// storage on the GSC. pubmod trusty_storage_superblock_mac { usesuper::*;
/// Used by the Trusty secure storage application to store the MAC of the /// current valid superblock. #[derive(Clone, Copy, Debug, Eq, IntoBytes, Immutable, PartialEq, TryFromBytes, Unaligned)] #[repr(u8)] pubenum TrustyStorageMacFileIndex { /// Tamper detect persist filesystem mac index.
TamperDetectPersist = 1, /// Tamper detect filesystem mac index.
TamperDetect = 2,
}
/// Trusty storage application data. #[derive(
Clone,
Copy,
Debug,
Default,
Eq,
FromBytes,
IntoBytes,
Immutable,
KnownLayout,
PartialEq,
Unaligned,
)] #[repr(C)] pubstruct TrustyStorageMacData { /// MAC data currently stored. pub mac: TrustyStorageMac, /// Super block flags. pub flags: TrustyStorageFlags,
}
/// Requests superblock mac reads/writes from the GSC. #[derive(Debug, Eq, IntoBytes, Immutable, PartialEq, Unaligned)] #[repr(C)] pubstruct Request { /// Operation to perform. pub command: TrustyStorageMacCommand, /// File identifier. pub index: TrustyStorageMacFileIndex, /// MAC data to write. pub data: TrustyStorageMacData,
}
/// Represents a response from a [`Request`] #[derive(Debug, Eq, FromBytes, Immutable, KnownLayout, PartialEq, Unaligned)] #[repr(C)] pubstruct Response { /// MAC data currently stored. pub data: TrustyStorageMacData,
}
}
/// Contains the requests and responses used to get device IDs from the GSC. pubmod get_device_ids { usesuper::*; use core::mem; use kmr_wire::legacy::SetAttestationIdsRequest; use static_assertions::const_assert_eq;
/// Subcommand to select the location to read from. #[derive(Clone, Copy, Debug, Eq, Immutable, IntoBytes, PartialEq, Unaligned)] #[repr(u8)] pubenum Subcommand { /// Read device IDs from the scratch location in NVMEM.
Nvmem = 1, /// Read device IDs stored in the info page.
Info = 2,
}
/// A single field contating a device ID. #[derive(
Clone,
Copy,
Debug,
Default,
Eq,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
PartialEq,
Unaligned,
)] #[repr(C)] pubstruct DeviceIDField { /// Length of the string stored in value. pub size: u8, /// Value is the stored string. 0xff for all unused bytes. pub value: [u8; DEVICE_ID_MAX_STR_LEN],
}
const_assert_eq!(mem::size_of::<DeviceIDField>(), DEVICE_ID_FIELD_SIZE);
const_assert_eq!((mem::size_of::<DeviceIDField>() * DEVICE_IDS_FIELD_COUNT) % WORD_SIZE, 0);
impl DeviceIDField { /// Initialize a new device ID field from a string. pubfn new(s: &str) -> Self { letmut value = [0xff; DEVICE_ID_MAX_STR_LEN]; if s.is_empty() { Self { size: 0xff, value }
} else { let len = s.len().min(DEVICE_ID_MAX_STR_LEN);
value[..len].copy_from_slice(s.as_bytes()); Self { size: len as u8, value }
}
}
/// Build a vector from the device ID field. pubfn to_vec(&self) -> Vec<u8> { self.value[..self.size.min(DEVICE_ID_MAX_STR_LEN as u8) as usize].to_vec()
}
}
/// Get device IDs header #[derive(
Clone,
Copy,
Debug,
Default,
FromBytes,
Immutable,
IntoBytes,
KnownLayout,
PartialEq,
Unaligned,
)] #[repr(C)] pubstruct DeviceIDsHeader { /// Version is the Device ID header version pub version: u8, /// storage_type indicates if the IDs are stored in INFO or scratch pub storage_type: u8, /// Total number of fields pub field_count: u8, /// Total size of all of the fields pub data_size: [u8; 2], /// Status of the entire struct. 0 for completely initialized and ok to /// commit. pub status: u8, /// Unused. pub unused: [u8; UNUSED_HEADER_BYTES],
}
const_assert_eq!(mem::size_of::<DeviceIDsHeader>() % WORD_SIZE, 0);
let req = TpmRequestMessage::<FakeRequest>::new_in_vec(&mut buf, 5).unwrap();
assert_eq!(req.request.rest_len.get(), 5);
assert_eq!(req.request.rest, [0; 5], "buf should have been zeroed");
assert_eq!(buf.len(), 33, "buf should have been truncated");
}
#[test] fn test_request_new_in_vec_overflow() { #[derive(FromZeros, KnownLayout, IntoBytes, Immutable, Unaligned)] #[repr(C)] struct FakeRequest; impl TpmvRequest for FakeRequest { const TAG: U16<BE> = NO_SESSION_TAG; const ORDINAL: U32<BE> = U32::new(2); const COMMAND_CODE: U16<BE> = U16::new(1); type TpmvResponse = FakeResponse;
} impl TpmvRequestBuild for FakeRequest { type BuildParams = (); type Err = ();
let tpm_response = TpmResponseMessage::<Response>::ref_from_bytes(&bytes).unwrap();
assert_eq!(*tpm_response, expected_response);
}
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.16Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-06-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.