Add config struct for AttestPlatform(), to configure event log source (#118)

This commit is contained in:
Tom D 2019-10-03 11:09:32 -07:00 committed by GitHub
parent 56dc743f14
commit de6a3af7e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 56 deletions

View File

@ -119,6 +119,9 @@ func (k *AIK) ActivateCredential(tpm *TPM, in EncryptedCredential) (secret []byt
} }
// Quote returns a quote over the platform state, signed by the AIK. // Quote returns a quote over the platform state, signed by the AIK.
//
// This is a low-level API. Consumers seeking to attest the state of the
// platform should use tpm.AttestPlatform() instead.
func (k *AIK) Quote(tpm *TPM, nonce []byte, alg HashAlg) (*Quote, error) { func (k *AIK) Quote(tpm *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
return k.aik.quote(tpm.tpm, nonce, alg) return k.aik.quote(tpm.tpm, nonce, alg)
} }

View File

@ -91,46 +91,22 @@ func ExampleAIK_credentialActivation() {
} }
} }
func ExampleAIK_quote() {
tpm, err := attest.OpenTPM(nil)
if err != nil {
log.Fatalf("Failed to open TPM: %v", err)
}
defer tpm.Close()
// Create a new AIK.
aik, err := tpm.NewAIK(nil)
if err != nil {
log.Fatalf("Failed to create AIK: %v", err)
}
defer aik.Close(tpm)
// The nonce would typically be provided by the server.
nonce := []byte{1, 2, 3, 4, 5, 6, 7, 8}
// Perform the quote & gather information necessary to verify it.
quote, err := aik.Quote(tpm, nonce, attest.HashSHA1)
if err != nil {
log.Fatalf("Failed to generate quote: %v", err)
}
pcrs, err := tpm.PCRs(attest.HashSHA1)
if err != nil {
log.Fatalf("Failed to collect PCR values: %v", err)
}
log.Printf("quote = %+v", quote)
log.Printf("PCRs = %+v", pcrs)
}
func TestExampleAIK(t *testing.T) { func TestExampleAIK(t *testing.T) {
if !*testExamples { if !*testExamples {
t.SkipNow() t.SkipNow()
} }
ExampleAIK() ExampleAIK()
ExampleAIK_credentialActivation() ExampleAIK_credentialActivation()
ExampleAIK_quote()
} }
func ExampleAIKPublic_Verify() { func TestExampleTPM(t *testing.T) {
if !*testExamples {
t.SkipNow()
}
ExampleTPM_AttestPlatform()
}
func ExampleTPM_AttestPlatform() {
tpm, err := attest.OpenTPM(nil) tpm, err := attest.OpenTPM(nil)
if err != nil { if err != nil {
log.Fatalf("Failed to open TPM: %v", err) log.Fatalf("Failed to open TPM: %v", err)
@ -147,30 +123,27 @@ func ExampleAIKPublic_Verify() {
// The nonce would typically be provided by the server. // The nonce would typically be provided by the server.
nonce := []byte{1, 2, 3, 4, 5, 6, 7, 8} nonce := []byte{1, 2, 3, 4, 5, 6, 7, 8}
// Perform the quote & gather information necessary to verify it. // Perform an attestation against the state of the plaform. Usually, you
quote, err := aik.Quote(tpm, nonce, attest.HashSHA256) // would pass a nil config, and the event log would be read from the
// platform. To ensure this example runs on platforms without event logs,
// we pass a fake EventLog value.
att, err := tpm.AttestPlatform(aik, nonce, &attest.PlatformAttestConfig{
EventLog: []byte{0},
})
if err != nil { if err != nil {
log.Fatalf("Failed to generate quote: %v", err) log.Fatalf("Failed to attest the platform state: %v", err)
}
pcrs, err := tpm.PCRs(attest.HashSHA256)
if err != nil {
log.Fatalf("Failed to collect PCR values: %v", err)
} }
// Construct an AIKPublic struct from the parameters of the key. // Construct an AIKPublic struct from the parameters of the key. This
// will be used to verify the quote signatures.
pub, err := attest.ParseAIKPublic(tpm.Version(), aik.AttestationParameters().Public) pub, err := attest.ParseAIKPublic(tpm.Version(), aik.AttestationParameters().Public)
if err != nil { if err != nil {
log.Fatalf("Failed to parse AIK public: %v", err) log.Fatalf("Failed to parse AIK public: %v", err)
} }
if err := pub.Verify(*quote, pcrs, nonce); err != nil { for i, q := range att.Quotes {
log.Fatalf("Verification failed: %v", err) if err := pub.Verify(q, att.PCRs, nonce); err != nil {
log.Fatalf("quote[%d] verification failed: %v", i, err)
}
} }
} }
func TestExampleAIKPublic(t *testing.T) {
if !*testExamples {
t.SkipNow()
}
ExampleAIKPublic_Verify()
}

View File

@ -298,6 +298,9 @@ func (t *TPM) LoadAIK(opaqueBlob []byte) (*AIK, error) {
} }
// MeasurementLog returns the present value of the System Measurement Log. // MeasurementLog returns the present value of the System Measurement Log.
//
// This is a low-level API. Consumers seeking to attest the state of the
// platform should use tpm.AttestPlatform() instead.
func (t *TPM) MeasurementLog() ([]byte, error) { func (t *TPM) MeasurementLog() ([]byte, error) {
return t.tpm.measurementLog() return t.tpm.measurementLog()
} }
@ -310,9 +313,8 @@ func (t *TPM) NewAIK(opts *AIKConfig) (*AIK, error) {
// PCRs returns the present value of Platform Configuration Registers with // PCRs returns the present value of Platform Configuration Registers with
// the given digest algorithm. // the given digest algorithm.
// //
// Use ParseEventLog to determine which algorithm to use to match the values // This is a low-level API. Consumers seeking to attest the state of the
// present in the event log. It's not always guarenteed that a system with TPM // platform should use tpm.AttestPlatform() instead.
// 2.0 will extend PCRs with SHA256 digests.
func (t *TPM) PCRs(alg HashAlg) ([]PCR, error) { func (t *TPM) PCRs(alg HashAlg) ([]PCR, error) {
return t.tpm.pcrs(alg) return t.tpm.pcrs(alg)
} }
@ -358,16 +360,36 @@ func (t *TPM) attestPlatform(aik *AIK, nonce []byte, eventLog []byte) (*Platform
return &out, nil return &out, nil
} }
// PlatformAttestConfig configures how attestations are generated through
// tpm.AttestPlatform().
type PlatformAttestConfig struct {
// If non-nil, the raw event log will be read from EventLog
// instead of being obtained from the running system.
EventLog []byte
}
// AttestPlatform computes the set of information necessary to attest the // AttestPlatform computes the set of information necessary to attest the
// state of the platform. For TPM 2.0 devices, AttestPlatform will attempt // state of the platform. For TPM 2.0 devices, AttestPlatform will attempt
// to read both SHA1 & SHA256 PCR banks and quote both of them, so bugs in // to read both SHA1 & SHA256 PCR banks and quote both of them, so bugs in
// platform firmware which break replay for one PCR bank can be mitigated // platform firmware which break replay for one PCR bank can be mitigated
// using the other. // using the other.
func (t *TPM) AttestPlatform(aik *AIK, nonce []byte) (*PlatformParameters, error) { // The provided config, if not nil, can be used to configure aspects of the
el, err := t.MeasurementLog() // platform attestation.
if err != nil { func (t *TPM) AttestPlatform(aik *AIK, nonce []byte, config *PlatformAttestConfig) (*PlatformParameters, error) {
if config == nil {
config = &PlatformAttestConfig{}
}
var el []byte
if config.EventLog != nil {
el = config.EventLog
} else {
var err error
if el, err = t.MeasurementLog(); err != nil {
return nil, fmt.Errorf("failed to read event log: %v", err) return nil, fmt.Errorf("failed to read event log: %v", err)
} }
}
return t.attestPlatform(aik, nonce, el) return t.attestPlatform(aik, nonce, el)
} }