attest: improve event log debugging (#190)

Event log verification is terrible and easy to mess up. Even if you
replay against the PCRs there are still values that can be tampered with
or reordered. PCRs also shouldn't be trusted unless they're attested to
have come from the correct TPM.

Given this, it seems advantageous to add some ability to consume raw
event logs, even if it's just for debugging.
This commit is contained in:
Eric Chiang 2020-11-30 12:22:43 -08:00 committed by GitHub
parent 63c5188962
commit 0efaf4b19f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -65,17 +65,71 @@ const (
)
// EventType indicates what kind of data an event is reporting.
//
// https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClientSpecPlat_TPM_2p0_1p04_pub.pdf#page=103
type EventType uint32
var eventTypeStrings = map[uint32]string{
0x00000000: "EV_PREBOOT_CERT",
0x00000001: "EV_POST_CODE",
0x00000002: "EV_UNUSED",
0x00000003: "EV_NO_ACTION",
0x00000004: "EV_SEPARATOR",
0x00000005: "EV_ACTION",
0x00000006: "EV_EVENT_TAG",
0x00000007: "EV_S_CRTM_CONTENTS",
0x00000008: "EV_S_CRTM_VERSION",
0x00000009: "EV_CPU_MICROCODE",
0x0000000A: "EV_PLATFORM_CONFIG_FLAGS",
0x0000000B: "EV_TABLE_OF_DEVICES",
0x0000000C: "EV_COMPACT_HASH",
0x0000000D: "EV_IPL",
0x0000000E: "EV_IPL_PARTITION_DATA",
0x0000000F: "EV_NONHOST_CODE",
0x00000010: "EV_NONHOST_CONFIG",
0x00000011: "EV_NONHOST_INFO",
0x00000012: "EV_OMIT_BOOT_DEVICE_EVENTS",
0x80000000: "EV_EFI_EVENT_BASE",
0x80000001: "EV_EFI_VARIABLE_DRIVER_CONFIG",
0x80000002: "EV_EFI_VARIABLE_BOOT",
0x80000003: "EV_EFI_BOOT_SERVICES_APPLICATION",
0x80000004: "EV_EFI_BOOT_SERVICES_DRIVER",
0x80000005: "EV_EFI_RUNTIME_SERVICES_DRIVER",
0x80000006: "EV_EFI_GPT_EVENT",
0x80000007: "EV_EFI_ACTION",
0x80000008: "EV_EFI_PLATFORM_FIRMWARE_BLOB",
0x80000009: "EV_EFI_HANDOFF_TABLES",
0x80000010: "EV_EFI_HCRTM_EVENT",
0x800000E0: "EV_EFI_VARIABLE_AUTHORITY",
}
// String returns the Spec name of the EventType, for example "EV_ACTION". If
// unknown, it returns a formatted string of the EventType value.
func (e EventType) String() string {
if s, ok := eventTypeStrings[uint32(e)]; ok {
return s
}
// NOTE: 0x00000013-0x0000FFFF are reserverd. Should we include that
// information in the formatting?
return fmt.Sprintf("EventType(0x%08x)", uint32(e))
}
// Event is a single event from a TCG event log. This reports descrete items such
// as BIOs measurements or EFI states.
//
// There are many pitfalls for using event log events correctly to determine the
// state of a machine[1]. In general it's must safer to only rely on the raw PCR
// values and use the event log for debugging.
//
// [1] https://github.com/google/go-attestation/blob/master/docs/event-log-disclosure.md
type Event struct {
// order of the event in the event log.
sequence int
// PCR index of the event.
// Index of the PCR that this event was replayed against.
Index int
// Type of the event.
// Untrusted type of the event. This value is not verified by event log replays
// and can be tampered with. It should NOT be used without additional context,
// and unrecognized event types should result in errors.
Type EventType
// Data of the event. For certain kinds of events, this must match the event
@ -132,8 +186,39 @@ func (e *EventLog) clone() *EventLog {
return &out
}
// Events returns events that have not been replayed against the PCR values and
// are therefore unverified. The returned events contain the digest that matches
// the provided hash algorithm, or are empty if that event didn't contain a
// digest for that hash.
//
// This method is insecure and should only be used for debugging.
func (e *EventLog) Events(hash HashAlg) []Event {
var events []Event
for _, re := range e.rawEvents {
ev := Event{
Index: re.index,
Type: re.typ,
Data: re.data,
}
for _, digest := range re.digests {
if hash.cryptoHash() != digest.hash {
continue
}
ev.Digest = digest.data
break
}
events = append(events, ev)
}
return events
}
// Verify replays the event log against a TPM's PCR values, returning the
// events which could be matched to a provided PCR value.
//
// PCRs provide no security guarentees unless they're attested to have been
// generated by a TPM. Verify does not perform these checks.
//
// An error is returned if the replayed digest for events with a given PCR
// index do not match any provided value for that PCR index.
func (e *EventLog) Verify(pcrs []PCR) ([]Event, error) {