mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
Coordinator vTPM: add method to check for previous node initialization
Signed-off-by: Malte Poll <mp@edgeless.systems>
This commit is contained in:
parent
af1aca4b34
commit
be004c971d
@ -1,6 +1,9 @@
|
||||
package vtpm
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-tpm/tpm2"
|
||||
"github.com/google/go-tpm/tpmutil"
|
||||
)
|
||||
@ -29,3 +32,57 @@ func MarkNodeAsInitialized(openTPM TPMOpenFunc, ownerID, clusterID []byte) error
|
||||
// clusterID is used to uniquely identify this running instance of Constellation
|
||||
return tpm2.PCREvent(tpm, PCRIndexClusterID, clusterID)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-tpm-tools/client"
|
||||
"github.com/google/go-tpm/tpm2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -47,3 +48,52 @@ func TestFailOpener(t *testing.T) {
|
||||
|
||||
assert.Error(MarkNodeAsInitialized(func() (io.ReadWriteCloser, error) { return nil, errors.New("failed") }, []byte{0x0, 0x1, 0x2, 0x3}, []byte{0x0, 0x1, 0x2, 0x3}))
|
||||
}
|
||||
|
||||
func TestIsNodeInitialized(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
pcrValueOwnerID []byte
|
||||
pcrValueClusterID []byte
|
||||
expectInitialized bool
|
||||
expectErr bool
|
||||
}{
|
||||
"uninitialized PCRs results in uninitialized node": {},
|
||||
"initializing PCRs result in initialized node": {
|
||||
pcrValueOwnerID: []byte{0x0, 0x1, 0x2, 0x3},
|
||||
pcrValueClusterID: []byte{0x4, 0x5, 0x6, 0x7},
|
||||
expectInitialized: true,
|
||||
},
|
||||
"initializing ownerID alone fails": {
|
||||
pcrValueOwnerID: []byte{0x0, 0x1, 0x2, 0x3},
|
||||
expectErr: true,
|
||||
},
|
||||
"initializing clusterID alone fails": {
|
||||
pcrValueClusterID: []byte{0x4, 0x5, 0x6, 0x7},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
require := require.New(t)
|
||||
tpm, err := OpenSimulatedTPM()
|
||||
require.NoError(err)
|
||||
defer tpm.Close()
|
||||
if tc.pcrValueOwnerID != nil {
|
||||
require.NoError(tpm2.PCREvent(tpm, PCRIndexOwnerID, tc.pcrValueOwnerID))
|
||||
}
|
||||
if tc.pcrValueClusterID != nil {
|
||||
require.NoError(tpm2.PCREvent(tpm, PCRIndexClusterID, tc.pcrValueClusterID))
|
||||
}
|
||||
initialized, err := IsNodeInitialized(func() (io.ReadWriteCloser, error) {
|
||||
return &simTPMNOPCloser{tpm}, nil
|
||||
})
|
||||
if tc.expectErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Equal(tc.expectInitialized, initialized)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user