From 9176b4bcb60fade9715d7514f8f5ec80a0d911c4 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Mon, 9 Dec 2019 16:56:49 -0800 Subject: [PATCH] Pay attention to digest size information in the headers Crypto agile logs may contain digest types that we don't currently handle. However, we still need to know how long each digest is in order to read over the appropriate amount of the buffer. This information is provided to us as part of the spec header - make use of it rather than hardcoding the set of digests and lengths we know about. --- attest/eventlog.go | 37 +++++++++++++++++++++---------------- attest/eventlog_test.go | 9 +++++++-- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/attest/eventlog.go b/attest/eventlog.go index b041e27..d27bfac 100644 --- a/attest/eventlog.go +++ b/attest/eventlog.go @@ -343,20 +343,21 @@ const eventTypeNoAction = 0x03 // ParseEventLog parses an unverified measurement log. func ParseEventLog(measurementLog []byte) (*EventLog, error) { + var specID *specIDEvent r := bytes.NewBuffer(measurementLog) parseFn := parseRawEvent var el EventLog - e, err := parseFn(r) + e, err := parseFn(r, specID) if err != nil { return nil, fmt.Errorf("parse first event: %v", err) } if e.typ == eventTypeNoAction { - specID, err := parseSpecIDEvent(e.data) + specID, err = parseSpecIDEvent(e.data) if err != nil { return nil, fmt.Errorf("failed to parse spec ID event: %v", err) } for _, alg := range specID.algs { - switch tpm2.Algorithm(alg) { + switch tpm2.Algorithm(alg.ID) { case tpm2.AlgSHA1: el.Algs = append(el.Algs, HashSHA1) case tpm2.AlgSHA256: @@ -378,7 +379,7 @@ func ParseEventLog(measurementLog []byte) (*EventLog, error) { } sequence := 1 for r.Len() != 0 { - e, err := parseFn(r) + e, err := parseFn(r, specID) if err != nil { return nil, err } @@ -390,7 +391,7 @@ func ParseEventLog(measurementLog []byte) (*EventLog, error) { } type specIDEvent struct { - algs []uint16 + algs []specAlgSize } type specAlgSize struct { @@ -450,7 +451,7 @@ func parseSpecIDEvent(b []byte) (*specIDEvent, error) { if err := binary.Read(r, binary.LittleEndian, &specAlg); err != nil { return nil, fmt.Errorf("reading algorithm: %v", err) } - e.algs = append(e.algs, specAlg.ID) + e.algs = append(e.algs, specAlg) } var vendorInfoSize uint8 @@ -489,7 +490,7 @@ func (e *eventSizeErr) Error() string { return fmt.Sprintf("event data size (%d bytes) is greater than remaining measurement log (%d bytes)", e.eventSize, e.logSize) } -func parseRawEvent(r *bytes.Buffer) (event rawEvent, err error) { +func parseRawEvent(r *bytes.Buffer, specID *specIDEvent) (event rawEvent, err error) { var h rawEventHeader if err = binary.Read(r, binary.LittleEndian, &h); err != nil { return event, err @@ -516,7 +517,7 @@ type rawEvent2Header struct { Type uint32 } -func parseRawEvent2(r *bytes.Buffer) (event rawEvent, err error) { +func parseRawEvent2(r *bytes.Buffer, specID *specIDEvent) (event rawEvent, err error) { var h rawEvent2Header if err = binary.Read(r, binary.LittleEndian, &h); err != nil { return event, err @@ -529,20 +530,24 @@ func parseRawEvent2(r *bytes.Buffer) (event rawEvent, err error) { if err := binary.Read(r, binary.LittleEndian, &numDigests); err != nil { return event, err } + for i := 0; i < int(numDigests); i++ { var algID uint16 if err := binary.Read(r, binary.LittleEndian, &algID); err != nil { return event, err } var digest []byte - switch algID { - case algSHA1: - digest = make([]byte, crypto.SHA1.Size()) - case algSHA256: - digest = make([]byte, crypto.SHA256.Size()) - default: - // ignore signatures that aren't SHA1 or SHA256 - continue + for _, alg := range specID.algs { + if alg.ID != algID { + continue + } + if uint16(r.Len()) < alg.Size { + return event, fmt.Errorf("reading digest: %v", io.ErrUnexpectedEOF) + } + digest = make([]byte, alg.Size) + } + if len(digest) == 0 { + return event, fmt.Errorf("unknown algorithm ID %x", algID) } if _, err := io.ReadFull(r, digest); err != nil { return event, err diff --git a/attest/eventlog_test.go b/attest/eventlog_test.go index c0572f5..cdf6782 100644 --- a/attest/eventlog_test.go +++ b/attest/eventlog_test.go @@ -232,13 +232,14 @@ func TestParseSpecIDEvent(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { spec, err := parseSpecIDEvent(test.data) + var algs []uint16 if (err != nil) != test.wantErr { t.Fatalf("parsing spec, wantErr=%t, got=%v", test.wantErr, err) } if err != nil { return } - algsEq := func(got, want []uint16) bool { + algsEq := func(want, got []uint16) bool { if len(got) != len(want) { return false } @@ -250,7 +251,11 @@ func TestParseSpecIDEvent(t *testing.T) { return true } - if !algsEq(test.want, spec.algs) { + for _, alg := range(spec.algs) { + algs = append(algs, alg.ID) + } + + if !algsEq(test.want, algs) { t.Errorf("algorithms, got=%x, want=%x", spec.algs, test.want) } })