44//
55// SPDX-License-Identifier: Apache-2.0
66
7- use crate :: { codecs:: VecOf , runtime_events :: DSTACK_RUNTIME_EVENT_TYPE , tdx:: TdxEvent } ;
7+ use crate :: { codecs:: VecOf , tdx:: TdxEvent } ;
88use anyhow:: { bail, Context , Result } ;
99use scale:: Decode ;
1010use std:: path:: PathBuf ;
@@ -302,8 +302,10 @@ impl TcgEventLog {
302302 }
303303
304304 pub fn decode_from_ccel_file ( ) -> Result < Self > {
305- let data = read_ccel_raw ( ) ?;
306- Self :: decode ( & mut data. as_slice ( ) )
305+ let path = ccel_file_path ( ) ?;
306+ let data = fs_err:: read ( & path)
307+ . with_context ( || format ! ( "failed to read CCEL from {}" , path. display( ) ) ) ?;
308+ Self :: decode ( & mut data. as_slice ( ) ) . context ( "failed to decode CCEL" )
307309 }
308310
309311 pub fn to_cc_event_log ( & self ) -> Result < Vec < TdxEvent > > {
@@ -318,8 +320,8 @@ impl TcgEventLog {
318320
319321/// Resolve the CCEL path, honoring `DSTACK_CCEL_FILE` when set.
320322///
321- /// Overrides must be non-empty absolute paths so relative values cannot
322- /// silently resolve against the process working directory.
323+ /// Overrides must be non-empty absolute paths so relative values cannot silently
324+ /// resolve against the process working directory.
323325fn ccel_file_path ( ) -> Result < PathBuf > {
324326 let Some ( value) = std:: env:: var_os ( CCEL_FILE_ENV ) else {
325327 return Ok ( PathBuf :: from ( CCEL_FILE ) ) ;
@@ -337,52 +339,6 @@ fn ccel_file_path() -> Result<PathBuf> {
337339 Ok ( path)
338340}
339341
340- /// Read the raw ACPI CCEL table bytes.
341- pub fn read_ccel_raw ( ) -> Result < Vec < u8 > > {
342- let path = ccel_file_path ( ) ?;
343- fs_err:: read ( & path) . with_context ( || format ! ( "failed to read CCEL from {}" , path. display( ) ) )
344- }
345-
346- /// Return the length of the valid TCG event log prefix within a raw CCEL buffer.
347- ///
348- /// ACPI CCEL tables are fixed-size regions padded with 0xFF; the event stream
349- /// either ends with a 0xFFFFFFFF terminator or by running into that padding.
350- /// This parses the buffer to find where real events end so the trailer can be
351- /// stripped before appending runtime events.
352- pub fn ccel_content_len ( raw : & [ u8 ] ) -> Result < usize > {
353- let input = & mut & raw [ ..] ;
354- TcgEventLog :: decode ( input) ?;
355- Ok ( raw. len ( ) - input. len ( ) )
356- }
357-
358- /// Encode dstack runtime events as TCG_PCR_EVENT2 records.
359- ///
360- /// Non-runtime events in the slice are skipped. Each runtime event becomes:
361- /// - pcrIndex = imr + 1 (0-based TdxEvent -> 1-based TCG pcrIndex)
362- /// - eventType = DSTACK_RUNTIME_EVENT_TYPE
363- /// - digests = [{ TPM_ALG_SHA384, <48-byte digest> }]
364- /// - event = the digest pre-image bytes (`preimage`), so that
365- /// sha384(event) == digest holds for any TCG parser.
366- pub fn encode_runtime_events_as_tcg ( events : & [ TdxEvent ] ) -> Vec < u8 > {
367- let mut out = Vec :: new ( ) ;
368- for event in events {
369- let Some ( runtime) = event. to_runtime_event ( ) else {
370- continue ;
371- } ;
372- let preimage = runtime. preimage ( ) ;
373- let digest = event. digest ( ) ;
374- let pcr_index = event. imr . saturating_add ( 1 ) ;
375- out. extend_from_slice ( & pcr_index. to_le_bytes ( ) ) ;
376- out. extend_from_slice ( & event. event_type . to_le_bytes ( ) ) ;
377- out. extend_from_slice ( & 1u32 . to_le_bytes ( ) ) ;
378- out. extend_from_slice ( & TPM_ALG_SHA384 . to_le_bytes ( ) ) ;
379- out. extend_from_slice ( & digest) ;
380- out. extend_from_slice ( & ( preimage. len ( ) as u32 ) . to_le_bytes ( ) ) ;
381- out. extend_from_slice ( & preimage) ;
382- }
383- out
384- }
385-
386342fn parse_spec_id_event_log < I : scale:: Input > (
387343 input : & mut I ,
388344) -> Result < ( TcgEvent , TcgEfiSpecIdEvent ) > {
@@ -430,9 +386,6 @@ impl TryFrom<TcgEvent> for TdxEvent {
430386 . next ( )
431387 . context ( "digest not found" ) ?
432388 . hash ;
433- let event_payload: Vec < u8 > = value. event . into ( ) ;
434- let preimage =
435- ( value. event_type == DSTACK_RUNTIME_EVENT_TYPE ) . then ( || hex:: encode ( & event_payload) ) ;
436389 Ok ( TdxEvent {
437390 imr : value
438391 . imr_index
@@ -441,29 +394,13 @@ impl TryFrom<TcgEvent> for TdxEvent {
441394 event_type : value. event_type ,
442395 digest,
443396 event : Default :: default ( ) ,
444- event_payload,
397+ event_payload : value . event . into ( ) ,
445398 version : Default :: default ( ) ,
446- preimage,
399+ preimage : None ,
447400 } )
448401 }
449402}
450403
451- /// Build a merged TCG binary event log: raw ACPI CCEL (boot-time) followed by
452- /// the given runtime events encoded as TCG_PCR_EVENT2 records.
453- ///
454- /// Non-runtime entries in `events` are ignored; only events with
455- /// `event_type == DSTACK_RUNTIME_EVENT_TYPE` are appended.
456- pub fn build_ccel_event_log ( events : & [ TdxEvent ] ) -> Result < Vec < u8 > > {
457- let raw = read_ccel_raw ( ) ?;
458- let end = ccel_content_len ( & raw ) ?;
459- let mut out = raw[ ..end] . to_vec ( ) ;
460- out. extend_from_slice ( & encode_runtime_events_as_tcg ( events) ) ;
461- // Append the 0xFFFFFFFF terminator so parsers know where the event
462- // stream ends (the original ACPI table has trailing 0xFF padding).
463- out. extend_from_slice ( & 0xFFFF_FFFFu32 . to_le_bytes ( ) ) ;
464- Ok ( out)
465- }
466-
467404#[ cfg( test) ]
468405mod tests {
469406 use super :: * ;
0 commit comments