attestation: tdx issuer/validator (#1265)

* Add TDX validator

* Add TDX issuer

---------

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2023-03-08 14:13:57 +01:00 committed by Malte Poll
parent d104af6e51
commit dd2da25ebe
53 changed files with 808 additions and 229 deletions

View file

@ -10,7 +10,6 @@ import (
"bytes"
"context"
"crypto"
"crypto/sha256"
"encoding/json"
"fmt"
"io"
@ -21,6 +20,7 @@ import (
tpmServer "github.com/google/go-tpm-tools/server"
"github.com/google/go-tpm/tpm2"
"github.com/edgelesssys/constellation/v2/internal/attestation"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
)
@ -66,12 +66,6 @@ type (
ValidateCVM func(attestation AttestationDocument, state *attest.MachineState) error
)
// AttestationLogger is a logger used to print warnings and infos during attestation validation.
type AttestationLogger interface {
Infof(format string, args ...any)
Warnf(format string, args ...any)
}
// AttestationDocument contains the TPM attestation with signed user data.
type AttestationDocument struct {
// Attestation contains the TPM event log, PCR values and quotes, and public key of the key used to sign the attestation.
@ -87,16 +81,16 @@ type Issuer struct {
openTPM TPMOpenFunc
getAttestationKey GetTPMAttestationKey
getInstanceInfo GetInstanceInfo
log AttestationLogger
log attestation.Logger
}
// NewIssuer returns a new Issuer.
func NewIssuer(
openTPM TPMOpenFunc, getAttestationKey GetTPMAttestationKey,
getInstanceInfo GetInstanceInfo, log AttestationLogger,
getInstanceInfo GetInstanceInfo, log attestation.Logger,
) *Issuer {
if log == nil {
log = &nopAttestationLogger{}
log = &attestation.NOPLogger{}
}
return &Issuer{
openTPM: openTPM,
@ -129,7 +123,7 @@ func (i *Issuer) Issue(ctx context.Context, userData []byte, nonce []byte) (res
defer aK.Close()
// Create an attestation using the loaded key
extraData := makeExtraData(userData, nonce)
extraData := attestation.MakeExtraData(userData, nonce)
tpmAttestation, err := aK.Attest(tpmClient.AttestOpts{Nonce: extraData})
if err != nil {
return nil, fmt.Errorf("creating attestation: %w", err)
@ -162,15 +156,15 @@ type Validator struct {
getTrustedKey GetTPMTrustedAttestationPublicKey
validateCVM ValidateCVM
log AttestationLogger
log attestation.Logger
}
// NewValidator returns a new Validator.
func NewValidator(expected measurements.M, getTrustedKey GetTPMTrustedAttestationPublicKey,
validateCVM ValidateCVM, log AttestationLogger,
validateCVM ValidateCVM, log attestation.Logger,
) *Validator {
if log == nil {
log = &nopAttestationLogger{}
log = &attestation.NOPLogger{}
}
return &Validator{
expected: expected,
@ -194,7 +188,7 @@ func (v *Validator) Validate(ctx context.Context, attDocRaw []byte, nonce []byte
return nil, fmt.Errorf("unmarshaling TPM attestation document: %w", err)
}
extraData := makeExtraData(attDoc.UserData, nonce)
extraData := attestation.MakeExtraData(attDoc.UserData, nonce)
// Verify and retrieve the trusted attestation public key using the provided instance info
aKP, err := v.getTrustedKey(ctx, attDoc, extraData)
@ -276,25 +270,9 @@ func GetSelectedMeasurements(open TPMOpenFunc, selection tpm2.PCRSelection) (mea
return nil, fmt.Errorf("invalid measurement: invalid length: %d", len(pcr))
}
m[i] = measurements.Measurement{
Expected: *(*[32]byte)(pcr),
Expected: pcr,
}
}
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{}
// Infof is a no-op.
func (nopAttestationLogger) Infof(string, ...interface{}) {}
// Warnf is a no-op.
func (nopAttestationLogger) Warnf(string, ...interface{}) {}