From e63219670e112db52b594581dcc013bdd4089732 Mon Sep 17 00:00:00 2001 From: Alex Lewontin Date: Fri, 14 Aug 2026 16:45:53 -0400 Subject: [PATCH 1/3] efi/preinstall: unpin checks from amd64 --- efi/preinstall/check_host_security.go | 152 +- efi/preinstall/check_host_security_amd.go | 4 +- efi/preinstall/check_host_security_amd64.go | 148 - .../check_host_security_amd64_test.go | 430 - .../check_host_security_amd_test.go | 4 +- efi/preinstall/check_host_security_intel.go | 9 +- .../check_host_security_intel_btgmsr.go | 2 - .../check_host_security_intel_btgmsr_test.go | 2 - .../check_host_security_intel_csme11.go | 4 +- .../check_host_security_intel_csme11_test.go | 4 +- .../check_host_security_intel_csme18.go | 4 +- .../check_host_security_intel_csme18_test.go | 4 +- .../check_host_security_intel_test.go | 17 +- efi/preinstall/check_host_security_null.go | 39 - efi/preinstall/check_host_security_test.go | 434 +- efi/preinstall/check_tpm.go | 42 +- efi/preinstall/check_tpm_amd64.go | 53 - efi/preinstall/check_tpm_amd64_test.go | 78 - efi/preinstall/check_tpm_intel.go | 4 +- efi/preinstall/check_tpm_intel_test.go | 12 +- efi/preinstall/check_tpm_null.go | 33 - efi/preinstall/check_tpm_test.go | 70 +- efi/preinstall/checks_context_test.go | 11152 +++++++--------- efi/preinstall/checks_fixture_test.go | 196 + efi/preinstall/checks_test.go | 6988 +++++----- .../{util_amd64.go => cpu_vendor.go} | 2 +- ...{util_amd64_test.go => cpu_vendor_test.go} | 2 +- efi/preinstall/export_amd64_test.go | 54 - efi/preinstall/export_test.go | 32 +- efi/preinstall/intel_util.go | 2 - internal/efi/default_env_amd64.go | 7 +- ..._env_null.go => default_env_amd64_null.go} | 0 ...test.go => default_env_amd64_null_test.go} | 0 internal/efi/default_env_amd64_test.go | 14 +- internal/efi/env.go | 16 +- 35 files changed, 9276 insertions(+), 10738 deletions(-) delete mode 100644 efi/preinstall/check_host_security_amd64.go delete mode 100644 efi/preinstall/check_host_security_amd64_test.go delete mode 100644 efi/preinstall/check_host_security_null.go delete mode 100644 efi/preinstall/check_tpm_amd64.go delete mode 100644 efi/preinstall/check_tpm_amd64_test.go delete mode 100644 efi/preinstall/check_tpm_null.go create mode 100644 efi/preinstall/checks_fixture_test.go rename efi/preinstall/{util_amd64.go => cpu_vendor.go} (96%) rename efi/preinstall/{util_amd64_test.go => cpu_vendor_test.go} (97%) delete mode 100644 efi/preinstall/export_amd64_test.go rename internal/efi/{default_env_null.go => default_env_amd64_null.go} (100%) rename internal/efi/{default_env_not_amd64_test.go => default_env_amd64_null_test.go} (100%) diff --git a/efi/preinstall/check_host_security.go b/efi/preinstall/check_host_security.go index 61c0f9ff..35567ac3 100644 --- a/efi/preinstall/check_host_security.go +++ b/efi/preinstall/check_host_security.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -21,12 +21,20 @@ package preinstall import ( "bytes" + "errors" + "fmt" + "runtime" "github.com/canonical/tcglog-parser" "github.com/pilebones/go-udev/netlink" internal_efi "github.com/snapcore/secboot/internal/efi" ) +// runtimeGOARCH is the architecture that host security checks are performed +// for. It is a variable so that tests can run the checks for architectures +// other than the one the test binary was built for. +var runtimeGOARCH = runtime.GOARCH + // discreteTPMPartialResetAttackMitigationStatus indicates whether a partial mitigation against // discrete TPM reset attacks should be enabled. See the documentation for // RequestPartialDiscreteTPMResetAttackMitigation @@ -145,3 +153,145 @@ Loop: } return nil } + +// Architecture-specific host security checks are dispatched at runtime rather than +// selected by build constraints, so that all architectures' checks are compiled and +// testable everywhere. + +// checkHostSecurity is the main entry point for verifying that the host security +// is sufficient. Errors that can't be resolved or which should prevent further checks from running +// are returned immediately and without any wrapping. Errors that can be resolved and which shouldn't +// prevent further checks from running are returned wrapped in [joinError]. +func checkHostSecurity(env internal_efi.HostEnvironment, log *tcglog.Log) (platformFirmwareIntegrityConfig, error) { + switch runtimeGOARCH { + case "amd64": + return checkHostSecurityAMD64(env, log) + default: + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("checking host security is not implemented on %s", runtimeGOARCH)} + } +} + +// checkDiscreteTPMPartialResetAttackMitigationStatus determines whether a partial mitigation +// against discrete TPM reset attacks should be enabled. See the documentation for +// RequestPartialDiscreteTPMResetAttackMitigation. +func checkDiscreteTPMPartialResetAttackMitigationStatus(env internal_efi.HostEnvironment, logResults *pcrBankResults) (discreteTPMPartialResetAttackMitigationStatus, error) { + switch runtimeGOARCH { + case "amd64": + return checkDiscreteTPMPartialResetAttackMitigationStatusAMD64(env, logResults) + default: + return dtpmPartialResetAttackMitigationNotRequired, nil + } +} + +func checkHostSecurityAMD64(env internal_efi.HostEnvironment, log *tcglog.Log) (platformFirmwareIntegrityConfig, error) { + cpuVendor, err := determineCPUVendor(env) + if err != nil { + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} + } + + amd64Env, err := env.AMD64() + if err != nil { + return platformFirmwareIntegrityNone, fmt.Errorf("cannot obtain AMD64 environment: %w", err) + } + + var errs []error + + var integrity platformFirmwareIntegrityConfig + switch cpuVendor { + case cpuVendorIntel: + if err := checkHostSecurityIntelBootGuard(env); err != nil { + var nohwrotErr *NoHardwareRootOfTrustError + ctxErr := fmt.Errorf("encountered an error when checking Intel BootGuard configuration: %w", err) + if !errors.As(err, &nohwrotErr) { + return platformFirmwareIntegrityNone, ctxErr + } + errs = append(errs, ctxErr) + } + if err := checkHostSecurityIntelCPUDebuggingLocked(amd64Env); err != nil { + return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error when checking Intel CPU debugging configuration: %w", err) + } + if len(errs) == 0 { + integrity = platformFirmwareIntegrityVerified + } + case cpuVendorAMD: + integrity, err = checkHostSecurityAMDPSP(env) + if err != nil { + ctxErr := fmt.Errorf("encountered an error when checking the AMD PSP configuration: %w", err) + var nohwrotErr *NoHardwareRootOfTrustError + if !errors.As(err, &nohwrotErr) { + return platformFirmwareIntegrityNone, ctxErr + } + errs = append(errs, ctxErr) + } + default: + panic("not reached") + } + + if err := checkSecureBootPolicyPCRForDegradedFirmwareSettings(log); err != nil { + var ce CompoundError + if !errors.As(err, &ce) { + return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error whilst checking the TCG log for degraded firmware settings: %w", err) + } + errs = append(errs, ce.Unwrap()...) + } + if err := checkForKernelIOMMU(env); err != nil { + switch { + case errors.Is(err, ErrNoKernelIOMMU): + errs = append(errs, err) + default: + return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error whilst checking sysfs to determine that kernel IOMMU support is enabled: %w", err) + } + } + + if len(errs) > 0 { + return platformFirmwareIntegrityNone, joinErrors(errs...) + } + + return integrity, nil +} + +func checkDiscreteTPMPartialResetAttackMitigationStatusAMD64(env internal_efi.HostEnvironment, logResults *pcrBankResults) (discreteTPMPartialResetAttackMitigationStatus, error) { + cpuVendor, err := determineCPUVendor(env) + if err != nil { + return dtpmPartialResetAttackMitigationUnknown, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} + } + + if cpuVendor != cpuVendorIntel { + // Only enable this on Intel systems. + return dtpmPartialResetAttackMitigationNotRequired, nil + } + + amd64Env, err := env.AMD64() + if err != nil { + return dtpmPartialResetAttackMitigationUnknown, fmt.Errorf("cannot obtain AMD64 environment: %w", err) + } + + discreteTPM, err := isTPMDiscrete(env) + if err != nil { + return dtpmPartialResetAttackMitigationUnknown, &TPM2DeviceError{err} + } + + switch { + case !discreteTPM: + // Not a discrete TPM. + return dtpmPartialResetAttackMitigationNotRequired, nil + case !logResults.Lookup(internal_efi.PlatformFirmwarePCR).Ok(): + // PCR0 is unusable. + return dtpmPartialResetAttackMitigationUnavailable, nil + } + + restrictedLocalities := restrictedTPMLocalitiesIntel(amd64Env) + for _, locality := range restrictedLocalities.Values() { + if locality == logResults.StartupLocality { + // The startup locality is not available to the OS, so + // we can enable the migitation because PCR0 cannot + // be recreated from the OS. + return dtpmPartialResetAttackMitigationPreferred, nil + } + } + + // The startup locality is available to the OS, so the mitigation + // is unavailable even though it would have been desired because + // PCR0 can be recreated from the OS. + return dtpmPartialResetAttackMitigationUnavailable, nil +} diff --git a/efi/preinstall/check_host_security_amd.go b/efi/preinstall/check_host_security_amd.go index 2e88c2a6..ea38304d 100644 --- a/efi/preinstall/check_host_security_amd.go +++ b/efi/preinstall/check_host_security_amd.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2025 Canonical Ltd + * Copyright (C) 2025-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_amd64.go b/efi/preinstall/check_host_security_amd64.go deleted file mode 100644 index 9571ca12..00000000 --- a/efi/preinstall/check_host_security_amd64.go +++ /dev/null @@ -1,148 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall - -import ( - "errors" - "fmt" - - "github.com/canonical/tcglog-parser" - internal_efi "github.com/snapcore/secboot/internal/efi" -) - -// checkHostSecurity is the main entry point for verifying that the host security -// is sufficient. Errors that can't be resolved or which should prevent further checks from running -// are returned immediately and without any wrapping. Errors that can be resolved and which shouldn't -// prevent further checks from running are returned wrapped in [joinError]. -func checkHostSecurity(env internal_efi.HostEnvironment, log *tcglog.Log) (platformFirmwareIntegrityConfig, error) { - cpuVendor, err := determineCPUVendor(env) - if err != nil { - return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} - } - - amd64Env, err := env.AMD64() - if err != nil { - return platformFirmwareIntegrityNone, fmt.Errorf("cannot obtain AMD64 environment: %w", err) - } - - var errs []error - - var integrity platformFirmwareIntegrityConfig - switch cpuVendor { - case cpuVendorIntel: - if err := checkHostSecurityIntelBootGuard(env); err != nil { - var nohwrotErr *NoHardwareRootOfTrustError - ctxErr := fmt.Errorf("encountered an error when checking Intel BootGuard configuration: %w", err) - if !errors.As(err, &nohwrotErr) { - return platformFirmwareIntegrityNone, ctxErr - } - errs = append(errs, ctxErr) - } - if err := checkHostSecurityIntelCPUDebuggingLocked(amd64Env); err != nil { - return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error when checking Intel CPU debugging configuration: %w", err) - } - if len(errs) == 0 { - integrity = platformFirmwareIntegrityVerified - } - case cpuVendorAMD: - integrity, err = checkHostSecurityAMDPSP(env) - if err != nil { - ctxErr := fmt.Errorf("encountered an error when checking the AMD PSP configuration: %w", err) - var nohwrotErr *NoHardwareRootOfTrustError - if !errors.As(err, &nohwrotErr) { - return platformFirmwareIntegrityNone, ctxErr - } - errs = append(errs, ctxErr) - } - default: - panic("not reached") - } - - if err := checkSecureBootPolicyPCRForDegradedFirmwareSettings(log); err != nil { - var ce CompoundError - if !errors.As(err, &ce) { - return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error whilst checking the TCG log for degraded firmware settings: %w", err) - } - errs = append(errs, ce.Unwrap()...) - } - if err := checkForKernelIOMMU(env); err != nil { - switch { - case errors.Is(err, ErrNoKernelIOMMU): - errs = append(errs, err) - default: - return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error whilst checking sysfs to determine that kernel IOMMU support is enabled: %w", err) - } - } - - if len(errs) > 0 { - return platformFirmwareIntegrityNone, joinErrors(errs...) - } - - return integrity, nil -} - -// checkDiscreteTPMPartialResetAttackMitigationStatus determines whether a partial mitigation -// against discrete TPM reset attacks should be enabled. See the documentation for -// RequestPartialDiscreteTPMResetAttackMitigation. -func checkDiscreteTPMPartialResetAttackMitigationStatus(env internal_efi.HostEnvironment, logResults *pcrBankResults) (discreteTPMPartialResetAttackMitigationStatus, error) { - cpuVendor, err := determineCPUVendor(env) - if err != nil { - return dtpmPartialResetAttackMitigationUnknown, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} - } - - if cpuVendor != cpuVendorIntel { - // Only enable this on Intel systems. - return dtpmPartialResetAttackMitigationNotRequired, nil - } - - amd64Env, err := env.AMD64() - if err != nil { - return dtpmPartialResetAttackMitigationUnknown, fmt.Errorf("cannot obtain AMD64 environment: %w", err) - } - - discreteTPM, err := isTPMDiscrete(env) - if err != nil { - return dtpmPartialResetAttackMitigationUnknown, &TPM2DeviceError{err} - } - - switch { - case !discreteTPM: - // Not a discrete TPM. - return dtpmPartialResetAttackMitigationNotRequired, nil - case !logResults.Lookup(internal_efi.PlatformFirmwarePCR).Ok(): - // PCR0 is unusable. - return dtpmPartialResetAttackMitigationUnavailable, nil - } - - restrictedLocalities := restrictedTPMLocalitiesIntel(amd64Env) - for _, locality := range restrictedLocalities.Values() { - if locality == logResults.StartupLocality { - // The startup locality is not available to the OS, so - // we can enable the migitation because PCR0 cannot - // be recreated from the OS. - return dtpmPartialResetAttackMitigationPreferred, nil - } - } - - // The startup locality is available to the OS, so the mitigation - // is unavailable even though it would have been desired because - // PCR0 can be recreated from the OS. - return dtpmPartialResetAttackMitigationUnavailable, nil -} diff --git a/efi/preinstall/check_host_security_amd64_test.go b/efi/preinstall/check_host_security_amd64_test.go deleted file mode 100644 index 2ea4892e..00000000 --- a/efi/preinstall/check_host_security_amd64_test.go +++ /dev/null @@ -1,430 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall_test - -import ( - "errors" - - . "gopkg.in/check.v1" - - "github.com/canonical/cpuid" - "github.com/canonical/go-tpm2" - . "github.com/snapcore/secboot/efi/preinstall" - internal_efi "github.com/snapcore/secboot/internal/efi" - "github.com/snapcore/secboot/internal/efitest" - "github.com/snapcore/secboot/internal/testutil" -) - -type hostSecurityAMD64Suite struct{} - -var _ = Suite(&hostSecurityAMD64Suite{}) - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelGood(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - integrity, err := CheckHostSecurity(env, log) - c.Check(err, IsNil) - c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityErrNotAMD64(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts() - - _, err := CheckHostSecurity(env, nil) - c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: not a AMD64 host`) - - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDGoodVerified(c *C) { - pspAttrs := map[string][]byte{ - "boot_integrity": []byte(`1 -`), - "debug_lock_on": []byte(`1 -`), - "fused_part": []byte(`1 -`), - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", pspAttrs, nil), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - integrity, err := CheckHostSecurity(env, log) - c.Check(err, IsNil) - c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDGoodMeasured(c *C) { - pspAttrs := map[string][]byte{ - "boot_integrity": []byte(`0 -`), - "debug_lock_on": []byte(`1 -`), - "fused_part": []byte(`1 -`), - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", pspAttrs, nil), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - integrity, err := CheckHostSecurity(env, log) - c.Check(err, IsNil) - c.Check(integrity, Equals, PlatformFirmwareIntegrityMeasured) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityErrUnrecognizedCpuVendor(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 0, nil), - ) - - _, err := CheckHostSecurity(env, nil) - c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) - - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelErrMEI(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 0, nil), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) - - // Check that there is a NoHardwareRootOfTrustError - // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. - var nhrotErr *NoHardwareRootOfTrustError - var cErr CompoundError - c.Check(errors.As(err, &cErr), testutil.IsTrue) - foundNhrot := false - for _, e := range cErr.Unwrap() { - if errors.As(e, &nhrotErr) { - foundNhrot = true - } - } - c.Check(foundNhrot, testutil.IsTrue) - c.Check(nhrotErr, ErrorMatches, `no hardware root-of-trust properly configured: system is in manufacturing mode`) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDErrPSP(c *C) { - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", nil, nil), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `encountered an error when checking the AMD PSP configuration: no hardware root-of-trust properly configured: PSP security reporting not available`) - - // Check that there is a NoHardwareRootOfTrustError - // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. - var nhrotErr *NoHardwareRootOfTrustError - var cErr CompoundError - c.Check(errors.As(err, &cErr), testutil.IsTrue) - foundNhrot := false - for _, e := range cErr.Unwrap() { - if errors.As(e, &nhrotErr) { - foundNhrot = true - } - } - c.Check(foundNhrot, testutil.IsTrue) - c.Check(nhrotErr, ErrorMatches, `no hardware root-of-trust properly configured: PSP security reporting not available`) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecuritySecureBootPolicyFirmwareDebugging(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `the platform firmware contains a debugging endpoint enabled`) - var tmpl CompoundError - c.Assert(err, Implements, &tmpl) - c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled}) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityNoIOMMU(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `no kernel IOMMU support was detected`) - var tmpl CompoundError - c.Assert(err, Implements, &tmpl) - c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrNoKernelIOMMU}) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecuritySecureBootPolicyFirmwareDebuggingAndNoIOMMU(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `2 errors detected: -- the platform firmware contains a debugging endpoint enabled -- no kernel IOMMU support was detected -`) - var tmpl CompoundError - c.Assert(err, Implements, &tmpl) - c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled, ErrNoKernelIOMMU}) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelErrCPUDebuggingUnlocked(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0x0}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `encountered an error when checking Intel CPU debugging configuration: CPU debugging features are not disabled and locked`) - c.Check(errors.Is(err, ErrCPUDebuggingNotLocked), testutil.IsTrue) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusNotRequiredAMD(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelNotDiscrete(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableInvalidPCR0(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelPreferred(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationPreferred) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableSL0(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableNoTXT(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 4, map[uint32]uint64{0x13a: (2 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusErrUnsupportedCpuVendor(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 0, nil), - ) - - _, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{})) - c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} diff --git a/efi/preinstall/check_host_security_amd_test.go b/efi/preinstall/check_host_security_amd_test.go index 8b3c0ddd..9a69c70c 100644 --- a/efi/preinstall/check_host_security_amd_test.go +++ b/efi/preinstall/check_host_security_amd_test.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2025 Canonical Ltd + * Copyright (C) 2025-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel.go b/efi/preinstall/check_host_security_intel.go index bedd4f92..3889208f 100644 --- a/efi/preinstall/check_host_security_intel.go +++ b/efi/preinstall/check_host_security_intel.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -26,7 +24,6 @@ import ( "errors" "fmt" - "github.com/canonical/cpuid" "github.com/canonical/go-tpm2" "github.com/pilebones/go-udev/netlink" internal_efi "github.com/snapcore/secboot/internal/efi" @@ -346,7 +343,7 @@ const ( func checkHostSecurityIntelCPUDebuggingLocked(env internal_efi.HostEnvironmentAMD64) error { // Check for "Silicon Debug Interface", returned in bit 11 of %ecx when calling // cpuid with %eax=1. - debugSupported := env.HasCPUIDFeature(cpuid.SDBG) + debugSupported := env.HasCPUIDFeature(internal_efi.CPUIDFeatureSDBG) if !debugSupported { return nil } @@ -374,7 +371,7 @@ func checkHostSecurityIntelCPUDebuggingLocked(env internal_efi.HostEnvironmentAM // restrictedTPMLocalitiesIntel returns the TPM localities with access restricted // from the OS. func restrictedTPMLocalitiesIntel(env internal_efi.HostEnvironmentAMD64) tpm2.Locality { - if env.HasCPUIDFeature(cpuid.SMX) { + if env.HasCPUIDFeature(internal_efi.CPUIDFeatureSMX) { // The Intel TXT spec says that locality 4 is only available to microcode, // and is locked before handing over to an ACM which has access to locality // 3. The SINIT ACM uses this to establish a D-RTM and then locks access to diff --git a/efi/preinstall/check_host_security_intel_btgmsr.go b/efi/preinstall/check_host_security_intel_btgmsr.go index d64a65bb..c408a9b7 100644 --- a/efi/preinstall/check_host_security_intel_btgmsr.go +++ b/efi/preinstall/check_host_security_intel_btgmsr.go @@ -1,5 +1,3 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* diff --git a/efi/preinstall/check_host_security_intel_btgmsr_test.go b/efi/preinstall/check_host_security_intel_btgmsr_test.go index 0025edf7..27faea03 100644 --- a/efi/preinstall/check_host_security_intel_btgmsr_test.go +++ b/efi/preinstall/check_host_security_intel_btgmsr_test.go @@ -1,5 +1,3 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* diff --git a/efi/preinstall/check_host_security_intel_csme11.go b/efi/preinstall/check_host_security_intel_csme11.go index 806cd6bb..b1a03e15 100644 --- a/efi/preinstall/check_host_security_intel_csme11.go +++ b/efi/preinstall/check_host_security_intel_csme11.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel_csme11_test.go b/efi/preinstall/check_host_security_intel_csme11_test.go index 74eea31e..e74fb6e9 100644 --- a/efi/preinstall/check_host_security_intel_csme11_test.go +++ b/efi/preinstall/check_host_security_intel_csme11_test.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel_csme18.go b/efi/preinstall/check_host_security_intel_csme18.go index 4693e4e4..7ceb2bf6 100644 --- a/efi/preinstall/check_host_security_intel_csme18.go +++ b/efi/preinstall/check_host_security_intel_csme18.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2025 Canonical Ltd + * Copyright (C) 2025-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel_csme18_test.go b/efi/preinstall/check_host_security_intel_csme18_test.go index 56339779..54f118aa 100644 --- a/efi/preinstall/check_host_security_intel_csme18_test.go +++ b/efi/preinstall/check_host_security_intel_csme18_test.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel_test.go b/efi/preinstall/check_host_security_intel_test.go index 7ede04e8..8ff36770 100644 --- a/efi/preinstall/check_host_security_intel_test.go +++ b/efi/preinstall/check_host_security_intel_test.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -28,7 +26,6 @@ import ( . "gopkg.in/check.v1" - "github.com/canonical/cpuid" "github.com/canonical/go-tpm2" . "github.com/snapcore/secboot/efi/preinstall" internal_efi "github.com/snapcore/secboot/internal/efi" @@ -730,7 +727,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDis } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDisabledMSR(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0x40000000})) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 0x40000000})) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -738,7 +735,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDis } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDisabledAvailable(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0})) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 0})) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -746,7 +743,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDis } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedEnabled(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 1})) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 1})) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -754,7 +751,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedEna } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedErrMissingMSR(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{})) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{})) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -764,7 +761,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedErr } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedErrNoMSRSupport(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 0, nil)) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 0, nil)) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -775,7 +772,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedErr func (s *hostSecurityIntelSuite) TestRestrictedTPMLocalitiesIntel(c *C) { env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 0, nil), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 0, nil), ) amd64Env, err := env.AMD64() c.Assert(err, IsNil) diff --git a/efi/preinstall/check_host_security_null.go b/efi/preinstall/check_host_security_null.go deleted file mode 100644 index ecaca284..00000000 --- a/efi/preinstall/check_host_security_null.go +++ /dev/null @@ -1,39 +0,0 @@ -//go:build !amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall - -import ( - "fmt" - "runtime" - - "github.com/canonical/tcglog-parser" - - internal_efi "github.com/snapcore/secboot/internal/efi" -) - -func checkHostSecurity(env internal_efi.HostEnvironment, log *tcglog.Log) (platformFirmwareIntegrityConfig, error) { - return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("checking host security is not implemented on %s", runtime.GOARCH)} -} - -func checkDiscreteTPMPartialResetAttackMitigationStatus(env internal_efi.HostEnvironment, logResults *pcrBankResults) (discreteTPMPartialResetAttackMitigationStatus, error) { - return dtpmPartialResetAttackMitigationNotRequired, nil -} diff --git a/efi/preinstall/check_host_security_test.go b/efi/preinstall/check_host_security_test.go index 404877db..1ca94879 100644 --- a/efi/preinstall/check_host_security_test.go +++ b/efi/preinstall/check_host_security_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -20,10 +20,15 @@ package preinstall_test import ( - . "gopkg.in/check.v1" + "errors" + "github.com/canonical/go-tpm2" . "github.com/snapcore/secboot/efi/preinstall" + internal_efi "github.com/snapcore/secboot/internal/efi" "github.com/snapcore/secboot/internal/efitest" + "github.com/snapcore/secboot/internal/testutil" + snapd_testutil "github.com/snapcore/snapd/testutil" + . "gopkg.in/check.v1" ) type hostSecuritySuite struct{} @@ -125,3 +130,428 @@ func (s *hostSecuritySuite) TestCheckSecureBootPolicyPCRForDegradedSettingsFirmw c.Assert(err, Implements, &tmpl) c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled, ErrInsufficientDMAProtection}) } + +type hostSecurityAMD64Suite struct { + snapd_testutil.BaseTest +} + +func (s *hostSecurityAMD64Suite) SetUpTest(c *C) { + s.BaseTest.SetUpTest(c) + s.AddCleanup(MockRuntimeGOARCH("amd64")) +} + +var _ = Suite(&hostSecurityAMD64Suite{}) + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelGood(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(err, IsNil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityErrNotAMD64(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts() + + _, err := CheckHostSecurity(env, nil) + c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: not a AMD64 host`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDGoodVerified(c *C) { + pspAttrs := map[string][]byte{ + "boot_integrity": []byte(`1 +`), + "debug_lock_on": []byte(`1 +`), + "fused_part": []byte(`1 +`), + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", pspAttrs, nil), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(err, IsNil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDGoodMeasured(c *C) { + pspAttrs := map[string][]byte{ + "boot_integrity": []byte(`0 +`), + "debug_lock_on": []byte(`1 +`), + "fused_part": []byte(`1 +`), + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", pspAttrs, nil), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(err, IsNil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityMeasured) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityErrUnrecognizedCpuVendor(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 0, nil), + ) + + _, err := CheckHostSecurity(env, nil) + c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelErrMEI(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusManufacturingMode, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 0, nil), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) + + // Check that there is a NoHardwareRootOfTrustError + // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. + var nhrotErr *NoHardwareRootOfTrustError + var cErr CompoundError + c.Check(errors.As(err, &cErr), testutil.IsTrue) + foundNhrot := false + for _, e := range cErr.Unwrap() { + if errors.As(e, &nhrotErr) { + foundNhrot = true + } + } + c.Check(foundNhrot, testutil.IsTrue) + c.Check(nhrotErr, ErrorMatches, `no hardware root-of-trust properly configured: system is in manufacturing mode`) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDErrPSP(c *C) { + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", nil, nil), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `encountered an error when checking the AMD PSP configuration: no hardware root-of-trust properly configured: PSP security reporting not available`) + + // Check that there is a NoHardwareRootOfTrustError + // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. + var nhrotErr *NoHardwareRootOfTrustError + var cErr CompoundError + c.Check(errors.As(err, &cErr), testutil.IsTrue) + foundNhrot := false + for _, e := range cErr.Unwrap() { + if errors.As(e, &nhrotErr) { + foundNhrot = true + } + } + c.Check(foundNhrot, testutil.IsTrue) + c.Check(nhrotErr, ErrorMatches, `no hardware root-of-trust properly configured: PSP security reporting not available`) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecuritySecureBootPolicyFirmwareDebugging(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `the platform firmware contains a debugging endpoint enabled`) + var tmpl CompoundError + c.Assert(err, Implements, &tmpl) + c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled}) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityNoIOMMU(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `no kernel IOMMU support was detected`) + var tmpl CompoundError + c.Assert(err, Implements, &tmpl) + c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrNoKernelIOMMU}) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecuritySecureBootPolicyFirmwareDebuggingAndNoIOMMU(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `2 errors detected: +- the platform firmware contains a debugging endpoint enabled +- no kernel IOMMU support was detected +`) + var tmpl CompoundError + c.Assert(err, Implements, &tmpl) + c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled, ErrNoKernelIOMMU}) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelErrCPUDebuggingUnlocked(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 0x0}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `encountered an error when checking Intel CPU debugging configuration: CPU debugging features are not disabled and locked`) + c.Check(errors.Is(err, ErrCPUDebuggingNotLocked), testutil.IsTrue) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusNotRequiredAMD(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelNotDiscrete(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (3 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableInvalidPCR0(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelPreferred(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationPreferred) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableSL0(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableNoTXT(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 4, map[uint32]uint64{0x13a: (2 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusErrUnsupportedCpuVendor(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 0, nil), + ) + + _, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{})) + c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecuritySuite) TestCheckHostSecurityUnsupportedArchitecture(c *C) { + restore := MockRuntimeGOARCH("ppc64le") + defer restore() + + integrity, err := CheckHostSecurity(nil, nil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityNone) + c.Check(err, ErrorMatches, `unsupported platform: checking host security is not implemented on ppc64le`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecuritySuite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusUnsupportedArchitecture(c *C) { + restore := MockRuntimeGOARCH("ppc64le") + defer restore() + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(nil, nil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) + c.Check(err, IsNil) +} diff --git a/efi/preinstall/check_tpm.go b/efi/preinstall/check_tpm.go index 55ba7e13..4a39e7b1 100644 --- a/efi/preinstall/check_tpm.go +++ b/efi/preinstall/check_tpm.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -21,6 +21,7 @@ package preinstall import ( "bytes" + "errors" "fmt" "github.com/canonical/go-tpm2" @@ -467,3 +468,42 @@ func openAndCheckTPM2Device(env internal_efi.HostEnvironment, flags checkTPM2Dev return tpm, nil } + +// Architecture-specific TPM discreteness checks are dispatched at runtime rather than +// selected by build constraints, so that all architectures' checks are compiled and +// testable everywhere. + +// isTPMDiscrete determines whether the default TPM is discrete. +func isTPMDiscrete(env internal_efi.HostEnvironment) (bool, error) { + switch runtimeGOARCH { + case "amd64": + return isTPMDiscreteAMD64(env) + default: + return false, &UnsupportedPlatformError{fmt.Errorf("checking for TPM discreteness is not implemented on %s", runtimeGOARCH)} + } +} + +func isTPMDiscreteAMD64(env internal_efi.HostEnvironment) (bool, error) { + amd64, err := env.AMD64() + if err != nil { + return false, err + } + + cpuVendor, err := determineCPUVendor(env) + if err != nil { + return false, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} + } + + switch cpuVendor { + case cpuVendorIntel: + discrete, err := isTPMDiscreteFromIntelBootGuard(amd64) + if err != nil { + return false, fmt.Errorf("cannot check TPM discreteness using Intel BootGuard status: %w", err) + } + return discrete, nil + case cpuVendorAMD: + return false, &UnsupportedPlatformError{errors.New("cannot check TPM discreteness on AMD systems")} + default: + panic("not reached") + } +} diff --git a/efi/preinstall/check_tpm_amd64.go b/efi/preinstall/check_tpm_amd64.go deleted file mode 100644 index bb0fecaf..00000000 --- a/efi/preinstall/check_tpm_amd64.go +++ /dev/null @@ -1,53 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall - -import ( - "errors" - "fmt" - - internal_efi "github.com/snapcore/secboot/internal/efi" -) - -// isTPMDiscrete determines whether the TPM is discrete -func isTPMDiscrete(env internal_efi.HostEnvironment) (bool, error) { - amd64, err := env.AMD64() - if err != nil { - return false, err - } - - cpuVendor, err := determineCPUVendor(env) - if err != nil { - return false, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} - } - - switch cpuVendor { - case cpuVendorIntel: - discrete, err := isTPMDiscreteFromIntelBootGuard(amd64) - if err != nil { - return false, fmt.Errorf("cannot check TPM discreteness using Intel BootGuard status: %w", err) - } - return discrete, nil - case cpuVendorAMD: - return false, &UnsupportedPlatformError{errors.New("cannot check TPM discreteness on AMD systems")} - default: - panic("not reached") - } -} diff --git a/efi/preinstall/check_tpm_amd64_test.go b/efi/preinstall/check_tpm_amd64_test.go deleted file mode 100644 index a6a8ea90..00000000 --- a/efi/preinstall/check_tpm_amd64_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall_test - -import ( - "errors" - - . "github.com/snapcore/secboot/efi/preinstall" - "github.com/snapcore/secboot/internal/efitest" - "github.com/snapcore/secboot/internal/testutil" - . "gopkg.in/check.v1" -) - -type tpmAmd64Suite struct{} - -var _ = Suite(&tpmAmd64Suite{}) - -func (s *tpmIntelSuite) TestIsTPMDiscreteIntelYes(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (2 << 1)}), - ) - discrete, err := IsTPMDiscrete(env) - c.Check(err, IsNil) - c.Check(discrete, testutil.IsTrue) -} - -func (s *tpmIntelSuite) TestIsTPMDiscreteIntelNo(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (3 << 1)}), - ) - discrete, err := IsTPMDiscrete(env) - c.Check(err, IsNil) - c.Check(discrete, testutil.IsFalse) -} - -func (s *tpmIntelSuite) TestIsTPMDiscreteIntelNoTPM2(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (0 << 1)}), - ) - _, err := IsTPMDiscrete(env) - c.Check(err, ErrorMatches, `cannot check TPM discreteness using Intel BootGuard status: no TPM2 device is available`) - c.Check(errors.Is(err, ErrNoTPM2Device), testutil.IsTrue) -} - -func (s *tpmIntelSuite) TestIsTPMDiscreteAMD(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 1, nil)) - _, err := IsTPMDiscrete(env) - c.Check(err, ErrorMatches, `unsupported platform: cannot check TPM discreteness on AMD systems`) - - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} - -func (s *tpmIntelSuite) TestIsTPMDiscreteUnrecognizedCPUVendor(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 1, nil)) - _, err := IsTPMDiscrete(env) - c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) - - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} diff --git a/efi/preinstall/check_tpm_intel.go b/efi/preinstall/check_tpm_intel.go index 1a5d9fe0..5a8cc8c2 100644 --- a/efi/preinstall/check_tpm_intel.go +++ b/efi/preinstall/check_tpm_intel.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_tpm_intel_test.go b/efi/preinstall/check_tpm_intel_test.go index 7c76081c..602e9aea 100644 --- a/efi/preinstall/check_tpm_intel_test.go +++ b/efi/preinstall/check_tpm_intel_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -23,10 +23,18 @@ import ( . "github.com/snapcore/secboot/efi/preinstall" "github.com/snapcore/secboot/internal/efitest" "github.com/snapcore/secboot/internal/testutil" + snapd_testutil "github.com/snapcore/snapd/testutil" . "gopkg.in/check.v1" ) -type tpmIntelSuite struct{} +type tpmIntelSuite struct { + snapd_testutil.BaseTest +} + +func (s *tpmIntelSuite) SetUpTest(c *C) { + s.BaseTest.SetUpTest(c) + s.AddCleanup(MockRuntimeGOARCH("amd64")) +} var _ = Suite(&tpmIntelSuite{}) diff --git a/efi/preinstall/check_tpm_null.go b/efi/preinstall/check_tpm_null.go deleted file mode 100644 index c30ae75b..00000000 --- a/efi/preinstall/check_tpm_null.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build !amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall - -import ( - "fmt" - "runtime" - - internal_efi "github.com/snapcore/secboot/internal/efi" -) - -func isTPMDiscrete(env internal_efi.HostEnvironment) (bool, error) { - return false, &UnsupportedPlatformError{fmt.Errorf("checking for TPM discreteness is not implemented on %s", runtime.GOARCH)} -} diff --git a/efi/preinstall/check_tpm_test.go b/efi/preinstall/check_tpm_test.go index 93a7e43c..bdeb03b5 100644 --- a/efi/preinstall/check_tpm_test.go +++ b/efi/preinstall/check_tpm_test.go @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -30,6 +30,7 @@ import ( "github.com/snapcore/secboot/internal/efitest" "github.com/snapcore/secboot/internal/testutil" "github.com/snapcore/secboot/internal/tpm2_device" + snapd_testutil "github.com/snapcore/snapd/testutil" . "gopkg.in/check.v1" ) @@ -1149,3 +1150,70 @@ func (s *tpmSuite) TestOpenAndCheckTPM2DeviceLockoutAvailabilitySkipped(c *C) { c.Assert(tpm, NotNil) c.Check(dev.NumberOpen(), Equals, int(1)) } + +type tpmAmd64Suite struct { + snapd_testutil.BaseTest +} + +func (s *tpmAmd64Suite) SetUpTest(c *C) { + s.BaseTest.SetUpTest(c) + s.AddCleanup(MockRuntimeGOARCH("amd64")) +} + +var _ = Suite(&tpmAmd64Suite{}) + +func (s *tpmIntelSuite) TestIsTPMDiscreteIntelYes(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (2 << 1)}), + ) + discrete, err := IsTPMDiscrete(env) + c.Check(err, IsNil) + c.Check(discrete, testutil.IsTrue) +} + +func (s *tpmIntelSuite) TestIsTPMDiscreteIntelNo(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (3 << 1)}), + ) + discrete, err := IsTPMDiscrete(env) + c.Check(err, IsNil) + c.Check(discrete, testutil.IsFalse) +} + +func (s *tpmIntelSuite) TestIsTPMDiscreteIntelNoTPM2(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (0 << 1)}), + ) + _, err := IsTPMDiscrete(env) + c.Check(err, ErrorMatches, `cannot check TPM discreteness using Intel BootGuard status: no TPM2 device is available`) + c.Check(errors.Is(err, ErrNoTPM2Device), testutil.IsTrue) +} + +func (s *tpmIntelSuite) TestIsTPMDiscreteAMD(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 1, nil)) + _, err := IsTPMDiscrete(env) + c.Check(err, ErrorMatches, `unsupported platform: cannot check TPM discreteness on AMD systems`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *tpmIntelSuite) TestIsTPMDiscreteUnrecognizedCPUVendor(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 1, nil)) + _, err := IsTPMDiscrete(env) + c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *tpmSuite) TestIsTPMDiscreteUnsupportedArchitecture(c *C) { + restore := MockRuntimeGOARCH("ppc64le") + defer restore() + + _, err := IsTPMDiscrete(nil) + c.Check(err, ErrorMatches, `unsupported platform: checking for TPM discreteness is not implemented on ppc64le`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} diff --git a/efi/preinstall/checks_context_test.go b/efi/preinstall/checks_context_test.go index e7ed9448..1f37b612 100644 --- a/efi/preinstall/checks_context_test.go +++ b/efi/preinstall/checks_context_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -28,7 +28,6 @@ import ( "io" "time" - "github.com/canonical/cpuid" efi "github.com/canonical/go-efilib" "github.com/canonical/go-tpm2" "github.com/canonical/go-tpm2/objectutil" @@ -90,6 +89,7 @@ type testRunChecksContextRunParams struct { } func (s *runChecksContextSuite) testRun(c *C, params *testRunChecksContextRunParams) (errs []*WithKindAndActionsError) { + s.ResetAndClearTPMSimulatorUsingPlatformHierarchy(c) dev, err := params.env.TPMDevice() if err == nil { s.allocatePCRBanks(c, params.enabledBanks...) @@ -215,182 +215,143 @@ func (s *runChecksContextSuite) testRun(c *C, params *testRunChecksContextRunPar func (s *runChecksContextSuite) TestRunGood(c *C) { // Good test on a fTPM with a single run - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodSHA384(c *C) { // Good test on a fTPM with a single run and SHA384 selected as the PCR bank - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "030ac3c913dab858f1d69239115545035cff671d6229f95577bb0ffbd827b35abaf6af6bfd223e04ecc9b60a9803642d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "030ac3c913dab858f1d69239115545035cff671d6229f95577bb0ffbd827b35abaf6af6bfd223e04ecc9b60a9803642d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "6c2df9007211786438be210b6908f2935d0b25ebdcd2c65621826fd2ec55fb9fbacbfe080d48db98f0ef970273b8254a")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "42f61b3089f5ce0646b422a59c9632065db2630f3e5b01690e63c41420ed31f10ff2a191f3440f9501109fc85f7fb00f")}, }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "6c2df9007211786438be210b6908f2935d0b25ebdcd2c65621826fd2ec55fb9fbacbfe080d48db98f0ef970273b8254a")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "42f61b3089f5ce0646b422a59c9632065db2630f3e5b01690e63c41420ed31f10ff2a191f3440f9501109fc85f7fb00f")}, - }, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA384, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA384, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodSHA1FromInitialFlags(c *C) { // Good test on a fTPM with a single run and SHA1 as the selected algorithm, // permitted by passing the PermitWeakPCRBanks flag as an initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, - initialFlags: PermitWeakPCRBanks, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, + initialFlags: PermitWeakPCRBanks, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, - }, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA1, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA1, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Test a good case that selects SHA1 without supplying the initial flag when we have an action to enable PermitWeakPCRBanks. @@ -398,544 +359,440 @@ func (s *runChecksContextSuite) TestRunGoodSHA1FromInitialFlags(c *C) { func (s *runChecksContextSuite) TestRunGoodPermitInsufficientDMAProtectionFromInitialFlags(c *C) { // Test case where there is an empty PCR bank, but it is permitted by // supplying PermitInsufficientDMAProtection as an initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitInsufficientDMAProtection, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindInsufficientDMAProtection: nil, - ErrorKindNoKernelIOMMU: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitInsufficientDMAProtection, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindInsufficientDMAProtection: nil, + ErrorKindNoKernelIOMMU: nil, + }, + expectedWarningsMatch: `4 errors detected: - the platform firmware indicates that DMA protections are insufficient - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 0) + }) + c.Assert(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitInsufficientDMAProtection(c *C) { // Test that ActionProceed enables PermitInsufficientDMAProtection. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - errs[0].Unwrap(), - )) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindInsufficientDMAProtection: nil, - ErrorKindNoKernelIOMMU: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + errs[0].Unwrap(), + )) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindInsufficientDMAProtection: nil, + ErrorKindNoKernelIOMMU: nil, + }, + expectedWarningsMatch: `4 errors detected: - the platform firmware indicates that DMA protections are insufficient - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 0) + }) + c.Assert(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitNoHardwareRootOfTrust(c *C) { // Test that ActionProceed enables PermitNoHardwareRootOfTrust. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindNoHardwareRootOfTrust, - nil, - []Action{ActionProceed}, - errs[0].Unwrap(), - )) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindNoHardwareRootOfTrust: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityInsufficientHWRootOfTrust + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindNoHardwareRootOfTrust, + nil, + []Action{ActionProceed}, + errs[0].Unwrap(), + )) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindNoHardwareRootOfTrust: nil, + }, + expectedWarningsMatch: `4 errors detected: - encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodPostInstall(c *C) { // Test good post-install scenario on a fTPM, which skips some tests related to // TPM ownership, lockout status and checking the number of available // NV counters. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PostInstallChecks, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PostInstallChecks, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodPreAndPostInstall(c *C) { // Test good pre-install and post-install scenario on a fTPM. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 4, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: +- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 +- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 +- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 +`, + }) + c.Check(errs, HasLen, 0) + + errs = s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + tpm2.PropertyPermanent: uint32(tpm2.AttrLockoutAuthSet), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PostInstallChecks, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: +- availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set +- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 +- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 +- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 +`, + }) + c.Check(errs, HasLen, 0) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 4, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: -- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 -- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 -- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 -`, - }) - c.Check(errs, HasLen, 0) - - errs = s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - tpm2.PropertyPermanent: uint32(tpm2.AttrLockoutAuthSet), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PostInstallChecks, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: -- availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set -- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 -- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 -- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 -`, - }) - c.Check(errs, HasLen, 0) } func (s *runChecksContextSuite) TestRunGoodPermitVirtualMachineFromInitialFlags(c *C) { // Test on a virtual machine, wehere PermitVirtualMachine is supplied via // the initial flags to permit it. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitVirtualMachine, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindRunningInVM: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitVirtualMachine, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindRunningInVM: nil, + }, + expectedWarningsMatch: `4 errors detected: - virtual machine environment detected - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitVirtualMachine(c *C) { // Test that ActionProceed turns on PermitVirtualMachine. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindRunningInVM, - nil, - []Action{ActionProceed}, - ErrVirtualMachineDetected, - )) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindRunningInVM: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindRunningInVM, + nil, + []Action{ActionProceed}, + ErrVirtualMachineDetected, + )) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindRunningInVM: nil, + }, + expectedWarningsMatch: `4 errors detected: - virtual machine environment detected - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodDiscreteTPMDetectedSL3(c *C) { // Test a good case on a dTPM where the startup locality is 3 and // access to locality 3 is restricted to ring 0 code. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation, - expectedWarningsMatch: `3 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality3InaccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Test a good case with a discrete TPM where the startup locality is 3, but not protected, when we have an action to turn on the PermitNoDiscreteTPMResetMitigation flag. @@ -943,57 +800,47 @@ func (s *runChecksContextSuite) TestRunGoodDiscreteTPMDetectedSL3(c *C) { func (s *runChecksContextSuite) TestRunGoodDiscreteTPMDetectedHCRTM(c *C) { // Test a good case on a dTPM where there is a H-CRTM event and // access to locality 4 is restricted to ring 0 code. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 4, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation, - expectedWarningsMatch: `3 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality4InaccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 4, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Test a good case with a discrete TPM where there is a HCRTM event but startup locality is 4 is not protected, when we have an action to turn on the PermitNoDiscreteTPMResetMitigation flag. @@ -1002,125 +849,111 @@ func (s *runChecksContextSuite) TestRunGoodInvalidPCR0Value(c *C) { // Test a good case where the value of PCR0 is inconsistent with the log, // but in a configuration where PCR0 isn't required because the system is // configured with verified boot and there is a fTPM. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\) - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + if fixture.additionalExpectedFlags&RequireLockToPlatformFirmware != 0 { + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) + continue + } + c.Check(errs, HasLen, 0) + } } -// TODO: Good test case for invalid PCR1 when we support it. - func (s *runChecksContextSuite) TestRunGoodInvalidPCR2ValueWhenOmittedFromPCRProfileOpts(c *C) { // Test a good case on a fTPM where the value of PCR2 is inconsistent // with the log, but PCR2 isn't required for the specified profile options. - restore := MockKnownCAs(AuthorityTrustDataSet{ - {internal_efi.MSUefiCA2011, AuthorityTrustDrivers}, - {internal_efi.MSUefiCA2023, 0}, - }) - defer restore() - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForAddonDrivers, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + func() { + restore := MockKnownCAs(AuthorityTrustDataSet{ + {internal_efi.MSUefiCA2011, AuthorityTrustDrivers}, + {internal_efi.MSUefiCA2023, 0}, + }) + defer restore() + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForAddonDrivers, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\) - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + }() + } } // TODO: Good test case for invalid PCR3 when we support it. @@ -1128,65 +961,54 @@ func (s *runChecksContextSuite) TestRunGoodInvalidPCR2ValueWhenOmittedFromPCRPro func (s *runChecksContextSuite) TestRunGoodInvalidPCR4ValueWhenOmittedFromPCRProfileOpts(c *C) { // Test a good case on a fTPM where the value of PCR4 is inconsistent // with the log, but PCR4 isn't required for the specified profile options. - restore := MockKnownCAs(AuthorityTrustDataSet{ - {internal_efi.MSUefiCA2011, AuthorityTrustBootCode}, - {internal_efi.MSUefiCA2023, 0}, - }) - defer restore() - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForBootCode, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + func() { + restore := MockKnownCAs(AuthorityTrustDataSet{ + {internal_efi.MSUefiCA2011, AuthorityTrustBootCode}, + {internal_efi.MSUefiCA2023, 0}, + }) + defer restore() + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForBootCode, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\) - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + }() + } } // TODO: Good test case for invalid PCR5 when we support it. @@ -1196,336 +1018,235 @@ func (s *runChecksContextSuite) TestRunGoodAddonDriversPresentFromInitialFlags(c // Test good case on a fTPM where there are value-added-retailer drivers // detected, and these are permitted with the PermitAddonDrivers // initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitAddonDrivers, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitAddonDrivers, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Test the above case without the initial flag when we have an action to set PermitAddonDrivers. func (s *runChecksContextSuite) TestRunGoodActionProceedPermitAddonDrivers(c *C) { // Test that ActionProceed turns on PermitAddonDrivers. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodSysPrepAppsPresentFromInitialFlags(c *C) { // Test good case on a fTPM where there are system preparation applications // detected, and these are permitted with the PermitSysPrepApplications // initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitSysPrepApplications, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindSysPrepApplicationsPresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitSysPrepApplications, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindSysPrepApplicationsPresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - system preparation applications were detected: - Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitSysPrepApplications(c *C) { // Test that ActionProceed enables PermitSysPrepApplications. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `system preparation applications were detected: -- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 -`) - imageInfo := []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ &efi.HardDriveDevicePathNode{ PartitionNumber: 1, PartitionStart: 0x800, @@ -1534,306 +1255,304 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedPermitSysPrepApplication MBRType: efi.GPT}, efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - } + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindSysPrepApplicationsPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &SysPrepApplicationsPresentError{ - Apps: imageInfo, - }, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindSysPrepApplicationsPresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + c.Check(errs[0], ErrorMatches, `system preparation applications were detected: +- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 +`) + imageInfo := []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), + }, + } + + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindSysPrepApplicationsPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &SysPrepApplicationsPresentError{ + Apps: imageInfo, + }, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindSysPrepApplicationsPresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - system preparation applications were detected: - Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 0) + }) + c.Assert(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodAbsoluteActiveFromInitialFlags(c *C) { // Test good case on a fTPM where Absolute is detected, and this is // permitted with the PermitAbsoluteComputrace initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - initialFlags: PermitAbsoluteComputrace, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAbsolutePresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + initialFlags: PermitAbsoluteComputrace, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAbsolutePresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - Absolute was detected to be active and it is advised that this is disabled - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitAbsolute(c *C) { // Test that ActionProceed enables PermitAbsoluteComputrace. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAbsolutePresent, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + ErrAbsoluteComputraceActive, + )) + } + }, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAbsolutePresent: nil, + }, + expectedWarningsMatch: `4 errors detected: +- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 +- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 +- Absolute was detected to be active and it is advised that this is disabled +- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 +`, + }) + c.Check(errs, HasLen, 0) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAbsolutePresent, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - ErrAbsoluteComputraceActive, - )) - } - }, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAbsolutePresent: nil, - }, - expectedWarningsMatch: `4 errors detected: -- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 -- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 -- Absolute was detected to be active and it is advised that this is disabled -- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 -`, - }) - c.Check(errs, HasLen, 0) -} +} // TODO: Test the above case without the initial flag when we have an action to set PermitAbsoluteComputrace. func (s *runChecksContextSuite) TestRunGoodNoBootManagerCodeProfileSupportWhenOmittedFromPCRProfileOpts(c *C) { // Test a good case on a fTPM where the launch digests in the log for OS components // are invalid, but the profile options permits the omission of PCR4. - restore := MockKnownCAs(AuthorityTrustDataSet{ - {internal_efi.MSUefiCA2011, AuthorityTrustBootCode}, - {internal_efi.MSUefiCA2023, 0}, - }) - defer restore() - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + func() { + restore := MockKnownCAs(AuthorityTrustDataSet{ + {internal_efi.MSUefiCA2011, AuthorityTrustBootCode}, + {internal_efi.MSUefiCA2023, 0}, + }) + defer restore() + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - }, - // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test - // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in - // the log so the test thinks that the log contains the flat file digest. - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, - }, - profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForBootCode, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test + // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in + // the log so the test thinks that the log contains the flat file digest. + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, + }, + profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForBootCode, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and/or the PE_COFF_IMAGE flag - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + }() + } } func (s *runChecksContextSuite) TestRunGoodPreOSSecureBootAuthByEnrolledDigestsFromInitialFlags(c *C) { // Test a good case where there are value-added-retailer drivers being loaded, // authenticated by way of a digest in db, permitted by supplying PermitPreOSSecureBootAuthByEnrolledDigests // as one of the initial flags. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `5 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `5 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -1841,254 +1560,215 @@ func (s *runChecksContextSuite) TestRunGoodPreOSSecureBootAuthByEnrolledDigestsF - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitSecureBootUserMode(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `secure boot is enabled but not in deployed mode`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidSecureBootMode, - SecureBootModeArg{ - Enabled: true, - Mode: efi.UserMode, - }, - []Action{ActionRebootToFWSettings, ActionProceed}, - ErrNoDeployedMode, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindInvalidSecureBootMode: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `secure boot is enabled but not in deployed mode`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidSecureBootMode, + SecureBootModeArg{ + Enabled: true, + Mode: efi.UserMode, + }, + []Action{ActionRebootToFWSettings, ActionProceed}, + ErrNoDeployedMode, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindInvalidSecureBootMode: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 - secure boot is enabled but not in deployed mode `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodPermitSecureBootUserModeFromInitialFlags(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitSecureBootUserMode, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindInvalidSecureBootMode: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitSecureBootUserMode, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindInvalidSecureBootMode: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 - secure boot is enabled but not in deployed mode `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitPreOSSecureBootAuthByEnrolledDigests(c *C) { // Test that ActionProceed enables the PermitPreOSSecureBootAuthByEnrolledDigests flag. As // this test generates 2 errors, it also tests the case where ActionProceed can // be used to ignore multiple errors. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 2) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 2) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `5 errors detected: + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `5 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -2096,66 +1776,53 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedPermitPreOSSecureBootAut - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodWeakSecureBootAlgsFromInitialFlags(c *C) { // Test a good case on a fTPM where there are weak secure boot algorithms // detected, but this is permitted because PermitWeakSecureBootAlgorithms // was supplied as an initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindWeakSecureBootAlgorithmsDetected: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `6 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindWeakSecureBootAlgorithmsDetected: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `6 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -2164,126 +1831,113 @@ func (s *runChecksContextSuite) TestRunGoodWeakSecureBootAlgsFromInitialFlags(c - a weak cryptographic algorithm was detected during secure boot verification - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitWeakSecureBootAlgs(c *C) { // Test that ActionProceed enables PermitWeakSecureBootAlgorithms. As // this test generates 3 errors, it also tests the case where ActionProceed // can be used to ignore multiple errors. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 3) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 3) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindWeakSecureBootAlgorithmsDetected, - nil, - []Action{ActionProceed}, - ErrWeakSecureBootAlgorithmDetected, - )) - - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindWeakSecureBootAlgorithmsDetected: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `6 errors detected: + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindWeakSecureBootAlgorithmsDetected, + nil, + []Action{ActionProceed}, + ErrWeakSecureBootAlgorithmDetected, + )) + + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindWeakSecureBootAlgorithmsDetected: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `6 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -2292,8 +1946,9 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedPermitWeakSecureBootAlgs - a weak cryptographic algorithm was detected during secure boot verification - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Good test case for invalid secure boot config (eg, no DeployedMode) when PCRProfileOptionPermitNoSecureBootPolicyProfile is supported. @@ -2301,143 +1956,129 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedPermitWeakSecureBootAlgs func (s *runChecksContextSuite) TestRunGoodActionProceedIndividualWithMultipleErrors(c *C) { // Test that ActionProceed can be used to ignore individual errors when // multiple errors are reported. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 4, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindWeakSecureBootAlgorithmsDetected}}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindPreOSSecureBootAuthByEnrolledDigests}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 3) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 4, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindWeakSecureBootAlgorithmsDetected}}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindPreOSSecureBootAuthByEnrolledDigests}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 3) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindWeakSecureBootAlgorithmsDetected, - nil, - []Action{ActionProceed}, - ErrWeakSecureBootAlgorithmDetected, - )) - - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - case 1: - c.Check(errs, HasLen, 2) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindWeakSecureBootAlgorithmsDetected, - nil, - []Action{ActionProceed}, - ErrWeakSecureBootAlgorithmDetected, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - case 2: - c.Check(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindWeakSecureBootAlgorithmsDetected: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `6 errors detected: + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindWeakSecureBootAlgorithmsDetected, + nil, + []Action{ActionProceed}, + ErrWeakSecureBootAlgorithmDetected, + )) + + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + case 1: + c.Check(errs, HasLen, 2) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindWeakSecureBootAlgorithmsDetected, + nil, + []Action{ActionProceed}, + ErrWeakSecureBootAlgorithmDetected, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + case 2: + c.Check(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindWeakSecureBootAlgorithmsDetected: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `6 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -2446,8 +2087,9 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedIndividualWithMultipleEr - a weak cryptographic algorithm was detected during secure boot verification - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodPostInstallTPMDeviceLockedOut(c *C) { @@ -2456,1231 +2098,1774 @@ func (s *runChecksContextSuite) TestRunGoodPostInstallTPMDeviceLockedOut(c *C) { // hierarchy has an authorization value. The TPM lockout is returned as // a warning because it's normally cleared during a successful boot and // it will be cleared during a reprovision as well. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - initialFlags: PostInstallChecks, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Trip the DA logic by triggering an auth failure with a DA protected - // resource. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) - pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) - c.Assert(err, IsNil) - key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) - c.Assert(err, IsNil) - key.SetAuthValue(nil) - _, err = s.TPM.Unseal(key, nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) - - // Take ownership of the lockout hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `5 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + initialFlags: PostInstallChecks, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Trip the DA logic by triggering an auth failure with a DA protected + // resource. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) + pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) + c.Assert(err, IsNil) + key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) + c.Assert(err, IsNil) + key.SetAuthValue(nil) + _, err = s.TPM.Unseal(key, nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) + + // Take ownership of the lockout hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `5 errors detected: - availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set - error with TPM2 device: TPM is in DA lockout mode - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionClearTPMSimple(c *C) { // Test that ActionClearTPMSimple works. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMSimple}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMSimple}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) - val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) - c.Assert(err, IsNil) - c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) + c.Assert(err, IsNil) + c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + } } func (s *runChecksContextSuite) TestRunGoodActionClearTPM(c *C) { // Test that ActionClearTPM works. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the lockout hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg("1234")}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the lockout hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg("1234")}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) - val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) - c.Assert(err, IsNil) - c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) + c.Assert(err, IsNil) + c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + } } func (s *runChecksContextSuite) TestRunGoodActionClearTPMMissingAuthValueArg(c *C) { // Test that ActionClearTPM works if the lockout hierarchy has no authorization - // value and no arguments are suppled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + // value and no arguments are supplied. + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) - val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) - c.Assert(err, IsNil) - c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) + c.Assert(err, IsNil) + c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + } } func (s *runChecksContextSuite) TestRunGoodStartupLocalityNotProtected(c *C) { // Test the case where there is a dTPM and the startup locality // is not protected from ring 0 access. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality0AccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with system security: cannot enable partial mitigation against discrete TPM reset attacks - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodInvalidPCR0ValueDiscreteTPM(c *C) { // Test the case where there is a dTPM and PCR0 is inconsistent with // the log. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `5 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `5 errors detected: - error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0x420bd3899738e6b41dccd18253a556e152e2b107559b89cbf0cbf1661ff6ee55, reconstructed from log 0xb0d6d5f50852be1524306ad88b928605c14338e56a1b8c0dc211a144524df2ef\) - error with system security: cannot enable partial mitigation against discrete TPM reset attacks - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 0) + }) + if fixture.additionalExpectedFlags&RequireLockToPlatformFirmware != 0 { + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0x420bd3899738e6b41dccd18253a556e152e2b107559b89cbf0cbf1661ff6ee55, reconstructed from log 0xb0d6d5f50852be1524306ad88b928605c14338e56a1b8c0dc211a144524df2ef\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) + continue + } + c.Assert(errs, HasLen, 0) + } } // **End of good cases ** // func (s *runChecksContextSuite) TestRunBadUnexpectedAction(c *C) { - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionClearTPMViaFirmware}}, - }) - c.Assert(errs, HasLen, 1) - c.Assert(errs[0], ErrorMatches, `specified action is not expected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindUnexpectedAction, nil, nil, errs[0].Unwrap())) + required := runChecksHostCapabilities(0) + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionClearTPMViaFirmware}}, + }) + c.Assert(errs, HasLen, 1) + c.Assert(errs[0], ErrorMatches, `specified action is not expected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindUnexpectedAction, nil, nil, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadExternalAction(c *C) { - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionRebootToFWSettings}, - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `specified action is not implemented directly by this package`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindUnexpectedAction, nil, nil, errs[0].Unwrap())) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionRebootToFWSettings}, + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `specified action is not implemented directly by this package`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindUnexpectedAction, nil, nil, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadVirtualMachine(c *C) { // Test the error case where a virtualized environment // is detected. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Assert(errs[0], ErrorMatches, `virtual machine environment detected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindRunningInVM, - nil, - []Action{ActionProceed}, - ErrVirtualMachineDetected, - )) + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Assert(errs[0], ErrorMatches, `virtual machine environment detected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindRunningInVM, + nil, + []Action{ActionProceed}, + ErrVirtualMachineDetected, + )) + } } func (s *runChecksContextSuite) TestRunBadNotEFI(c *C) { // Test the error case where the host system is not EFI - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Assert(errs[0], ErrorMatches, `host system is not an EFI system`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindSystemNotEFI, nil, nil, ErrSystemNotEFI)) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Assert(errs[0], ErrorMatches, `host system is not an EFI system`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindSystemNotEFI, nil, nil, ErrSystemNotEFI)) + } } func (s *runChecksContextSuite) TestRunBadEFIVariableAccessError(c *C) { // Test the error case where an EFI variable access fails - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Err: efi.ErrVarDeviceError}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Assert(errs[0], ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read AuditMode variable: variable access failed because of a hardware error`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindEFIVariableAccess, EFIVarDeviceError, []Action{ActionContactOEM}, errs[0].Unwrap())) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Err: efi.ErrVarDeviceError}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Assert(errs[0], ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read AuditMode variable: variable access failed because of a hardware error`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindEFIVariableAccess, EFIVarDeviceError, []Action{ActionContactOEM}, errs[0].Unwrap())) } func (s *runChecksContextSuite) TestRunBadNoTPM2Device(c *C) { // Test the error case where no valid TPM2 device is detected. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: cannot open TPM device: cannot obtain TPM device: no TPM2 device is available`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitableTPM2Device, nil, nil, errs[0].Unwrap())) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: cannot open TPM device: cannot obtain TPM device: no TPM2 device is available`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitableTPM2Device, nil, nil, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadTPMDeviceFailure(c *C) { // Test the error case where the TPM device is in failure mode. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // The next command following this is inside openAndCheckTPM2Device - // which runs TPM2_SelfTest(false) and will trigger the device's - // failure mode. - s.Mssim(c).TestFailureMode() - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is in failure mode`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceFailure, nil, []Action{ActionReboot, ActionContactOEM}, errs[0].Unwrap())) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // The next command following this is inside openAndCheckTPM2Device + // which runs TPM2_SelfTest(false) and will trigger the device's + // failure mode. + s.Mssim(c).TestFailureMode() + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is in failure mode`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceFailure, nil, []Action{ActionReboot, ActionContactOEM}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadNoPCClientTPMDevice(c *C) { // Test the error case where there is a TPM2 device, but it isn't // a PC Client device. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 2, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but it is not a PC-Client TPM`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitableTPM2Device, nil, nil, errs[0].Unwrap())) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 2, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but it is not a PC-Client TPM`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitableTPM2Device, nil, nil, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadTPM2DeviceDisabled(c *C) { // Test the error case where the TPM has been disabled by firmware. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + nil, + )), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadTPM2DeviceDisabledRunEnableTPMViaFirmwareAction(c *C) { // Test the error case where the TPM has been disabled by firmware, and // we run the ActionEnableTPMViaFirmware action. + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Disable owner and endorsement hierarchies on the first iteration + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + } + }, + iterations: 2, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"EnableTPM()"}) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Disable owner and endorsement hierarchies on the first iteration - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - } - }, - iterations: 2, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) - } - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - - c.Check(p.called, DeepEquals, []string{"EnableTPM()"}) -} +} func (s *runChecksContextSuite) TestRunBadTPM2DeviceDisabledRunEnableAndClearTPMViaFirmwareAction(c *C) { // Test the error case where the TPM has been disabled by firmware, and // we run the ActionEnableAndClearTPMViaFirmware action. + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Disable owner and endorsement hierarchies on the first iteration - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - } - }, - iterations: 2, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableAndClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) - } - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Disable owner and endorsement hierarchies on the first iteration + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + } + }, + iterations: 2, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableAndClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + } } func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwned(c *C) { // Test the error case where one or more hierarchies of the TPM are already owned. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the endorsement hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the endorsement hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_ENDORSEMENT has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedRunActionClearTPMViaFirmware(c *C) { // Test the error case where one or more hierarchies of the TPM are already owned, and // we run the ActionClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the endorsement hierarchy on the + // first iteration. + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedRunActionEnableAndClearTPMViaFirmware(c *C) { + // Test the error case where one or more hierarchies of the TPM are already owned, and + // we run the ActionEnableAndClearTPMViaFirmware action. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the endorsement hierarchy on the first iteration. + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableAndClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) } +} - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, +func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOut(c *C) { + // Test the error case where the TPM's lockout hierarchy is locked out. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) + + // Disable the lockout hierarchy by authorizing it incorrectly + s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) + err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM's lockout hierarchy is unavailable because it is locked out`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMDeviceLockoutLockedOut, + TPMDeviceLockoutRecoveryArg(24*time.Hour), + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) } +} - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the endorsement hierarchy on the - // first iteration. - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: +func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionClearTPMViaFirmware(c *C) { + // Test the error case where the TPM's lockout hierarchy is locked out, and + // we run the ActionClearTPMViaFirmware action. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Disable the lockout hierarchy on the first iteration. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) + + // Disable the lockout hierarchy by authorizing it incorrectly + s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) + err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMDeviceLockoutLockedOut, + TPMDeviceLockoutRecoveryArg(24*time.Hour), + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) + } +} + +func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionEnableAndClearTPMViaFirmware(c *C) { + // Test the error case where the TPM's lockout hierarchy is locked out, and + // we run the ActionEnableAndClearTPMViaFirmware action. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Disable the lockout hierarchy on the first iteration. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) + + // Disable the lockout hierarchy by authorizing it incorrectly + s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) + err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableAndClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMDeviceLockoutLockedOut, + TPMDeviceLockoutRecoveryArg(24*time.Hour), + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + } +} + +func (s *runChecksContextSuite) TestRunBadTPMInsufficientCounters(c *C) { + // Test the error case where there appears to be too few NV counters. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: insufficient NV counters available`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientTPMStorage, + nil, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } +} + +func (s *runChecksContextSuite) TestRunBadTPMInsufficientCountersRunActionClearTPMViaFirmware(c *C) { + // Test the error case where there appears to be too few NV counters, and + // we run the ActionClearTPMViaFirmware action. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { c.Assert(errs, HasLen, 1) c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + ErrorKindInsufficientTPMStorage, + nil, []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, errs[0].Unwrap(), )) - } - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) + c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) + } } -func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedRunActionEnableAndClearTPMViaFirmware(c *C) { - // Test the error case where one or more hierarchies of the TPM are already owned, and +func (s *runChecksContextSuite) TestRunBadTPMInsufficientCountersRunActionEnableAndClearTPMViaFirmware(c *C) { + // Test the error case where there appears to be too few NV counters, and // we run the ActionEnableAndClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - } + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the endorsement hierarchy on the first iteration. - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableAndClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableAndClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { c.Assert(errs, HasLen, 1) c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + ErrorKindInsufficientTPMStorage, + nil, []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, errs[0].Unwrap(), )) - } - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + } } -func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOut(c *C) { - // Test the error case where the TPM's lockout hierarchy is locked out. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedAndLockedOut(c *C) { + // Test case with more than one TPM error - in this case, one of the errors + // is ErrTPMLockout which is converted to a warning and suppressed unless + // RunChecks completes with success. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Trip the DA logic by triggering an auth failure with a DA protected + // resource. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) + pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) + c.Assert(err, IsNil) + key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) + c.Assert(err, IsNil) + key.SetAuthValue(nil) + _, err = s.TPM.Unseal(key, nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) + + // Take ownership of the lockout hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: +- TPM_RH_LOCKOUT has an authorization value +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksContextSuite) TestRunBadTCGLog(c *C) { + // Test the error case where the TCG log cannot be decoded. + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: nil log`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindMeasuredBoot, nil, nil, errs[0].Unwrap())) } - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) - - // Disable the lockout hierarchy by authorizing it incorrectly - s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) - err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM's lockout hierarchy is unavailable because it is locked out`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMDeviceLockoutLockedOut, - TPMDeviceLockoutRecoveryArg(24*time.Hour), - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) } -func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionClearTPMViaFirmware(c *C) { - // Test the error case where the TPM's lockout hierarchy is locked out, and - // we run the ActionClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +// TODO: Test another bad case where PCR0 is mandatory but unusable, but is mandatory +// because the firmware is only protected with measured boot (this isn't supported yet, +// but it would result in the "no-suitable-pcr-bank" error kind). + +func (s *runChecksContextSuite) TestRunBadInvalidPCR2Value(c *C) { + // Test the error case where PCR2 is inconsistent with the log, but it + // has been marked as mandatory due to the usage of the Microsoft UEFI CA. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksContextSuite) TestRunBadInvalidPCR4Value(c *C) { + // Test the error case where PCR4 is inconsistent with the log, but it + // has been marked as mandatory due to the usage of the Microsoft UEFI CA. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) } +} - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, +func (s *runChecksContextSuite) TestRunBadInvalidPCR7Value(c *C) { + // Test the error case where PCR7 is inconsistent with the log, but it + // has been marked as mandatory because the default profile options + // require it. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) } +} - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Disable the lockout hierarchy on the first iteration. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) +// TODO: Add a test for ErrorKindUnsupportedPlatform - // Disable the lockout hierarchy by authorizing it incorrectly - s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) - err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMDeviceLockoutLockedOut, - TPMDeviceLockoutRecoveryArg(24*time.Hour), - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) +func (s *runChecksContextSuite) TestRunBadUEFIDebuggingEnabled(c *C) { + // Test the error case where a UEFI debugger is enabled. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + FirmwareDebugger: true, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware contains a debugging endpoint enabled`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindHostSecurity, nil, []Action{ActionContactOEM}, errs[0].Unwrap())) + } +} - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) +func (s *runChecksContextSuite) TestRunBadInsufficientDMAProtection(c *C) { + // Test the error case where DMA protection is disabled. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + errs[0].Unwrap(), + )) + } +} - c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) +func (s *runChecksContextSuite) TestRunBadNoKernelIOMMU(c *C) { + // Test the error case where the kernel doesn't enable a IOMMU + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindNoKernelIOMMU, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOSVendor}, + errs[0].Unwrap(), + )) + } } -func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionEnableAndClearTPMViaFirmware(c *C) { - // Test the error case where the TPM's lockout hierarchy is locked out, and - // we run the ActionEnableAndClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksContextSuite) TestRunChecksBadTPMHierarchiesOwnedAndNoKernelIOMMU(c *C) { + // Test case where a TPM hierarchy is owned and there is a host security error. + // This tests the case where ActionProceed is suppressed because one of the returned + // errors doesn't permit it. + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + prepare: func(_ int) { + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 2) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: +- TPM_RH_OWNER has an authorization value +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + c.Check(errs[1], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindNoKernelIOMMU, + nil, + []Action{ActionRebootToFWSettings, ActionContactOSVendor}, + errs[1].Unwrap(), + )) + } +} + +func (s *runChecksContextSuite) TestRunBadNoHardwareRootOfTrust(c *C) { + // Test the error case where the hardware root of trust is insufficient. + required := runChecksHostCapabilityInsufficientHWRootOfTrust + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoHardwareRootOfTrust, nil, []Action{ActionProceed}, errs[0].Unwrap())) } +} + +func (s *runChecksContextSuite) TestRunBadHostSecurityErrorMissingIntelMEModule(c *C) { + s.AddCleanup(MockRuntimeGOARCH("amd64")) + + // Test case where host security checks fail because the intel ME kernel module is missing. devices := []internal_efi.SysfsDevice{ efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00:16:0", map[string]string{"PCI_CLASS": "78000", "PCI_ID": "8086:7E70"}, "pci", nil, nil), } errs := s.testRun(c, &testRunChecksContextRunParams{ env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ tpm2.PropertyNVCountersMax: 0, @@ -3688,49 +3873,18 @@ func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionEnab tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Disable the lockout hierarchy on the first iteration. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) - - // Disable the lockout hierarchy by authorizing it incorrectly - s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) - err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableAndClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMDeviceLockoutLockedOut, - TPMDeviceLockoutRecoveryArg(24*time.Hour), - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, + actions: []actionAndArgs{{action: ActionNone}}, }) c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - - c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: the kernel module "mei_me" must be loaded`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindInternal, nil, nil, errs[0].Unwrap())) + c.Check(errors.Is(errs[0], MissingKernelModuleError("mei_me")), testutil.IsTrue) } -func (s *runChecksContextSuite) TestRunBadTPMInsufficientCounters(c *C) { - // Test the error case where there appears to be too few NV counters. +func (s *runChecksContextSuite) TestRunBadHostSecurityErrorMissingMSR(c *C) { + s.AddCleanup(MockRuntimeGOARCH("amd64")) + + // Test case where host security checks fail because the MSR kernel module is missing. meiAttrs := map[string][]byte{ "fw_ver": []byte(`0:16.1.27.2176 0:16.1.27.2176 @@ -3745,1210 +3899,374 @@ func (s *runChecksContextSuite) TestRunBadTPMInsufficientCounters(c *C) { "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, )), } + errs := s.testRun(c, &testRunChecksContextRunParams{ env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 0, nil), efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, + tpm2.PropertyNVCountersMax: 0, tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, actions: []actionAndArgs{{action: ActionNone}}, }) c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: insufficient NV counters available`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientTPMStorage, - nil, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel CPU debugging configuration: the kernel module "msr" must be loaded`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindInternal, nil, nil, errs[0].Unwrap())) + c.Check(errors.Is(errs[0], MissingKernelModuleError("msr")), testutil.IsTrue) } -func (s *runChecksContextSuite) TestRunBadTPMInsufficientCountersRunActionClearTPMViaFirmware(c *C) { - // Test the error case where there appears to be too few NV counters, and - // we run the ActionClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +func (s *runChecksContextSuite) TestRunBadSHA1(c *C) { + // Test the error case where there is no suitable PCR bank other + // than SHA1, but SHA1 is disallowed by default. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, + }, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA1, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: the PCR bank is missing from the TCG log. +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) } +} - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, +func (s *runChecksContextSuite) TestRunBadPCRProfileMostSecure(c *C) { + // Test the error case where the profile options are set to "most secure". + // This is currently unsupported because of a lack of source for some + // PCRs - it is intended that this will work eventually. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionMostSecure, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 3) + c.Check(errs[0], ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(1), nil, errs[0].Unwrap())) + + c.Check(errs[1], ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(3), nil, errs[1].Unwrap())) + + c.Check(errs[2], ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(5), nil, errs[2].Unwrap())) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientTPMStorage, - nil, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - - c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) -} - -func (s *runChecksContextSuite) TestRunBadTPMInsufficientCountersRunActionEnableAndClearTPMViaFirmware(c *C) { - // Test the error case where there appears to be too few NV counters, and - // we run the ActionEnableAndClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableAndClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientTPMStorage, - nil, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - - c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) -} - -func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedAndLockedOut(c *C) { - // Test case with more than one TPM error - in this case, one of the errors - // is ErrTPMLockout which is converted to a warning and suppressed unless - // RunChecks completes with success. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Trip the DA logic by triggering an auth failure with a DA protected - // resource. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) - pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) - c.Assert(err, IsNil) - key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) - c.Assert(err, IsNil) - key.SetAuthValue(nil) - _, err = s.TPM.Unseal(key, nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) - - // Take ownership of the lockout hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: -- TPM_RH_LOCKOUT has an authorization value -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunBadTCGLog(c *C) { - // Test the error case where the TCG log cannot be decoded. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: nil log`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindMeasuredBoot, nil, nil, errs[0].Unwrap())) -} - -// TODO: Test another bad case where PCR0 is mandatory but unusable, but is mandatory -// because the firmware is only protected with measured boot (this isn't supported yet, -// but it would result in the "no-suitable-pcr-bank" error kind). - -func (s *runChecksContextSuite) TestRunBadInvalidPCR2Value(c *C) { - // Test the error case where PCR2 is inconsistent with the log, but it - // has been marked as mandatory due to the usage of the Microsoft UEFI CA. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\). -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadInvalidPCR4Value(c *C) { - // Test the error case where PCR4 is inconsistent with the log, but it - // has been marked as mandatory due to the usage of the Microsoft UEFI CA. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\). -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadInvalidPCR7Value(c *C) { - // Test the error case where PCR7 is inconsistent with the log, but it - // has been marked as mandatory because the default profile options - // require it. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\). -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) -} - -// TODO: Add a test for ErrorKindUnsupportedPlatform - -func (s *runChecksContextSuite) TestRunBadUEFIDebuggingEnabled(c *C) { - // Test the error case where a UEFI debugger is enabled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - FirmwareDebugger: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware contains a debugging endpoint enabled`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindHostSecurity, nil, []Action{ActionContactOEM}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadInsufficientDMAProtection(c *C) { - // Test the error case where DMA protection is disabled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunBadNoKernelIOMMU(c *C) { - // Test the error case where the kernel doesn't enable a IOMMU - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindNoKernelIOMMU, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOSVendor}, - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunChecksBadTPMHierarchiesOwnedAndNoKernelIOMMU(c *C) { - // Test case where a TPM hierarchy is owned and there is a host security error. - // This tests the case where ActionProceed is suppressed because one of the returned - // errors doesn't permit it. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - prepare: func(_ int) { - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 2) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: -- TPM_RH_OWNER has an authorization value -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - - c.Check(errs[1], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindNoKernelIOMMU, - nil, - []Action{ActionRebootToFWSettings, ActionContactOSVendor}, - errs[1].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunBadHostSecurityErrorMissingIntelMEModule(c *C) { - // Test case where host security checks fail because the intel ME kernel module is missing. - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00:16:0", map[string]string{"PCI_CLASS": "78000", "PCI_ID": "8086:7E70"}, "pci", nil, nil), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: the kernel module "mei_me" must be loaded`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindInternal, nil, nil, errs[0].Unwrap())) - c.Check(errors.Is(errs[0], MissingKernelModuleError("mei_me")), testutil.IsTrue) -} - -func (s *runChecksContextSuite) TestRunBadHostSecurityErrorMissingMSR(c *C) { - // Test case where host security checks fail because the MSR kernel module is missing. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 0, nil), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel CPU debugging configuration: the kernel module "msr" must be loaded`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindInternal, nil, nil, errs[0].Unwrap())) - c.Check(errors.Is(errs[0], MissingKernelModuleError("msr")), testutil.IsTrue) -} - -func (s *runChecksContextSuite) TestRunBadNoHardwareRootOfTrust(c *C) { - // Test the error case where we're running on an Intel based device - // and BootGuard is mis-configured. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoHardwareRootOfTrust, nil, []Action{ActionProceed}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadSHA1(c *C) { - // Test the error case where there is no suitable PCR bank other - // than SHA1, but SHA1 is disallowed by default. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), - }, - }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, - }, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA1, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: the PCR bank is missing from the TCG log. -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadPCRProfileMostSecure(c *C) { - // Test the error case where the profile options are set to "most secure". - // This is currently unsupported because of a lack of source for some - // PCRs - it is intended that this will work eventually. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionMostSecure, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 3) - c.Check(errs[0], ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(1), nil, errs[0].Unwrap())) - - c.Check(errs[1], ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(3), nil, errs[1].Unwrap())) - - c.Check(errs[2], ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(5), nil, errs[2].Unwrap())) -} +} func (s *runChecksContextSuite) TestRunBadInvalidPCR7ValuePCRProfilePermitNoSecureBoot(c *C) { // Test the error case where PCR7 is unusable and the profile options are set // to permit policies without PCR7, but this fails due to a lack of support // for some mandatory alternative PCRs - it is intended that this case will // work in the future. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionPermitNoSecureBootPolicyProfile, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 3) - c.Check(errs[0], ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(1), nil, errs[0].Unwrap())) + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionPermitNoSecureBootPolicyProfile, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 3) + c.Check(errs[0], ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(1), nil, errs[0].Unwrap())) - c.Check(errs[1], ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(3), nil, errs[1].Unwrap())) + c.Check(errs[1], ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(3), nil, errs[1].Unwrap())) - c.Check(errs[2], ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(5), nil, errs[2].Unwrap())) + c.Check(errs[2], ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(5), nil, errs[2].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadAddonDriversPresent(c *C) { // Test the error case where value-added-retailer drivers have been detected // but the initial flags do not permit these. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + } } func (s *runChecksContextSuite) TestRunBadSysPrepAppsPresent(c *C) { // Test the error case where system preparations have been detected // but the initial flags do not permit these. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `system preparation applications were detected: + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `system preparation applications were detected: - Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 `) - imageInfo := []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - } + imageInfo := []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), + }, + } - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindSysPrepApplicationsPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &SysPrepApplicationsPresentError{ - Apps: imageInfo, - }, - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindSysPrepApplicationsPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &SysPrepApplicationsPresentError{ + Apps: imageInfo, + }, + )) + } } func (s *runChecksContextSuite) TestRunBadAbsoluteActive(c *C) { // Test the error case where Absolute has been detected but the initial // flags do not permit this. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `Absolute was detected to be active and it is advised that this is disabled`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAbsolutePresent, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + ErrAbsoluteComputraceActive, + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `Absolute was detected to be active and it is advised that this is disabled`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAbsolutePresent, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - ErrAbsoluteComputraceActive, - )) } func (s *runChecksContextSuite) TestRunBadNotAllBootManagerCodeDigestsVerified(c *C) { @@ -4957,411 +4275,333 @@ func (s *runChecksContextSuite) TestRunBadNotAllBootManagerCodeDigestsVerified(c // profile options were supplied, but where PCR4 is marked unusable because // not all of the EFI applications that were part of the current boot were // supplied when creating the RunChecksContext. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: grubDigestDefault}, }, - &mockImage{contents: []byte("mock grub executable"), digest: grubDigestDefault}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with boot manager code \(PCR4\) measurements: cannot verify correctness of EV_EFI_BOOT_SERVICES_APPLICATION event digest: not enough images supplied`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(4), []Action{ActionContactOEM}, errs[0].Unwrap())) + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with boot manager code \(PCR4\) measurements: cannot verify correctness of EV_EFI_BOOT_SERVICES_APPLICATION event digest: not enough images supplied`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(4), []Action{ActionContactOEM}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeSecureBootDisabled(c *C) { // Test the error case where PCR7 is mandatory with the supplied profile options, // but is marked invalid because secure boot is disabled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + SecureBootDisabled: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidSecureBootMode, + SecureBootModeArg{ + Enabled: false, + Mode: efi.UserMode, + }, + []Action{ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - SecureBootDisabled: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidSecureBootMode, - SecureBootModeArg{ - Enabled: false, - Mode: efi.UserMode, - }, - []Action{ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) } func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeSecureBootDisabledAndNoSBATLevel(c *C) { // Simulate running on a machine with secure boot disabled and running // shim on a system with an empty SbatLevel variable. In this case, // there are no EV_EFI_VARIABLE_AUTHORITY events which caused - // https://launchpad.net/bugs/2125439 - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - SecureBootDisabled: true, - NoSBAT: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidSecureBootMode, - SecureBootModeArg{ - Enabled: false, - Mode: efi.UserMode, - }, - []Action{ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + // https://launchpad.net/bugs/2125439 + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + SecureBootDisabled: true, + NoSBAT: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidSecureBootMode, + SecureBootModeArg{ + Enabled: false, + Mode: efi.UserMode, + }, + []Action{ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadNoSecureBootPolicySupport(c *C) { // Test the error case where PCR7 is mandatory but the secure boot checks fail // because dbx is measured twice. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}}) - var eventsCopy []*tcglog.Event - for _, ev := range log.Events { - eventsCopy = append(eventsCopy, ev) - - if ev.PCRIndex != internal_efi.SecureBootPolicyPCR { - continue - } - if ev.EventType != tcglog.EventTypeEFIVariableDriverConfig { - continue - } - data, ok := ev.Data.(*tcglog.EFIVariableData) - c.Assert(ok, testutil.IsTrue) - if data.UnicodeName == "dbx" { - // Measure dbx twice + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}}) + var eventsCopy []*tcglog.Event + for _, ev := range log.Events { eventsCopy = append(eventsCopy, ev) + + if ev.PCRIndex != internal_efi.SecureBootPolicyPCR { + continue + } + if ev.EventType != tcglog.EventTypeEFIVariableDriverConfig { + continue + } + data, ok := ev.Data.(*tcglog.EFIVariableData) + c.Assert(ok, testutil.IsTrue) + if data.UnicodeName == "dbx" { + // Measure dbx twice + eventsCopy = append(eventsCopy, ev) + } } + log.Events = eventsCopy + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(log), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: unexpected EV_EFI_VARIABLE_DRIVER_CONFIG event: all expected secure boot variable have been measured`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(7), []Action{ActionContactOEM}, errs[0].Unwrap())) } - log.Events = eventsCopy - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(log), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: unexpected EV_EFI_VARIABLE_DRIVER_CONFIG event: all expected secure boot variable have been measured`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(7), []Action{ActionContactOEM}, errs[0].Unwrap())) } func (s *runChecksContextSuite) TestRunBadWeakSecureBootAlgs(c *C) { // Test the error case where PCR7 is mandatory with the supplied profile options, // but is marked invalid because the use of weak algorithms were detected during // the current boot. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 3) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 3) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], ErrorMatches, `a weak cryptographic algorithm was detected during secure boot verification`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindWeakSecureBootAlgorithmsDetected, - nil, - []Action{ActionProceed}, - ErrWeakSecureBootAlgorithmDetected, - )) - - c.Check(errs[2], ErrorMatches, `some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest`) - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], ErrorMatches, `a weak cryptographic algorithm was detected during secure boot verification`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindWeakSecureBootAlgorithmsDetected, + nil, + []Action{ActionProceed}, + ErrWeakSecureBootAlgorithmDetected, + )) + + c.Check(errs[2], ErrorMatches, `some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest`) + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } } func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeNoDeployedMode(c *C) { // Test the error case where PCR7 is mandatory with the supplied profile options, // but is marked invalid because the system is not in deployed mode. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `secure boot is enabled but not in deployed mode`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidSecureBootMode, + SecureBootModeArg{ + Enabled: true, + Mode: efi.UserMode, + }, + []Action{ActionRebootToFWSettings, ActionProceed}, + ErrNoDeployedMode, + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `secure boot is enabled but not in deployed mode`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidSecureBootMode, - SecureBootModeArg{ - Enabled: true, - Mode: efi.UserMode, - }, - []Action{ActionRebootToFWSettings, ActionProceed}, - ErrNoDeployedMode, - )) } // TODO: This is disabled temporarily until a follow-up PR which adds warnings to the returned errors @@ -5396,7 +4636,7 @@ func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeNoDeployedMode(c // efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ // Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, // })), -// efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), +// efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), // efitest.WithSysfsDevices(devices...), // efitest.WithMockVars(efitest.MockVars{ // {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, @@ -5463,7 +4703,7 @@ func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeNoDeployedMode(c // efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ // Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, // })), -// efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), +// efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), // efitest.WithSysfsDevices(devices...), // efitest.WithMockVars(efitest.MockVars{ // {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, @@ -5510,1696 +4750,1492 @@ func (s *runChecksContextSuite) TestRunChecksBadInsufficientDMAProtectionAndNoKe // Test with a system that has insufficient DMA protection and no kernel IOMMU. // As both errors support ActionProceed, it is a valid action for // both of the returned errors. - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 2) + + c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + errs[0].Unwrap(), + )) + + c.Check(errs[1], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindNoKernelIOMMU, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOSVendor}, + errs[1].Unwrap(), + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 2) - - c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - errs[0].Unwrap(), - )) - - c.Check(errs[1], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindNoKernelIOMMU, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOSVendor}, - errs[1].Unwrap(), - )) } func (s *runChecksContextSuite) TestRunChecksActionEnableTPMViaFirmwareNotAvailable(c *C) { // Generate an error that could be fixed by ActionEnableTPMViaFirmware when // this action is not available. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + nil, + )), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunChecksActionEnableAndClearTPMViaFirmwareNotAvailable(c *C) { // Generate an error that could be fixed by ActionEnableAndClearTPMViaFirmware when // this action is not available. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionShutdownRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionShutdownRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + nil, + )), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunChecksActionClearTPMViaFirmwareNotAvailable(c *C) { // Generate an error that could be fixed by ActionClearTPMViaFirmware when this action // is not available. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the endorsement hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the endorsement hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_ENDORSEMENT has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, - []Action{ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksPPIActionWithShutdownTransition(c *C) { // Generate an error that can be resolve using a PPI action, with the // state transition action being "shutdown" rather than the more common - // "reboot". - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionShutdownRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Disable owner and endorsement hierarchies on the first iteration - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableTPMViaFirmware}, - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a shutdown is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindShutdownRequired, nil, []Action{ActionShutdown}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunChecksActionProceedUnavailable(c *C) { - // Return 2 errors where only 1 supports ActionProceed. It should - // be suppressed in this case. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + // "reboot". + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionShutdownRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Disable owner and endorsement hierarchies on the first iteration + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableTPMViaFirmware}, + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a shutdown is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindShutdownRequired, nil, []Action{ActionShutdown}, errs[0].Unwrap())) } +} - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationClearTPM: ppi.OperationPPRequired, +func (s *runChecksContextSuite) TestRunChecksActionProceedUnavailable(c *C) { + // Return 2 errors where only 1 supports ActionProceed. It should + // be suppressed in this case. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the endorsement hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 2) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the endorsement hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 2) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_ENDORSEMENT has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, - []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - - c.Check(errs[1], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionContactOEM}, - errs[1].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + c.Check(errs[1], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionContactOEM}, + errs[1].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksActionProceedErrorsOrderedAfterOtherErrors(c *C) { // Ensure that errors which support ActionProceed get reordered to be // returned after other errors. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func(_ int) { - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 2) + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func(_ int) { + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 2) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_OWNER has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - - c.Check(errs[1], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionContactOEM}, - errs[1].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + c.Check(errs[1], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionContactOEM}, + errs[1].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksActionProceedUnsupportedArgumentType(c *C) { // Test that passing an unsupported type as an argument to ActionProceed // generates an error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed, args: map[string]any{"error-kinds": 1}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 1) - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed, args: map[string]any{"error-kinds": 1}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 1) + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `cannot deserialize argument map from JSON to type preinstall.ActionProceedArgs: json: cannot unmarshal number into Go value of type \[\]preinstall.ErrorKind`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "error-kinds", - Reason: InvalidActionArgumentReasonType, - }, - nil, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `cannot deserialize argument map from JSON to type preinstall.ActionProceedArgs: json: cannot unmarshal number into Go value of type \[\]preinstall.ErrorKind`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "error-kinds", + Reason: InvalidActionArgumentReasonType, + }, + nil, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksActionProceedUnexpectedErrorKind1(c *C) { // Test that passing an unexpected ErrorKind as an argument to ActionProceed // generates an error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindPreOSSecureBootAuthByEnrolledDigests}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 1) - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindPreOSSecureBootAuthByEnrolledDigests}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 1) + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `invalid value for argument "error-kinds" at index 0: "pre-os-secure-boot-auth-by-enrolled-digests" is not expected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "error-kinds", - Reason: InvalidActionArgumentReasonValue, - }, - nil, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `invalid value for argument "error-kinds" at index 0: "pre-os-secure-boot-auth-by-enrolled-digests" is not expected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "error-kinds", + Reason: InvalidActionArgumentReasonValue, + }, + nil, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksActionProceedUnexpectedErrorKind2(c *C) { // Test that passing the same ErrorKind as an argument to ActionProceed // more than once generates an error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 3, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 2) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, - }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } - - c.Check(errs[0], ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - case 1: - c.Check(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `invalid value for argument "error-kinds" at index 0: "addon-drivers-present" is not expected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "error-kinds", - Reason: InvalidActionArgumentReasonValue, - }, - nil, - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunChecksActionProceedUnexpectedErrorKind3(c *C) { - // Test that passing any ErrorKind as an argument to ActionProceed after - // already accepting all errors generates an error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 3, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 2) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 3, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 2) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + case 1: + c.Check(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `invalid value for argument "error-kinds" at index 0: "addon-drivers-present" is not expected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "error-kinds", + Reason: InvalidActionArgumentReasonValue, + }, + nil, + errs[0].Unwrap(), + )) + } +} - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `specified action is not expected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindUnexpectedAction, - nil, - nil, - errs[0].Unwrap(), - )) +func (s *runChecksContextSuite) TestRunChecksActionProceedUnexpectedErrorKind3(c *C) { + // Test that passing any ErrorKind as an argument to ActionProceed after + // already accepting all errors generates an error. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 3, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 2) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), + }, + } + + c.Check(errs[0], ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `specified action is not expected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindUnexpectedAction, + nil, + nil, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksClearTPMNotAvailable(c *C) { // Test the case where neither ActionClearTPMSimple and ActionClearTPM are // not available because owner clear is disabled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - // Disable owner clear. - c.Assert(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + // Disable owner clear. + c.Assert(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_OWNER has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksClearTPMSimpleNotAvailable(c *C) { // Test the case where ActionClearTPMSimple is not available because the // lockout hierarchy has a non-empty authorization value. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the lockout hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the lockout hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_LOCKOUT has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleFailsInvalidAuthValue(c *C) { // Test that ActionClearTPMSimple returns an error if something sets // the authorization value for the lockout hierarchy in between // receiving the first error and submitting the action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - case 1: - // Set an authorization value for the lockout hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMSimple}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: -- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 -- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 -- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 -`, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `specified action is no longer available because the TPM's lockout hierarchy now has a non-empty auth value: use "clear-tpm" action instead`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindUnexpectedAction, - nil, nil, // args, actions - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleFailsWithError(c *C) { - // Test that ActionClearTPMSimple returns an error if clearing the - // TPM fails for some reason. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - case 1: - // Disable owner clear - c.Check(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMSimple}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + case 1: + // Set an authorization value for the lockout hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMSimple}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `cannot clear TPM: TPM returned an error whilst executing command TPM_CC_Clear: TPM_RC_DISABLED \(the command is disabled\)`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindActionFailed, - nil, nil, // args, actions - errs[0].Unwrap(), - )) -} + }) + c.Assert(errs, HasLen, 1) -func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleBecomesUnavailableAfterLockoutAuthFailure(c *C) { - // Test that ActionClearTPMSimple becomes unavailable if the lockout - // hierarchy is used with an invalid auth value. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + c.Check(errs[0], ErrorMatches, `specified action is no longer available because the TPM's lockout hierarchy now has a non-empty auth value: use "clear-tpm" action instead`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindUnexpectedAction, + nil, nil, // args, actions + errs[0].Unwrap(), + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 3, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - case 1: - // Set an authorization value for the lockout hierarchy, - // so that we can run ActionClearTPM with the wrong value. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg("5678")}, - {action: ActionClearTPMSimple}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - case 1: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "auth-value", - Reason: InvalidActionArgumentReasonValue, +} + +func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleFailsWithError(c *C) { + // Test that ActionClearTPMSimple returns an error if clearing the + // TPM fails for some reason. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - nil, // actions, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + case 1: + // Disable owner clear + c.Check(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMSimple}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `cannot clear TPM: TPM returned an error whilst executing command TPM_CC_Clear: TPM_RC_DISABLED \(the command is disabled\)`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindActionFailed, + nil, nil, // args, actions + errs[0].Unwrap(), + )) + } +} + +func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleBecomesUnavailableAfterLockoutAuthFailure(c *C) { + // Test that ActionClearTPMSimple becomes unavailable if the lockout + // hierarchy is used with an invalid auth value. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 3, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + case 1: + // Set an authorization value for the lockout hierarchy, + // so that we can run ActionClearTPM with the wrong value. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg("5678")}, + {action: ActionClearTPMSimple}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + case 1: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "auth-value", + Reason: InvalidActionArgumentReasonValue, + }, + nil, // actions, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: +- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 +- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 +- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 +`, + }) + c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `specified action is no longer available`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindUnexpectedAction, - nil, nil, // args, actions - errs[0].Unwrap(), - )) + c.Check(errs[0], ErrorMatches, `specified action is no longer available`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindUnexpectedAction, + nil, nil, // args, actions + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMInvalidAuthValueArgumentType(c *C) { // Test that ActionClearTPM returns an error if the supplied lockout // hierarchy authorization value argument is the wrong type. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: map[string]any{"auth-value": 1}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: map[string]any{"auth-value": 1}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `cannot deserialize argument map from JSON to type preinstall.TPMAuthValueArg: json: cannot unmarshal number into Go value of type \[\]uint8`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "auth-value", - Reason: InvalidActionArgumentReasonType, - }, - nil, // actions - errs[0].Unwrap(), - )) + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `cannot deserialize argument map from JSON to type preinstall.TPMAuthValueArg: json: cannot unmarshal number into Go value of type \[\]uint8`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "auth-value", + Reason: InvalidActionArgumentReasonType, + }, + nil, // actions + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMInvalidAuthValue(c *C) { // Test that ActionClearTPM returns an error if the supplied lockout // hierarchy authorization value is inconsistent with the value of // the lockoutAuthSet attribute. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg("1234")}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg("1234")}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `supplied TPM lockout hierarchy authorization value is inconsistent with the value of the TPM_PT_PERMANENT lockoutAuthSet attribute`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "auth-value", - Reason: InvalidActionArgumentReasonValue, - }, - nil, // actions - errs[0].Unwrap(), - )) + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `supplied TPM lockout hierarchy authorization value is inconsistent with the value of the TPM_PT_PERMANENT lockoutAuthSet attribute`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "auth-value", + Reason: InvalidActionArgumentReasonValue, + }, + nil, // actions + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMFailsWithError(c *C) { // Test that ActionClearTPM returns an error if clearing the // TPM fails for some reason. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - case 1: - // Disable owner clear - c.Check(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg(nil)}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + case 1: + // Disable owner clear + c.Check(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg(nil)}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) + }) + c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `cannot clear TPM: TPM returned an error whilst executing command TPM_CC_Clear: TPM_RC_DISABLED \(the command is disabled\)`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindActionFailed, - nil, nil, // args, actions - errs[0].Unwrap(), - )) + c.Check(errs[0], ErrorMatches, `cannot clear TPM: TPM returned an error whilst executing command TPM_CC_Clear: TPM_RC_DISABLED \(the command is disabled\)`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindActionFailed, + nil, nil, // args, actions + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMBecomesUnavailableAfterLockoutAuthFailure(c *C) { // Test that ActionClearTPM becomes unavailable if the lockout // hierarchy is used with an invalid auth value. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 3, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the lockout hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg("5678")}, - {action: ActionClearTPM}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - case 1: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "auth-value", - Reason: InvalidActionArgumentReasonValue, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - nil, // actions, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 3, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the lockout hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg("5678")}, + {action: ActionClearTPM}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + case 1: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "auth-value", + Reason: InvalidActionArgumentReasonValue, + }, + nil, // actions, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) + }) + c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `specified action is no longer available`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindUnexpectedAction, - nil, nil, // args, actions - errs[0].Unwrap(), - )) + c.Check(errs[0], ErrorMatches, `specified action is no longer available`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindUnexpectedAction, + nil, nil, // args, actions + errs[0].Unwrap(), + )) + } } type insertActionProceedTestSuite struct{} diff --git a/efi/preinstall/checks_fixture_test.go b/efi/preinstall/checks_fixture_test.go new file mode 100644 index 00000000..cb5c9694 --- /dev/null +++ b/efi/preinstall/checks_fixture_test.go @@ -0,0 +1,196 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2026 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package preinstall_test + +import ( + . "github.com/snapcore/secboot/efi/preinstall" + internal_efi "github.com/snapcore/secboot/internal/efi" + "github.com/snapcore/secboot/internal/efitest" + . "gopkg.in/check.v1" +) + +type runChecksHostCapabilities uint32 + +const ( + runChecksHostCapabilityValid runChecksHostCapabilities = 1 << iota + + // Platform/runtime topology. + runChecksHostCapabilityVirtualMachine + runChecksHostCapabilityNotVirtualMachine + runChecksHostCapabilityNoKernelIOMMU + runChecksHostCapabilityFirmwareTPM + runChecksHostCapabilityDiscreteTPM + + // Hardware security properties. + runChecksHostCapabilityInsufficientHWRootOfTrust + + // Discrete-TPM locality properties. + runChecksHostCapabilityStartupLocality0AccessibleFromOS + runChecksHostCapabilityStartupLocality3InaccessibleFromOS + runChecksHostCapabilityStartupLocality3AccessibleFromOS + runChecksHostCapabilityStartupLocality4InaccessibleFromOS + runChecksHostCapabilityStartupLocality4AccessibleFromOS +) + +// Platform identity capabilities do not imply security properties. In +// particular, HasIntelBootGuard does not imply that any TPM startup locality is +// inaccessible from the OS; fixtures must declare locality properties +// separately. + +// runChecksHostFixture abstracts host-specific details from scenario logic in +// the shared RunChecks and RunChecksContext tests. +type runChecksHostFixture struct { + name string + capabilities runChecksHostCapabilities + environment efitest.MockHostEnvironmentOption + virtualizationMode string + virtualizationDetection internal_efi.DetectVirtMode + sysfsDevices []internal_efi.SysfsDevice + + // arch is the GOARCH that this fixture emulates; host security checks dispatch on it at runtime. + arch string + + // additionalExpectedFlags allows a host fixture to inject fixture-specific + // CheckResultFlags to the expected value. For example, platforms that validate + // platformFirmwareIntegrity via measured boot instead of reading a fused key will + // report RequireLockToPlatformFirmware, which needs to be OR'd against the + // test-specific expected flags. + additionalExpectedFlags CheckResultFlags +} + +func runChecksHostFixturesFor(c *C, required runChecksHostCapabilities) []runChecksHostFixture { + var matches []runChecksHostFixture + for _, fixture := range runChecksPlatformHostFixtures() { + if fixture.capabilities&required == required { + matches = append(matches, fixture) + } + } + if len(matches) == 0 { + c.Skip("no platform fixture provides the required host capabilities") + } + return matches +} + +func (f *runChecksHostFixture) newEnvironment(options ...efitest.MockHostEnvironmentOption) internal_efi.HostEnvironment { + base := []efitest.MockHostEnvironmentOption{ + f.environment, + efitest.WithVirtMode(f.virtualizationMode, f.virtualizationDetection), + } + devices := append([]internal_efi.SysfsDevice(nil), f.sysfsDevices...) + base = append(base, efitest.WithSysfsDevices(devices...)) + return efitest.NewMockHostEnvironmentWithOpts(append(base, options...)...) +} + +func (f *runChecksHostFixture) mockRuntimeGOARCH(s interface{ AddCleanup(func()) }) { + s.AddCleanup(MockRuntimeGOARCH(f.arch)) +} +func runChecksPlatformHostFixtures() []runChecksHostFixture { + intelDevices := func(status []byte, withIOMMU bool) []internal_efi.SysfsDevice { + attrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": status, + } + var devices []internal_efi.SysfsDevice + if withIOMMU { + devices = append(devices, + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + ) + } + return append(devices, efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", attrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + ))) + } + + return []runChecksHostFixture{ + // amd64 fixtures + { + name: "intel-ptt", + capabilities: runChecksHostCapabilityValid | + runChecksHostCapabilityNotVirtualMachine | + runChecksHostCapabilityFirmwareTPM, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusBase, true), + arch: "amd64", + }, + { + name: "intel-dtpm-smx", + capabilities: runChecksHostCapabilityValid | + runChecksHostCapabilityNotVirtualMachine | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality0AccessibleFromOS | + runChecksHostCapabilityStartupLocality3InaccessibleFromOS | + runChecksHostCapabilityStartupLocality4InaccessibleFromOS, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusBase, true), + arch: "amd64", + }, + { + name: "intel-dtpm-no-smx", + capabilities: runChecksHostCapabilityValid | + runChecksHostCapabilityNotVirtualMachine | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality0AccessibleFromOS | + runChecksHostCapabilityStartupLocality3AccessibleFromOS | + runChecksHostCapabilityStartupLocality4AccessibleFromOS, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusBase, true), + arch: "amd64", + }, + { + name: "intel-ptt-no-kernel-iommu", + capabilities: runChecksHostCapabilityNotVirtualMachine | runChecksHostCapabilityNoKernelIOMMU | runChecksHostCapabilityFirmwareTPM, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusBase, false), + arch: "amd64", + }, + { + name: "intel-mfg-mode", + capabilities: runChecksHostCapabilityNotVirtualMachine | runChecksHostCapabilityInsufficientHWRootOfTrust, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusManufacturingMode, true), + arch: "amd64", + }, + // RunChecks skips host security checks inside a VM, so the emulated + // architecture is irrelevant here; we keep exactly one virtual-machine + // fixture rather than duplicating it per-arch. + { + name: "virtual-machine", + capabilities: runChecksHostCapabilityVirtualMachine, + environment: func(*efitest.MockHostEnvironment) {}, + virtualizationMode: "qemu", + virtualizationDetection: internal_efi.DetectVirtModeVM, + arch: "amd64", + }, + } +} diff --git a/efi/preinstall/checks_test.go b/efi/preinstall/checks_test.go index 834f14f9..088a427d 100644 --- a/efi/preinstall/checks_test.go +++ b/efi/preinstall/checks_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -26,7 +26,6 @@ import ( "errors" "io" - "github.com/canonical/cpuid" efi "github.com/canonical/go-efilib" "github.com/canonical/go-tpm2" "github.com/canonical/go-tpm2/objectutil" @@ -73,6 +72,7 @@ type testRunChecksParams struct { } func (s *runChecksSuite) testRunChecks(c *C, params *testRunChecksParams) (warnings []error, err error) { + s.ResetAndClearTPMSimulatorUsingPlatformHierarchy(c) s.allocatePCRBanks(c, params.enabledBanks...) log, err := params.env.ReadEventLog() c.Assert(err, IsNil) @@ -131,3332 +131,2445 @@ func (s *runChecksSuite) testRunChecks(c *C, params *testRunChecksParams) (warni } func (s *runChecksSuite) TestRunChecksGood(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodSHA384(c *C) { - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "030ac3c913dab858f1d69239115545035cff671d6229f95577bb0ffbd827b35abaf6af6bfd223e04ecc9b60a9803642d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), +func (s *runChecksSuite) TestRunChecksGoodSHA384(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "030ac3c913dab858f1d69239115545035cff671d6229f95577bb0ffbd827b35abaf6af6bfd223e04ecc9b60a9803642d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "6c2df9007211786438be210b6908f2935d0b25ebdcd2c65621826fd2ec55fb9fbacbfe080d48db98f0ef970273b8254a")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "42f61b3089f5ce0646b422a59c9632065db2630f3e5b01690e63c41420ed31f10ff2a191f3440f9501109fc85f7fb00f")}, }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "6c2df9007211786438be210b6908f2935d0b25ebdcd2c65621826fd2ec55fb9fbacbfe080d48db98f0ef970273b8254a")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "42f61b3089f5ce0646b422a59c9632065db2630f3e5b01690e63c41420ed31f10ff2a191f3440f9501109fc85f7fb00f")}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA384, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + expectedPcrAlg: tpm2.HashAlgorithmSHA384, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) -func (s *runChecksSuite) TestRunChecksGoodSHA1(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitWeakPCRBanks, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), +func (s *runChecksSuite) TestRunChecksGoodSHA1(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitWeakPCRBanks, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA1, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + expectedPcrAlg: tpm2.HashAlgorithmSHA1, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodEmptySHA384(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `the PCR bank for TPM_ALG_SHA384 is missing from the TCG log but active and with one or more empty PCRs on the TPM`) + var epbe *EmptyPCRBanksError + c.Check(errors.As(warning, &epbe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `the PCR bank for TPM_ALG_SHA384 is missing from the TCG log but active and with one or more empty PCRs on the TPM`) - var epbe *EmptyPCRBanksError - c.Check(errors.As(warning, &epbe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) } func (s *runChecksSuite) TestRunChecksGoodPostInstall(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PostInstallChecks, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PostInstallChecks, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodVirtualMachine(c *C) { - family, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyFamilyIndicator) - c.Assert(err, IsNil) - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: family, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerMSFT), - tpm2.PropertyHRPersistentMin: 7, // The simulator seems to set this to 2 - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitVirtualMachine, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + family, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyFamilyIndicator) + c.Assert(err, IsNil) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: family, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerMSFT), + tpm2.PropertyHRPersistentMin: 7, // The simulator seems to set this to 2 + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitVirtualMachine, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warning := warnings[0] - c.Check(warning, Equals, ErrVirtualMachineDetected) + warning := warnings[0] + c.Check(warning, Equals, ErrVirtualMachineDetected) - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetected(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality0AccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) + var hse *HostSecurityError + c.Assert(errors.As(warning, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) - var hse *HostSecurityError - c.Assert(errors.As(warning, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetectedSL3(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality3InaccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetectedSL3NotProtected(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality3AccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) + var hse *HostSecurityError + c.Assert(errors.As(warning, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) - var hse *HostSecurityError - c.Assert(errors.As(warning, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetectedHCRTM(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality4InaccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 4, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 4, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetectedHCRTMLocality4NotProtected(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality4AccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 4, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) + var hse *HostSecurityError + c.Assert(errors.As(warning, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 4, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) - var hse *HostSecurityError - c.Assert(errors.As(warning, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) } func (s *runChecksSuite) TestRunChecksGoodInvalidPCR0Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformFirmwareProfileSupport | PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformFirmwareProfileSupport | PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\)`) - var pfe *PlatformFirmwarePCRError - c.Check(errors.As(warning, &pfe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\)`) + var pfe *PlatformFirmwarePCRError + c.Check(errors.As(warning, &pfe), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodInvalidPCR0ValueWithDiscreteTPM(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformFirmwareProfileSupport | PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\)`) - var pfe *PlatformFirmwarePCRError - c.Check(errors.As(warning, &pfe), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } +} - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) - var hse *HostSecurityError - c.Assert(errors.As(warning, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) +func (s *runChecksSuite) TestRunChecksGoodInvalidPCR0ValueWithDiscreteTPM(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformFirmwareProfileSupport | PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\)`) + var pfe *PlatformFirmwarePCRError + c.Check(errors.As(warning, &pfe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) + var hse *HostSecurityError + c.Assert(errors.As(warning, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } // TODO: Good test case for invalid PCR1 when we support it. func (s *runChecksSuite) TestRunChecksGoodInvalidPCR2Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\)`) - var de *DriversAndAppsPCRError - c.Check(errors.As(warning, &de), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\)`) + var de *DriversAndAppsPCRError + c.Check(errors.As(warning, &de), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } // TODO: Good test case for invalid PCR3 when we support it. func (s *runChecksSuite) TestRunChecksGoodInvalidPCR4Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\)`) - var bme *BootManagerCodePCRError - c.Check(errors.As(warning, &bme), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\)`) + var bme *BootManagerCodePCRError + c.Check(errors.As(warning, &bme), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } // TODO: Good test case for invalid PCR5 when we support it. func (s *runChecksSuite) TestRunChecksGoodInvalidPCR7Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport | fixture.additionalExpectedFlags, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\)`) - var sbe *SecureBootPolicyPCRError - c.Check(errors.As(warning, &sbe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\)`) + var sbe *SecureBootPolicyPCRError + c.Check(errors.As(warning, &sbe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodAddonDriversPresent(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +`) + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), + }, + }) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: +func (s *runChecksSuite) TestRunChecksGoodVARDriversPresentWithInvalidPCR2Value(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0x33da7dc7c748c1767c14a1328487ad2f1a058cda30956405bc9ccf02a75bcfb9, reconstructed from log 0x6a16b79136a20b5fa1d3d3812165fddf6e2a4d9c5a682e15f26c6e4fbc8f4d04\)`) + var de *DriversAndAppsPCRError + c.Check(errors.As(warning, &de), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) + }) - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodVARDriversPresentWithInvalidPCR2Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0x33da7dc7c748c1767c14a1328487ad2f1a058cda30956405bc9ccf02a75bcfb9, reconstructed from log 0x6a16b79136a20b5fa1d3d3812165fddf6e2a4d9c5a682e15f26c6e4fbc8f4d04\)`) - var de *DriversAndAppsPCRError - c.Check(errors.As(warning, &de), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +func (s *runChecksSuite) TestRunChecksGoodSysPrepAppsPresent(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSysPrepApplications, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `system preparation applications were detected: +- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 `) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + var spape *SysPrepApplicationsPresentError + c.Check(errors.As(warning, &spape), testutil.IsTrue) + c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + }) -func (s *runChecksSuite) TestRunChecksGoodSysPrepAppsPresent(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSysPrepApplications, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `system preparation applications were detected: +func (s *runChecksSuite) TestRunChecksGoodSysPrepAppsPresentWithInvalidPCR4Value(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSysPrepApplications, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoBootManagerCodeProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0xe17df8a36f5af4ae49c1ca567f6194bb06269c81339d87be07a3b3993edc6773, reconstructed from log 0x37704821d1e3005e2b31a7011ae80beec847c639699ed234bcaf9e0dd2fe47fe\)`) + var bme *BootManagerCodePCRError + c.Check(errors.As(warning, &bme), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `system preparation applications were detected: - Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 `) - var spape *SysPrepApplicationsPresentError - c.Check(errors.As(warning, &spape), testutil.IsTrue) - c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + var spape *SysPrepApplicationsPresentError + c.Check(errors.As(warning, &spape), testutil.IsTrue) + c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - }) + }) - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksGoodSysPrepAppsPresentWithInvalidPCR4Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } +func (s *runChecksSuite) TestRunChecksGoodAbsoluteActive(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAbsoluteComputrace, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSysPrepApplications, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoBootManagerCodeProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0xe17df8a36f5af4ae49c1ca567f6194bb06269c81339d87be07a3b3993edc6773, reconstructed from log 0x37704821d1e3005e2b31a7011ae80beec847c639699ed234bcaf9e0dd2fe47fe\)`) - var bme *BootManagerCodePCRError - c.Check(errors.As(warning, &bme), testutil.IsTrue) + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) + warning = warnings[2] + c.Check(warning, Equals, ErrAbsoluteComputraceActive) - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } +} - warning = warnings[3] - c.Check(warning, ErrorMatches, `system preparation applications were detected: -- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 -`) - var spape *SysPrepApplicationsPresentError - c.Check(errors.As(warning, &spape), testutil.IsTrue) - c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), +func (s *runChecksSuite) TestRunChecksGoodAbsoluteActiveWithInvalidPCR4Value(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - }) + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAbsoluteComputrace, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x7b023f4133ed7e29f9445fa186592378dbaac21c2a9737f37e170b3062e174cb, reconstructed from log 0xf9464e8dcd68eddcaa704e885ba08a129bc4d0178f7f88593c68be8a27bc5f01\)`) + var bme *BootManagerCodePCRError + c.Check(errors.As(warning, &bme), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodAbsoluteActive(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAbsoluteComputrace, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, Equals, ErrAbsoluteComputraceActive) - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } +} - warning = warnings[2] - c.Check(warning, Equals, ErrAbsoluteComputraceActive) +func (s *runChecksSuite) TestRunChecksGoodNoBootManagerCodeProfileSupport(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test + // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in + // the log so the test thinks that the log contains the flat file digest. + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodAbsoluteActiveWithInvalidPCR4Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAbsoluteComputrace, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x7b023f4133ed7e29f9445fa186592378dbaac21c2a9737f37e170b3062e174cb, reconstructed from log 0xf9464e8dcd68eddcaa704e885ba08a129bc4d0178f7f88593c68be8a27bc5f01\)`) - var bme *BootManagerCodePCRError - c.Check(errors.As(warning, &bme), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, Equals, ErrAbsoluteComputraceActive) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and\/or the PE_COFF_IMAGE flag`) + var bme *BootManagerCodePCRError + c.Check(errors.As(warning, &bme), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodNoBootManagerCodeProfileSupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), +func (s *runChecksSuite) TestRunChecksGoodPreOSSecureBootAuthByEnrolledDigests(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +`) + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test - // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in - // the log so the test thinks that the log contains the flat file digest. - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and\/or the PE_COFF_IMAGE flag`) - var bme *BootManagerCodePCRError - c.Check(errors.As(warning, &bme), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + }) -func (s *runChecksSuite) TestRunChecksGoodPreOSSecureBootAuthByEnrolledDigests(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 -`) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, - }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) - warning = warnings[4] - c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) + warning = warnings[4] + c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) + } } func (s *runChecksSuite) TestRunChecksGoodPreOSSecureBootAuthByEnrolledDigestsWithInvalidPCR7Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport | PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 6) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0x41cc3a26db1bf43609d3fb0b15b1e87a3f68822a6770ab1b912e1b07e6e49952, reconstructed from log 0x3cb6f84240068b76a933839a170565fdf5de48ff7d6ef361b6474a41e2cd60af\)`) - var sbe *SecureBootPolicyPCRError - c.Check(errors.As(warning, &sbe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 -`) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[5] - c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) -} - -func (s *runChecksSuite) TestRunChecksGoodWeakSecureBootAlgs(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 6) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 -`) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, Equals, ErrWeakSecureBootAlgorithmDetected) - - warning = warnings[5] - c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) -} - -func (s *runChecksSuite) TestRunChecksGoodWeakSecureBootAlgsWithInvalidPCR7Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport | PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 7) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0x97fe6e8a33309869583ba98ecc25b5c528270db96e41dfdd75ebf20eb7562441, reconstructed from log 0x5e99922ef40f9e7e64ca71f1128423e8400c9e5fe60cfbad3d905bb91b9e8949\)`) - var sbe *SecureBootPolicyPCRError - c.Check(errors.As(warning, &sbe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport | PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 6) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0x41cc3a26db1bf43609d3fb0b15b1e87a3f68822a6770ab1b912e1b07e6e49952, reconstructed from log 0x3cb6f84240068b76a933839a170565fdf5de48ff7d6ef361b6474a41e2cd60af\)`) + var sbe *SecureBootPolicyPCRError + c.Check(errors.As(warning, &sbe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[5] - c.Check(warning, Equals, ErrWeakSecureBootAlgorithmDetected) - - warning = warnings[6] - c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) -} - -func (s *runChecksSuite) TestRunChecksGoodNoSecureBootPolicyProfileSupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) - var sbpe *SecureBootPolicyPCRError - c.Assert(errors.As(warning, &sbpe), testutil.IsTrue) - c.Check(errors.Is(sbpe, ErrNoSecureBoot), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksGoodNoSecureBootDeployedMode(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSecureBootUserMode, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `secure boot is enabled but not in deployed mode`) - c.Check(errors.Is(warning, ErrNoDeployedMode), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksGoodTPMLockout(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - // Trip the DA logic by setting newMaxTries to 0. This also prevents - // the lockout hierarchy availability test from clearing the lockout, - // although that test does still run. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 0, 10000, 10000, nil), IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with TPM2 device: TPM is in DA lockout mode`) - var tde *TPM2DeviceError - c.Assert(errors.As(warning, &tde), testutil.IsTrue) - c.Check(errors.Is(tde, ErrTPMLockout), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksGoodPostInstallLockoutAvailabilityCheckSkipped(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - // Take ownership of the lockout hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PostInstallChecks, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set`) - c.Check(errors.Is(warning, ErrTPMLockoutAvailabilityNotChecked), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadVirtualMachine(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - }) - c.Check(err, Equals, ErrVirtualMachineDetected) -} - -func (s *runChecksSuite) TestRunChecksBadNotEFI(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - }) - c.Check(err, Equals, ErrSystemNotEFI) -} - -func (s *runChecksSuite) TestRunChecksBadTPM2DeviceDisabled(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - }, - }) - c.Check(err, ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) - c.Check(errors.Is(err, ErrTPMDisabled), testutil.IsTrue) - var te *TPM2DeviceError - c.Check(errors.As(err, &te), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadTPMOwnedHierarchiesAndLockedOut(c *C) { - // Test case with more than one TPM error - in this case, one of the errors - // is ErrTPMLockout which is converted to a warning and suppressed unless - // RunChecks completes with success. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - // Trip the DA logic by triggering an auth failure with a DA protected - // resource. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) - pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) - c.Assert(err, IsNil) - key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) - c.Assert(err, IsNil) - key.SetAuthValue(nil) - _, err = s.TPM.Unseal(key, nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) - - // Take ownership of the lockout hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, - }) - c.Check(err, ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: -- TPM_RH_LOCKOUT has an authorization value -`) - - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) - - var te *TPM2DeviceError - c.Assert(errors.As(errs[0], &te), testutil.IsTrue) - var ohe *TPM2OwnedHierarchiesError - c.Check(errors.As(te, &ohe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadInvalidPCR0Value(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{}, 1, map[uint32]uint64{0x13a: (3 << 1)}), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\). -`) - var te *MeasuredBootError - c.Assert(errors.As(err, &te), testutil.IsTrue) - var pe *NoSuitablePCRAlgorithmError - c.Check(errors.As(te, &pe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadInvalidPCR2Value(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{}, 1, map[uint32]uint64{0x13a: (3 << 1)}), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\). -`) - var te *MeasuredBootError - c.Assert(errors.As(err, &te), testutil.IsTrue) - var pe *NoSuitablePCRAlgorithmError - c.Check(errors.As(te, &pe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadInvalidPCR4Value(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{}, 1, map[uint32]uint64{0x13a: (3 << 1)}), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\). -`) - var te *MeasuredBootError - c.Assert(errors.As(err, &te), testutil.IsTrue) - var pe *NoSuitablePCRAlgorithmError - c.Check(errors.As(te, &pe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadInvalidPCR7Value(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{}, 1, map[uint32]uint64{0x13a: (3 << 1)}), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\). -`) - var te *MeasuredBootError - c.Assert(errors.As(err, &te), testutil.IsTrue) - var pe *NoSuitablePCRAlgorithmError - c.Check(errors.As(te, &pe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadNoHardwareRootOfTrustError(c *C) { - // Test case with no hardware root-of-trust configured. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - - c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) - - // Check that there is a NoHardwareRootOfTrustError wrapped in a HostSecurityError - // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. - var hse *HostSecurityError - var cErr CompoundError - c.Check(errors.As(err, &cErr), testutil.IsTrue) - foundHse := false - for _, e := range cErr.Unwrap() { - if errors.As(e, &hse) { - foundHse = true - } - } - c.Check(foundHse, testutil.IsTrue) - var rote *NoHardwareRootOfTrustError - c.Check(errors.As(hse, &rote), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadHostSecurityMissingIntelMEModule(c *C) { - // Test case where host security checks fail because the intel ME kernel module is missing. - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0", map[string]string{"PCI_CLASS": "78000", "PCI_ID": "8086:7E70"}, "pci", nil, nil), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: the kernel module "mei_me" must be loaded`) - var hse *HostSecurityError - c.Assert(errors.As(err, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, MissingKernelModuleError("mei_me")), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadHostSecurityMissingMSR(c *C) { - // Test case where host security checks fail because the MSR kernel module is missing. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 0, nil), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel CPU debugging configuration: the kernel module "msr" must be loaded`) - var hse *HostSecurityError - c.Assert(errors.As(err, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, MissingKernelModuleError("msr")), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadUEFIDebuggingEnabledAndNoKernelIOMMU(c *C) { - // Test case with more than one host security error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + }) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + + warning = warnings[5] + c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - FirmwareDebugger: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, - }) - c.Check(err, ErrorMatches, `2 errors detected: -- error with system security: the platform firmware contains a debugging endpoint enabled -- error with system security: no kernel IOMMU support was detected +func (s *runChecksSuite) TestRunChecksGoodWeakSecureBootAlgs(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 6) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), + }, + }) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 2) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - var hse *HostSecurityError - c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrUEFIDebuggingEnabled), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) - c.Assert(errors.As(errs[1], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoKernelIOMMU), testutil.IsTrue) -} + warning = warnings[4] + c.Check(warning, Equals, ErrWeakSecureBootAlgorithmDetected) -func (s *runChecksSuite) TestRunChecksBadSHA1(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[5] + c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), - }, +func (s *runChecksSuite) TestRunChecksGoodWeakSecureBootAlgsWithInvalidPCR7Value(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, - }, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: the PCR bank is missing from the TCG log. + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport | PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 7) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0x97fe6e8a33309869583ba98ecc25b5c528270db96e41dfdd75ebf20eb7562441, reconstructed from log 0x5e99922ef40f9e7e64ca71f1128423e8400c9e5fe60cfbad3d905bb91b9e8949\)`) + var sbe *SecureBootPolicyPCRError + c.Check(errors.As(warning, &sbe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), + }, + }) - var e *NoSuitablePCRAlgorithmError - c.Assert(errors.As(err, &e), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - // Test that we can access individual errors. - c.Check(e.Errs[tpm2.HashAlgorithmSHA512], DeepEquals, []error{ErrPCRBankMissingFromLog}) - c.Check(e.Errs[tpm2.HashAlgorithmSHA384], DeepEquals, []error{ErrPCRBankMissingFromLog}) - c.Check(e.Errs[tpm2.HashAlgorithmSHA256], DeepEquals, []error{ErrPCRBankMissingFromLog}) -} + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksBadMandatoryPCR1(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, + warning = warnings[5] + c.Check(warning, Equals, ErrWeakSecureBootAlgorithmDetected) + + warning = warnings[6] + c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksGoodNoSecureBootPolicyProfileSupport(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + var sbpe *SecureBootPolicyPCRError + c.Assert(errors.As(warning, &sbpe), testutil.IsTrue) + c.Check(errors.Is(sbpe, ErrNoSecureBoot), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) +func (s *runChecksSuite) TestRunChecksGoodNoSecureBootDeployedMode(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSecureBootUserMode, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - var pce *PlatformConfigPCRError - c.Check(errors.As(errs[0], &pce), testutil.IsTrue) -} + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksBadMandatoryPCR3(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `secure boot is enabled but not in deployed mode`) + c.Check(errors.Is(warning, ErrNoDeployedMode), testutil.IsTrue) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksGoodTPMLockout(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + // Trip the DA logic by setting newMaxTries to 0. This also prevents + // the lockout hierarchy availability test from clearing the lockout, + // although that test does still run. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 0, 10000, 10000, nil), IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with TPM2 device: TPM is in DA lockout mode`) + var tde *TPM2DeviceError + c.Assert(errors.As(warning, &tde), testutil.IsTrue) + c.Check(errors.Is(tde, ErrTPMLockout), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) +func (s *runChecksSuite) TestRunChecksGoodPostInstallLockoutAvailabilityCheckSkipped(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + // Take ownership of the lockout hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PostInstallChecks, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + warning := warnings[0] + c.Check(warning, ErrorMatches, `availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set`) + c.Check(errors.Is(warning, ErrTPMLockoutAvailabilityNotChecked), testutil.IsTrue) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(errs[0], &dce), testutil.IsTrue) + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadMandatoryPCR5(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksSuite) TestRunChecksBadVirtualMachine(c *C) { + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + }) + c.Check(err, Equals, ErrVirtualMachineDetected) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksBadNotEFI(c *C) { + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + }) + c.Check(err, Equals, ErrSystemNotEFI) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) +func (s *runChecksSuite) TestRunChecksBadTPM2DeviceDisabled(c *C) { + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + }, + }) + c.Check(err, ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) + c.Check(errors.Is(err, ErrTPMDisabled), testutil.IsTrue) + var te *TPM2DeviceError + c.Check(errors.As(err, &te), testutil.IsTrue) + } +} - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) +func (s *runChecksSuite) TestRunChecksBadTPMOwnedHierarchiesAndLockedOut(c *C) { + // Test case with more than one TPM error - in this case, one of the errors + // is ErrTPMLockout which is converted to a warning and suppressed unless + // RunChecks completes with success. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + // Trip the DA logic by triggering an auth failure with a DA protected + // resource. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) + pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) + c.Assert(err, IsNil) + key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) + c.Assert(err, IsNil) + key.SetAuthValue(nil) + _, err = s.TPM.Unseal(key, nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) + + // Take ownership of the lockout hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, + }) + c.Check(err, ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: +- TPM_RH_LOCKOUT has an authorization value +`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(errs[0], &bmce), testutil.IsTrue) -} + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) -func (s *runChecksSuite) TestRunChecksBadAddonDriversPresent(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + var te *TPM2DeviceError + c.Assert(errors.As(errs[0], &te), testutil.IsTrue) + var ohe *TPM2OwnedHierarchiesError + c.Check(errors.As(te, &ohe), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +func (s *runChecksSuite) TestRunChecksBadInvalidPCR0Value(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\). `) + var te *MeasuredBootError + c.Assert(errors.As(err, &te), testutil.IsTrue) + var pe *NoSuitablePCRAlgorithmError + c.Check(errors.As(te, &pe), testutil.IsTrue) + } +} - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) - - var adpe *AddonDriversPresentError - c.Check(errors.As(errs[0], &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, +func (s *runChecksSuite) TestRunChecksBadInvalidPCR2Value(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\). +`) + var te *MeasuredBootError + c.Assert(errors.As(err, &te), testutil.IsTrue) + var pe *NoSuitablePCRAlgorithmError + c.Check(errors.As(te, &pe), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadSysPrepAppsPresent(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +func (s *runChecksSuite) TestRunChecksBadInvalidPCR4Value(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\). +`) + var te *MeasuredBootError + c.Assert(errors.As(err, &te), testutil.IsTrue) + var pe *NoSuitablePCRAlgorithmError + c.Check(errors.As(te, &pe), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `system preparation applications were detected: -- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 +func (s *runChecksSuite) TestRunChecksBadInvalidPCR7Value(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\). `) + var te *MeasuredBootError + c.Assert(errors.As(err, &te), testutil.IsTrue) + var pe *NoSuitablePCRAlgorithmError + c.Check(errors.As(te, &pe), testutil.IsTrue) + } +} - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) - - var spape *SysPrepApplicationsPresentError - c.Check(errors.As(errs[0], &spape), testutil.IsTrue) - c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), +func (s *runChecksSuite) TestRunChecksBadNoHardwareRootOfTrustError(c *C) { + // Test case with no hardware root-of-trust configured. + required := runChecksHostCapabilityInsufficientHWRootOfTrust + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - }) + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + + c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) + + // Check that there is a NoHardwareRootOfTrustError wrapped in a HostSecurityError + // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. + var hse *HostSecurityError + var cErr CompoundError + c.Check(errors.As(err, &cErr), testutil.IsTrue) + foundHse := false + for _, e := range cErr.Unwrap() { + if errors.As(e, &hse) { + foundHse = true + } + } + c.Check(foundHse, testutil.IsTrue) + var rote *NoHardwareRootOfTrustError + c.Check(errors.As(hse, &rote), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadAbsoluteActive(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } +func (s *runChecksSuite) TestRunChecksBadHostSecurityMissingIntelMEModule(c *C) { + s.AddCleanup(MockRuntimeGOARCH("amd64")) + + // Test case where host security checks fail because the intel ME kernel module is missing. devices := []internal_efi.SysfsDevice{ efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0", map[string]string{"PCI_CLASS": "78000", "PCI_ID": "8086:7E70"}, "pci", nil, nil), } _, err := s.testRunChecks(c, &testRunChecksParams{ env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ tpm2.PropertyNVCountersMax: 0, tpm2.PropertyPSFamilyIndicator: 1, tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, }) - c.Check(err, ErrorMatches, `Absolute was detected to be active and it is advised that this is disabled`) - - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) - - c.Check(errors.Is(errs[0], ErrAbsoluteComputraceActive), testutil.IsTrue) + c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: the kernel module "mei_me" must be loaded`) + var hse *HostSecurityError + c.Assert(errors.As(err, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, MissingKernelModuleError("mei_me")), testutil.IsTrue) } -func (s *runChecksSuite) TestRunChecksBadWeakSecureBootAlgs(c *C) { +func (s *runChecksSuite) TestRunChecksBadHostSecurityMissingMSR(c *C) { + s.AddCleanup(MockRuntimeGOARCH("amd64")) + + // Test case where host security checks fail because the MSR kernel module is missing. meiAttrs := map[string][]byte{ "fw_ver": []byte(`0:16.1.27.2176 0:16.1.27.2176 @@ -3476,363 +2589,716 @@ func (s *runChecksSuite) TestRunChecksBadWeakSecureBootAlgs(c *C) { env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 0, nil), efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ tpm2.PropertyNVCountersMax: 0, tpm2.PropertyPSFamilyIndicator: 1, tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, }) - c.Check(err, ErrorMatches, `2 errors detected: -- a weak cryptographic algorithm was detected during secure boot verification -- some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest + c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel CPU debugging configuration: the kernel module "msr" must be loaded`) + var hse *HostSecurityError + c.Assert(errors.As(err, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, MissingKernelModuleError("msr")), testutil.IsTrue) +} + +func (s *runChecksSuite) TestRunChecksBadUEFIDebuggingEnabledAndNoKernelIOMMU(c *C) { + // Test case with more than one host security error. + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + FirmwareDebugger: true, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, + }) + c.Check(err, ErrorMatches, `2 errors detected: +- error with system security: the platform firmware contains a debugging endpoint enabled +- error with system security: no kernel IOMMU support was detected `) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 2) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 2) - c.Check(errors.Is(errs[0], ErrWeakSecureBootAlgorithmDetected), testutil.IsTrue) - c.Check(errors.Is(errs[1], ErrPreOSSecureBootAuthByEnrolledDigests), testutil.IsTrue) -} + var hse *HostSecurityError + c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrUEFIDebuggingEnabled), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksBadPreOSSecureBootAuthByEnrolledDigests(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + c.Assert(errors.As(errs[1], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoKernelIOMMU), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest`) +func (s *runChecksSuite) TestRunChecksBadSHA1(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, + }, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: the PCR bank is missing from the TCG log. +`) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + var e *NoSuitablePCRAlgorithmError + c.Assert(errors.As(err, &e), testutil.IsTrue) - c.Check(errors.Is(errs[0], ErrPreOSSecureBootAuthByEnrolledDigests), testutil.IsTrue) + // Test that we can access individual errors. + c.Check(e.Errs[tpm2.HashAlgorithmSHA512], DeepEquals, []error{ErrPCRBankMissingFromLog}) + c.Check(e.Errs[tpm2.HashAlgorithmSHA384], DeepEquals, []error{ErrPCRBankMissingFromLog}) + c.Check(e.Errs[tpm2.HashAlgorithmSHA256], DeepEquals, []error{ErrPCRBankMissingFromLog}) + } } -func (s *runChecksSuite) TestRunChecksBadEFIVariableAccessError(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } +func (s *runChecksSuite) TestRunChecksBadMandatoryPCR1(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Err: efi.ErrVarDeviceError}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read AuditMode variable: variable access failed because of a hardware error`) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) - var e *EFIVariableAccessError - c.Assert(errors.As(err, &e), testutil.IsTrue) - c.Check(errors.Is(e, efi.ErrVarDeviceError), testutil.IsTrue) + var pce *PlatformConfigPCRError + c.Check(errors.As(errs[0], &pce), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadNoBootManagerCodeProfileSupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksSuite) TestRunChecksBadMandatoryPCR3(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(errs[0], &dce), testutil.IsTrue) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksBadMandatoryPCR5(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var bmce *BootManagerConfigPCRError + c.Check(errors.As(errs[0], &bmce), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), +func (s *runChecksSuite) TestRunChecksBadAddonDriversPresent(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var adpe *AddonDriversPresentError + c.Check(errors.As(errs[0], &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test - // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in - // the log so the test thinks that the log contains the flat file digest. - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and\/or the PE_COFF_IMAGE flag`) + }) + } +} - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) +func (s *runChecksSuite) TestRunChecksBadSysPrepAppsPresent(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `system preparation applications were detected: +- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 +`) - var bce *BootManagerCodePCRError - c.Check(errors.As(errs[0], &bce), testutil.IsTrue) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var spape *SysPrepApplicationsPresentError + c.Check(errors.As(errs[0], &spape), testutil.IsTrue) + c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), + }, + }) + } } -func (s *runChecksSuite) TestRunChecksBadEFIVariableAccessErrorSetupMode(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +func (s *runChecksSuite) TestRunChecksBadAbsoluteActive(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `Absolute was detected to be active and it is advised that this is disabled`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + c.Check(errors.Is(errs[0], ErrAbsoluteComputraceActive), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read SetupMode variable: variable does not exist`) +func (s *runChecksSuite) TestRunChecksBadWeakSecureBootAlgs(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `2 errors detected: +- a weak cryptographic algorithm was detected during secure boot verification +- some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest +`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 2) - var e *EFIVariableAccessError - c.Assert(errors.As(err, &e), testutil.IsTrue) + c.Check(errors.Is(errs[0], ErrWeakSecureBootAlgorithmDetected), testutil.IsTrue) + c.Check(errors.Is(errs[1], ErrPreOSSecureBootAuthByEnrolledDigests), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksSuite) TestRunChecksBadPreOSSecureBootAuthByEnrolledDigests(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + c.Check(errors.Is(errs[0], ErrPreOSSecureBootAuthByEnrolledDigests), testutil.IsTrue) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksBadEFIVariableAccessError(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Err: efi.ErrVarDeviceError}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read AuditMode variable: variable access failed because of a hardware error`) + + var e *EFIVariableAccessError + c.Assert(errors.As(err, &e), testutil.IsTrue) + c.Check(errors.Is(e, efi.ErrVarDeviceError), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) +func (s *runChecksSuite) TestRunChecksBadNoBootManagerCodeProfileSupport(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test + // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in + // the log so the test thinks that the log contains the flat file digest. + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and\/or the PE_COFF_IMAGE flag`) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) - var sbe *SecureBootPolicyPCRError - c.Assert(errors.As(errs[0], &sbe), testutil.IsTrue) - c.Check(errors.Is(sbe, ErrNoSecureBoot), testutil.IsTrue) + var bce *BootManagerCodePCRError + c.Check(errors.As(errs[0], &bce), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupportNoDeployedMode(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksSuite) TestRunChecksBadEFIVariableAccessErrorSetupMode(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read SetupMode variable: variable does not exist`) + + var e *EFIVariableAccessError + c.Assert(errors.As(err, &e), testutil.IsTrue) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupport(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var sbe *SecureBootPolicyPCRError + c.Assert(errors.As(errs[0], &sbe), testutil.IsTrue) + c.Check(errors.Is(sbe, ErrNoSecureBoot), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `secure boot is enabled but not in deployed mode`) +func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupportNoDeployedMode(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `secure boot is enabled but not in deployed mode`) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) - c.Check(errors.Is(errs[0], ErrNoDeployedMode), testutil.IsTrue) + c.Check(errors.Is(errs[0], ErrNoDeployedMode), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupportSecureBootDisabledAndNoSBATLevel(c *C) { @@ -3840,407 +3306,355 @@ func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupportSecureB // shim on a system with an empty SbatLevel variable. In this case, // there are no EV_EFI_VARIABLE_AUTHORITY events which caused // https://launchpad.net/bugs/2125439 - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - SecureBootDisabled: true, - NoSBAT: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + SecureBootDisabled: true, + NoSBAT: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) - var sbe *SecureBootPolicyPCRError - c.Assert(errors.As(errs[0], &sbe), testutil.IsTrue) - c.Check(errors.Is(sbe, ErrNoSecureBoot), testutil.IsTrue) + var sbe *SecureBootPolicyPCRError + c.Assert(errors.As(errs[0], &sbe), testutil.IsTrue) + c.Check(errors.Is(sbe, ErrNoSecureBoot), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksBadTPMHierarchiesOwnedAndNoSecureBootPolicySupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - c.Assert(s.TPM.HierarchyChangeAuth(s.TPM.LockoutHandleContext(), []byte{1, 2, 3, 4}, nil), IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, ErrorMatches, `2 errors detected: + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + c.Assert(s.TPM.HierarchyChangeAuth(s.TPM.LockoutHandleContext(), []byte{1, 2, 3, 4}, nil), IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + c.Assert(err, ErrorMatches, `2 errors detected: - error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_LOCKOUT has an authorization value - error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles `) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 2) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 2) - var te *TPM2DeviceError - c.Assert(errors.As(errs[0], &te), testutil.IsTrue) - var ohe *TPM2OwnedHierarchiesError - c.Check(errors.As(te, &ohe), testutil.IsTrue) + var te *TPM2DeviceError + c.Assert(errors.As(errs[0], &te), testutil.IsTrue) + var ohe *TPM2OwnedHierarchiesError + c.Check(errors.As(te, &ohe), testutil.IsTrue) - var sbpe *SecureBootPolicyPCRError - c.Check(errors.As(errs[1], &sbpe), testutil.IsTrue) - c.Check(errors.Is(sbpe, ErrNoSecureBoot), testutil.IsTrue) + var sbpe *SecureBootPolicyPCRError + c.Check(errors.As(errs[1], &sbpe), testutil.IsTrue) + c.Check(errors.Is(sbpe, ErrNoSecureBoot), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksBadInsufficientDMAProtectionAndNoBootManagerCodeProfileSupport(c *C) { - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: grubDigestDefault}, }, - &mockImage{contents: []byte("mock grub executable"), digest: grubDigestDefault}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, ErrorMatches, `3 errors detected: + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + c.Assert(err, ErrorMatches, `3 errors detected: - error with system security: the platform firmware indicates that DMA protections are insufficient - error with boot manager code \(PCR4\) measurements: cannot verify correctness of EV_EFI_BOOT_SERVICES_APPLICATION event digest: not enough images supplied - error with secure boot policy \(PCR7\) measurements: unexpected EV_EFI_ACTION event "DMA Protection Disabled" whilst measuring config `) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 3) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 3) - var hse *HostSecurityError - c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrInsufficientDMAProtection), testutil.IsTrue) + var hse *HostSecurityError + c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrInsufficientDMAProtection), testutil.IsTrue) - var bme *BootManagerCodePCRError - c.Check(errors.As(errs[1], &bme), testutil.IsTrue) + var bme *BootManagerCodePCRError + c.Check(errors.As(errs[1], &bme), testutil.IsTrue) - var sbpe *SecureBootPolicyPCRError - c.Check(errors.As(errs[2], &sbpe), testutil.IsTrue) + var sbpe *SecureBootPolicyPCRError + c.Check(errors.As(errs[2], &sbpe), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksBadInsufficientDMAProtectionAndNoKernelIOMMU(c *C) { - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, ErrorMatches, `3 errors detected: + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + c.Assert(err, ErrorMatches, `3 errors detected: - error with system security: the platform firmware indicates that DMA protections are insufficient - error with system security: no kernel IOMMU support was detected - error with secure boot policy \(PCR7\) measurements: unexpected EV_EFI_ACTION event "DMA Protection Disabled" whilst measuring config `) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 3) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 3) - var hse *HostSecurityError - c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrInsufficientDMAProtection), testutil.IsTrue) + var hse *HostSecurityError + c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrInsufficientDMAProtection), testutil.IsTrue) - c.Assert(errors.As(errs[1], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoKernelIOMMU), testutil.IsTrue) + c.Assert(errors.As(errs[1], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoKernelIOMMU), testutil.IsTrue) - var sbpe *SecureBootPolicyPCRError - c.Check(errors.As(errs[2], &sbpe), testutil.IsTrue) + var sbpe *SecureBootPolicyPCRError + c.Check(errors.As(errs[2], &sbpe), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksAllowInsufficientDMAProtection(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitInsufficientDMAProtection, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitInsufficientDMAProtection, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `the platform firmware indicates that DMA protections are insufficient`) - c.Check(errors.Is(warning, ErrInsufficientDMAProtection), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `no kernel IOMMU support was detected`) - c.Check(errors.Is(warning, ErrNoKernelIOMMU), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `the platform firmware indicates that DMA protections are insufficient`) + c.Check(errors.Is(warning, ErrInsufficientDMAProtection), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `no kernel IOMMU support was detected`) + c.Check(errors.Is(warning, ErrNoKernelIOMMU), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksAllowNoHardwareRootOfTrust(c *C) { // Test that PermitNoHardwareRootOfTrust converts related errors to warnings - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityInsufficientHWRootOfTrust + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoHardwareRootOfTrust, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, "encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode") + var nohwrot *NoHardwareRootOfTrustError + c.Check(errors.As(warning, &nohwrot), testutil.IsTrue) + + // Do not check the error messages below, as it is verified in another test + warning = warnings[1] + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ +func (s *runChecksSuite) TestRunChecksBadHostSecurityUnsupportedArchitecture(c *C) { + s.AddCleanup(MockRuntimeGOARCH("ppc64le")) + + _, err := s.testRunChecks(c, &testRunChecksParams{ env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ tpm2.PropertyNVCountersMax: 0, tpm2.PropertyPSFamilyIndicator: 1, tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoHardwareRootOfTrust, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, "encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode") - var nohwrot *NoHardwareRootOfTrustError - c.Check(errors.As(warning, &nohwrot), testutil.IsTrue) - - // Do not check the error messages below, as it is verified in another test - warning = warnings[1] - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + c.Check(err, ErrorMatches, `error with system security: unsupported platform: checking host security is not implemented on ppc64le`) + var hse *HostSecurityError + c.Check(errors.As(err, &hse), testutil.IsTrue) + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) } diff --git a/efi/preinstall/util_amd64.go b/efi/preinstall/cpu_vendor.go similarity index 96% rename from efi/preinstall/util_amd64.go rename to efi/preinstall/cpu_vendor.go index c8532f84..8da28d82 100644 --- a/efi/preinstall/util_amd64.go +++ b/efi/preinstall/cpu_vendor.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/util_amd64_test.go b/efi/preinstall/cpu_vendor_test.go similarity index 97% rename from efi/preinstall/util_amd64_test.go rename to efi/preinstall/cpu_vendor_test.go index 3b15a95e..5b8d1eaf 100644 --- a/efi/preinstall/util_amd64_test.go +++ b/efi/preinstall/cpu_vendor_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/export_amd64_test.go b/efi/preinstall/export_amd64_test.go deleted file mode 100644 index 03de4c17..00000000 --- a/efi/preinstall/export_amd64_test.go +++ /dev/null @@ -1,54 +0,0 @@ -//go:build amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall - -type ( - CpuVendor = cpuVendor - HfstsRegisters = hfstsRegisters - HfstsRegistersCsme11 = hfstsRegistersCsme11 - HfstsRegistersCsme18 = hfstsRegistersCsme18 - MeVersion = meVersion -) - -const ( - CpuVendorIntel = cpuVendorIntel - CpuVendorAMD = cpuVendorAMD - MeFamilyUnknown = meFamilyUnknown - MeFamilySps = meFamilySps - MeFamilyTxe = meFamilyTxe - MeFamilyMe = meFamilyMe - MeFamilyCsme = meFamilyCsme -) - -var ( - CalculateIntelMEFamily = calculateIntelMEFamily - CheckHostSecurityAMDPSP = checkHostSecurityAMDPSP - CheckHostSecurityIntelBootGuard = checkHostSecurityIntelBootGuard - CheckHostSecurityIntelBootGuardCSME11 = checkHostSecurityIntelBootGuardCSME11 - CheckHostSecurityIntelBootGuardCSME18 = checkHostSecurityIntelBootGuardCSME18 - CheckHostSecurityIntelBootGuardMSR = checkHostSecurityIntelBootGuardMSR - CheckHostSecurityIntelCPUDebuggingLocked = checkHostSecurityIntelCPUDebuggingLocked - DetermineCPUVendor = determineCPUVendor - IsTPMDiscreteFromIntelBootGuard = isTPMDiscreteFromIntelBootGuard - ReadIntelHFSTSRegistersFromMEISysfs = readIntelHFSTSRegistersFromMEISysfs - ReadIntelMEVersionFromMEISysfs = readIntelMEVersionFromMEISysfs -) diff --git a/efi/preinstall/export_test.go b/efi/preinstall/export_test.go index 753f468e..7c3273a9 100644 --- a/efi/preinstall/export_test.go +++ b/efi/preinstall/export_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -37,8 +37,13 @@ type ( BootManagerCodeResult = bootManagerCodeResult CheckFirmwareLogFlags = checkFirmwareLogFlags CheckTPM2DeviceFlags = checkTPM2DeviceFlags + CpuVendor = cpuVendor DetectVirtResult = detectVirtResult + HfstsRegisters = hfstsRegisters + HfstsRegistersCsme11 = hfstsRegistersCsme11 + HfstsRegistersCsme18 = hfstsRegistersCsme18 JoinError = joinError + MeVersion = meVersion PcrResults = pcrResults SecureBootPolicyResult = secureBootPolicyResult SecureBootPolicyResultFlags = secureBootPolicyResultFlags @@ -49,6 +54,8 @@ const ( AuthorityTrustDrivers = authorityTrustDrivers CheckFirmwareLogPermitWeakPCRBanks = checkFirmwareLogPermitWeakPCRBanks CheckTPM2DevicePostInstall = checkTPM2DevicePostInstall + CpuVendorAMD = cpuVendorAMD + CpuVendorIntel = cpuVendorIntel DetectVirtNone = detectVirtNone DetectVirtVM = detectVirtVM DiscreteTPMDetected = discreteTPMDetected @@ -56,6 +63,12 @@ const ( DtpmPartialResetAttackMitigationPreferred = dtpmPartialResetAttackMitigationPreferred DtpmPartialResetAttackMitigationUnavailable = dtpmPartialResetAttackMitigationUnavailable InsufficientDMAProtectionDetected = insufficientDMAProtectionDetected + MeFamilyCsme = meFamilyCsme + MeFamilyMe = meFamilyMe + MeFamilySps = meFamilySps + MeFamilyTxe = meFamilyTxe + MeFamilyUnknown = meFamilyUnknown + PlatformFirmwareIntegrityNone = platformFirmwareIntegrityNone PlatformFirmwareIntegrityMeasured = platformFirmwareIntegrityMeasured PlatformFirmwareIntegrityVerified = platformFirmwareIntegrityVerified SecureBootIncludesWeakAlg = secureBootIncludesWeakAlg @@ -65,7 +78,14 @@ const ( ) var ( + CalculateIntelMEFamily = calculateIntelMEFamily CheckBootManagerCodeMeasurements = checkBootManagerCodeMeasurements + CheckHostSecurityAMDPSP = checkHostSecurityAMDPSP + CheckHostSecurityIntelBootGuard = checkHostSecurityIntelBootGuard + CheckHostSecurityIntelBootGuardCSME11 = checkHostSecurityIntelBootGuardCSME11 + CheckHostSecurityIntelBootGuardCSME18 = checkHostSecurityIntelBootGuardCSME18 + CheckHostSecurityIntelBootGuardMSR = checkHostSecurityIntelBootGuardMSR + CheckHostSecurityIntelCPUDebuggingLocked = checkHostSecurityIntelCPUDebuggingLocked CheckDiscreteTPMPartialResetAttackMitigationStatus = checkDiscreteTPMPartialResetAttackMitigationStatus CheckDriversAndAppsMeasurements = checkDriversAndAppsMeasurements CheckFirmwareLogAndChoosePCRBank = checkFirmwareLogAndChoosePCRBank @@ -76,16 +96,20 @@ var ( CheckSystemIsEFI = checkSystemIsEFI CheckTPM2ForRequiredPCClientFeatures = checkTPM2ForRequiredPCClientFeatures ClearTPM = clearTPM + DetermineCPUVendor = determineCPUVendor DetectVirtualization = detectVirtualization ErrInvalidLockoutAuthValueSupplied = errInvalidLockoutAuthValueSupplied InsertActionProceed = insertActionProceed IsLaunchedFromLoadOption = isLaunchedFromLoadOption IsPPIActionAvailable = isPPIActionAvailable IsTPMDiscrete = isTPMDiscrete + IsTPMDiscreteFromIntelBootGuard = isTPMDiscreteFromIntelBootGuard JoinErrors = joinErrors MatchLaunchToLoadOption = matchLaunchToLoadOption NewX509CertificateID = newX509CertificateID OpenAndCheckTPM2Device = openAndCheckTPM2Device + ReadIntelHFSTSRegistersFromMEISysfs = readIntelHFSTSRegistersFromMEISysfs + ReadIntelMEVersionFromMEISysfs = readIntelMEVersionFromMEISysfs ReadOrderedLoadOptionVariables = readOrderedLoadOptionVariables RestrictedTPMLocalitiesIntel = restrictedTPMLocalitiesIntel RunPPIAction = runPPIAction @@ -158,3 +182,9 @@ func NewPCRBankResults(alg tpm2.HashAlgorithmId, sl uint8, pcrs [8]PcrResults) * pcrs: pcrs, } } + +func MockRuntimeGOARCH(arch string) (restore func()) { + orig := runtimeGOARCH + runtimeGOARCH = arch + return func() { runtimeGOARCH = orig } +} diff --git a/efi/preinstall/intel_util.go b/efi/preinstall/intel_util.go index f044d1b9..6306fe73 100644 --- a/efi/preinstall/intel_util.go +++ b/efi/preinstall/intel_util.go @@ -1,5 +1,3 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* diff --git a/internal/efi/default_env_amd64.go b/internal/efi/default_env_amd64.go index b9b13917..df718091 100644 --- a/internal/efi/default_env_amd64.go +++ b/internal/efi/default_env_amd64.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -19,6 +19,11 @@ package efi +// This file remains restricted to amd64 by its filename because +// github.com/canonical/cpuid does not compile on other architectures. +// default_env_amd64_null.go supplies the stub AMD64() implementation for all +// other architectures. + import ( "encoding/binary" "errors" diff --git a/internal/efi/default_env_null.go b/internal/efi/default_env_amd64_null.go similarity index 100% rename from internal/efi/default_env_null.go rename to internal/efi/default_env_amd64_null.go diff --git a/internal/efi/default_env_not_amd64_test.go b/internal/efi/default_env_amd64_null_test.go similarity index 100% rename from internal/efi/default_env_not_amd64_test.go rename to internal/efi/default_env_amd64_null_test.go diff --git a/internal/efi/default_env_amd64_test.go b/internal/efi/default_env_amd64_test.go index abec67f1..4920e316 100644 --- a/internal/efi/default_env_amd64_test.go +++ b/internal/efi/default_env_amd64_test.go @@ -3,7 +3,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2021-2024 Canonical Ltd + * Copyright (C) 2021-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -137,3 +137,15 @@ func (s *defaultEnvAMD64Suite) TestReadMSR(c *C) { 1: 0x40000000, }) } + +func (s *defaultEnvAMD64Suite) TestCPUIDFeatureSMXMatchesCpuidPackage(c *C) { + // Drift guard: CPUIDFeatureSMX must equal cpuid.SMX. If the cpuid + // package ever changes its bit positions this test will catch it. + c.Check(CPUIDFeatureSMX, Equals, cpuid.SMX) +} + +func (s *defaultEnvAMD64Suite) TestCPUIDFeatureSDBGMatchesCpuidPackage(c *C) { + // Drift guard: CPUIDFeatureSDBG must equal cpuid.SDBG. If the cpuid + // package ever changes its bit positions this test will catch it. + c.Check(CPUIDFeatureSDBG, Equals, cpuid.SDBG) +} diff --git a/internal/efi/env.go b/internal/efi/env.go index c0a0b3ae..15ff4889 100644 --- a/internal/efi/env.go +++ b/internal/efi/env.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -65,6 +65,14 @@ type SysfsDevice interface { AttributeReader(attr string) (io.ReadCloser, error) } +// CPUIDFeatureSMX is the CPUID feature flag for Safer Mode Extensions (Intel TXT), +// from leaf 1, ECX bit 6. Use with [HostEnvironmentAMD64.HasCPUIDFeature]. +const CPUIDFeatureSMX = uint64(1) << 6 + +// CPUIDFeatureSDBG is the CPUID feature flag for the Silicon Debug interface, +// from leaf 1, ECX bit 11. Use with [HostEnvironmentAMD64.HasCPUIDFeature]. +const CPUIDFeatureSDBG = uint64(1) << 11 + // HostEnvironmentAMD64 is an interface that abstracts out a host environment specific // to AMD64 platforms. type HostEnvironmentAMD64 interface { @@ -74,8 +82,10 @@ type HostEnvironmentAMD64 interface { // CPUFamily returns the CPU family ID. CPUFamily() uint32 - // HasCPUIDFeature returns if feature from FeatureNames map in the - // github.com/intel-go/cpuid package is available. + // HasCPUIDFeature returns if the given CPUID feature is available. Callers + // should use the CPUIDFeature* constants declared in this package, because + // github.com/canonical/cpuid only builds on x86 and callers of this interface + // are architecture independent. HasCPUIDFeature(feature uint64) bool // ReadMSRs reads the value of the specified MSR for all CPUs, From bfc8c1d1b6e5b0986e7eaa9cffb7c1ee6cc10e05 Mon Sep 17 00:00:00 2001 From: Alex Lewontin Date: Wed, 2 Sep 2026 15:11:29 -0400 Subject: [PATCH 2/3] internal/efi: abstract cpuid behind an arch-gated wrapper github.com/canonical/cpuid does not compile on non-x86 architectures, which forced the AMD64 host environment to be split across a filename gated default_env_amd64.go and a default_env_amd64_null.go stub. That made the implementation invisible to the compiler, and untestable, on every other architecture. Confine that dependency to a new internal/cpuid package. It is a deliberately thin wrapper, and the only place in the tree that is gated by architecture at build time. It exposes VendorIdentificator, Family and HasFeature, delegating to the upstream package on amd64 and returning zero values elsewhere. internal/efi is now architecture neutral: it carries no build constraints, the AMD64 implementation collapses into default_env.go, and AMD64() selects on a mockable runtimeGOARCH rather than a build tag. This mirrors the runtime dispatch used elsewhere for host security checks. The CPUIDFeature* constants stay in internal/efi, so callers are unchanged. Their drift guards against the upstream bit positions move to internal/cpuid, which is now the only package able to see both. The AMD64 tests lose their build constraints and drive the CPU identity through new mock hooks instead of mutating upstream package variables, so they run everywhere. TestNotAMD64Host no longer depends on the host architecture, and therefore now runs on amd64 too. --- internal/cpuid/cpuid_amd64.go | 47 ++++++ internal/cpuid/cpuid_amd64_test.go | 52 ++++++ .../cpuid_null.go} | 28 ++-- internal/efi/default_env.go | 98 +++++++++++- internal/efi/default_env_amd64.go | 121 -------------- internal/efi/default_env_amd64_null.go | 27 ---- internal/efi/default_env_amd64_test.go | 151 ------------------ internal/efi/default_env_test.go | 129 ++++++++++++++- internal/efi/export_amd64_test.go | 38 ----- internal/efi/export_test.go | 42 ++++- 10 files changed, 381 insertions(+), 352 deletions(-) create mode 100644 internal/cpuid/cpuid_amd64.go create mode 100644 internal/cpuid/cpuid_amd64_test.go rename internal/{efi/default_env_amd64_null_test.go => cpuid/cpuid_null.go} (52%) delete mode 100644 internal/efi/default_env_amd64.go delete mode 100644 internal/efi/default_env_amd64_null.go delete mode 100644 internal/efi/default_env_amd64_test.go delete mode 100644 internal/efi/export_amd64_test.go diff --git a/internal/cpuid/cpuid_amd64.go b/internal/cpuid/cpuid_amd64.go new file mode 100644 index 00000000..c278ddda --- /dev/null +++ b/internal/cpuid/cpuid_amd64.go @@ -0,0 +1,47 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2026 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// Package cpuid is a deliberately thin, architecture-gated wrapper around +// github.com/canonical/cpuid, which does not compile on non-x86 architectures. +// Confining that dependency here keeps every consumer architecture-neutral, so +// that consumers are compiled and unit tested on every architecture rather than +// being gated by build constraints. +// +// On amd64 the functions delegate to the upstream package. On every other +// architecture they return zero values, because CPUID is x86-only. +package cpuid + +import ( + upstream_cpuid "github.com/canonical/cpuid" +) + +// VendorIdentificator returns the CPU vendor identificator string, e.g. "GenuineIntel". +func VendorIdentificator() string { + return upstream_cpuid.VendorIdentificatorString +} + +// Family returns the CPU display family ID. +func Family() uint32 { + return upstream_cpuid.DisplayFamily +} + +// HasFeature returns whether the supplied CPUID feature bit is set. +func HasFeature(feature uint64) bool { + return upstream_cpuid.HasFeature(feature) +} diff --git a/internal/cpuid/cpuid_amd64_test.go b/internal/cpuid/cpuid_amd64_test.go new file mode 100644 index 00000000..95412d2b --- /dev/null +++ b/internal/cpuid/cpuid_amd64_test.go @@ -0,0 +1,52 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2026 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// This file contains drift-guard tests comparing the architecture-neutral +// CPUIDFeature* constants declared in internal/efi against their upstream +// cpuid equivalents. This package is the only place permitted to import +// github.com/canonical/cpuid, so it is the only place that can compare our +// constants against upstream's bit positions. + +package cpuid_test + +import ( + "testing" + + upstream_cpuid "github.com/canonical/cpuid" + internal_efi "github.com/snapcore/secboot/internal/efi" + . "gopkg.in/check.v1" +) + +func Test(t *testing.T) { TestingT(t) } + +type cpuidSuite struct{} + +var _ = Suite(&cpuidSuite{}) + +func (s *cpuidSuite) TestCPUIDFeatureSMXMatchesCpuidPackage(c *C) { + // Drift guard: CPUIDFeatureSMX must equal cpuid.SMX. If the cpuid + // package ever changes its bit positions this test will catch it. + c.Check(internal_efi.CPUIDFeatureSMX, Equals, upstream_cpuid.SMX) +} + +func (s *cpuidSuite) TestCPUIDFeatureSDBGMatchesCpuidPackage(c *C) { + // Drift guard: CPUIDFeatureSDBG must equal cpuid.SDBG. If the cpuid + // package ever changes its bit positions this test will catch it. + c.Check(internal_efi.CPUIDFeatureSDBG, Equals, upstream_cpuid.SDBG) +} diff --git a/internal/efi/default_env_amd64_null_test.go b/internal/cpuid/cpuid_null.go similarity index 52% rename from internal/efi/default_env_amd64_null_test.go rename to internal/cpuid/cpuid_null.go index 316544c5..2f529731 100644 --- a/internal/efi/default_env_amd64_null_test.go +++ b/internal/cpuid/cpuid_null.go @@ -3,7 +3,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2021-2024 Canonical Ltd + * Copyright (C) 2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -19,18 +19,22 @@ * */ -package efi_test +package cpuid -import ( - . "github.com/snapcore/secboot/internal/efi" - . "gopkg.in/check.v1" -) - -type defaultEnvAMD64Suite struct{} +// VendorIdentificator returns the CPU vendor identificator string. +// CPUID is x86-only; this stub always returns "" on this architecture. +func VendorIdentificator() string { + return "" +} -var _ = Suite(&defaultEnvAMD64Suite{}) +// Family returns the CPU display family ID. +// CPUID is x86-only; this stub always returns 0 on this architecture. +func Family() uint32 { + return 0 +} -func (s *defaultEnvAMD64Suite) TestNotAMD64Host(c *C) { - _, err := DefaultEnv.AMD64() - c.Check(err, Equals, ErrNotAMD64Host) +// HasFeature returns whether the supplied CPUID feature bit is set. +// CPUID is x86-only; this stub always returns false on this architecture. +func HasFeature(feature uint64) bool { + return false } diff --git a/internal/efi/default_env.go b/internal/efi/default_env.go index 20e851fc..cbbc55fd 100644 --- a/internal/efi/default_env.go +++ b/internal/efi/default_env.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2021 Canonical Ltd + * Copyright (C) 2021-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -22,24 +22,35 @@ package efi import ( "bytes" "context" + "encoding/binary" + "errors" "fmt" "io" "os" "os/exec" "path/filepath" + "runtime" + "strconv" + "syscall" efi "github.com/canonical/go-efilib" "github.com/canonical/tcglog-parser" "github.com/pilebones/go-udev/crawler" "github.com/pilebones/go-udev/netlink" + internal_cpuid "github.com/snapcore/secboot/internal/cpuid" "github.com/snapcore/secboot/internal/tpm2_device" ) var ( crawlerExistingDevices = crawler.ExistingDevices + cpuidFamily = internal_cpuid.Family + cpuidHasFeature = internal_cpuid.HasFeature + cpuidVendorIdentificator = internal_cpuid.VendorIdentificator + devcpuPath = "/dev/cpu" osOpen = os.Open osReadFile = os.ReadFile osReadlink = os.Readlink + runtimeGOARCH = runtime.GOARCH tpm2_deviceDefaultDevice = tpm2_device.DefaultDevice eventLogPath = "/sys/kernel/security/tpm0/binary_bios_measurements" // Path of the TCG event log for the default TPM, in binary form @@ -240,3 +251,88 @@ func (defaultEnvImpl) EnumerateDevices(matcher netlink.Matcher) ([]SysfsDevice, // DefaultEnv corresponds to the environment associated with the host // machine. var DefaultEnv = defaultEnvImpl{} + +type defaultEnvAMD64Impl struct{} + +// CPUVendorIdentificator implements [HostEnvironmentAMD64.CPUVendorIdentificator]. +func (defaultEnvAMD64Impl) CPUVendorIdentificator() string { + return cpuidVendorIdentificator() +} + +// CPUFamily implements [HostEnvironmentAMD64.CPUFamily]. +func (defaultEnvAMD64Impl) CPUFamily() uint32 { + return cpuidFamily() +} + +// HasCPUIDFeature implements [HostEnvironmentAMD64.HasCPUIDFeature]. +func (defaultEnvAMD64Impl) HasCPUIDFeature(feature uint64) bool { + return cpuidHasFeature(feature) +} + +// ReadMSRs implements [HostEnvironmentAMD64.ReadMSRs]. +func (defaultEnvAMD64Impl) ReadMSRs(msr uint32) (map[uint32]uint64, error) { + dir, err := os.Open(devcpuPath) + switch { + case os.IsNotExist(err): + return nil, ErrNoKernelMSRSupport + case err != nil: + return nil, err + } + defer dir.Close() + + entries, err := dir.ReadDir(-1) + if err != nil { + return nil, err + } + + out := make(map[uint32]uint64) + + for _, entry := range entries { + cpuNo, err := strconv.ParseUint(entry.Name(), 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid CPU number for name %s: %w", entry.Name(), err) + } + + val, err := func(name string) (uint64, error) { + f, err := os.Open(filepath.Join(dir.Name(), name, "msr")) + switch { + case os.IsNotExist(err): + return 0, ErrNoKernelMSRSupport + case errors.Is(err, syscall.EIO): + return 0, ErrNoMSRSupport + case err != nil: + return 0, err + } + defer f.Close() + + var data [8]byte + _, err = f.ReadAt(data[:], int64(msr)) + switch { + case errors.Is(err, syscall.EIO): // I think the kernel returns -EIO if the MSR is not supported, but this is poorly documented. + return 0, ErrNoMSRSupport + case err != nil: + return 0, fmt.Errorf("cannot read from MSR device: %w", err) + } + + return binary.LittleEndian.Uint64(data[:]), nil + }(entry.Name()) + if err != nil { + return nil, fmt.Errorf("cannot read value for CPU %s: %w", entry.Name(), err) + } + + out[uint32(cpuNo)] = val + } + + return out, nil +} + +// AMD64 implements [HostEnvironment.AMD64]. +// +// The architecture is checked at runtime (rather than by build constraint) so +// that this implementation is compiled and unit tested on every architecture. +func (defaultEnvImpl) AMD64() (HostEnvironmentAMD64, error) { + if runtimeGOARCH != "amd64" { + return nil, ErrNotAMD64Host + } + return defaultEnvAMD64Impl{}, nil +} diff --git a/internal/efi/default_env_amd64.go b/internal/efi/default_env_amd64.go deleted file mode 100644 index df718091..00000000 --- a/internal/efi/default_env_amd64.go +++ /dev/null @@ -1,121 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024-2026 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package efi - -// This file remains restricted to amd64 by its filename because -// github.com/canonical/cpuid does not compile on other architectures. -// default_env_amd64_null.go supplies the stub AMD64() implementation for all -// other architectures. - -import ( - "encoding/binary" - "errors" - "fmt" - "os" - "path/filepath" - "strconv" - "syscall" - - "github.com/canonical/cpuid" -) - -var ( - cpuidHasFeature = cpuid.HasFeature - devcpuPath = "/dev/cpu" -) - -type defaultEnvAMD64Impl struct{} - -// CPUVendorIdentificator implements [HostEnvironmentAMD64.CPUVendorIdentificator]. -func (defaultEnvAMD64Impl) CPUVendorIdentificator() string { - return cpuid.VendorIdentificatorString -} - -// CPUFamily implements [HostEnvironmentAMD64.CPUFamily]. -func (defaultEnvAMD64Impl) CPUFamily() uint32 { - return cpuid.DisplayFamily -} - -// HasCPUIDFeature implements [HostEnvironmentAMD64.HasCPUIDFeature]. -func (defaultEnvAMD64Impl) HasCPUIDFeature(feature uint64) bool { - return cpuidHasFeature(feature) -} - -// ReadMSR implements [HostEnvironmentAMD64.ReadMSRs]. -func (defaultEnvAMD64Impl) ReadMSRs(msr uint32) (map[uint32]uint64, error) { - dir, err := os.Open(devcpuPath) - switch { - case os.IsNotExist(err): - return nil, ErrNoKernelMSRSupport - case err != nil: - return nil, err - } - defer dir.Close() - - entries, err := dir.ReadDir(-1) - if err != nil { - return nil, err - } - - out := make(map[uint32]uint64) - - for _, entry := range entries { - cpuNo, err := strconv.ParseUint(entry.Name(), 10, 32) - if err != nil { - return nil, fmt.Errorf("invalid CPU number for name %s: %w", entry.Name(), err) - } - - val, err := func(name string) (uint64, error) { - f, err := os.Open(filepath.Join(dir.Name(), name, "msr")) - switch { - case os.IsNotExist(err): - return 0, ErrNoKernelMSRSupport - case errors.Is(err, syscall.EIO): - return 0, ErrNoMSRSupport - case err != nil: - return 0, err - } - defer f.Close() - - var data [8]byte - _, err = f.ReadAt(data[:], int64(msr)) - switch { - case errors.Is(err, syscall.EIO): // I think the kernel returns -EIO if the MSR is not supported, but this is poorly documented. - return 0, ErrNoMSRSupport - case err != nil: - return 0, fmt.Errorf("cannot read from MSR device: %w", err) - } - - return binary.LittleEndian.Uint64(data[:]), nil - }(entry.Name()) - if err != nil { - return nil, fmt.Errorf("cannot read value for CPU %s: %w", entry.Name(), err) - } - - out[uint32(cpuNo)] = val - } - - return out, nil -} - -// AMD64 implements [HostEnvironment.AMD64]. -func (defaultEnvImpl) AMD64() (HostEnvironmentAMD64, error) { - return defaultEnvAMD64Impl{}, nil -} diff --git a/internal/efi/default_env_amd64_null.go b/internal/efi/default_env_amd64_null.go deleted file mode 100644 index dbea4dc4..00000000 --- a/internal/efi/default_env_amd64_null.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package efi - -// AMD64 implements [HostEnvironment.AMD64]. -func (defaultEnvImpl) AMD64() (HostEnvironmentAMD64, error) { - return nil, ErrNotAMD64Host -} diff --git a/internal/efi/default_env_amd64_test.go b/internal/efi/default_env_amd64_test.go deleted file mode 100644 index 4920e316..00000000 --- a/internal/efi/default_env_amd64_test.go +++ /dev/null @@ -1,151 +0,0 @@ -//go:build amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2021-2026 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package efi_test - -import ( - "encoding/binary" - "os" - "path/filepath" - - "github.com/canonical/cpuid" - . "github.com/snapcore/secboot/internal/efi" - "github.com/snapcore/secboot/internal/testutil" - . "gopkg.in/check.v1" -) - -type defaultEnvAMD64Suite struct{} - -var _ = Suite(&defaultEnvAMD64Suite{}) - -func (s *defaultEnvAMD64Suite) TestCPUVendorIdentificatorIntel(c *C) { - orig := cpuid.VendorIdentificatorString - cpuid.VendorIdentificatorString = "GenuineIntel" - defer func() { cpuid.VendorIdentificatorString = orig }() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.CPUVendorIdentificator(), Equals, "GenuineIntel") -} - -func (s *defaultEnvAMD64Suite) TestCPUVendorIdentificatorAMD(c *C) { - orig := cpuid.VendorIdentificatorString - cpuid.VendorIdentificatorString = "AuthenticAMD" - defer func() { cpuid.VendorIdentificatorString = orig }() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.CPUVendorIdentificator(), Equals, "AuthenticAMD") -} - -func (s *defaultEnvAMD64Suite) TestCPUFamily1(c *C) { - orig := cpuid.DisplayFamily - cpuid.DisplayFamily = 0x12 - defer func() { cpuid.DisplayFamily = orig }() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.CPUFamily(), Equals, uint32(0x12)) -} - -func (s *defaultEnvAMD64Suite) TestCPUFamily2(c *C) { - orig := cpuid.DisplayFamily - cpuid.DisplayFamily = 0x17 - defer func() { cpuid.DisplayFamily = orig }() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.CPUFamily(), Equals, uint32(0x17)) -} - -func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSDBGTrue(c *C) { - restore := MockCPUIDHasFeature(func(feature uint64) bool { - c.Check(feature, Equals, cpuid.SDBG) - return true - }) - defer restore() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.HasCPUIDFeature(cpuid.SDBG), testutil.IsTrue) -} - -func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSDBGFalse(c *C) { - restore := MockCPUIDHasFeature(func(feature uint64) bool { - c.Check(feature, Equals, cpuid.SDBG) - return false - }) - defer restore() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.HasCPUIDFeature(cpuid.SDBG), testutil.IsFalse) -} - -func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSSE3True(c *C) { - restore := MockCPUIDHasFeature(func(feature uint64) bool { - c.Check(feature, Equals, cpuid.SSE3) - return true - }) - defer restore() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.HasCPUIDFeature(cpuid.SSE3), testutil.IsTrue) -} - -func (s *defaultEnvAMD64Suite) TestReadMSR(c *C) { - dir := c.MkDir() - restore := MockDevcpuPath(dir) - defer restore() - - c.Assert(os.Mkdir(filepath.Join(dir, "0"), 0755), IsNil) - c.Assert(os.Mkdir(filepath.Join(dir, "1"), 0755), IsNil) - - data := make([]byte, 0xc80) - var data8 [8]byte - binary.LittleEndian.PutUint64(data8[:], 0x40000000) - data = append(data, data8[:]...) - - c.Assert(os.WriteFile(filepath.Join(dir, "0/msr"), data, 0644), IsNil) - c.Assert(os.WriteFile(filepath.Join(dir, "1/msr"), data, 0644), IsNil) - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - vals, err := amd64.ReadMSRs(0xc80) - c.Assert(err, IsNil) - c.Check(vals, DeepEquals, map[uint32]uint64{ - 0: 0x40000000, - 1: 0x40000000, - }) -} - -func (s *defaultEnvAMD64Suite) TestCPUIDFeatureSMXMatchesCpuidPackage(c *C) { - // Drift guard: CPUIDFeatureSMX must equal cpuid.SMX. If the cpuid - // package ever changes its bit positions this test will catch it. - c.Check(CPUIDFeatureSMX, Equals, cpuid.SMX) -} - -func (s *defaultEnvAMD64Suite) TestCPUIDFeatureSDBGMatchesCpuidPackage(c *C) { - // Drift guard: CPUIDFeatureSDBG must equal cpuid.SDBG. If the cpuid - // package ever changes its bit positions this test will catch it. - c.Check(CPUIDFeatureSDBG, Equals, cpuid.SDBG) -} diff --git a/internal/efi/default_env_test.go b/internal/efi/default_env_test.go index 70f7e69e..e6b2dd67 100644 --- a/internal/efi/default_env_test.go +++ b/internal/efi/default_env_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2021-2024 Canonical Ltd + * Copyright (C) 2021-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -21,6 +21,7 @@ package efi_test import ( "context" + "encoding/binary" "errors" "io" "os" @@ -638,3 +639,129 @@ func (s *defaultEnvSuite) TestSysfsDeviceParentNoParent(c *C) { c.Check(err, IsNil) c.Check(parent, IsNil) } + +type defaultEnvAMD64Suite struct { + restoreGOARCH func() +} + +var _ = Suite(&defaultEnvAMD64Suite{}) + +func (s *defaultEnvAMD64Suite) SetUpTest(c *C) { + s.restoreGOARCH = MockRuntimeGOARCH("amd64") +} + +func (s *defaultEnvAMD64Suite) TearDownTest(c *C) { + s.restoreGOARCH() + s.restoreGOARCH = nil +} + +func (s *defaultEnvAMD64Suite) TestCPUVendorIdentificatorIntel(c *C) { + restore := MockCPUIDVendorIdentificator(func() string { return "GenuineIntel" }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.CPUVendorIdentificator(), Equals, "GenuineIntel") +} + +func (s *defaultEnvAMD64Suite) TestCPUVendorIdentificatorAMD(c *C) { + restore := MockCPUIDVendorIdentificator(func() string { return "AuthenticAMD" }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.CPUVendorIdentificator(), Equals, "AuthenticAMD") +} + +func (s *defaultEnvAMD64Suite) TestCPUFamily1(c *C) { + restore := MockCPUIDFamily(func() uint32 { return 0x12 }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.CPUFamily(), Equals, uint32(0x12)) +} + +func (s *defaultEnvAMD64Suite) TestCPUFamily2(c *C) { + restore := MockCPUIDFamily(func() uint32 { return 0x17 }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.CPUFamily(), Equals, uint32(0x17)) +} + +func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSDBGTrue(c *C) { + restore := MockCPUIDHasFeature(func(feature uint64) bool { + c.Check(feature, Equals, CPUIDFeatureSDBG) + return true + }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.HasCPUIDFeature(CPUIDFeatureSDBG), testutil.IsTrue) +} + +func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSDBGFalse(c *C) { + restore := MockCPUIDHasFeature(func(feature uint64) bool { + c.Check(feature, Equals, CPUIDFeatureSDBG) + return false + }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.HasCPUIDFeature(CPUIDFeatureSDBG), testutil.IsFalse) +} + +func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureArbitraryBitPassedThrough(c *C) { + // Verify that an arbitrary feature bit is forwarded unchanged to the + // underlying hook (architecture-neutral replacement for SSE3-specific test). + const arbitraryFeature = uint64(1) << 0 // leaf 1, ECX bit 0 + restore := MockCPUIDHasFeature(func(feature uint64) bool { + c.Check(feature, Equals, arbitraryFeature) + return true + }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.HasCPUIDFeature(arbitraryFeature), testutil.IsTrue) +} + +func (s *defaultEnvAMD64Suite) TestReadMSR(c *C) { + dir := c.MkDir() + restore := MockDevcpuPath(dir) + defer restore() + + c.Assert(os.Mkdir(filepath.Join(dir, "0"), 0755), IsNil) + c.Assert(os.Mkdir(filepath.Join(dir, "1"), 0755), IsNil) + + data := make([]byte, 0xc80) + var data8 [8]byte + binary.LittleEndian.PutUint64(data8[:], 0x40000000) + data = append(data, data8[:]...) + + c.Assert(os.WriteFile(filepath.Join(dir, "0/msr"), data, 0644), IsNil) + c.Assert(os.WriteFile(filepath.Join(dir, "1/msr"), data, 0644), IsNil) + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + vals, err := amd64.ReadMSRs(0xc80) + c.Assert(err, IsNil) + c.Check(vals, DeepEquals, map[uint32]uint64{ + 0: 0x40000000, + 1: 0x40000000, + }) +} + +func (s *defaultEnvAMD64Suite) TestNotAMD64Host(c *C) { + // Override the arch pinned by SetUpTest to simulate a non-amd64 host. + // This now runs on every architecture including amd64 itself. + restore := MockRuntimeGOARCH("arm64") + defer restore() + + _, err := DefaultEnv.AMD64() + c.Check(err, Equals, ErrNotAMD64Host) +} diff --git a/internal/efi/export_amd64_test.go b/internal/efi/export_amd64_test.go deleted file mode 100644 index d75b464d..00000000 --- a/internal/efi/export_amd64_test.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package efi - -func MockDevcpuPath(path string) (restore func()) { - orig := devcpuPath - devcpuPath = path - return func() { - devcpuPath = orig - } -} - -func MockCPUIDHasFeature(fn func(uint64) bool) (restore func()) { - orig := cpuidHasFeature - cpuidHasFeature = fn - return func() { - cpuidHasFeature = orig - } -} diff --git a/internal/efi/export_test.go b/internal/efi/export_test.go index e2828882..e9635503 100644 --- a/internal/efi/export_test.go +++ b/internal/efi/export_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2019-2024 Canonical Ltd + * Copyright (C) 2019-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -74,3 +74,43 @@ func MockOsReadlink(fn func(string) (string, error)) (restore func()) { osReadlink = orig } } + +func MockCPUIDVendorIdentificator(fn func() string) (restore func()) { + orig := cpuidVendorIdentificator + cpuidVendorIdentificator = fn + return func() { + cpuidVendorIdentificator = orig + } +} + +func MockCPUIDFamily(fn func() uint32) (restore func()) { + orig := cpuidFamily + cpuidFamily = fn + return func() { + cpuidFamily = orig + } +} + +func MockCPUIDHasFeature(fn func(uint64) bool) (restore func()) { + orig := cpuidHasFeature + cpuidHasFeature = fn + return func() { + cpuidHasFeature = orig + } +} + +func MockDevcpuPath(path string) (restore func()) { + orig := devcpuPath + devcpuPath = path + return func() { + devcpuPath = orig + } +} + +func MockRuntimeGOARCH(arch string) (restore func()) { + orig := runtimeGOARCH + runtimeGOARCH = arch + return func() { + runtimeGOARCH = orig + } +} From 44b4c701479053a88aa488089a44f7acd44ce05b Mon Sep 17 00:00:00 2001 From: Alex Lewontin Date: Thu, 3 Sep 2026 12:40:24 -0400 Subject: [PATCH 3/3] efi/preinstall: clean up comments Signed-off-by: Alex Lewontin --- efi/preinstall/check_tpm_intel_test.go | 1 + efi/preinstall/checks_fixture_test.go | 29 ++++++++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/efi/preinstall/check_tpm_intel_test.go b/efi/preinstall/check_tpm_intel_test.go index 602e9aea..222458d0 100644 --- a/efi/preinstall/check_tpm_intel_test.go +++ b/efi/preinstall/check_tpm_intel_test.go @@ -33,6 +33,7 @@ type tpmIntelSuite struct { func (s *tpmIntelSuite) SetUpTest(c *C) { s.BaseTest.SetUpTest(c) + // All Intel TPM tests assume an amd64 host s.AddCleanup(MockRuntimeGOARCH("amd64")) } diff --git a/efi/preinstall/checks_fixture_test.go b/efi/preinstall/checks_fixture_test.go index cb5c9694..d40de2de 100644 --- a/efi/preinstall/checks_fixture_test.go +++ b/efi/preinstall/checks_fixture_test.go @@ -49,15 +49,22 @@ const ( runChecksHostCapabilityStartupLocality4AccessibleFromOS ) -// Platform identity capabilities do not imply security properties. In -// particular, HasIntelBootGuard does not imply that any TPM startup locality is -// inaccessible from the OS; fixtures must declare locality properties -// separately. - // runChecksHostFixture abstracts host-specific details from scenario logic in // the shared RunChecks and RunChecksContext tests. type runChecksHostFixture struct { - name string + name string + // capabilities represent high level abstractions of one or more aspects of a host fixture + // that tests can use to determine if the fixture meets the requirements for a given scenario. + // + // For example, a scenario that tests fTPM-specific behavior may fail when run on a fixture + // with a dTPM. Depending on the level of the behavior being tested, this failure may not be + // particularly meaningful, and it may make more sense for the test to only run on fixtures + // that actually provide an fTPM. + // + // Capabilities simply summarize and label information encoded in other fields of the fixture. + // Declaring a capability by itself does not instantiate any mock behaviors, and it is the + // responsibility of the author to make sure that the capabilities are a faithful reflection + // of the actual behavior of the fixture. capabilities runChecksHostCapabilities environment efitest.MockHostEnvironmentOption virtualizationMode string @@ -101,6 +108,16 @@ func (f *runChecksHostFixture) newEnvironment(options ...efitest.MockHostEnviron func (f *runChecksHostFixture) mockRuntimeGOARCH(s interface{ AddCleanup(func()) }) { s.AddCleanup(MockRuntimeGOARCH(f.arch)) } + +// runChecksPlatformHostFixtures returns an array of mock platform host configurations +// for testing. Each fixture can define an EFI environment with CPU features, a set of sysfs +// devices, virtualization information, and host ISA. Each fixture also includes a set of +// "capabilities" which can be used by tests to decide whether they should expect a +// certain fixture to work for a given test scenario or not. +// +// To add fixtures, append them to the array returned by this function. To add capabilities, +// add them to the const block at the top of this file and then audit the existing fixtures +// and add the new capability to any existing fixtures to which it might apply. func runChecksPlatformHostFixtures() []runChecksHostFixture { intelDevices := func(status []byte, withIOMMU bool) []internal_efi.SysfsDevice { attrs := map[string][]byte{