Support AIKPublic.validate20Quote() consuming PCRs not part of the quote (#115)

This commit is contained in:
Tom D
2019-09-26 15:11:31 -07:00
committed by GitHub
parent 5d5d6d83ca
commit 56dc743f14
5 changed files with 69 additions and 19 deletions

View File

@ -33,7 +33,7 @@ func setupSimulatedTPM(t *testing.T) (*simulator.Simulator, *TPM) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
return tpm, &TPM{&platformTPM{ return tpm, &TPM{tpm: &platformTPM{
version: TPMVersion20, version: TPMVersion20,
interf: TPMInterfaceKernelManaged, interf: TPMInterfaceKernelManaged,
sysPath: "/dev/tpmrm0", sysPath: "/dev/tpmrm0",
@ -148,7 +148,7 @@ func TestParseAIKPublic20(t *testing.T) {
} }
} }
func TestSimTPM20Quote(t *testing.T) { func TestSimTPM20QuoteAndVerify(t *testing.T) {
sim, tpm := setupSimulatedTPM(t) sim, tpm := setupSimulatedTPM(t)
defer sim.Close() defer sim.Close()
@ -163,9 +163,51 @@ func TestSimTPM20Quote(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("aik.Quote() failed: %v", err) t.Fatalf("aik.Quote() failed: %v", err)
} }
// TODO(jsonp): Parse quote structure once gotpm/tpm2 supports it.
if quote == nil { // Providing both PCR banks to AIKPublic.Verify() ensures we can handle
t.Error("quote was nil, want *Quote") // the case where extra PCRs of a different digest algorithm are provided.
var pcrs []PCR
for _, alg := range []HashAlg{HashSHA256, HashSHA1} {
p, err := tpm.PCRs(alg)
if err != nil {
t.Fatalf("tpm.PCRs(%v) failed: %v", alg, err)
}
pcrs = append(pcrs, p...)
}
pub, err := ParseAIKPublic(tpm.Version(), aik.AttestationParameters().Public)
if err != nil {
t.Fatalf("ParseAIKPublic() failed: %v", err)
}
if err := pub.Verify(*quote, pcrs, nonce); err != nil {
t.Errorf("quote verification failed: %v", err)
}
}
func TestSimTPM20AttestPlatform(t *testing.T) {
sim, tpm := setupSimulatedTPM(t)
defer sim.Close()
aik, err := tpm.NewAIK(nil)
if err != nil {
t.Fatalf("NewAIK() failed: %v", err)
}
defer aik.Close(tpm)
nonce := []byte{1, 2, 3, 4, 5, 6, 7, 8}
attestation, err := tpm.attestPlatform(aik, nonce, nil)
if err != nil {
t.Fatalf("AttestPlatform() failed: %v", err)
}
pub, err := ParseAIKPublic(attestation.TPMVersion, attestation.Public)
if err != nil {
t.Fatalf("ParseAIKPublic() failed: %v", err)
}
for i, q := range attestation.Quotes {
if err := pub.Verify(q, attestation.PCRs, nonce); err != nil {
t.Errorf("quote[%d] verification failed: %v", i, err)
}
} }
} }

View File

@ -198,9 +198,13 @@ func (a *AIKPublic) validate20Quote(quote Quote, pcrs []PCR, nonce []byte) error
} }
pcrByIndex := map[int][]byte{} pcrByIndex := map[int][]byte{}
pcrDigestLength := HashAlg(att.AttestedQuoteInfo.PCRSelection.Hash).cryptoHash().Size()
for _, pcr := range pcrs { for _, pcr := range pcrs {
// TODO(jsonp): Use pcr.DigestAlg once #116 is fixed.
if len(pcr.Digest) == pcrDigestLength {
pcrByIndex[pcr.Index] = pcr.Digest pcrByIndex[pcr.Index] = pcr.Digest
} }
}
n := len(att.AttestedQuoteInfo.PCRDigest) n := len(att.AttestedQuoteInfo.PCRDigest)
hash, ok := hashBySize[n] hash, ok := hashBySize[n]

View File

@ -329,20 +329,11 @@ func (t *TPM) attestPCRs(aik *AIK, nonce []byte, alg HashAlg) (*Quote, []PCR, er
return quote, pcrs, nil return quote, pcrs, nil
} }
// AttestPlatform computes the set of information necessary to attest the func (t *TPM) attestPlatform(aik *AIK, nonce []byte, eventLog []byte) (*PlatformParameters, error) {
// 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
// platform firmware which break replay for one PCR bank can be mitigated
// using the other.
func (t *TPM) AttestPlatform(aik *AIK, nonce []byte) (*PlatformParameters, error) {
out := PlatformParameters{ out := PlatformParameters{
TPMVersion: t.Version(), TPMVersion: t.Version(),
Public: aik.AttestationParameters().Public, Public: aik.AttestationParameters().Public,
} EventLog: eventLog,
var err error
if out.EventLog, err = t.MeasurementLog(); err != nil {
return nil, fmt.Errorf("failed to read event log: %v", err)
} }
algs := []HashAlg{HashSHA1} algs := []HashAlg{HashSHA1}
@ -367,6 +358,19 @@ func (t *TPM) AttestPlatform(aik *AIK, nonce []byte) (*PlatformParameters, error
return &out, nil return &out, nil
} }
// AttestPlatform computes the set of information necessary to attest the
// 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
// platform firmware which break replay for one PCR bank can be mitigated
// using the other.
func (t *TPM) AttestPlatform(aik *AIK, nonce []byte) (*PlatformParameters, error) {
el, err := t.MeasurementLog()
if err != nil {
return nil, fmt.Errorf("failed to read event log: %v", err)
}
return t.attestPlatform(aik, nonce, el)
}
// Version returns the version of the TPM. // Version returns the version of the TPM.
func (t *TPM) Version() TPMVersion { func (t *TPM) Version() TPMVersion {
return t.tpm.tpmVersion() return t.tpm.tpmVersion()

View File

@ -122,7 +122,7 @@ func openTPM(tpm probedTPM) (*TPM, error) {
} }
} }
return &TPM{&platformTPM{ return &TPM{tpm: &platformTPM{
version: tpm.Version, version: tpm.Version,
interf: interf, interf: interf,
sysPath: tpm.Path, sysPath: tpm.Path,

View File

@ -89,7 +89,7 @@ func openTPM(tpm probedTPM) (*TPM, error) {
return nil, fmt.Errorf("tbsConvertVersion(%v) failed: %v", info.TBSInfo.TPMVersion, err) return nil, fmt.Errorf("tbsConvertVersion(%v) failed: %v", info.TBSInfo.TPMVersion, err)
} }
return &TPM{&platformTPM{ return &TPM{tpm: &platformTPM{
pcp: pcp, pcp: pcp,
version: vers, version: vers,
}}, nil }}, nil