@@ -489,20 +489,6 @@ impl DstackVerifiedReport {
489489 | DstackVerifiedReport :: DstackAwsNitroTpm ( _) => None ,
490490 }
491491 }
492-
493- pub fn aws_nitro_tpm_public_key ( & self ) -> Option < & [ u8 ] > {
494- match self {
495- DstackVerifiedReport :: DstackAwsNitroTpm ( report) => report. public_key . as_deref ( ) ,
496- _ => None ,
497- }
498- }
499-
500- pub fn aws_nitro_tpm_nonce ( & self ) -> Option < & [ u8 ] > {
501- match self {
502- DstackVerifiedReport :: DstackAwsNitroTpm ( report) => report. nonce . as_deref ( ) ,
503- _ => None ,
504- }
505- }
506492}
507493
508494/// Represents a verified attestation
@@ -1111,27 +1097,20 @@ impl DstackNitroQuote {
11111097const AWS_NITRO_TPM_BOOT_PCRS : & [ u16 ] = & [ 4 , 7 , 12 ] ;
11121098/// All dstack measured events (TDX RTMR3 analogue). Non-resettable on NitroTPM.
11131099const AWS_NITRO_TPM_EVENT_PCR : u16 = 14 ;
1114- /// Optional config commitment PCR (mr_config-like). Extended from shared-disk config only .
1115- pub const AWS_NITRO_TPM_CONFIG_PCR : u16 = 8 ;
1100+ /// Optional config commitment PCR, extended once from the guest-computed MrConfig V2 id .
1101+ pub ( crate ) const AWS_NITRO_TPM_CONFIG_PCR : u16 = 8 ;
11161102
11171103fn aws_nitro_tpm_pcr ( pcrs : & std:: collections:: BTreeMap < u16 , Vec < u8 > > , index : u16 ) -> Result < & [ u8 ] > {
11181104 pcrs. get ( & index)
11191105 . map ( Vec :: as_slice)
11201106 . with_context ( || format ! ( "PCR {index} not found" ) )
11211107}
11221108
1123- /// Replay boundary for AWS event PCR, aligned with bare TDX RTMR3:
1124- /// - `boottime_mr`: stop at `boot-mr-done` (early / KMS pin snapshot)
1125- /// - otherwise: replay the full event log present in the quote
1126- fn aws_nitro_tpm_event_boundary ( boottime_mr : bool ) -> Option < & ' static str > {
1127- boottime_mr. then_some ( "boot-mr-done" )
1128- }
1129-
11301109fn aws_nitro_tpm_replayed_event_pcr (
11311110 runtime_events : & [ RuntimeEvent ] ,
11321111 boottime_mr : bool ,
11331112) -> <Sha384 as Hasher >:: Output {
1134- replay_runtime_events :: < Sha384 > ( runtime_events, aws_nitro_tpm_event_boundary ( boottime_mr) )
1113+ replay_runtime_events :: < Sha384 > ( runtime_events, boottime_mr. then_some ( "boot-mr-done" ) )
11351114}
11361115
11371116/// Bind the event log to the quoted PCR14 register.
@@ -1180,7 +1159,7 @@ pub fn aws_nitro_tpm_boot_pcr_digest(
11801159}
11811160
11821161impl DstackAwsNitroTpmQuote {
1183- pub fn decode_pcrs ( & self ) -> Result < std:: collections:: BTreeMap < u16 , Vec < u8 > > > {
1162+ pub ( crate ) fn decode_pcrs ( & self ) -> Result < std:: collections:: BTreeMap < u16 , Vec < u8 > > > {
11841163 let cose = nsm_qvl:: CoseSign1 :: from_bytes ( & self . attestation_doc )
11851164 . context ( "failed to decode NitroTPM COSE document" ) ?;
11861165 let doc = nsm_qvl:: AttestationDocument :: from_cbor ( & cose. payload )
@@ -2036,12 +2015,11 @@ impl Attestation {
20362015 AttestationMode :: DstackNitroEnclave => String :: new ( ) ,
20372016 } ;
20382017 let runtime_events = match mode {
2039- AttestationMode :: DstackTdx | AttestationMode :: DstackGcpTdx => {
2018+ AttestationMode :: DstackTdx
2019+ | AttestationMode :: DstackGcpTdx
2020+ | AttestationMode :: DstackAwsNitroTpm => {
20402021 RuntimeEvent :: read_all ( ) . context ( "Failed to read runtime events" ) ?
20412022 }
2042- AttestationMode :: DstackAwsNitroTpm => {
2043- RuntimeEvent :: read_all ( ) . context ( "failed to read runtime events" ) ?
2044- }
20452023 AttestationMode :: DstackAmdSevSnp => vec ! [ ] ,
20462024 AttestationMode :: DstackNitroEnclave => match app_id {
20472025 Some ( app_id) => vec ! [ RuntimeEvent :: new( "app-id" . to_string( ) , app_id. to_vec( ) ) ] ,
@@ -2085,12 +2063,8 @@ impl Attestation {
20852063 AttestationMode :: DstackAwsNitroTpm => {
20862064 // Challenge binding is report_data → NitroTPM user_data only
20872065 // (same role as TDX/GCP report_data; no separate nonce/public_key).
2088- let attestation_doc = crate :: aws_nitro_tpm:: attestation_document (
2089- Some ( report_data. to_vec ( ) ) ,
2090- None ,
2091- None ,
2092- )
2093- . context ( "failed to get NitroTPM attestation document" ) ?;
2066+ let attestation_doc = crate :: aws_nitro_tpm:: attestation_document ( report_data)
2067+ . context ( "failed to get NitroTPM attestation document" ) ?;
20942068 AttestationQuote :: DstackAwsNitroTpm ( DstackAwsNitroTpmQuote { attestation_doc } )
20952069 }
20962070 } ;
@@ -2123,9 +2097,11 @@ impl Attestation {
21232097 . context ( "vm_config.aws_measurement is required on AWS NitroTPM" ) ?;
21242098 document
21252099 . verify ( & vm_config. os_image_hash )
2100+ . map_err ( anyhow:: Error :: msg)
21262101 . context ( "aws_measurement does not match os_image_hash" ) ?;
21272102 let measurement = document
21282103 . decode_measurement ( )
2104+ . map_err ( anyhow:: Error :: msg)
21292105 . context ( "failed to decode aws_measurement" ) ?;
21302106 let quoted_digest = aws_nitro_tpm_boot_pcr_digest ( & pcrs)
21312107 . context ( "failed to compute boot_pcr_digest from attestation" ) ?;
@@ -2699,6 +2675,13 @@ mod tests {
26992675 assert_eq ! ( mrs. mr_system, changed_mrs. mr_system) ;
27002676 assert_ne ! ( mrs. mr_aggregated, changed_mrs. mr_aggregated) ;
27012677
2678+ let mut changed_pcrs = pcrs. clone ( ) ;
2679+ changed_pcrs. insert ( 12 , vec ! [ 0x99 ; 48 ] ) ;
2680+ let changed_pcr12 =
2681+ decode_mr_aws_nitro_tpm_from_pcrs ( false , & mr_key_provider, & changed_pcrs, & events) ?;
2682+ assert_ne ! ( mrs. mr_system, changed_pcr12. mr_system) ;
2683+ assert_ne ! ( mrs. mr_aggregated, changed_pcr12. mr_aggregated) ;
2684+
27022685 let mut missing_pcrs = pcrs. clone ( ) ;
27032686 missing_pcrs. remove ( & AWS_NITRO_TPM_EVENT_PCR ) ;
27042687 let err = match decode_mr_aws_nitro_tpm_from_pcrs (
@@ -2727,89 +2710,6 @@ mod tests {
27272710 Ok ( ( ) )
27282711 }
27292712
2730- #[ test]
2731- fn aws_nitro_tpm_mr_aggregated_binds_pcr12 ( ) -> Result < ( ) > {
2732- let pcr4 = vec ! [ 0x04 ; 48 ] ;
2733- let pcr7 = vec ! [ 0x07 ; 48 ] ;
2734- let pcr12 = vec ! [ 0x12 ; 48 ] ;
2735- let events = vec ! [
2736- RuntimeEvent :: new( "app-id" . into( ) , vec![ 0x11 ; 20 ] ) ,
2737- RuntimeEvent :: new( "compose-hash" . into( ) , vec![ 0x22 ; 32 ] ) ,
2738- RuntimeEvent :: new( "instance-id" . into( ) , vec![ 0x33 ; 20 ] ) ,
2739- RuntimeEvent :: new( "key-provider" . into( ) , b"tpm" . to_vec( ) ) ,
2740- ] ;
2741- let replayed_pcr14 = cc_eventlog:: replay_events :: < Sha384 > ( & events, None ) ;
2742- let mr_key_provider = sha256 ( b"aws nitrotpm key provider" ) ;
2743-
2744- let mut pcrs = std:: collections:: BTreeMap :: from ( [
2745- ( 4u16 , pcr4. clone ( ) ) ,
2746- ( 7u16 , pcr7. clone ( ) ) ,
2747- ( 12u16 , pcr12. clone ( ) ) ,
2748- ( AWS_NITRO_TPM_EVENT_PCR , replayed_pcr14. to_vec ( ) ) ,
2749- ] ) ;
2750- let base = decode_mr_aws_nitro_tpm_from_pcrs ( false , & mr_key_provider, & pcrs, & events) ?;
2751-
2752- pcrs. insert ( 12u16 , vec ! [ 0x99 ; 48 ] ) ;
2753- let changed_pcr12 =
2754- decode_mr_aws_nitro_tpm_from_pcrs ( false , & mr_key_provider, & pcrs, & events) ?;
2755- assert_ne ! ( base. mr_system, changed_pcr12. mr_system) ;
2756- assert_ne ! ( base. mr_aggregated, changed_pcr12. mr_aggregated) ;
2757-
2758- pcrs. remove ( & 12u16 ) ;
2759- let err = match decode_mr_aws_nitro_tpm_from_pcrs ( false , & mr_key_provider, & pcrs, & events) {
2760- Ok ( _) => panic ! ( "missing PCR12 must be rejected" ) ,
2761- Err ( err) => err,
2762- } ;
2763- assert ! (
2764- format!( "{err:#}" ) . contains( "PCR 12 not found" ) ,
2765- "unexpected error: {err:#}"
2766- ) ;
2767- Ok ( ( ) )
2768- }
2769-
2770- #[ test]
2771- fn aws_nitro_tpm_rejects_reordered_or_replayed_runtime_events ( ) -> Result < ( ) > {
2772- let events = vec ! [
2773- RuntimeEvent :: new( "app-id" . into( ) , vec![ 0x11 ; 20 ] ) ,
2774- RuntimeEvent :: new( "compose-hash" . into( ) , vec![ 0x22 ; 32 ] ) ,
2775- RuntimeEvent :: new( "instance-id" . into( ) , vec![ 0x33 ; 20 ] ) ,
2776- RuntimeEvent :: new( "key-provider" . into( ) , b"tpm" . to_vec( ) ) ,
2777- ] ;
2778- let quoted_pcr14 = cc_eventlog:: replay_events :: < Sha384 > ( & events, None ) ;
2779- let mr_key_provider = sha256 ( b"aws nitrotpm key provider" ) ;
2780- let pcrs = std:: collections:: BTreeMap :: from ( [
2781- ( 4u16 , vec ! [ 0x04 ; 48 ] ) ,
2782- ( 7u16 , vec ! [ 0x07 ; 48 ] ) ,
2783- ( 12u16 , vec ! [ 0x12 ; 48 ] ) ,
2784- ( AWS_NITRO_TPM_EVENT_PCR , quoted_pcr14. to_vec ( ) ) ,
2785- ] ) ;
2786-
2787- let mut reordered = events. clone ( ) ;
2788- reordered. swap ( 1 , 2 ) ;
2789- let err =
2790- match decode_mr_aws_nitro_tpm_from_pcrs ( false , & mr_key_provider, & pcrs, & reordered) {
2791- Ok ( _) => panic ! ( "runtime event reordering must be rejected" ) ,
2792- Err ( err) => err,
2793- } ;
2794- assert ! (
2795- format!( "{err:#}" ) . contains( "PCR14 mismatch" ) ,
2796- "unexpected error: {err:#}"
2797- ) ;
2798-
2799- let mut replayed = events. clone ( ) ;
2800- replayed. push ( RuntimeEvent :: new ( "compose-hash" . into ( ) , vec ! [ 0x22 ; 32 ] ) ) ;
2801- let err = match decode_mr_aws_nitro_tpm_from_pcrs ( false , & mr_key_provider, & pcrs, & replayed)
2802- {
2803- Ok ( _) => panic ! ( "runtime event replay/duplication must be rejected" ) ,
2804- Err ( err) => err,
2805- } ;
2806- assert ! (
2807- format!( "{err:#}" ) . contains( "PCR14 mismatch" ) ,
2808- "unexpected error: {err:#}"
2809- ) ;
2810- Ok ( ( ) )
2811- }
2812-
28132713 #[ test]
28142714 fn aws_nitro_tpm_pcr14_replays_full_event_log_like_rtmr3 ( ) -> Result < ( ) > {
28152715 // Single PCR14 lane: all events (including after system-ready) are
0 commit comments