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.
This commit is contained in:
Matthew Garrett
2019-12-09 16:56:49 -08:00
parent 9746da2bfe
commit 9176b4bcb6
2 changed files with 28 additions and 18 deletions

View File

@ -343,20 +343,21 @@ const eventTypeNoAction = 0x03
// ParseEventLog parses an unverified measurement log. // ParseEventLog parses an unverified measurement log.
func ParseEventLog(measurementLog []byte) (*EventLog, error) { func ParseEventLog(measurementLog []byte) (*EventLog, error) {
var specID *specIDEvent
r := bytes.NewBuffer(measurementLog) r := bytes.NewBuffer(measurementLog)
parseFn := parseRawEvent parseFn := parseRawEvent
var el EventLog var el EventLog
e, err := parseFn(r) e, err := parseFn(r, specID)
if err != nil { if err != nil {
return nil, fmt.Errorf("parse first event: %v", err) return nil, fmt.Errorf("parse first event: %v", err)
} }
if e.typ == eventTypeNoAction { if e.typ == eventTypeNoAction {
specID, err := parseSpecIDEvent(e.data) specID, err = parseSpecIDEvent(e.data)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to parse spec ID event: %v", err) return nil, fmt.Errorf("failed to parse spec ID event: %v", err)
} }
for _, alg := range specID.algs { for _, alg := range specID.algs {
switch tpm2.Algorithm(alg) { switch tpm2.Algorithm(alg.ID) {
case tpm2.AlgSHA1: case tpm2.AlgSHA1:
el.Algs = append(el.Algs, HashSHA1) el.Algs = append(el.Algs, HashSHA1)
case tpm2.AlgSHA256: case tpm2.AlgSHA256:
@ -378,7 +379,7 @@ func ParseEventLog(measurementLog []byte) (*EventLog, error) {
} }
sequence := 1 sequence := 1
for r.Len() != 0 { for r.Len() != 0 {
e, err := parseFn(r) e, err := parseFn(r, specID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -390,7 +391,7 @@ func ParseEventLog(measurementLog []byte) (*EventLog, error) {
} }
type specIDEvent struct { type specIDEvent struct {
algs []uint16 algs []specAlgSize
} }
type specAlgSize struct { type specAlgSize struct {
@ -450,7 +451,7 @@ func parseSpecIDEvent(b []byte) (*specIDEvent, error) {
if err := binary.Read(r, binary.LittleEndian, &specAlg); err != nil { if err := binary.Read(r, binary.LittleEndian, &specAlg); err != nil {
return nil, fmt.Errorf("reading algorithm: %v", err) return nil, fmt.Errorf("reading algorithm: %v", err)
} }
e.algs = append(e.algs, specAlg.ID) e.algs = append(e.algs, specAlg)
} }
var vendorInfoSize uint8 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) 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 var h rawEventHeader
if err = binary.Read(r, binary.LittleEndian, &h); err != nil { if err = binary.Read(r, binary.LittleEndian, &h); err != nil {
return event, err return event, err
@ -516,7 +517,7 @@ type rawEvent2Header struct {
Type uint32 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 var h rawEvent2Header
if err = binary.Read(r, binary.LittleEndian, &h); err != nil { if err = binary.Read(r, binary.LittleEndian, &h); err != nil {
return event, err 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 { if err := binary.Read(r, binary.LittleEndian, &numDigests); err != nil {
return event, err return event, err
} }
for i := 0; i < int(numDigests); i++ { for i := 0; i < int(numDigests); i++ {
var algID uint16 var algID uint16
if err := binary.Read(r, binary.LittleEndian, &algID); err != nil { if err := binary.Read(r, binary.LittleEndian, &algID); err != nil {
return event, err return event, err
} }
var digest []byte var digest []byte
switch algID { for _, alg := range specID.algs {
case algSHA1: if alg.ID != algID {
digest = make([]byte, crypto.SHA1.Size()) continue
case algSHA256: }
digest = make([]byte, crypto.SHA256.Size()) if uint16(r.Len()) < alg.Size {
default: return event, fmt.Errorf("reading digest: %v", io.ErrUnexpectedEOF)
// ignore signatures that aren't SHA1 or SHA256 }
continue 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 { if _, err := io.ReadFull(r, digest); err != nil {
return event, err return event, err

View File

@ -232,13 +232,14 @@ func TestParseSpecIDEvent(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
spec, err := parseSpecIDEvent(test.data) spec, err := parseSpecIDEvent(test.data)
var algs []uint16
if (err != nil) != test.wantErr { if (err != nil) != test.wantErr {
t.Fatalf("parsing spec, wantErr=%t, got=%v", test.wantErr, err) t.Fatalf("parsing spec, wantErr=%t, got=%v", test.wantErr, err)
} }
if err != nil { if err != nil {
return return
} }
algsEq := func(got, want []uint16) bool { algsEq := func(want, got []uint16) bool {
if len(got) != len(want) { if len(got) != len(want) {
return false return false
} }
@ -250,7 +251,11 @@ func TestParseSpecIDEvent(t *testing.T) {
return true 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) t.Errorf("algorithms, got=%x, want=%x", spec.algs, test.want)
} }
}) })