diff --git a/attest/eventlog_events.go b/attest/eventlog_events.go new file mode 100644 index 00000000..17bbd494 --- /dev/null +++ b/attest/eventlog_events.go @@ -0,0 +1,281 @@ +// Copyright 2019 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +package attest + +import ( + "bytes" + "encoding/binary" + "errors" + "unicode/utf16" + "unicode/utf8" +) + +const ( + // BIOS Events (TCG PC Client Specific Implementation Specification for Conventional BIOS 1.21) + prebootCert EventType = 0x00000000 + postCode EventType = 0x00000001 + unused EventType = 0x00000002 + noAction EventType = 0x00000003 + separator EventType = 0x00000004 + action EventType = 0x00000005 + eventTag EventType = 0x00000006 + sCRTMContents EventType = 0x00000007 + sCRTMVersion EventType = 0x00000008 + cpuMicrocode EventType = 0x00000009 + platformConfigFlags EventType = 0x0000000A + tableOfDevices EventType = 0x0000000B + compactHash EventType = 0x0000000C + ipl EventType = 0x0000000D + iplPartitionData EventType = 0x0000000E + nonhostCode EventType = 0x0000000F + nonhostConfig EventType = 0x00000010 + nonhostInfo EventType = 0x00000011 + omitBootDeviceEvents EventType = 0x00000012 + + // EFI Events (TCG EFI Platform Specification Version 1.22) + efiEventBase EventType = 0x80000000 + efiVariableDriverConfig EventType = 0x80000001 + efiVariableBoot EventType = 0x80000002 + efiBootServicesApplication EventType = 0x80000003 + efiBootServicesDriver EventType = 0x80000004 + efiRuntimeServicesDriver EventType = 0x80000005 + efiGPTEvent EventType = 0x80000006 + efiAction EventType = 0x80000007 + efiPlatformFirmwareBlob EventType = 0x80000008 + efiHandoffTables EventType = 0x80000009 + efiHCRTMEvent EventType = 0x80000010 + efiVariableAuthority EventType = 0x800000e0 +) + +type eventID uint32 + +const ( + smbios eventID = 0x00 + bisCertificate eventID = 0x01 + postBIOSROM eventID = 0x02 + escdeventID eventID = 0x03 + cmos eventID = 0x04 + nvram eventID = 0x05 + optionROMExecute eventID = 0x06 + optionROMConfiguration eventID = 0x07 +) + +type TPMEvent interface { + eventType() EventType + base() rawEvent +} + +type stringEvent struct { + rawEvent + Message string +} + +type PrebootCertEvent struct { + rawEvent +} + +type PostEvent struct { + stringEvent +} + +type NoActionEvent struct { + rawEvent +} + +type SeparatorEvent struct { + rawEvent +} + +type ActionEvent struct { + stringEvent +} + +type EventTagEvent struct { + rawEvent + EventID eventID + EventData []byte +} + +type CRTMContentEvent struct { + stringEvent +} + +type CRTMEvent struct { + stringEvent +} + +type MicrocodeEvent struct { + stringEvent +} + +type PlatformConfigFlagsEvent struct { + rawEvent +} + +type TableOfDevicesEvent struct { + rawEvent +} + +type CompactHashEvent struct { + rawEvent +} + +type IPLEvent struct { + stringEvent +} + +type IPLPartitionEvent struct { + rawEvent +} + +type NonHostCodeEvent struct { + rawEvent +} + +type NonHostConfigEvent struct { + rawEvent +} + +type NonHostInfoEvent struct { + rawEvent +} + +type OmitBootDeviceEventsEvent struct { + stringEvent +} + +func (event rawEvent) base() rawEvent { + return event +} + +func (event rawEvent) eventType() EventType { + return event.typ +} + +func parseStringData(b []byte) (string, error) { + var buf []uint16 + for i := 0; i < len(b); i += 2 { + if b[i+1] != 0x00 { + buf = nil + break + } + buf = append(buf, binary.LittleEndian.Uint16(b[i:])) + } + + if buf != nil { + return string(utf16.Decode(buf)), nil + } + + if !utf8.Valid(b) { + return "", errors.New("invalid UTF-8 string") + } + + return string(b), nil +} + +func ParseEvents(events *EventLog) ([]TPMEvent, error) { + var parsedEvents []TPMEvent + + for _, event := range events.rawEvents { + buf := bytes.NewBuffer(event.data) + switch event.typ { + case prebootCert: // 0x00 + var parsedEvent PrebootCertEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case postCode: // 0x01 + var parsedEvent PostEvent + parsedEvent.rawEvent = event + parsedEvent.Message, _ = parseStringData(event.data) + parsedEvents = append(parsedEvents, parsedEvent) + case noAction: // 0x03 + var parsedEvent NoActionEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case separator: // 0x04 + var parsedEvent SeparatorEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case action: // 0x05 + var parsedEvent ActionEvent + parsedEvent.rawEvent = event + parsedEvent.Message, _ = parseStringData(event.data) + parsedEvents = append(parsedEvents, parsedEvent) + case eventTag: // 0x06 + var parsedEvent EventTagEvent + parsedEvent.rawEvent = event + if err := binary.Read(buf, binary.LittleEndian, &parsedEvent.EventID); err != nil { + continue + } + parsedEvent.EventData = event.data[4:] + parsedEvents = append(parsedEvents, parsedEvent) + case sCRTMContents: // 0x07 + var parsedEvent CRTMContentEvent + parsedEvent.rawEvent = event + parsedEvent.Message, _ = parseStringData(event.data) + parsedEvents = append(parsedEvents, parsedEvent) + case sCRTMVersion: // 0x08 + var parsedEvent CRTMEvent + parsedEvent.rawEvent = event + parsedEvent.Message, _ = parseStringData(event.data) + parsedEvents = append(parsedEvents, parsedEvent) + case cpuMicrocode: // 0x09 + var parsedEvent MicrocodeEvent + parsedEvent.rawEvent = event + parsedEvent.Message, _ = parseStringData(event.data) + parsedEvents = append(parsedEvents, parsedEvent) + case platformConfigFlags: // 0x0a + var parsedEvent PlatformConfigFlagsEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case tableOfDevices: // 0x0b + var parsedEvent TableOfDevicesEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case compactHash: // 0x0c + var parsedEvent CompactHashEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case ipl: // 0x0d + var parsedEvent IPLEvent + parsedEvent.rawEvent = event + parsedEvent.Message, _ = parseStringData(event.data) + parsedEvents = append(parsedEvents, parsedEvent) + case iplPartitionData: // 0x0e + var parsedEvent IPLPartitionEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case nonhostCode: // 0x0f + var parsedEvent NonHostCodeEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case nonhostConfig: // 0x10 + var parsedEvent NonHostConfigEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case nonhostInfo: // 0x11 + var parsedEvent NonHostInfoEvent + parsedEvent.rawEvent = event + parsedEvents = append(parsedEvents, parsedEvent) + case omitBootDeviceEvents: // 0x0f + var parsedEvent OmitBootDeviceEventsEvent + parsedEvent.rawEvent = event + parsedEvent.Message, _ = parseStringData(event.data) + parsedEvents = append(parsedEvents, parsedEvent) + } + } + + return parsedEvents, nil +}