diff --git a/pkg/measure-config/src/measurefs.go b/pkg/measure-config/src/measurefs.go index 729c0135a4..92e51dbd53 100644 --- a/pkg/measure-config/src/measurefs.go +++ b/pkg/measure-config/src/measurefs.go @@ -7,6 +7,7 @@ package main import ( "crypto/sha256" + "encoding/binary" "encoding/hex" "fmt" "io" @@ -24,16 +25,115 @@ const ( TpmDevicePath = "/dev/tpmrm0" configPCRIndex = 14 configPCRHandle = tpmutil.Handle(tpm2.PCRFirst + configPCRIndex) + //PCREvent (TPM2_PCR_Event) supports event size of maximum 1024 bytes. + maxEventDataSize = 1024 + evAlgSHA256 = 0xb + evEfiAction = 0x80000007 + measurefsTpmEventLog = "/persist/status/measurefs_tpm_event_log" ) +// the following structs created based on "Crypto Agile Log Entry Format" +// https://trustedcomputinggroup.org/wp-content/uploads/EFI-Protocol-Specification-rev13-160330final.pdf +type tcgPcrEvent2 struct { + PcrIndex uint32 + EventType uint32 + Digest tpmlDigestValues + EventSize uint32 + Event []uint8 +} + +type tpmlDigestValues struct { + Count uint32 + Digests []tpmtHa +} + +type tpmtHa struct { + HashAlg uint16 + DigestData []byte +} + type fileInfo struct { exist bool measureContent bool } type tpmEvent struct { - data string - pcr []byte + tcgEvent tcgPcrEvent2 + data string + pcr []byte +} + +func (event *tcgPcrEvent2) MarshalBinary() ([]byte, error) { + buffer := make([]byte, event.size()) + offset := 0 + + binary.LittleEndian.PutUint32(buffer[offset:], event.PcrIndex) + offset += 4 + + binary.LittleEndian.PutUint32(buffer[offset:], event.EventType) + offset += 4 + + digestBytes, err := event.Digest.MarshalBinary() + if err != nil { + return nil, err + } + + copy(buffer[offset:], digestBytes) + offset += len(digestBytes) + + binary.LittleEndian.PutUint32(buffer[offset:], event.EventSize) + offset += 4 + + copy(buffer[offset:], event.Event) + + return buffer, nil +} + +func (event *tcgPcrEvent2) size() int { + return 4 + 4 + event.Digest.size() + 4 + len(event.Event) +} + +func (digestValue *tpmlDigestValues) MarshalBinary() ([]byte, error) { + buffer := make([]byte, digestValue.size()) + offset := 0 + + binary.LittleEndian.PutUint32(buffer[offset:], digestValue.Count) + offset += 4 + + for _, digest := range digestValue.Digests { + digestBytes, err := digest.MarshalBinary() + if err != nil { + return nil, err + } + copy(buffer[offset:], digestBytes) + offset += len(digestBytes) + } + + return buffer, nil +} + +func (digestValue *tpmlDigestValues) size() int { + size := 4 + for _, digest := range digestValue.Digests { + size += digest.size() + } + return size +} + +func (digest *tpmtHa) MarshalBinary() ([]byte, error) { + buffer := make([]byte, digest.size()) + offset := 0 + + binary.LittleEndian.PutUint16(buffer[offset:], digest.HashAlg) + offset += 2 + + copy(buffer[offset:], digest.DigestData) + + return buffer, nil +} + +func (digest *tpmtHa) size() int { + return 2 + len(digest.DigestData) } // we do not measure content of following files @@ -84,55 +184,57 @@ func sha256sumForFile(filePath string) (string, error) { return hex.EncodeToString(hash.Sum(nil)), nil } -func sha256sumString(s string) [32]byte { - return sha256.Sum256([]byte(s)) -} - -func measureFileContent(filePath string, tpm io.ReadWriter) (*tpmEvent, error) { - hash, err := sha256sumForFile(filePath) +func performMeasurement(filePath string, tpm io.ReadWriter, exist bool, content bool) (*tpmEvent, error) { + var eventData string - if err != nil { - return nil, fmt.Errorf("cannot measure %s :%v", filePath, err) + // Max size for PCREvent data is 1024 bytes, truncate the file path if it + // is longer than 512 bytes. + eventFilePath := filePath + if len(filePath) > 512 { + // in this case just get the file name, it maxes out at 255 chars. + eventFilePath = filepath.Base(filePath) } - eventData := fmt.Sprintf("file:%s hash:%s", filePath, hash) - - // it seems PCRExtend expects a hash not data itself. - eventDataHash := sha256sumString(eventData) - - err = tpm2.PCREvent(tpm, configPCRHandle, eventDataHash[:]) - - if err != nil { - return nil, fmt.Errorf("cannot measure %s. couldn't extend PCR: %v", filePath, err) + if content { + hash, err := sha256sumForFile(filePath) + if err != nil { + return nil, fmt.Errorf("can not measure %s :%w", filePath, err) + } + eventData = fmt.Sprintf("file:%s exist:true content-hash:%s", eventFilePath, hash) + } else { + eventData = fmt.Sprintf("file:%s exist:%t", eventFilePath, exist) } - pcr, err := readConfigPCR(tpm) - + // PCREvent internally hashes the data with all supported algorithms + // associated with the PCR banks, and extends them all before return. + err := tpm2.PCREvent(tpm, configPCRHandle, []byte(eventData)) if err != nil { - return nil, fmt.Errorf("cannot measure %s. couldn't read PCR: %v", filePath, err) + return nil, fmt.Errorf("can not measure %s. couldn't extend PCR: %w", filePath, err) } - return &tpmEvent{eventData, pcr}, nil -} - -func measureFilePath(filePath string, tpm io.ReadWriter, exist bool) (*tpmEvent, error) { - eventData := fmt.Sprintf("file:%s exist:%t", filePath, exist) - // it seems PCRExtend expects a hash not data itself. - eventDataHash := sha256sumString(eventData) - - err := tpm2.PCREvent(tpm, configPCRHandle, eventDataHash[:]) - + pcr, err := readConfigPCR(tpm) if err != nil { - return nil, fmt.Errorf("cannot measure path %s. couldn't extend PCR: %v", filePath, err) + return nil, fmt.Errorf("can not measure %s. couldn't read PCR: %w", filePath, err) } - pcr, err := readConfigPCR(tpm) - - if err != nil { - return nil, fmt.Errorf("cannot measure path %s. couldn't read PCR: %v", filePath, err) + eventHash := sha256.Sum256([]byte(eventData)) + tcgEvent := tcgPcrEvent2{ + PcrIndex: configPCRIndex, + EventType: evEfiAction, + Digest: tpmlDigestValues{ + Count: 1, + Digests: []tpmtHa{ + { + HashAlg: evAlgSHA256, + DigestData: eventHash[:], + }, + }, + }, + EventSize: uint32(len(eventData)), + Event: []uint8(eventData), } - return &tpmEvent{eventData, pcr}, nil + return &tpmEvent{tcgEvent, eventData, pcr}, nil } func getFileMap() (map[string]fileInfo, error) { @@ -183,11 +285,12 @@ func getSortedFileList(files map[string]fileInfo) []string { return keys } -func measureConfig(tpm io.ReadWriter) error { +func measureConfig(tpm io.ReadWriter) ([]tcgPcrEvent2, error) { files, err := getFileMap() + events := make([]tcgPcrEvent2, 0) if err != nil { - return fmt.Errorf("cannot get file list: %v", err) + return []tcgPcrEvent2{}, fmt.Errorf("can not get file list: %w", err) } //get sorted list of files. We must always go the same order @@ -201,29 +304,30 @@ func measureConfig(tpm io.ReadWriter) error { if info.exist { if info.measureContent { - event, err = measureFileContent(file, tpm) + event, err = performMeasurement(file, tpm, true, true) } else { - event, err = measureFilePath(file, tpm, true) + event, err = performMeasurement(file, tpm, true, false) } } else { - event, err = measureFilePath(file, tpm, false) + event, err = performMeasurement(file, tpm, false, false) } if err != nil { - return fmt.Errorf("cannot measure %s: %v", file, err) + return []tcgPcrEvent2{}, fmt.Errorf("can not measure %s: %w", file, err) } + //Now we have a new value of PCR and an event - //TODO: add events to the event log - // for now just print our measurements to boot log log.Printf("%s pcr:%s", event.data, hex.EncodeToString(event.pcr)) + events = append(events, event.tcgEvent) } - return nil + + return events, nil } func readConfigPCR(tpm io.ReadWriter) ([]byte, error) { pcr, err := tpm2.ReadPCR(tpm, configPCRIndex, tpm2.AlgSHA256) if err != nil { - return nil, fmt.Errorf("cannot read PCR %d: %v", configPCRIndex, err) + return nil, fmt.Errorf("can not read PCR %d: %w", configPCRIndex, err) } return pcr, nil } @@ -234,14 +338,37 @@ func readConfigPCR(tpm io.ReadWriter) ([]byte, error) { func main() { tpm, err := tpm2.OpenTPM(TpmDevicePath) if err != nil { - log.Printf("couldn't open TPM device %s. Exiting", TpmDevicePath) - return + log.Fatalf("couldn't open TPM device %s. Exiting", TpmDevicePath) } defer tpm.Close() - err = measureConfig(tpm) - + events, err := measureConfig(tpm) if err != nil { log.Fatal(err) } + + // loop over events and marshal them to binary + eventLog := make([]byte, 0) + for _, event := range events { + eventBytes, err := event.MarshalBinary() + if err != nil { + log.Printf("[WARNING] failed to construct measure-config tpm event log : %v", err) + return + } + + eventLog = append(eventLog, eventBytes...) + } + + // no need for an atomic file operations here, this file is created + // on every boot. + file, err := os.Create(measurefsTpmEventLog) + if err != nil { + log.Printf("[WARNING] failed to create measure-config tpm event log : %v", err) + return + } + defer file.Close() + + if _, err := file.Write(eventLog); err != nil { + log.Printf("[WARNING] failed to write measure-config tpm event log : %v", err) + } } diff --git a/pkg/pillar/evetpm/tpm.go b/pkg/pillar/evetpm/tpm.go index 28a821bf95..9272c8f72c 100644 --- a/pkg/pillar/evetpm/tpm.go +++ b/pkg/pillar/evetpm/tpm.go @@ -16,7 +16,6 @@ import ( "io/ioutil" "math/big" "os" - "path/filepath" "sort" "unsafe" @@ -87,13 +86,12 @@ const ( // fails to unseal the vault key from TPM. measurementLogUnsealFail = types.PersistStatusDir + "/tpm_measurement_unseal_fail" + // measurefsTpmEventLog is the file containing the event log from the measure-config + measurefsTpmEventLog = types.PersistStatusDir + "/measurefs_tpm_event_log" + // measurementLogFile is a kernel exposed variable that contains the // TPM measurements and events log. - measurementLogFile = "binary_bios_measurements" - - // syfsTpmDir is directory that TPMs get mapped on sysfs, and it contains - // measurement logs. - syfsTpmDir = "/hostfs/sys/kernel/security/tpm*" + measurementLogFile = "/hostfs/sys/kernel/security/tpm0/binary_bios_measurements" ) // PCRBank256Status stores info about support for @@ -453,13 +451,13 @@ func writeDiskKey(key []byte) error { tpm2.AttrOwnerWrite|tpm2.AttrOwnerRead, uint16(len(key)), ); err != nil { - return fmt.Errorf("NVDefineSpace failed: %v", err) + return fmt.Errorf("NVDefineSpace failed: %w", err) } // Write the data if err := tpm2.NVWrite(rw, tpm2.HandleOwner, TpmDiskKeyHdl, EmptyPassword, key, 0); err != nil { - return fmt.Errorf("NVWrite failed: %v", err) + return fmt.Errorf("NVWrite failed: %w", err) } return nil } @@ -475,7 +473,7 @@ func readDiskKey() ([]byte, error) { keyBytes, err := tpm2.NVReadEx(rw, TpmDiskKeyHdl, tpm2.HandleOwner, EmptyPassword, 0) if err != nil { - return nil, fmt.Errorf("NVReadEx failed: %v", err) + return nil, fmt.Errorf("NVReadEx failed: %w", err) } return keyBytes, nil } @@ -595,12 +593,12 @@ func SealDiskKey(log *base.LogObject, key []byte, pcrSel tpm2.PCRSelection) erro session, policy, err := PolicyPCRSession(rw, pcrSel) if err != nil { - return fmt.Errorf("PolicyPCRSession failed: %v", err) + return fmt.Errorf("PolicyPCRSession failed: %w", err) } //Don't need the handle, we need only the policy for sealing if err := tpm2.FlushContext(rw, session); err != nil { - return fmt.Errorf("flushing session handle %v failed: %v", session, err) + return fmt.Errorf("flushing session handle %v failed: %w", session, err) } priv, public, err := tpm2.Seal(rw, TpmSRKHdl, EmptyPassword, EmptyPassword, policy, key) @@ -618,13 +616,13 @@ func SealDiskKey(log *base.LogObject, key []byte, pcrSel tpm2.PCRSelection) erro tpm2.AttrOwnerWrite|tpm2.AttrOwnerRead, uint16(len(priv)), ); err != nil { - return fmt.Errorf("NVDefineSpace %v failed: %v", TpmSealedDiskPrivHdl, err) + return fmt.Errorf("NVDefineSpace %v failed: %w", TpmSealedDiskPrivHdl, err) } // Write the private data if err := tpm2.NVWrite(rw, tpm2.HandleOwner, TpmSealedDiskPrivHdl, EmptyPassword, priv, 0); err != nil { - return fmt.Errorf("NVWrite %v failed: %v", TpmSealedDiskPrivHdl, err) + return fmt.Errorf("NVWrite %v failed: %w", TpmSealedDiskPrivHdl, err) } // Define space in NV storage @@ -637,12 +635,12 @@ func SealDiskKey(log *base.LogObject, key []byte, pcrSel tpm2.PCRSelection) erro tpm2.AttrOwnerWrite|tpm2.AttrOwnerRead, uint16(len(public)), ); err != nil { - return fmt.Errorf("NVDefineSpace %v failed: %v", TpmSealedDiskPubHdl, err) + return fmt.Errorf("NVDefineSpace %v failed: %w", TpmSealedDiskPubHdl, err) } // Write the public data if err := tpm2.NVWrite(rw, tpm2.HandleOwner, TpmSealedDiskPubHdl, EmptyPassword, public, 0); err != nil { - return fmt.Errorf("NVWrite %v failed: %v", TpmSealedDiskPubHdl, err) + return fmt.Errorf("NVWrite %v failed: %w", TpmSealedDiskPubHdl, err) } // save a snapshot of current PCR values @@ -650,22 +648,21 @@ func SealDiskKey(log *base.LogObject, key []byte, pcrSel tpm2.PCRSelection) erro log.Warnf("saving snapshot of sealing PCRs failed: %s", err) } - // Backup the previous pair of logs if any, so at most we have two pairs of - // measurement logs (per available tpm devices). This is needed because if the - // failing devices get connected to the controller and collects the backup key, - // we end up here again and will override the MeasurementLogSealSuccess with - // current measurement log (which is same as the content of MeasurementLogSealFail) - // and lose the ability to diff and diagnose the issue. + // In order to not lose the ability to diff and diagnose the issue, + // first backup the previous pair of logs (if any). This is needed because + // once the failing devices get connected to the controller to fetch the + // backup key, we end up here again and it'll override the MeasurementLogSealSuccess + // file content with current tpm measurement logs (which is same as the + // content of MeasurementLogSealFail). if err := backupCopiedMeasurementLogs(); err != nil { - log.Warnf("collecting previous snapshot of TPM event log failed: %s", err) + log.Warnf("copying previous snapshot of TPM event log failed: %s", err) } // fresh start, remove old copies of measurement logs. - if err := removeCopiedMeasurementLogs(); err != nil { - log.Warnf("removing old copies of TPM measurement log failed: %s", err) - } + removeCopiedMeasurementLogs() - // save a copy of the current measurement log + // save a copy of the current measurement log, this is also called + // if unseal fails to have copy when we fail to unlock the vault. if err := copyMeasurementLog(measurementLogSealSuccess); err != nil { log.Warnf("copying current TPM measurement log failed: %s", err) } @@ -702,13 +699,13 @@ func UnsealDiskKey(pcrSel tpm2.PCRSelection) ([]byte, error) { priv, err := tpm2.NVReadEx(rw, TpmSealedDiskPrivHdl, tpm2.HandleOwner, EmptyPassword, 0) if err != nil { - return nil, fmt.Errorf("NVReadEx %v failed: %v", TpmSealedDiskPrivHdl, err) + return nil, fmt.Errorf("NVReadEx %v failed: %w", TpmSealedDiskPrivHdl, err) } // Read all of the data with NVReadEx pub, err := tpm2.NVReadEx(rw, TpmSealedDiskPubHdl, tpm2.HandleOwner, EmptyPassword, 0) if err != nil { - return nil, fmt.Errorf("NVReadEx %v failed: %v", TpmSealedDiskPubHdl, err) + return nil, fmt.Errorf("NVReadEx %v failed: %w", TpmSealedDiskPubHdl, err) } sealedObjHandle, _, err := tpm2.Load(rw, TpmSRKHdl, "", pub, priv) @@ -719,7 +716,7 @@ func UnsealDiskKey(pcrSel tpm2.PCRSelection) ([]byte, error) { session, _, err := PolicyPCRSession(rw, pcrSel) if err != nil { - return nil, fmt.Errorf("PolicyPCRSession failed: %v", err) + return nil, fmt.Errorf("PolicyPCRSession failed: %w", err) } defer tpm2.FlushContext(rw, session) @@ -757,7 +754,7 @@ func PolicyPCRSession(rw io.ReadWriteCloser, pcrSel tpm2.PCRSelection) (tpmutil. /*symmetric=*/ tpm2.AlgNull, /*authHash=*/ tpm2.AlgSHA256) if err != nil { - return tpm2.HandleNull, nil, fmt.Errorf("StartAuthSession failed: %v", err) + return tpm2.HandleNull, nil, fmt.Errorf("StartAuthSession failed: %w", err) } defer func() { if session != tpm2.HandleNull && err != nil { @@ -766,7 +763,7 @@ func PolicyPCRSession(rw io.ReadWriteCloser, pcrSel tpm2.PCRSelection) (tpmutil. }() if err = tpm2.PolicyPCR(rw, session, nil, pcrSel); err != nil { - return session, nil, fmt.Errorf("PolicyPCR failed: %v", err) + return session, nil, fmt.Errorf("PolicyPCR failed: %w", err) } policy, err := tpm2.PolicyGetDigest(rw, session) @@ -850,127 +847,54 @@ func pcrBankSHA256EnabledHelper() bool { return err == nil } -func getLogCopyPath(destination string, tpmIndex int) string { - return fmt.Sprintf("%s-tpm%d", destination, tpmIndex) -} - -func getLogBackupPath(destination string) string { - return fmt.Sprintf("%s-backup", destination) -} - -func getMappedTpmsPath() ([]string, error) { - paths, err := filepath.Glob(syfsTpmDir) - if err != nil { - return nil, fmt.Errorf("failed to enumerate TPM(s) in sysfs: %w", err) - } else if len(paths) == 0 { - return nil, fmt.Errorf("found no TPM in sysfs") - } - - return paths, nil -} - -func countMappedTpms() (int, error) { - paths, err := getMappedTpmsPath() - if err != nil { - return 0, fmt.Errorf("getMappedTpmsPath failed: %w", err) - } - - return len(paths), nil -} - -func getMeasurementLogFiles() ([]string, error) { - paths, err := getMappedTpmsPath() - if err != nil { - return nil, fmt.Errorf("getMappedTpmsPath failed: %w", err) - } +func backupCopiedMeasurementLogs() error { + sealSuccessBackupPath := fmt.Sprintf("%s-backup", measurementLogSealSuccess) + unsealFailBackupPath := fmt.Sprintf("%s-backup", measurementLogUnsealFail) - enumerated := make([]string, 0) - for _, path := range paths { - fullPath := filepath.Join(path, measurementLogFile) - if fileutils.FileExists(nil, fullPath) { - enumerated = append(enumerated, fullPath) + if fileutils.FileExists(nil, measurementLogSealSuccess) { + if err := os.Rename(measurementLogSealSuccess, sealSuccessBackupPath); err != nil { + return fmt.Errorf("failed to backup tpm \"seal success event\" previously copied measurement log: %w", err) } } - return enumerated, nil -} - -func backupCopiedMeasurementLogs() error { - counted, err := countMappedTpms() - if err != nil { - return fmt.Errorf("countMappedTPMs failed: %w", err) - } - - leftToBackup := counted - for i := 0; i < counted; i++ { - sealSuccessPath := getLogCopyPath(measurementLogSealSuccess, i) - unsealFailPath := getLogCopyPath(measurementLogUnsealFail, i) - if fileutils.FileExists(nil, sealSuccessPath) && fileutils.FileExists(nil, unsealFailPath) { - sealSuccessBackupPath := getLogBackupPath(sealSuccessPath) - unsealFailBackupPath := getLogBackupPath(unsealFailPath) - if err := os.Rename(sealSuccessPath, sealSuccessBackupPath); err != nil { - fmt.Fprintf(os.Stderr, "failed to backup tpm%d \"seal success\" previously copied measurement log: %v", i, err) - continue - } - if err := os.Rename(unsealFailPath, unsealFailBackupPath); err != nil { - fmt.Fprintf(os.Stderr, "failed to backup tpm%d \"unseal fail\" previously copied measurement log: %v", i, err) - _ = os.Rename(sealSuccessBackupPath, sealSuccessPath) - continue - } + if fileutils.FileExists(nil, measurementLogUnsealFail) { + if err := os.Rename(measurementLogUnsealFail, unsealFailBackupPath); err != nil { + _ = os.Rename(sealSuccessBackupPath, measurementLogSealSuccess) + return fmt.Errorf("failed to backup tpm \"unseal fail event\" previously copied measurement log: %w", err) } - - leftToBackup-- - } - - if leftToBackup != 0 { - return fmt.Errorf("failed to backup %d number of previously copied TPM measurement logs", leftToBackup) } return nil } -func removeCopiedMeasurementLogs() error { - counted, err := countMappedTpms() - if err != nil { - return fmt.Errorf("countMappedTPMs failed: %w", err) - } - - for i := 0; i < counted; i++ { - sealSuccessPath := getLogCopyPath(measurementLogSealSuccess, i) - unsealFailPath := getLogCopyPath(measurementLogUnsealFail, i) - _ = os.Remove(sealSuccessPath) - _ = os.Remove(unsealFailPath) - } - - return nil +func removeCopiedMeasurementLogs() { + os.Remove(measurementLogSealSuccess) + os.Remove(measurementLogUnsealFail) } func copyMeasurementLog(dstPath string) error { - paths, err := getMeasurementLogFiles() + var appendErr error + tpmEventLog, err := os.ReadFile(measurementLogFile) if err != nil { - return fmt.Errorf("enumSourceEventLogFiles failed: %w", err) + return fmt.Errorf("failed to read TPM measurements log file: %w", err) } - leftToCopy := len(paths) - for i, path := range paths { - measurementLogContent, err := os.ReadFile(path) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to read stored measurement log file: %v", err) - continue - } + measurefsEventLog, err := os.ReadFile(measurefsTpmEventLog) + if err == nil { + // append the measurefs event log to the tpm event log + tpmEventLog = append(tpmEventLog, measurefsEventLog...) + } else { + // don't fail yet, we might still be able to copy tpm event logs + appendErr = fmt.Errorf("failed to read measure-config measurements log file: %w", err) + } - copyPath := getLogCopyPath(dstPath, i) - err = fileutils.WriteRename(copyPath, measurementLogContent) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to copy stored measurement log file: %v", err) - continue + err = fileutils.WriteRename(dstPath, tpmEventLog) + if err != nil { + if appendErr != nil { + return fmt.Errorf("failed to copy tpm and measurefs event logs: %w, %v", err, appendErr) } - leftToCopy-- - } - - if leftToCopy != 0 { - return fmt.Errorf("failed to copy %d number of stored measurement log files", leftToCopy) + return fmt.Errorf("failed to copy tpm measurement log data: %w", err) } return nil diff --git a/pkg/pillar/evetpm/tpm_test.go b/pkg/pillar/evetpm/tpm_test.go index 9c0b51333c..9deb6e6467 100644 --- a/pkg/pillar/evetpm/tpm_test.go +++ b/pkg/pillar/evetpm/tpm_test.go @@ -8,6 +8,7 @@ package evetpm import ( "bytes" "crypto/sha256" + "fmt" "os" "reflect" "strings" @@ -30,16 +31,15 @@ func TestSealUnseal(t *testing.T) { dataToSeal := []byte("secret") if err := SealDiskKey(log, dataToSeal, DiskKeySealingPCRs); err != nil { - t.Errorf("Seal operation failed with err: %v", err) - return + t.Fatalf("Seal operation failed with err: %v", err) } + unsealedData, err := UnsealDiskKey(DiskKeySealingPCRs) if err != nil { - t.Errorf("Unseal operation failed with err: %v", err) - return + t.Fatalf("Unseal operation failed with err: %v", err) } if !reflect.DeepEqual(dataToSeal, unsealedData) { - t.Errorf("Seal/Unseal operation failed, want %v, but got %v", dataToSeal, unsealedData) + t.Fatalf("Seal/Unseal operation failed, want %v, but got %v", dataToSeal, unsealedData) } } @@ -51,35 +51,30 @@ func TestSealUnsealMismatchReport(t *testing.T) { rw, err := tpm2.OpenTPM(TpmDevicePath) if err != nil { - t.Errorf("OpenTPM failed with err: %v", err) - return + t.Fatalf("OpenTPM failed with err: %v", err) } defer rw.Close() dataToSeal := []byte("secret") if err := SealDiskKey(log, dataToSeal, DiskKeySealingPCRs); err != nil { - t.Errorf("Seal operation failed with err: %v", err) - return + t.Fatalf("Seal operation failed with err: %v", err) } pcrIndexes := [3]int{1, 7, 8} pcrValue := bytes.Repeat([]byte{0xF}, sha256.Size) for _, pcr := range pcrIndexes { if err = tpm2.PCRExtend(rw, tpmutil.Handle(pcr), tpm2.AlgSHA256, pcrValue, ""); err != nil { - t.Errorf("Failed to extend PCR %d: %s", pcr, err) - return + t.Fatalf("Failed to extend PCR %d: %s", pcr, err) } } _, err = UnsealDiskKey(DiskKeySealingPCRs) if err == nil { - t.Errorf("Expected error from UnsealDiskKey, got nil") - return + t.Fatalf("Expected error from UnsealDiskKey, got nil") } if !strings.Contains(err.Error(), "[1 7 8]") { - t.Errorf("UnsealDiskKey expected to report mismatching PCR indexes, got : %v", err) - return + t.Fatalf("UnsealDiskKey expected to report mismatching PCR indexes, got : %v", err) } } @@ -91,70 +86,58 @@ func TestSealUnsealTpmEventLogCollect(t *testing.T) { rw, err := tpm2.OpenTPM(TpmDevicePath) if err != nil { - t.Errorf("OpenTPM failed with err: %v", err) - return + t.Fatalf("OpenTPM failed with err: %v", err) } defer rw.Close() - // this should write the save the first event log + // this should write tpm event log to measurementLogSealSuccess file dataToSeal := []byte("secret") if err := SealDiskKey(log, dataToSeal, DiskKeySealingPCRs); err != nil { - t.Errorf("Seal operation failed with err: %v", err) - return + t.Fatalf("Seal operation failed with err: %v", err) } - // this won't write to event log, but still triggers saving it on unseal. + // this should cause UnsealDiskKey to fail pcrValue := bytes.Repeat([]byte{0xF}, sha256.Size) if err = tpm2.PCRExtend(rw, tpmutil.Handle(1), tpm2.AlgSHA256, pcrValue, ""); err != nil { - t.Errorf("Failed to extend PCR[1]: %v", err) - return + t.Fatalf("Failed to extend PCR[1]: %v", err) } - // this should fail and result in saving the second tpm event log + // this should fail and result in saving creating measurementLogUnsealFail _, err = UnsealDiskKey(DiskKeySealingPCRs) if err == nil { - t.Errorf("Expected error from UnsealDiskKey, got nil") - return + t.Fatalf("Expected error from UnsealDiskKey, got nil") } - // just check for tpm0 - sealSuccess := getLogCopyPath(measurementLogSealSuccess, 0) - sealFail := getLogCopyPath(measurementLogUnsealFail, 0) - if !fileutils.FileExists(nil, sealSuccess) { - t.Errorf("TPM measurement log \"%s\" not found, Expected to be copied", sealSuccess) - return + if !fileutils.FileExists(nil, measurementLogSealSuccess) { + t.Fatalf("TPM measurement log \"%s\" not found, expected to exist", measurementLogSealSuccess) } - if !fileutils.FileExists(nil, sealFail) { - t.Errorf("TPM measurement log \"%s\" not found, Expected to be copied", sealFail) - return + if !fileutils.FileExists(nil, measurementLogUnsealFail) { + t.Fatalf("TPM measurement log \"%s\" not found, expected to exist", measurementLogUnsealFail) } - // this should trigger collecting previous tpm event logs + // this should trigger backing up previously saved tpm event logs if err := SealDiskKey(log, dataToSeal, DiskKeySealingPCRs); err != nil { - t.Errorf("Seal operation failed with err: %v", err) - return + t.Fatalf("Seal operation failed with err: %v", err) } - // current measurement log should exist - if !fileutils.FileExists(nil, sealSuccess) { - t.Errorf("TPM measurement log \"%s\" not found, Expected to be copied", sealSuccess) - return + // a new measurementLogSealSuccess file should exist + if !fileutils.FileExists(nil, measurementLogSealSuccess) { + t.Fatalf("TPM measurement log \"%s\" not found, Expected to be copied", measurementLogSealSuccess) } - // this shouldn't exist because SealDiskKey will do a clean up - if fileutils.FileExists(nil, sealFail) { - t.Errorf("TPM measurement log \"%s\" found, Expected to not exist", sealFail) - return + + // measurementLogUnsealFail file shouldn't exist because SealDiskKey + // will do a clean up. + if fileutils.FileExists(nil, measurementLogUnsealFail) { + t.Fatalf("TPM measurement log \"%s\" found, Expected to not exist", measurementLogUnsealFail) } // backed up measurement logs both should exist - prevSealSuccess := getLogBackupPath(sealSuccess) - prevSealFail := getLogBackupPath(sealFail) + prevSealSuccess := fmt.Sprintf("%s-backup", measurementLogSealSuccess) + prevSealFail := fmt.Sprintf("%s-backup", measurementLogUnsealFail) if !fileutils.FileExists(nil, prevSealSuccess) { - t.Errorf("TPM measurement log \"%s\" not found, Expected to be backed up", prevSealSuccess) - return + t.Fatalf("TPM measurement log \"%s\" not found, Expected to be backed up", prevSealSuccess) } if !fileutils.FileExists(nil, prevSealFail) { - t.Errorf("TPM measurement log \"%s\" not found, Expected to be backed up", prevSealFail) - return + t.Fatalf("TPM measurement log \"%s\" not found, Expected to be backed up", prevSealFail) } }