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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 {
t.Fatal(err)
}
return tpm, &TPM{&platformTPM{
return tpm, &TPM{tpm: &platformTPM{
version: TPMVersion20,
interf: TPMInterfaceKernelManaged,
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)
defer sim.Close()
@ -163,9 +163,51 @@ func TestSimTPM20Quote(t *testing.T) {
if err != nil {
t.Fatalf("aik.Quote() failed: %v", err)
}
// TODO(jsonp): Parse quote structure once gotpm/tpm2 supports it.
if quote == nil {
t.Error("quote was nil, want *Quote")
// Providing both PCR banks to AIKPublic.Verify() ensures we can handle
// 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,8 +198,12 @@ func (a *AIKPublic) validate20Quote(quote Quote, pcrs []PCR, nonce []byte) error
}
pcrByIndex := map[int][]byte{}
pcrDigestLength := HashAlg(att.AttestedQuoteInfo.PCRSelection.Hash).cryptoHash().Size()
for _, pcr := range pcrs {
pcrByIndex[pcr.Index] = pcr.Digest
// TODO(jsonp): Use pcr.DigestAlg once #116 is fixed.
if len(pcr.Digest) == pcrDigestLength {
pcrByIndex[pcr.Index] = pcr.Digest
}
}
n := len(att.AttestedQuoteInfo.PCRDigest)

View File

@ -329,20 +329,11 @@ func (t *TPM) attestPCRs(aik *AIK, nonce []byte, alg HashAlg) (*Quote, []PCR, er
return quote, pcrs, 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) {
func (t *TPM) attestPlatform(aik *AIK, nonce []byte, eventLog []byte) (*PlatformParameters, error) {
out := PlatformParameters{
TPMVersion: t.Version(),
Public: aik.AttestationParameters().Public,
}
var err error
if out.EventLog, err = t.MeasurementLog(); err != nil {
return nil, fmt.Errorf("failed to read event log: %v", err)
EventLog: eventLog,
}
algs := []HashAlg{HashSHA1}
@ -367,6 +358,19 @@ func (t *TPM) AttestPlatform(aik *AIK, nonce []byte) (*PlatformParameters, error
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.
func (t *TPM) Version() 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,
interf: interf,
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 &TPM{&platformTPM{
return &TPM{tpm: &platformTPM{
pcp: pcp,
version: vers,
}}, nil