@@ -549,9 +549,9 @@ impl TpmEngineHelper {
549
549
// VM has a small-vTPM mitigation marker. Don't touch anything, but
550
550
// log whether the AK cert exists, as that previous write might have
551
551
// failed.
552
- let mut output = [ 0u8 ; MAX_NV_INDEX_SIZE as usize ] ;
552
+ let mut output = vec ! [ 0u8 ; MAX_NV_INDEX_SIZE as usize ] ;
553
553
let r = self . read_from_nv_index ( TPM_NV_INDEX_AIK_CERT , & mut output) ;
554
- tracing:: warn!( "VM has 16k vTPM mitigation marker; not resizing AKCert index " ) ;
554
+ tracing:: warn!( "VM has 16k vTPM mitigation marker" ) ;
555
555
match r {
556
556
Err ( e) => tracing:: error!(
557
557
err = & e as & dyn std:: error:: Error ,
@@ -564,7 +564,40 @@ impl TpmEngineHelper {
564
564
let nv_bits = TpmaNvBits :: from ( res. nv_public . nv_public . attributes . 0 . get ( ) ) ;
565
565
let size = res. nv_public . nv_public . data_size . get ( ) ;
566
566
567
- tracing:: info!( ?nv_bits, size, "AKCert index exists" )
567
+ tracing:: info!( ?nv_bits, size, "AKCert index exists" ) ;
568
+
569
+ if nv_bits. nv_platformcreate ( ) {
570
+ tracing:: info!( "AKCert index is platform owned; restoring owner auth" ) ;
571
+ let existing_cert = self . take_existing_ak_cert ( ) ?;
572
+ if let AkCertType :: PlatformOwned ( cert) = existing_cert {
573
+ self . nv_define_space (
574
+ TPM20_RH_OWNER ,
575
+ 0 ,
576
+ TPM_NV_INDEX_AIK_CERT ,
577
+ cert. len ( ) as u16 ,
578
+ )
579
+ . map_err ( |error| {
580
+ TpmHelperError :: TpmCommandError {
581
+ command_debug_info : CommandDebugInfo {
582
+ command_code : CommandCodeEnum :: NV_DefineSpace ,
583
+ auth_handle : Some ( TPM20_RH_OWNER ) ,
584
+ nv_index : Some ( TPM_NV_INDEX_AIK_CERT ) ,
585
+ } ,
586
+ error,
587
+ }
588
+ } ) ?;
589
+
590
+ self . nv_write ( TPM20_RH_OWNER , None , TPM_NV_INDEX_AIK_CERT , & cert)
591
+ . map_err ( |error| TpmHelperError :: TpmCommandError {
592
+ command_debug_info : CommandDebugInfo {
593
+ command_code : CommandCodeEnum :: NV_Write ,
594
+ auth_handle : Some ( TPM20_RH_OWNER ) ,
595
+ nv_index : Some ( TPM_NV_INDEX_AIK_CERT ) ,
596
+ } ,
597
+ error,
598
+ } ) ?;
599
+ }
600
+ }
568
601
}
569
602
Ok ( NvIndexState :: Uninitialized ) => {
570
603
tracing:: warn!( "AKCert index uninitialized with mitigation marker" )
@@ -635,12 +668,22 @@ impl TpmEngineHelper {
635
668
"allocate nv index for previous platform AK cert"
636
669
) ;
637
670
671
+ let ( handle, auth, write_auth_handle) = if will_mitigate_cert {
672
+ ( TPM20_RH_OWNER , None , TPM20_RH_OWNER )
673
+ } else {
674
+ (
675
+ TPM20_RH_PLATFORM ,
676
+ Some ( auth_value) ,
677
+ ReservedHandle ( TPM_NV_INDEX_AIK_CERT . into ( ) ) ,
678
+ )
679
+ } ;
680
+
638
681
let result = self
639
- . nv_define_space ( TPM20_RH_PLATFORM , auth_value , TPM_NV_INDEX_AIK_CERT , size)
682
+ . nv_define_space ( handle , auth . unwrap_or ( 0 ) , TPM_NV_INDEX_AIK_CERT , size)
640
683
. map_err ( |error| TpmHelperError :: TpmCommandError {
641
684
command_debug_info : CommandDebugInfo {
642
685
command_code : CommandCodeEnum :: NV_DefineSpace ,
643
- auth_handle : Some ( TPM20_RH_PLATFORM ) ,
686
+ auth_handle : Some ( handle ) ,
644
687
nv_index : Some ( TPM_NV_INDEX_AIK_CERT ) ,
645
688
} ,
646
689
error,
@@ -668,7 +711,17 @@ impl TpmEngineHelper {
668
711
// boot-time AK cert request fails.
669
712
tracing:: info!( "Preserve previous AK cert across boot" ) ;
670
713
671
- self . write_to_nv_index ( auth_value, TPM_NV_INDEX_AIK_CERT , & cert) ?;
714
+ self . nv_write ( write_auth_handle, auth, TPM_NV_INDEX_AIK_CERT , & cert)
715
+ . map_err ( |error| TpmHelperError :: TpmCommandError {
716
+ command_debug_info : CommandDebugInfo {
717
+ command_code : CommandCodeEnum :: NV_Write ,
718
+ auth_handle : Some ( ReservedHandle (
719
+ TPM_NV_INDEX_AIK_CERT . into ( ) ,
720
+ ) ) ,
721
+ nv_index : Some ( TPM_NV_INDEX_AIK_CERT ) ,
722
+ } ,
723
+ error,
724
+ } ) ?;
672
725
}
673
726
}
674
727
}
@@ -1436,12 +1489,20 @@ impl TpmEngineHelper {
1436
1489
let session_tag = SessionTagEnum :: Sessions ;
1437
1490
1438
1491
// Use password-based authorization and allow owner to read
1439
- let attributes = TpmaNvBits :: new ( )
1440
- . with_nv_authread ( true )
1441
- . with_nv_authwrite ( true )
1442
- . with_nv_ownerread ( true )
1443
- . with_nv_platformcreate ( true )
1444
- . with_nv_no_da ( true ) ;
1492
+ let attributes = if auth_handle == TPM20_RH_PLATFORM {
1493
+ TpmaNvBits :: new ( )
1494
+ . with_nv_authread ( true )
1495
+ . with_nv_authwrite ( true )
1496
+ . with_nv_ownerread ( true )
1497
+ . with_nv_platformcreate ( true )
1498
+ . with_nv_no_da ( true )
1499
+ } else {
1500
+ TpmaNvBits :: new ( )
1501
+ . with_nv_ownerread ( true )
1502
+ . with_nv_ownerwrite ( true )
1503
+ . with_nv_authread ( true )
1504
+ . with_nv_authwrite ( true )
1505
+ } ;
1445
1506
1446
1507
let public_info = TpmsNvPublic :: new (
1447
1508
nv_index,
@@ -3552,4 +3613,53 @@ mod tests {
3552
3613
panic ! ( )
3553
3614
}
3554
3615
}
3616
+
3617
+ #[ test]
3618
+ fn test_restore_owner_defined ( ) {
3619
+ const AK_CERT_INPUT_512 : [ u8 ; 512 ] = [ 7u8 ; 512 ] ;
3620
+
3621
+ let mut tpm_engine_helper = create_tpm_engine_helper ( ) ;
3622
+ restart_tpm_engine ( & mut tpm_engine_helper, false , true ) ;
3623
+
3624
+ // Test allocating a platform-defined AKCert index and mitigating it back to owner-defined.
3625
+
3626
+ let result =
3627
+ tpm_engine_helper. allocate_guest_attestation_nv_indices ( AUTH_VALUE , false , true , false ) ;
3628
+ assert ! ( result. is_ok( ) ) ;
3629
+
3630
+ let result = tpm_engine_helper
3631
+ . find_nv_index ( TPM_NV_INDEX_AIK_CERT )
3632
+ . expect ( "find_nv_index should succeed" )
3633
+ . expect ( "AKCert NV index present" ) ;
3634
+ let nv_bits = TpmaNvBits :: from ( result. nv_public . nv_public . attributes . 0 . get ( ) ) ;
3635
+ assert ! ( nv_bits. nv_platformcreate( ) ) ;
3636
+
3637
+ let result = tpm_engine_helper. write_to_nv_index (
3638
+ AUTH_VALUE ,
3639
+ TPM_NV_INDEX_AIK_CERT ,
3640
+ & AK_CERT_INPUT_512 ,
3641
+ ) ;
3642
+ assert ! ( result. is_ok( ) ) ;
3643
+
3644
+ let result = tpm_engine_helper. nv_define_space (
3645
+ TPM20_RH_PLATFORM ,
3646
+ AUTH_VALUE ,
3647
+ TPM_NV_INDEX_MITIGATED ,
3648
+ 1 ,
3649
+ ) ;
3650
+ assert ! ( result. is_ok( ) ) ;
3651
+
3652
+ // TPM has a platform-defined AKCert index and a mitigation marker. This should restore
3653
+ // the owner-defined AKCert index.
3654
+ let result =
3655
+ tpm_engine_helper. allocate_guest_attestation_nv_indices ( AUTH_VALUE , false , true , true ) ;
3656
+ assert ! ( result. is_ok( ) ) ;
3657
+
3658
+ let result = tpm_engine_helper
3659
+ . find_nv_index ( TPM_NV_INDEX_AIK_CERT )
3660
+ . expect ( "find_nv_index should succeed" )
3661
+ . expect ( "AKCert NV index present" ) ;
3662
+ let nv_bits = TpmaNvBits :: from ( result. nv_public . nv_public . attributes . 0 . get ( ) ) ;
3663
+ assert ! ( !nv_bits. nv_platformcreate( ) ) ;
3664
+ }
3555
3665
}
0 commit comments