-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add an initial implementation of parsing event types
Raw events aren't enormously helpful. Add an initial implementation of some of the basic event types - this is largely a scratch proposal so we can figure out API design.
- Loading branch information
Matthew Garrett
committed
Sep 20, 2019
1 parent
b60a7cc
commit 64b577d
Showing
1 changed file
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |