mirror of
https://github.com/google/go-attestation.git
synced 2024-12-21 05:53:25 +00:00
internal/eventlog: add code for parsing secure boot variables
This is being prototyped in an internal package as we start to open source. This code will either live in attest, or in a separate eventlog package in the future.
This commit is contained in:
parent
07feb34890
commit
9021153e89
185
attest/attest-tool/internal/eventlog/eventlog.go
Normal file
185
attest/attest-tool/internal/eventlog/eventlog.go
Normal file
@ -0,0 +1,185 @@
|
||||
// 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 eventlog implements experimental logic for parsing the TCG event log format.
|
||||
package eventlog
|
||||
|
||||
import "fmt"
|
||||
|
||||
// eventType indicates what kind of data an event is reporting.
|
||||
type eventType uint32
|
||||
|
||||
func isReserved(t eventType) bool {
|
||||
if 0x00000013 <= t && t <= 0x0000FFFF {
|
||||
return true
|
||||
}
|
||||
if 0x800000E1 <= t && t <= 0x8000FFFF {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// String returns the name as defined by the TCG specification.
|
||||
func (e eventType) String() string {
|
||||
if s, ok := eventTypeNames[e]; ok {
|
||||
return s
|
||||
}
|
||||
s := fmt.Sprintf("eventType(0x%08x)", int(e))
|
||||
if isReserved(e) {
|
||||
s += " (reserved)"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
const (
|
||||
// https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_Specific_Platform_Profile_for_TPM_2p0_1p04_PUBLIC.pdf#page=103
|
||||
|
||||
// Reserved for future use.
|
||||
evPrebootCert eventType = 0x00000000
|
||||
|
||||
// Host platform trust chain measurements. The event data can contain one of
|
||||
// the following, indicating different points of boot: "POST CODE", "SMM CODE",
|
||||
// "ACPI DATA", "BIS CODE", "Embedded UEFI Driver".
|
||||
//
|
||||
// PCR[0] MUST be extended with this event type.
|
||||
//
|
||||
// https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_Specific_Platform_Profile_for_TPM_2p0_1p04_PUBLIC.pdf#page=38
|
||||
evPostCode eventType = 0x00000001
|
||||
|
||||
// The event type was never used and is considered reserved.
|
||||
evUnused eventType = 0x00000002
|
||||
|
||||
// Used for PCRs[0,6]. This event type doesn't extend the PCR, the digest MUST
|
||||
// be all zeros, and the data holds information intended for parsers such as
|
||||
// delimiting a switch to the agile crypto event format.
|
||||
//
|
||||
// This event MUST NOT extend any PCR
|
||||
evNoAction eventType = 0x00000003
|
||||
|
||||
// Delineates the point where the Platform Firmware relinquishes control of TPM
|
||||
// measurements to the operating system.
|
||||
//
|
||||
// Event data size MUST contain either 0x00000000 or 0xFFFFFFFF, the digest MUST
|
||||
// match the data.
|
||||
//
|
||||
// This event MUST extend the PCRs 0 through 7 inclusive.
|
||||
evSeparator eventType = 0x00000004
|
||||
|
||||
// An event indicating a particular action in the boot sequence, for example
|
||||
// "User Password Entered" or "Booting BCV Device s".
|
||||
//
|
||||
// The digests field contains the tagged hash of the event field for each PCR bank.
|
||||
//
|
||||
// Used for PCRs [1, 2, 3, 4, 5, and 6].
|
||||
evAction eventType = 0x00000005
|
||||
|
||||
// Used for PCRs defined for OS and application usage. The digest field MUST
|
||||
// contain a hash of the data. The data contains a TCG_PCClientTaggedEvent
|
||||
// sructure.
|
||||
evEventTag eventType = 0x00000006
|
||||
|
||||
// Used for PCR[0] only. The digest contains the hash of the SRTM for each PCR
|
||||
// bank. The data is informative and not expected to match the digest.
|
||||
evSCRTMContents eventType = 0x00000007
|
||||
evSCRTMVersion eventType = 0x00000008
|
||||
|
||||
// The digests field contains the tagged hash of the microcode patch applied for
|
||||
// each PCR bank. The data is informative and not expected to match the digest.
|
||||
evCUPMicrocode eventType = 0x00000009
|
||||
|
||||
// TODO(ericchiang): explain these events
|
||||
evPlatformConfigFiles eventType = 0x0000000A
|
||||
evTableOfDevices eventType = 0x0000000B
|
||||
|
||||
// Can be used for any PCRs except 0, 1, 2, or 3.
|
||||
evCompactHash eventType = 0x0000000C
|
||||
|
||||
// IPL events are deprecated
|
||||
evIPL eventType = 0x0000000D
|
||||
evIPLPartitionData eventType = 0x0000000E
|
||||
|
||||
// Used for PCR[0] only.
|
||||
//
|
||||
// TODO(ericchiang): explain these events
|
||||
evNonhostCode eventType = 0x0000000F
|
||||
evNonhostConfig eventType = 0x00000010
|
||||
evNonhostInfo eventType = 0x00000011
|
||||
evOmitBootDeviceEvents eventType = 0x00000012
|
||||
|
||||
// The following events are UEFI specific.
|
||||
|
||||
// Data contains a UEFI_VARIABLE_DATA structure.
|
||||
evEFIVariableDriverConfig eventType = 0x80000001 // PCR[1,3,5]
|
||||
evEFIVariableBoot eventType = 0x80000002 // PCR[1]
|
||||
|
||||
// Data contains a UEFI_IMAGE_LOAD_EVENT structure.
|
||||
evEFIBootServicesApplication eventType = 0x80000003 // PCR[2,4]
|
||||
evEFIBootServicesDriver eventType = 0x80000004 // PCR[0,2]
|
||||
evEFIRuntimeServicesDriver eventType = 0x80000005 // PCR[2,4]
|
||||
|
||||
// Data contains a UEFI_GPT_DATA structure.
|
||||
evEFIGPTEvent eventType = 0x80000006 // PCR[5]
|
||||
|
||||
evEFIAction eventType = 0x80000007 // PCR[1,2,3,4,5,6,7]
|
||||
|
||||
// Data contains a UEFI_PLATFORM_FIRMWARE_BLOB structure.
|
||||
evEFIPlatformFirmwareBlob eventType = 0x80000008 // PCR[0,2,4]
|
||||
|
||||
// Data contains a UEFI_HANDOFF_TABLE_POINTERS structure.
|
||||
evEFIHandoffTables eventType = 0x80000009 // PCR[1]
|
||||
|
||||
// The digests field contains the tagged hash of the H-CRTM event
|
||||
// data for each PCR bank.
|
||||
//
|
||||
// The Event Data MUST be the string: “HCRTM”.
|
||||
evEFIHCRTMEvent eventType = 0x80000010 // PCR[0]
|
||||
|
||||
// Data contains a UEFI_VARIABLE_DATA structure.
|
||||
evEFIVariableAuthority eventType = 0x800000E0 // PCR[7]
|
||||
)
|
||||
|
||||
var eventTypeNames = map[eventType]string{
|
||||
evPrebootCert: "EV_PREBOOT_CERT",
|
||||
evPostCode: "EV_POST_CODE",
|
||||
evUnused: "EV_UNUSED",
|
||||
evNoAction: "EV_NO_ACTION",
|
||||
evSeparator: "EV_SEPARATOR",
|
||||
evAction: "EV_ACTION",
|
||||
evEventTag: "EV_EVENT_TAG",
|
||||
evSCRTMContents: "EV_S_CRTM_CONTENTS",
|
||||
evSCRTMVersion: "EV_S_CRTM_VERSION",
|
||||
evCUPMicrocode: "EV_CPU_MICROCODE",
|
||||
evPlatformConfigFiles: "EV_PLATFORM_CONFIG_FLAGS",
|
||||
evTableOfDevices: "EV_TABLE_OF_DEVICES",
|
||||
evCompactHash: "EV_COMPACT_HASH",
|
||||
evIPL: "EV_IPL (deprecated)",
|
||||
evIPLPartitionData: "EV_IPL_PARTITION_DATA (deprecated)",
|
||||
evNonhostCode: "EV_NONHOST_CODE",
|
||||
evNonhostConfig: "EV_NONHOST_CONFIG",
|
||||
evNonhostInfo: "EV_NONHOST_INFO",
|
||||
evOmitBootDeviceEvents: "EV_OMIT_BOOT_DEVICE_EVENTS",
|
||||
|
||||
// UEFI events
|
||||
evEFIVariableDriverConfig: "EV_EFI_VARIABLE_DRIVER_CONFIG",
|
||||
evEFIVariableBoot: "EV_EFI_VARIABLE_BOOT",
|
||||
evEFIBootServicesApplication: "EV_EFI_BOOT_SERVICES_APPLICATION",
|
||||
evEFIBootServicesDriver: "EV_EFI_BOOT_SERVICES_DRIVER",
|
||||
evEFIRuntimeServicesDriver: "EV_EFI_RUNTIME_SERVICES_DRIVER",
|
||||
evEFIGPTEvent: "EV_EFI_GPT_EVENT",
|
||||
evEFIAction: "EV_EFI_ACTION",
|
||||
evEFIPlatformFirmwareBlob: "EV_EFI_PLATFORM_FIRMWARE_BLOB",
|
||||
evEFIHandoffTables: "EV_EFI_HANDOFF_TABLES",
|
||||
evEFIHCRTMEvent: "EV_EFI_HCRTM_EVENT",
|
||||
evEFIVariableAuthority: "EV_EFI_VARIABLE_AUTHORITY",
|
||||
}
|
225
attest/attest-tool/internal/eventlog/secureboot.go
Normal file
225
attest/attest-tool/internal/eventlog/secureboot.go
Normal file
@ -0,0 +1,225 @@
|
||||
// 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 eventlog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"unicode/utf16"
|
||||
|
||||
"github.com/google/go-attestation/attest"
|
||||
)
|
||||
|
||||
var (
|
||||
// https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf#page=153
|
||||
efiGlobalVariable = efiGUID{
|
||||
0x8BE4DF61, 0x93CA, 0x11d2, [8]uint8{0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C}}
|
||||
|
||||
efiGlobalVariableSecureBoot = "SecureBoot"
|
||||
efiGlobalVariablePlatformKey = "PK"
|
||||
efiGlobalVariableKeyExchangeKey = "KEK"
|
||||
|
||||
// https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf#page=1804
|
||||
efiImageSecurityDatabaseGUID = efiGUID{
|
||||
0xd719b2cb, 0x3d3a, 0x4596, [8]uint8{0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f}}
|
||||
|
||||
efiImageSecurityDatabase = "db"
|
||||
efiImageSecurityDatabase1 = "dbx"
|
||||
efiImageSecurityDatabase2 = "dbt"
|
||||
efiImageSecurityDatabase3 = "dbr"
|
||||
)
|
||||
|
||||
type efiGUID struct {
|
||||
Data1 uint32
|
||||
Data2 uint16
|
||||
Data3 uint16
|
||||
Data4 [8]uint8
|
||||
}
|
||||
|
||||
func (e efiGUID) String() string {
|
||||
if s, ok := efiGUIDString[e]; ok {
|
||||
return s
|
||||
}
|
||||
return fmt.Sprintf("{0x%x,0x%x,0x%x,{%x}}", e.Data1, e.Data2, e.Data3, e.Data4)
|
||||
}
|
||||
|
||||
var efiGUIDString = map[efiGUID]string{
|
||||
efiGlobalVariable: "EFI_GLOBAL_VARIABLE",
|
||||
efiImageSecurityDatabaseGUID: "EFI_IMAGE_SECURITY_DATABASE_GUID",
|
||||
}
|
||||
|
||||
type uefiVariableData struct {
|
||||
id efiGUID
|
||||
name string
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (d *uefiVariableData) String() string {
|
||||
return fmt.Sprintf("%s %s data length %d", d.id, d.name, len(d.data))
|
||||
}
|
||||
|
||||
// SecureBoot holds parsed PCR 7 values representing secure boot settings for
|
||||
// the device.
|
||||
type SecureBoot struct {
|
||||
Enabled bool
|
||||
|
||||
// TODO(ericchiang): parse these as EFI_SIGNATURE_LIST
|
||||
//
|
||||
// https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf#page=1788
|
||||
|
||||
PK []byte
|
||||
KEK []byte
|
||||
|
||||
DB []byte
|
||||
DBX []byte
|
||||
|
||||
DBT []byte
|
||||
DBR []byte
|
||||
|
||||
// Authority is the set of certificate that were used during secure boot
|
||||
// validation. This will be a subset of the certifiates in DB.
|
||||
Authority []byte
|
||||
}
|
||||
|
||||
// ParseSecureBoot parses UEFI secure boot variables (PCR[7) from a verified event log.
|
||||
//
|
||||
// See https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_Specific_Platform_Profile_for_TPM_2p0_1p04_PUBLIC.pdf#page=56
|
||||
func ParseSecureBoot(events []attest.Event) (*SecureBoot, error) {
|
||||
var sb SecureBoot
|
||||
seenSep := false
|
||||
for i, e := range events {
|
||||
if e.Index != 7 {
|
||||
continue
|
||||
}
|
||||
t := eventType(e.Type)
|
||||
switch t {
|
||||
case evEFIVariableDriverConfig:
|
||||
if seenSep {
|
||||
return nil, fmt.Errorf("event %d %s after %s", i, t, evSeparator)
|
||||
}
|
||||
data, err := parseUEFIVariableData(e.Data, e.Digest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing event %d, PCR[%02d] %s: %v", i, e.Index, t, err)
|
||||
}
|
||||
|
||||
switch data.id {
|
||||
case efiGlobalVariable:
|
||||
switch data.name {
|
||||
case efiGlobalVariableSecureBoot:
|
||||
if len(data.data) != 1 {
|
||||
return nil, fmt.Errorf("%s/%s was %d bytes", data.id, data.name, len(data.data))
|
||||
}
|
||||
switch data.data[0] {
|
||||
case 0x0:
|
||||
sb.Enabled = false
|
||||
case 0x1:
|
||||
sb.Enabled = true
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid %s/%s value 0x%x", data.id, data.name, data.data)
|
||||
}
|
||||
case efiGlobalVariablePlatformKey:
|
||||
sb.PK = data.data
|
||||
case efiGlobalVariableKeyExchangeKey:
|
||||
sb.KEK = data.data
|
||||
}
|
||||
case efiImageSecurityDatabaseGUID:
|
||||
switch data.name {
|
||||
case efiImageSecurityDatabase:
|
||||
sb.DB = data.data
|
||||
case efiImageSecurityDatabase1:
|
||||
sb.DBX = data.data
|
||||
case efiImageSecurityDatabase2:
|
||||
sb.DBT = data.data
|
||||
case efiImageSecurityDatabase3:
|
||||
sb.DBR = data.data
|
||||
}
|
||||
}
|
||||
case evEFIVariableAuthority:
|
||||
if !seenSep {
|
||||
return nil, fmt.Errorf("event %d %s before %s", i, t, evSeparator)
|
||||
}
|
||||
data, err := parseUEFIVariableData(e.Data, e.Digest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing event %d, PCR[%02d] %s: %v", i, e.Index, t, err)
|
||||
}
|
||||
switch data.id {
|
||||
case efiImageSecurityDatabaseGUID:
|
||||
switch data.name {
|
||||
case efiImageSecurityDatabase:
|
||||
if !sb.Enabled {
|
||||
return nil, fmt.Errorf("%s/%s present when secure boot wasn't enabled", t, data.name)
|
||||
}
|
||||
sb.Authority = data.data
|
||||
}
|
||||
}
|
||||
case evSeparator:
|
||||
seenSep = true
|
||||
}
|
||||
}
|
||||
return &sb, nil
|
||||
}
|
||||
|
||||
func binaryRead(r io.Reader, i interface{}) error {
|
||||
return binary.Read(r, binary.LittleEndian, i)
|
||||
}
|
||||
|
||||
var hashBySize = map[int]crypto.Hash{
|
||||
crypto.SHA1.Size(): crypto.SHA1,
|
||||
crypto.SHA256.Size(): crypto.SHA256,
|
||||
}
|
||||
|
||||
func verifyDigest(digest, data []byte) bool {
|
||||
h, ok := hashBySize[len(digest)]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
hash := h.New()
|
||||
hash.Write(data)
|
||||
return bytes.Equal(digest, hash.Sum(nil))
|
||||
}
|
||||
|
||||
// parseUEFIVariableData parses a UEFI_VARIABLE_DATA struct and validates the
|
||||
// digest of an event entry.
|
||||
//
|
||||
// https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_Specific_Platform_Profile_for_TPM_2p0_1p04_PUBLIC.pdf#page=100
|
||||
func parseUEFIVariableData(b, digest []byte) (*uefiVariableData, error) {
|
||||
r := bytes.NewBuffer(b)
|
||||
var hdr struct {
|
||||
ID efiGUID
|
||||
NameLength uint64
|
||||
DataLength uint64
|
||||
}
|
||||
if err := binaryRead(r, &hdr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := make([]uint16, hdr.NameLength)
|
||||
if err := binaryRead(r, &name); err != nil {
|
||||
return nil, fmt.Errorf("parsing name: %v", err)
|
||||
}
|
||||
if r.Len() != int(hdr.DataLength) {
|
||||
return nil, fmt.Errorf("remaining bytes %d doesn't match data length %d", r.Len(), hdr.DataLength)
|
||||
}
|
||||
data := r.Bytes()
|
||||
// TODO(ericchiang): older UEFI firmware (Lenovo Bios version 1.17) logs the
|
||||
// digest of the data, which doesn't encapsulate the ID or name. This lets
|
||||
// attackers alter keys and we should determine if this is an acceptable risk.
|
||||
if !verifyDigest(digest, b) && !verifyDigest(digest, data) {
|
||||
return nil, fmt.Errorf("digest didn't match data")
|
||||
}
|
||||
return &uefiVariableData{id: hdr.ID, name: string(utf16.Decode(name)), data: r.Bytes()}, nil
|
||||
}
|
105
attest/attest-tool/internal/eventlog/secureboot_test.go
Normal file
105
attest/attest-tool/internal/eventlog/secureboot_test.go
Normal file
@ -0,0 +1,105 @@
|
||||
// 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 eventlog
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-attestation/attest"
|
||||
"github.com/google/go-attestation/attest/attest-tool/internal"
|
||||
)
|
||||
|
||||
func parseEvents(t *testing.T, testdata string) []attest.Event {
|
||||
data, err := ioutil.ReadFile(testdata)
|
||||
if err != nil {
|
||||
t.Fatalf("reading test data: %v", err)
|
||||
}
|
||||
var dump internal.Dump
|
||||
if err := json.Unmarshal(data, &dump); err != nil {
|
||||
t.Fatalf("parsing test data: %v", err)
|
||||
}
|
||||
|
||||
aik, err := attest.ParseAIKPublic(dump.Static.TPMVersion, dump.AIK.Public)
|
||||
if err != nil {
|
||||
t.Fatalf("parsing AIK: %v", err)
|
||||
}
|
||||
if err := aik.Verify(attest.Quote{
|
||||
Version: dump.Static.TPMVersion,
|
||||
Quote: dump.Quote.Quote,
|
||||
Signature: dump.Quote.Signature,
|
||||
}, dump.Log.PCRs, dump.Quote.Nonce); err != nil {
|
||||
t.Fatalf("verifying quote: %v", err)
|
||||
}
|
||||
|
||||
el, err := attest.ParseEventLog(dump.Log.Raw)
|
||||
if err != nil {
|
||||
t.Fatalf("parsing event log: %v", err)
|
||||
}
|
||||
events, err := el.Verify(dump.Log.PCRs)
|
||||
if err != nil {
|
||||
t.Fatalf("validating event log: %v", err)
|
||||
}
|
||||
return events
|
||||
}
|
||||
|
||||
func notEmpty(t *testing.T, name string, field []byte) {
|
||||
t.Helper()
|
||||
if len(field) == 0 {
|
||||
t.Errorf("field %s wasn't populated", name)
|
||||
}
|
||||
}
|
||||
|
||||
func isEmpty(t *testing.T, name string, field []byte) {
|
||||
t.Helper()
|
||||
if len(field) != 0 {
|
||||
t.Errorf("expected field %s not to be populated", name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseSecureBootWindows(t *testing.T) {
|
||||
events := parseEvents(t, "../../../testdata/windows_gcp_shielded_vm.json")
|
||||
sb, err := ParseSecureBoot(events)
|
||||
if err != nil {
|
||||
t.Fatalf("parse secure boot: %v", err)
|
||||
}
|
||||
if !sb.Enabled {
|
||||
t.Errorf("expected secure boot to be enabled")
|
||||
}
|
||||
notEmpty(t, "db", sb.DB)
|
||||
notEmpty(t, "dbx", sb.DBX)
|
||||
notEmpty(t, "pk", sb.PK)
|
||||
notEmpty(t, "kek", sb.KEK)
|
||||
isEmpty(t, "dbt", sb.DBT)
|
||||
isEmpty(t, "dbr", sb.DBR)
|
||||
notEmpty(t, "Authority", sb.Authority)
|
||||
}
|
||||
|
||||
func TestParseSecureBootLinux(t *testing.T) {
|
||||
events := parseEvents(t, "../../../testdata/linux_tpm12.json")
|
||||
sb, err := ParseSecureBoot(events)
|
||||
if err != nil {
|
||||
t.Errorf("parse secure boot: %v", err)
|
||||
}
|
||||
if sb.Enabled {
|
||||
t.Errorf("expected secure boot to be disabled")
|
||||
}
|
||||
notEmpty(t, "db", sb.DB)
|
||||
notEmpty(t, "dbx", sb.DBX)
|
||||
isEmpty(t, "dbt", sb.DBT)
|
||||
isEmpty(t, "dbr", sb.DBR)
|
||||
isEmpty(t, "Authority", sb.Authority)
|
||||
}
|
Loading…
Reference in New Issue
Block a user