2022-03-22 11:03:15 -04:00
package vtpm
import (
2022-04-11 04:34:15 -04:00
"errors"
"fmt"
2022-03-22 11:03:15 -04:00
"github.com/google/go-tpm/tpm2"
"github.com/google/go-tpm/tpmutil"
)
const (
// PCRIndexOwnerID is a PCR we extend to mark the node as initialized.
// The value used to extend is derived from Constellation's master key.
PCRIndexOwnerID = tpmutil . Handle ( 11 )
// PCRIndexClusterID is a PCR we extend to mark the node as initialized.
// The value used to extend is a random generated 32 Byte value.
PCRIndexClusterID = tpmutil . Handle ( 12 )
)
// MarkNodeAsInitialized marks a node as initialized by extending PCRs.
func MarkNodeAsInitialized ( openTPM TPMOpenFunc , ownerID , clusterID [ ] byte ) error {
tpm , err := openTPM ( )
if err != nil {
return err
}
defer tpm . Close ( )
// ownerID is used to identify the Constellation as belonging to a specific master key
if err := tpm2 . PCREvent ( tpm , PCRIndexOwnerID , ownerID ) ; err != nil {
return err
}
// clusterID is used to uniquely identify this running instance of Constellation
return tpm2 . PCREvent ( tpm , PCRIndexClusterID , clusterID )
}
2022-04-11 04:34:15 -04:00
// IsNodeInitialized checks if a node is already initialized by reading PCRs.
func IsNodeInitialized ( openTPM TPMOpenFunc ) ( bool , error ) {
tpm , err := openTPM ( )
if err != nil {
return false , err
}
defer tpm . Close ( )
idxOwner := int ( PCRIndexOwnerID )
idxCluster := int ( PCRIndexClusterID )
selection := tpm2 . PCRSelection {
Hash : tpm2 . AlgSHA256 ,
PCRs : [ ] int { idxOwner , idxCluster } ,
}
pcrs , err := tpm2 . ReadPCRs ( tpm , selection )
if err != nil {
return false , err
}
if len ( pcrs [ idxOwner ] ) == 0 {
return false , errors . New ( "owner ID PCR does not exist" )
}
if len ( pcrs [ idxCluster ] ) == 0 {
return false , errors . New ( "cluster ID PCR does not exist" )
}
ownerInitialized := pcrInitialized ( pcrs [ idxOwner ] )
clusterInitialized := pcrInitialized ( pcrs [ idxCluster ] )
if ownerInitialized == clusterInitialized {
return ownerInitialized && clusterInitialized , nil
}
ownerState := "not initialized"
if ownerInitialized {
ownerState = "initialized"
}
clusterState := "not initialized"
if clusterInitialized {
clusterState = "initialized"
}
return false , fmt . Errorf ( "PCRs %v and %v are not consistent: PCR[%v]=%v (%v), PCR[%v]=%v (%v)" , idxOwner , idxCluster , idxOwner , pcrs [ idxOwner ] , ownerState , idxCluster , pcrs [ idxCluster ] , clusterState )
}
// pcrInitialized checks if a PCR value is set to a non-zero value.
func pcrInitialized ( pcr [ ] byte ) bool {
for _ , b := range pcr {
if b != 0 {
return true
}
}
return false
}