mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
attestation: bind user data to PCR state
This commit is contained in:
parent
5e7dc0d7db
commit
dd7d6334ba
@ -47,3 +47,7 @@ func (t *simulatedTPM) Close() error {
|
||||
// never close the underlying simulated TPM to allow calling the TPMOpenFunc again
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*simulatedTPM) EventLog() ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -80,9 +80,8 @@ type AttestationDocument struct {
|
||||
Attestation *attest.Attestation
|
||||
// InstanceInfo is used to verify the provided public key.
|
||||
InstanceInfo []byte
|
||||
// arbitrary data, signed by the TPM.
|
||||
// arbitrary data, quoted by the TPM.
|
||||
UserData []byte
|
||||
UserDataSignature []byte
|
||||
}
|
||||
|
||||
// Issuer handles issuing of TPM based attestation documents.
|
||||
@ -117,7 +116,8 @@ func (i *Issuer) Issue(userData []byte, nonce []byte) ([]byte, error) {
|
||||
defer aK.Close()
|
||||
|
||||
// Create an attestation using the loaded key
|
||||
attestation, err := aK.Attest(tpmClient.AttestOpts{Nonce: nonce})
|
||||
extraData := makeExtraData(userData, nonce)
|
||||
attestation, err := aK.Attest(tpmClient.AttestOpts{Nonce: extraData})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating attestation: %w", err)
|
||||
}
|
||||
@ -128,17 +128,10 @@ func (i *Issuer) Issue(userData []byte, nonce []byte) ([]byte, error) {
|
||||
return nil, fmt.Errorf("fetching instance info: %w", err)
|
||||
}
|
||||
|
||||
// Sign user provided data using the loaded key
|
||||
userDataSigned, err := aK.SignData(userData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("signing user data: %w", err)
|
||||
}
|
||||
|
||||
attDoc := AttestationDocument{
|
||||
Attestation: attestation,
|
||||
InstanceInfo: instanceInfo,
|
||||
UserData: userData,
|
||||
UserDataSignature: userDataSigned,
|
||||
}
|
||||
return json.Marshal(attDoc)
|
||||
}
|
||||
@ -198,7 +191,7 @@ func (v *Validator) Validate(attDocRaw []byte, nonce []byte) (userData []byte, e
|
||||
if _, err := tpmServer.VerifyAttestation(
|
||||
attDoc.Attestation,
|
||||
tpmServer.VerifyOpts{
|
||||
Nonce: nonce,
|
||||
Nonce: makeExtraData(attDoc.UserData, nonce),
|
||||
TrustedAKs: []crypto.PublicKey{aKP},
|
||||
AllowSHA1: false,
|
||||
},
|
||||
@ -220,12 +213,6 @@ func (v *Validator) Validate(attDocRaw []byte, nonce []byte) (userData []byte, e
|
||||
}
|
||||
}
|
||||
|
||||
// Verify signed user data
|
||||
digest := sha256.Sum256(attDoc.UserData)
|
||||
if err = v.verifyUserData(aKP, crypto.SHA256, digest[:], attDoc.UserDataSignature); err != nil {
|
||||
return nil, fmt.Errorf("verifying signed user data: %w", err)
|
||||
}
|
||||
|
||||
v.log.Infof("Successfully validated attestation document")
|
||||
return attDoc.UserData, nil
|
||||
}
|
||||
@ -284,6 +271,13 @@ func GetSelectedMeasurements(open TPMOpenFunc, selection tpm2.PCRSelection) (mea
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func makeExtraData(userData []byte, nonce []byte) []byte {
|
||||
data := append([]byte{}, userData...)
|
||||
data = append(data, nonce...)
|
||||
digest := sha256.Sum256(data)
|
||||
return digest[:]
|
||||
}
|
||||
|
||||
// nopAttestationLogger is a no-op implementation of AttestationLogger.
|
||||
type nopAttestationLogger struct{}
|
||||
|
||||
|
@ -66,13 +66,17 @@ func TestValidate(t *testing.T) {
|
||||
}
|
||||
|
||||
testExpectedPCRs := measurements.M{
|
||||
0: measurements.WithAllBytes(0x00, true),
|
||||
1: measurements.WithAllBytes(0x00, true),
|
||||
0: measurements.WithAllBytes(0x00, false),
|
||||
1: measurements.WithAllBytes(0x00, false),
|
||||
uint32(measurements.PCRIndexClusterID): measurements.WithAllBytes(0x00, false),
|
||||
}
|
||||
warnLog := &testAttestationLogger{}
|
||||
|
||||
issuer := NewIssuer(newSimTPMWithEventLog, tpmclient.AttestationKeyRSA, fakeGetInstanceInfo)
|
||||
validator := NewValidator(testExpectedPCRs, fakeGetTrustedKey, fakeValidateCVM, VerifyPKCS1v15, warnLog)
|
||||
tpmOpen, tpmCloser := tpmsim.NewSimulatedTPMOpenFunc()
|
||||
defer tpmCloser.Close()
|
||||
|
||||
issuer := NewIssuer(tpmOpen, tpmclient.AttestationKeyRSA, fakeGetInstanceInfo)
|
||||
validator := NewValidator(testExpectedPCRs, fakeGetTrustedKey, fakeValidateCVM, VerifyPKCS1v15, nil)
|
||||
|
||||
nonce := []byte{1, 2, 3, 4}
|
||||
challenge := []byte("Constellation")
|
||||
@ -90,6 +94,24 @@ func TestValidate(t *testing.T) {
|
||||
require.NoError(err)
|
||||
require.Equal(challenge, out)
|
||||
|
||||
// validation must fail after bootstrapping (change of enforced PCR)
|
||||
require.NoError(MarkNodeAsBootstrapped(tpmOpen, []byte{2}))
|
||||
attDocBootstrappedRaw, err := issuer.Issue(challenge, nonce)
|
||||
require.NoError(err)
|
||||
_, err = validator.Validate(attDocBootstrappedRaw, nonce)
|
||||
require.Error(err)
|
||||
|
||||
// userData must be bound to PCR state
|
||||
attDocBootstrappedRaw, err = issuer.Issue([]byte{2, 3}, nonce)
|
||||
require.NoError(err)
|
||||
var attDocBootstrapped AttestationDocument
|
||||
require.NoError(json.Unmarshal(attDocBootstrappedRaw, &attDocBootstrapped))
|
||||
attDocBootstrapped.Attestation = attDoc.Attestation
|
||||
attDocBootstrappedRaw, err = json.Marshal(attDocBootstrapped)
|
||||
require.NoError(err)
|
||||
_, err = validator.Validate(attDocBootstrappedRaw, nonce)
|
||||
require.Error(err)
|
||||
|
||||
expectedPCRs := measurements.M{
|
||||
0: measurements.WithAllBytes(0x00, true),
|
||||
1: measurements.WithAllBytes(0x00, true),
|
||||
@ -128,6 +150,11 @@ func TestValidate(t *testing.T) {
|
||||
nonce []byte
|
||||
wantErr bool
|
||||
}{
|
||||
"valid": {
|
||||
validator: NewValidator(testExpectedPCRs, fakeGetTrustedKey, fakeValidateCVM, VerifyPKCS1v15, warnLog),
|
||||
attDoc: mustMarshalAttestation(attDoc, require),
|
||||
nonce: nonce,
|
||||
},
|
||||
"invalid nonce": {
|
||||
validator: NewValidator(testExpectedPCRs, fakeGetTrustedKey, fakeValidateCVM, VerifyPKCS1v15, warnLog),
|
||||
attDoc: mustMarshalAttestation(attDoc, require),
|
||||
@ -140,7 +167,6 @@ func TestValidate(t *testing.T) {
|
||||
Attestation: attDoc.Attestation,
|
||||
InstanceInfo: attDoc.InstanceInfo,
|
||||
UserData: []byte("wrong data"),
|
||||
UserDataSignature: attDoc.UserDataSignature,
|
||||
}, require),
|
||||
nonce: nonce,
|
||||
wantErr: true,
|
||||
@ -196,7 +222,6 @@ func TestValidate(t *testing.T) {
|
||||
},
|
||||
InstanceInfo: attDoc.InstanceInfo,
|
||||
UserData: attDoc.UserData,
|
||||
UserDataSignature: attDoc.UserDataSignature,
|
||||
}, require),
|
||||
nonce: nonce,
|
||||
wantErr: true,
|
||||
|
Loading…
Reference in New Issue
Block a user