diff --git a/events/events.go b/events/events.go new file mode 100644 index 00000000..6d35ca2f --- /dev/null +++ b/events/events.go @@ -0,0 +1,308 @@ +// 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 events + +import ( + "bytes" + "encoding/binary" + "errors" + "unicode/utf16" + "unicode/utf8" + + "github.com/google/go-attestation/attest" +) + +const ( + // BIOS Events (TCG PC Client Specific Implementation Specification for Conventional BIOS 1.21) + prebootCert attest.EventType = 0x00000000 + postCode attest.EventType = 0x00000001 + unused attest.EventType = 0x00000002 + noAction attest.EventType = 0x00000003 + separator attest.EventType = 0x00000004 + action attest.EventType = 0x00000005 + eventTag attest.EventType = 0x00000006 + sCRTMContents attest.EventType = 0x00000007 + sCRTMVersion attest.EventType = 0x00000008 + cpuMicrocode attest.EventType = 0x00000009 + platformConfigFlags attest.EventType = 0x0000000A + tableOfDevices attest.EventType = 0x0000000B + compactHash attest.EventType = 0x0000000C + ipl attest.EventType = 0x0000000D + iplPartitionData attest.EventType = 0x0000000E + nonhostCode attest.EventType = 0x0000000F + nonhostConfig attest.EventType = 0x00000010 + nonhostInfo attest.EventType = 0x00000011 + omitBootDeviceEvents attest.EventType = 0x00000012 + + // EFI Events (TCG EFI Platform Specification Version 1.22) + efiEventBase attest.EventType = 0x80000000 + efiVariableDriverConfig attest.EventType = 0x80000001 + efiVariableBoot attest.EventType = 0x80000002 + efiBootServicesApplication attest.EventType = 0x80000003 + efiBootServicesDriver attest.EventType = 0x80000004 + efiRuntimeServicesDriver attest.EventType = 0x80000005 + efiGPTEvent attest.EventType = 0x80000006 + efiAction attest.EventType = 0x80000007 + efiPlatformFirmwareBlob attest.EventType = 0x80000008 + efiHandoffTables attest.EventType = 0x80000009 + efiHCRTMEvent attest.EventType = 0x80000010 + efiVariableAuthority attest.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() attest.EventType + base() attest.Event +} + +type baseEvent struct { + attest.Event + Err error +} + +type stringEvent struct { + baseEvent + Message string +} + +type PrebootCertEvent struct { + baseEvent +} + +type PostEvent struct { + stringEvent +} + +type NoActionEvent struct { + baseEvent +} + +type SeparatorEvent struct { + baseEvent +} + +type ActionEvent struct { + stringEvent +} + +type EventTagEvent struct { + baseEvent + EventID eventID + EventData []byte +} + +type CRTMContentEvent struct { + stringEvent +} + +type CRTMEvent struct { + stringEvent +} + +type MicrocodeEvent struct { + stringEvent +} + +type PlatformConfigFlagsEvent struct { + baseEvent +} + +type TableOfDevicesEvent struct { + baseEvent +} + +type CompactHashEvent struct { + baseEvent +} + +type IPLEvent struct { + stringEvent +} + +type IPLPartitionEvent struct { + baseEvent +} + +type NonHostCodeEvent struct { + baseEvent +} + +type NonHostConfigEvent struct { + baseEvent +} + +type NonHostInfoEvent struct { + baseEvent +} + +type OmitBootDeviceEventsEvent struct { + stringEvent +} + +func (event baseEvent) base() attest.Event { + return event.Event +} + +func (event baseEvent) eventType() attest.EventType { + return event.Type +} + +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 []attest.Event) ([]TPMEvent, error) { + var parsedEvents []TPMEvent + + for _, event := range events { + buf := bytes.NewBuffer(event.Data) + var err error + switch event.Type { + case prebootCert: // 0x00 + var parsedEvent PrebootCertEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case postCode: // 0x01 + var parsedEvent PostEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + parsedEvent.Message, err = parseStringData(event.Data) + if err != nil { + parsedEvent.Err = err + } + case noAction: // 0x03 + var parsedEvent NoActionEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case separator: // 0x04 + var parsedEvent SeparatorEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case action: // 0x05 + var parsedEvent ActionEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + parsedEvent.Message, err = parseStringData(event.Data) + if err != nil { + parsedEvent.Err = err + } + case eventTag: // 0x06 + var parsedEvent EventTagEvent + parsedEvent.EventData = event.Data[4:] + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + if err := binary.Read(buf, binary.LittleEndian, &parsedEvent.EventID); err != nil { + parsedEvent.Err = err + continue + } + case sCRTMContents: // 0x07 + var parsedEvent CRTMContentEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + parsedEvent.Message, err = parseStringData(event.Data) + case sCRTMVersion: // 0x08 + var parsedEvent CRTMEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + parsedEvent.Message, err = parseStringData(event.Data) + if err != nil { + parsedEvent.Err = err + } + case cpuMicrocode: // 0x09 + var parsedEvent MicrocodeEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + parsedEvent.Message, err = parseStringData(event.Data) + if err != nil { + parsedEvent.Err = err + } + case platformConfigFlags: // 0x0a + var parsedEvent PlatformConfigFlagsEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case tableOfDevices: // 0x0b + var parsedEvent TableOfDevicesEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case compactHash: // 0x0c + var parsedEvent CompactHashEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case ipl: // 0x0d + var parsedEvent IPLEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + parsedEvent.Message, err = parseStringData(event.Data) + if err != nil { + parsedEvent.Err = err + } + case iplPartitionData: // 0x0e + var parsedEvent IPLPartitionEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case nonhostCode: // 0x0f + var parsedEvent NonHostCodeEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case nonhostConfig: // 0x10 + var parsedEvent NonHostConfigEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case nonhostInfo: // 0x11 + var parsedEvent NonHostInfoEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + case omitBootDeviceEvents: // 0x0f + var parsedEvent OmitBootDeviceEventsEvent + parsedEvents = append(parsedEvents, parsedEvent) + parsedEvent.Event = event + parsedEvent.Message, err = parseStringData(event.Data) + if err != nil { + parsedEvent.Err = err + } + } + } + + return parsedEvents, nil +}