diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index a4321cee..5ea679f5 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -6,9 +6,12 @@ on: branches: [ "master" ] jobs: tests: - runs-on: ubuntu-24.04 + runs-on: ${{ matrix.runner }} strategy: matrix: + runner: + - ubuntu-24.04 + - ubuntu-24.04-arm goversion: - 1.18 # The unit tests currently fail against the new stable go diff --git a/efi/preinstall/check_host_security.go b/efi/preinstall/check_host_security.go index 61c0f9ff..4d673f9e 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,223 @@ 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) + case "arm64": + return checkHostSecurityARM64(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) + case "arm64": + return checkDiscreteTPMPartialResetAttackMitigationStatusARM64(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 +} + +// checkHostSecurityARM64Platform selects the platform-specific firmware +// integrity check. Tests replace this to supply synthetic platforms. +var checkHostSecurityARM64Platform = func(env internal_efi.HostEnvironmentARM64, cpuManufacturer string) (platformFirmwareIntegrityConfig, error) { + switch cpuManufacturer { + case "NVIDIA": + return checkHostSecurityNVIDIA(env) + default: + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("unsupported CPU manufacturer: %s", cpuManufacturer)} + } +} + +func checkHostSecurityARM64(env internal_efi.HostEnvironment, log *tcglog.Log) (platformFirmwareIntegrityConfig, error) { + arm64Env, err := env.ARM64() + if err != nil { + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("cannot obtain ARM64 environment: %w", err)} + } + + cpuManufacturer, err := arm64Env.CPUManufacturer() + if err != nil { + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU manufacturer: %w", err)} + } + + integrity, err := checkHostSecurityARM64Platform(arm64Env, cpuManufacturer) + if err != nil { + return platformFirmwareIntegrityNone, err + } + + return checkHostSecurityARM64Generic(env, log, integrity) +} + +func checkHostSecurityARM64Generic(env internal_efi.HostEnvironment, log *tcglog.Log, integrity platformFirmwareIntegrityConfig) (platformFirmwareIntegrityConfig, error) { + var errs []error + + 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 integrity, joinErrors(errs...) + } + + return integrity, nil +} + +// checkDiscreteTPMPartialResetAttackMitigationStatusARM64 determines whether a partial mitigation +// against discrete TPM reset attacks should be enabled. +func checkDiscreteTPMPartialResetAttackMitigationStatusARM64(env internal_efi.HostEnvironment, _ *pcrBankResults) (discreteTPMPartialResetAttackMitigationStatus, error) { + discreteTPM, err := isTPMDiscrete(env) + if err != nil { + return dtpmPartialResetAttackMitigationUnknown, &TPM2DeviceError{err} + } + if !discreteTPM { + return dtpmPartialResetAttackMitigationNotRequired, nil + } + + // ARM64 has no generic mechanism to establish that the TPM startup locality + // is protected by the hardware root of trust, so PCR0 binding cannot be relied + // on to mitigate an independent reset of a discrete TPM. + 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_nvidia.go b/efi/preinstall/check_host_security_nvidia.go new file mode 100644 index 00000000..1bd2f751 --- /dev/null +++ b/efi/preinstall/check_host_security_nvidia.go @@ -0,0 +1,61 @@ +// -*- 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 + +import ( + "fmt" + "strings" + + internal_efi "github.com/snapcore/secboot/internal/efi" +) + +const nvidiaDGXSparkCPUVersion = "GB10" +const nvidiaRTXSparkCPUVersionPrefix = "NVIDIA RTX Spark" + +// isNvidiaSparkCPUVersion reports whether cpuVersion identifies a supported NVIDIA +// Spark platform: either the DGX Spark (exact match on "GB10") or any RTX Spark +// variant (prefix match on "NVIDIA RTX Spark"). +func isNvidiaSparkCPUVersion(cpuVersion string) bool { + return cpuVersion == nvidiaDGXSparkCPUVersion || strings.HasPrefix(cpuVersion, nvidiaRTXSparkCPUVersionPrefix) +} + +func checkHostSecurityNVIDIA(env internal_efi.HostEnvironmentARM64) (platformFirmwareIntegrityConfig, error) { + cpuVersion, err := env.CPUVersion() + if err != nil { + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU version: %w", err)} + } + + switch { + case isNvidiaSparkCPUVersion(cpuVersion): + return checkHostSecurityNVIDIASpark(env) + default: + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("unsupported NVIDIA CPU version: %s", cpuVersion)} + } +} + +func checkHostSecurityNVIDIASpark(env internal_efi.HostEnvironmentARM64) (platformFirmwareIntegrityConfig, error) { + // TODO: Implement proper HW ROT fusing checks, once we have the documentation + // from NVIDIA to do so. This will involve checking fuses and will return + // platformFirmwareIntegrityVerified if set correctly. + + // TODO: Implement proper debug authentication checks, once we have the documentation + // from NVIDIA to do so. + return platformFirmwareIntegrityVerified, nil +} diff --git a/efi/preinstall/check_host_security_nvidia_test.go b/efi/preinstall/check_host_security_nvidia_test.go new file mode 100644 index 00000000..414488c1 --- /dev/null +++ b/efi/preinstall/check_host_security_nvidia_test.go @@ -0,0 +1,74 @@ +// -*- 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 ( + "errors" + + . "github.com/snapcore/secboot/efi/preinstall" + "github.com/snapcore/secboot/internal/efitest" + "github.com/snapcore/secboot/internal/testutil" + . "gopkg.in/check.v1" +) + +func (s *hostSecurityARM64Suite) TestCheckHostSecurityGoodDGXSparkVerified(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment("NVIDIA", "GB10"), + efitest.WithSysfsDevices(makeArm64IOMMUDevices()...), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(err, IsNil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) +} + +func (s *hostSecurityARM64Suite) TestCheckHostSecurityGoodRTXSparkVerified(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment("NVIDIA", "NVIDIA RTX Spark N1X (5120-core GPU, 18-core CPU)"), + efitest.WithSysfsDevices(makeArm64IOMMUDevices()...), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(err, IsNil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) +} + +func (s *hostSecurityARM64Suite) TestCheckHostSecurityGoodRTXSparkAlternativeSKUVerified(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment("NVIDIA", "NVIDIA RTX Spark N1X (4096-core GPU, 16-core CPU)"), + efitest.WithSysfsDevices(makeArm64IOMMUDevices()...), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(err, IsNil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) +} + +func (s *hostSecurityARM64Suite) TestCheckHostSecurityErrUnsupportedNVIDIACPUVersion(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithARM64Environment("NVIDIA", "N2X")) + + _, err := CheckHostSecurity(env, nil) + c.Check(err, ErrorMatches, `unsupported platform: unsupported NVIDIA CPU version: N2X`) + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} diff --git a/efi/preinstall/check_host_security_test.go b/efi/preinstall/check_host_security_test.go index 404877db..9b81e2b0 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,587 @@ 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) +} + +type hostSecurityARM64Suite struct { + snapd_testutil.BaseTest +} + +func (s *hostSecurityARM64Suite) SetUpTest(c *C) { + s.BaseTest.SetUpTest(c) + s.AddCleanup(MockRuntimeGOARCH("arm64")) +} + +var _ = Suite(&hostSecurityARM64Suite{}) + +type hostSecurityARM64ErrorEnv struct { + cpuManufacturer string + cpuVersion string +} + +func (e *hostSecurityARM64ErrorEnv) CPUManufacturer() (string, error) { + return e.cpuManufacturer, nil +} + +func (e *hostSecurityARM64ErrorEnv) CPUVersion() (string, error) { + return e.cpuVersion, nil +} + +func makeArm64IOMMUDevices() []internal_efi.SysfsDevice { + return []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/platform/soc@0/8000000.iommu", nil, "iommu", nil, nil), + } +} + +func makeArm64PCRResults(c *C) *PCRBankResults { + return NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + }) +} + +func (s *hostSecurityARM64Suite) TestCheckHostSecurityErrNotARM64(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts() + + _, err := CheckHostSecurity(env, nil) + c.Check(err, ErrorMatches, `unsupported platform: cannot obtain ARM64 environment: not a ARM64 host`) + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecurityARM64Suite) TestCheckHostSecurityErrUnknownCPUManufacturer(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithARM64Environment("ACME", exampleARM64CPUVersion)) + + _, err := CheckHostSecurity(env, nil) + c.Check(err, ErrorMatches, `unsupported platform: unsupported CPU manufacturer: ACME`) + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecurityARM64Suite) TestCheckHostSecurityUEFIDebuggerFinding(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment(exampleARM64CPUManufacturer, exampleARM64CPUVersion), + efitest.WithSysfsDevices(makeArm64IOMMUDevices()...), + ) + log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(integrity, Equals, PlatformFirmwareIntegrityMeasured) + 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 *hostSecurityARM64Suite) TestCheckHostSecurityInsufficientDMAProtection(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment(exampleARM64CPUManufacturer, exampleARM64CPUVersion), + efitest.WithSysfsDevices(makeArm64IOMMUDevices()...), + ) + log := efitest.NewLog(c, &efitest.LogOptions{DMAProtection: efitest.DMAProtectionDisabled}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(integrity, Equals, PlatformFirmwareIntegrityMeasured) + c.Check(err, ErrorMatches, `the platform firmware indicates that DMA protections are insufficient`) + var tmpl CompoundError + c.Assert(err, Implements, &tmpl) + c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrInsufficientDMAProtection}) +} + +func (s *hostSecurityARM64Suite) TestCheckHostSecurityNoIOMMU(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment(exampleARM64CPUManufacturer, exampleARM64CPUVersion), + efitest.WithSysfsDevices(), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(integrity, Equals, PlatformFirmwareIntegrityMeasured) + 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 *hostSecurityARM64Suite) TestCheckHostSecurityMultipleRecoverableErrors(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment(exampleARM64CPUManufacturer, exampleARM64CPUVersion), + efitest.WithSysfsDevices(), + ) + log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(integrity, Equals, PlatformFirmwareIntegrityMeasured) + 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 *hostSecurityARM64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusUnknownForUnsupportedCPUManufacturer(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment(exampleARM64CPUManufacturer, exampleARM64CPUVersion), + efitest.WithSysfsDevices(makeArm64TPMDevice("tpm_crb")), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, makeArm64PCRResults(c)) + c.Check(status, Equals, DtpmPartialResetAttackMitigationUnknown) + c.Check(err, ErrorMatches, `error with TPM2 device: unsupported platform: unsupported CPU manufacturer: `+exampleARM64CPUManufacturer) + var tpmErr *TPM2DeviceError + c.Check(errors.As(err, &tpmErr), testutil.IsTrue) + c.Check(status, Equals, DtpmPartialResetAttackMitigationUnknown) +} + +func (s *hostSecurityARM64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusNotRequiredForOPTEE(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment(exampleARM64CPUManufacturer, exampleARM64CPUVersion), + efitest.WithSysfsDevices(makeArm64TPMDevice("optee-ftpm")), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, makeArm64PCRResults(c)) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) +} + +func (s *hostSecurityARM64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusUnavailableForNvidiaDGXSpark(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment("NVIDIA", "GB10"), + efitest.WithSysfsDevices(makeArm64TPMDevice("tpm_crb")), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, makeArm64PCRResults(c)) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) +} + +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..078ff680 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,9 +21,11 @@ package preinstall import ( "bytes" + "errors" "fmt" "github.com/canonical/go-tpm2" + "github.com/pilebones/go-udev/netlink" internal_efi "github.com/snapcore/secboot/internal/efi" ) @@ -467,3 +469,106 @@ 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) + case "arm64": + return isTPMDiscreteARM64(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") + } +} + +// isTPMDiscreteARM64 determines whether the default TPM is discrete. OP-TEE firmware +// TPMs are identified by their backing kernel driver. Other implementations use +// platform-specific knowledge. +func isTPMDiscreteARM64(env internal_efi.HostEnvironment) (bool, error) { + isOpteefTPM, err := isTPMFirmwareOptee(env) + if err != nil { + return false, err + } + if isOpteefTPM { + return false, nil + } + + arm64Env, err := env.ARM64() + if err != nil { + return false, err + } + + cpuManufacturer, err := arm64Env.CPUManufacturer() + if err != nil { + return false, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU manufacturer: %w", err)} + } + + switch cpuManufacturer { + case "NVIDIA": + return isTPMDiscreteNvidia(arm64Env) + default: + return false, &UnsupportedPlatformError{fmt.Errorf("unsupported CPU manufacturer: %s", cpuManufacturer)} + } +} + +// isTPMFirmwareOptee determines whether the default TPM is an OP-TEE firmware TPM, +// as identified by its backing kernel driver +func isTPMFirmwareOptee(env internal_efi.HostEnvironment) (bool, error) { + devices, err := env.EnumerateDevices(&netlink.RuleDefinition{ + Env: map[string]string{ + "SUBSYSTEM": "tpm", + "DEVNAME": "tpm0", + }, + }) + if err != nil { + return false, fmt.Errorf("cannot enumerate TPM devices: %w", err) + } + if len(devices) != 1 { + return false, fmt.Errorf("internal error: expected one tpm0 device, found %d", len(devices)) + } + + parent, err := devices[0].Parent() + if err != nil { + return false, fmt.Errorf("cannot obtain parent of tpm0 device: %w", err) + } + if parent == nil { + return false, fmt.Errorf("internal error: tpm0 device has no parent") + } + + switch parent.Properties()["DRIVER"] { + case "optee-ftpm", "ftpm-tee": + return true, nil + default: + return false, nil + } +} 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_amd64.go b/efi/preinstall/check_tpm_nvidia.go similarity index 54% rename from efi/preinstall/check_tpm_amd64.go rename to efi/preinstall/check_tpm_nvidia.go index bb0fecaf..9041734d 100644 --- a/efi/preinstall/check_tpm_amd64.go +++ b/efi/preinstall/check_tpm_nvidia.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 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 @@ -20,34 +20,23 @@ 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() +// isTPMDiscreteNvidia determines whether the default TPM is discrete on NVIDIA systems +func isTPMDiscreteNvidia(env internal_efi.HostEnvironmentARM64) (bool, error) { + cpuVersion, err := env.CPUVersion() if err != nil { - return false, err + return false, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU version: %w", 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")} + switch { + // We just happen to know that the NVIDIA DGX Spark and RTX Spark have a dTPM + case isNvidiaSparkCPUVersion(cpuVersion): + return true, nil default: - panic("not reached") + return false, &UnsupportedPlatformError{fmt.Errorf("unsupported NVIDIA CPU version: %s", cpuVersion)} } } diff --git a/efi/preinstall/check_tpm_nvidia_test.go b/efi/preinstall/check_tpm_nvidia_test.go new file mode 100644 index 00000000..09b08811 --- /dev/null +++ b/efi/preinstall/check_tpm_nvidia_test.go @@ -0,0 +1,74 @@ +// -*- 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 ( + "errors" + + . "github.com/snapcore/secboot/efi/preinstall" + "github.com/snapcore/secboot/internal/efitest" + "github.com/snapcore/secboot/internal/testutil" + . "gopkg.in/check.v1" +) + +func (s *tpmARM64Suite) TestIsTPMDiscreteDGXSpark(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment("NVIDIA", "GB10"), + efitest.WithSysfsDevices(makeArm64TPMDevice("tpm_crb")), + ) + + discrete, err := IsTPMDiscrete(env) + c.Check(err, IsNil) + c.Check(discrete, testutil.IsTrue) +} + +func (s *tpmARM64Suite) TestIsTPMDiscreteRTXSpark(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment("NVIDIA", "NVIDIA RTX Spark N1X (5120-core GPU, 18-core CPU)"), + efitest.WithSysfsDevices(makeArm64TPMDevice("tpm_crb")), + ) + + discrete, err := IsTPMDiscrete(env) + c.Check(err, IsNil) + c.Check(discrete, testutil.IsTrue) +} + +func (s *tpmARM64Suite) TestIsTPMDiscreteRTXSparkAlternativeSKU(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment("NVIDIA", "NVIDIA RTX Spark N1X (4096-core GPU, 16-core CPU)"), + efitest.WithSysfsDevices(makeArm64TPMDevice("tpm_crb")), + ) + + discrete, err := IsTPMDiscrete(env) + c.Check(err, IsNil) + c.Check(discrete, testutil.IsTrue) +} + +func (s *tpmARM64Suite) TestIsTPMDiscreteErrUnsupportedNVIDIACPUVersion(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment("NVIDIA", "N2X"), + efitest.WithSysfsDevices(makeArm64TPMDevice("tpm_crb")), + ) + + _, err := IsTPMDiscrete(env) + c.Check(err, ErrorMatches, `unsupported platform: unsupported NVIDIA CPU version: N2X`) + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} diff --git a/efi/preinstall/check_tpm_test.go b/efi/preinstall/check_tpm_test.go index 93a7e43c..b242ac18 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 @@ -27,9 +27,11 @@ import ( "github.com/canonical/go-tpm2/objectutil" tpm2_testutil "github.com/canonical/go-tpm2/testutil" . "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" "github.com/snapcore/secboot/internal/tpm2_device" + snapd_testutil "github.com/snapcore/snapd/testutil" . "gopkg.in/check.v1" ) @@ -1149,3 +1151,120 @@ 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) +} + +type tpmARM64Suite struct { + snapd_testutil.BaseTest +} + +func (s *tpmARM64Suite) SetUpTest(c *C) { + s.BaseTest.SetUpTest(c) + s.AddCleanup(MockRuntimeGOARCH("arm64")) +} + +var _ = Suite(&tpmARM64Suite{}) + +func makeArm64TPMDevice(driver string) internal_efi.SysfsDevice { + parent := efitest.NewMockSysfsDevice( + "/sys/devices/platform/firmware-tpm", + map[string]string{"DRIVER": driver}, + "platform", + nil, + nil, + ) + return efitest.NewMockSysfsDevice( + "/sys/devices/platform/firmware-tpm/tpm/tpm0", + map[string]string{"DEVNAME": "tpm0"}, + "tpm", + nil, + parent, + ) +} + +func (s *tpmARM64Suite) TestIsTPMDiscreteOPTEE(c *C) { + for _, driver := range []string{"optee-ftpm", "ftpm-tee"} { + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithSysfsDevices(makeArm64TPMDevice(driver))) + + discrete, err := IsTPMDiscrete(env) + c.Check(err, IsNil, Commentf("driver %q", driver)) + c.Check(discrete, testutil.IsFalse, Commentf("driver %q", driver)) + } +} + +func (s *tpmARM64Suite) TestIsTPMDiscreteUnsupportedCPUManufacturer(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithARM64Environment("ACME", "Unknown"), + efitest.WithSysfsDevices(makeArm64TPMDevice("tpm_crb")), + ) + + _, err := IsTPMDiscrete(env) + c.Check(err, ErrorMatches, `unsupported platform: unsupported CPU manufacturer: ACME`) + 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..f50fad27 --- /dev/null +++ b/efi/preinstall/checks_fixture_test.go @@ -0,0 +1,269 @@ +// -*- 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 + devices []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.devices...) + 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)) +} + +const ( + exampleARM64CPUManufacturer = "Example Manufacturer" + exampleARM64CPUVersion = "Example OP-TEE SoC" +) + +func init() { + RegisterARM64TestPlatform(exampleARM64CPUManufacturer, exampleARM64CPUVersion) +} + +func runChecksArm64TPMDevice(driver string) internal_efi.SysfsDevice { + parent := efitest.NewMockSysfsDevice( + "/sys/devices/platform/firmware-tpm", + map[string]string{"DRIVER": driver}, + "platform", + nil, + nil, + ) + + return efitest.NewMockSysfsDevice( + "/sys/devices/platform/firmware-tpm/tpm/tpm0", + map[string]string{"DEVNAME": "tpm0"}, + "tpm", + nil, + parent, + ) +} + +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, + ))) + } + + newDevices := func(tpmDriver string, withIOMMU bool) []internal_efi.SysfsDevice { + devices := []internal_efi.SysfsDevice{runChecksArm64TPMDevice(tpmDriver)} + if withIOMMU { + devices = append([]internal_efi.SysfsDevice{efitest.NewMockSysfsDevice("/sys/devices/platform/smmu0", nil, "iommu", nil, nil)}, devices...) + } + return devices + } + + 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, + devices: 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, + devices: 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, + devices: 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, + devices: 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, + devices: 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", + }, + // arm64 fixtures + { + name: "example-arm64-optee-ftpm", + capabilities: runChecksHostCapabilityValid | + runChecksHostCapabilityNotVirtualMachine | + runChecksHostCapabilityFirmwareTPM, + environment: efitest.WithARM64Environment(exampleARM64CPUManufacturer, exampleARM64CPUVersion), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + devices: newDevices("optee-ftpm", true), + additionalExpectedFlags: RequireLockToPlatformFirmware, + arch: "arm64", + }, + { + name: "example-arm64-optee-ftpm-no-kernel-iommu", + capabilities: runChecksHostCapabilityNotVirtualMachine | runChecksHostCapabilityNoKernelIOMMU | runChecksHostCapabilityFirmwareTPM, + environment: efitest.WithARM64Environment(exampleARM64CPUManufacturer, exampleARM64CPUVersion), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + devices: newDevices("optee-ftpm", false), + additionalExpectedFlags: RequireLockToPlatformFirmware, + arch: "arm64", + }, + { + name: "nvidia-dgx-spark-tpm-crb", + capabilities: runChecksHostCapabilityValid | + runChecksHostCapabilityNotVirtualMachine | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality0AccessibleFromOS | + runChecksHostCapabilityStartupLocality3AccessibleFromOS | + runChecksHostCapabilityStartupLocality4AccessibleFromOS, + environment: efitest.WithARM64Environment("NVIDIA", "GB10"), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + devices: newDevices("tpm_crb", true), + arch: "arm64", + }, + } +} diff --git a/efi/preinstall/checks_test.go b/efi/preinstall/checks_test.go index d1a5a4cb..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) @@ -124,3336 +124,2452 @@ func (s *runChecksSuite) testRunChecks(c *C, params *testRunChecksParams) (warni c.Assert(dev.(*tpmDevice).TPMDevice, testutil.ConvertibleTo, &tpm2_testutil.TransportBackedDevice{}) c.Check(dev.(*tpmDevice).TPMDevice.(*tpm2_testutil.TransportBackedDevice).NumberOpen(), Equals, 0) - return result.Warnings.Unwrap(), nil + if result.Warnings != nil { + warnings = result.Warnings.Unwrap() + } + return warnings, nil } 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, + 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) } - 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) TestRunChecksGoodDiscreteTPMDetectedHCRTM(c *C) { + 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) + + 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.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, - )), +func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetectedHCRTMLocality4NotProtected(c *C) { + 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, 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) } -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, - )), - } +func (s *runChecksSuite) TestRunChecksGoodInvalidPCR0Value(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() { + _, 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}, - 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 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[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) -} + 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) -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, - )), - } + 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) - 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[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) 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, - )), + 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) } - - 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[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, + 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) } - 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, - })), - 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: -- \[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) } 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, - )), - } - - 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: + 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[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[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[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, - )), - } - - 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: + 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 `) - 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[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) 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, - )), - } - - 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 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: + 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[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[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) 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, - )), - } - - 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) + 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) - 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 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[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, Equals, ErrAbsoluteComputraceActive) + warning = warnings[2] + c.Check(warning, Equals, ErrAbsoluteComputraceActive) - 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) 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, - )), - } + 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}, + 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) - 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[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) 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[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) } +} - 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) 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")}, }, - // 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) + 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[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: + 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, + 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[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 @@ -3473,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) { @@ -3837,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..762599b0 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 @@ -22,6 +22,7 @@ package preinstall import ( "crypto" "encoding/json" + "fmt" "io" efi "github.com/canonical/go-efilib" @@ -37,8 +38,14 @@ type ( BootManagerCodeResult = bootManagerCodeResult CheckFirmwareLogFlags = checkFirmwareLogFlags CheckTPM2DeviceFlags = checkTPM2DeviceFlags + CpuVendor = cpuVendor DetectVirtResult = detectVirtResult + HfstsRegisters = hfstsRegisters + HfstsRegistersCsme11 = hfstsRegistersCsme11 + HfstsRegistersCsme18 = hfstsRegistersCsme18 JoinError = joinError + MeVersion = meVersion + PCRBankResults = pcrBankResults PcrResults = pcrResults SecureBootPolicyResult = secureBootPolicyResult SecureBootPolicyResultFlags = secureBootPolicyResultFlags @@ -49,6 +56,8 @@ const ( AuthorityTrustDrivers = authorityTrustDrivers CheckFirmwareLogPermitWeakPCRBanks = checkFirmwareLogPermitWeakPCRBanks CheckTPM2DevicePostInstall = checkTPM2DevicePostInstall + CpuVendorAMD = cpuVendorAMD + CpuVendorIntel = cpuVendorIntel DetectVirtNone = detectVirtNone DetectVirtVM = detectVirtVM DiscreteTPMDetected = discreteTPMDetected @@ -56,6 +65,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 +80,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 +98,21 @@ var ( CheckSystemIsEFI = checkSystemIsEFI CheckTPM2ForRequiredPCClientFeatures = checkTPM2ForRequiredPCClientFeatures ClearTPM = clearTPM + DetermineCPUVendor = determineCPUVendor DetectVirtualization = detectVirtualization + DtpmPartialResetAttackMitigationUnknown = dtpmPartialResetAttackMitigationUnknown 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 +185,28 @@ 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 } +} + +func RegisterARM64TestPlatform(cpuManufacturer, cpuVersion string) { + previous := checkHostSecurityARM64Platform + checkHostSecurityARM64Platform = func(env internal_efi.HostEnvironmentARM64, manufacturer string) (platformFirmwareIntegrityConfig, error) { + if manufacturer != cpuManufacturer { + return previous(env, manufacturer) + } + + version, err := env.CPUVersion() + if err != nil { + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU version: %w", err)} + } + if version != cpuVersion { + return previous(env, manufacturer) + } + + return platformFirmwareIntegrityMeasured, nil + } +} 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.go b/internal/efi/default_env.go index 20e851fc..c1f91bae 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 @@ -27,6 +27,8 @@ import ( "os" "os/exec" "path/filepath" + "runtime" + "strings" efi "github.com/canonical/go-efilib" "github.com/canonical/tcglog-parser" @@ -43,6 +45,13 @@ var ( 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 + + // 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. + runtimeGOARCH = runtime.GOARCH + + dmiProcessorInfoPath = "/sys/firmware/dmi/entries/4-0/raw" ) func SetEventLogPath(path string) { @@ -240,3 +249,92 @@ func (defaultEnvImpl) EnumerateDevices(matcher netlink.Matcher) ([]SysfsDevice, // DefaultEnv corresponds to the environment associated with the host // machine. var DefaultEnv = defaultEnvImpl{} + +type defaultEnvARM64Impl struct{} + +// smbiosType4ManufacturerOffset is the byte offset of the Manufacturer string +// index within an SMBIOS type 4 (Processor Information) formatted area. +const smbiosType4ManufacturerOffset = 0x07 + +// smbiosType4VersionOffset is the byte offset of the Version string index +// within an SMBIOS type 4 (Processor Information) formatted area. +const smbiosType4VersionOffset = 0x10 + +// decodeSMBIOSType4Field decodes a string field from an SMBIOS type 4 +// (Processor Information) structure blob. data is the raw binary blob read +// from the kernel's DMI entries sysfs interface. fieldOffset is the byte +// offset within the formatted area that holds the 1-based string index. +// +// Layout (DMTF SMBIOS specification): +// - byte 0: structure type (must be 4) +// - byte 1: length of the formatted area including the header +// - bytes 2-3: handle +// - bytes 4…: remaining formatted area +// - after the formatted area: NUL-terminated strings; string set ends +// with an additional NUL (empty string sentinel) +func decodeSMBIOSType4Field(data []byte, fieldOffset uint8) (string, error) { + if len(data) < 4 { + return "", fmt.Errorf("SMBIOS structure too short for header: have %d bytes", len(data)) + } + structType := data[0] + formattedLen := data[1] + if structType != 4 { + return "", fmt.Errorf("unexpected SMBIOS structure type %d (expected 4)", structType) + } + if int(formattedLen) <= int(fieldOffset) { + return "", fmt.Errorf("SMBIOS structure too short to contain field at offset 0x%02x: formatted area length is %d", fieldOffset, formattedLen) + } + if len(data) < int(formattedLen) { + return "", fmt.Errorf("SMBIOS structure data truncated: have %d bytes, formatted area length is %d", len(data), formattedLen) + } + strIdx := data[fieldOffset] + if strIdx == 0 { + return "", fmt.Errorf("SMBIOS field at offset 0x%02x is unset", fieldOffset) + } + stringsData := data[formattedLen:] + var n uint8 + for i := 0; i < len(stringsData); { + end := i + for end < len(stringsData) && stringsData[end] != 0 { + end++ + } + if i == end { + // Empty string: end-of-string-set sentinel. + break + } + n++ + if n == strIdx { + return strings.TrimSpace(string(stringsData[i:end])), nil + } + i = end + 1 + } + return "", fmt.Errorf("SMBIOS string index %d is out of range", strIdx) +} + +// CPUManufacturer implements [HostEnvironmentARM64.CPUManufacturer]. +func (defaultEnvARM64Impl) CPUManufacturer() (string, error) { + data, err := osReadFile(dmiProcessorInfoPath) + if err != nil { + return "", fmt.Errorf("cannot read %s: %w", dmiProcessorInfoPath, err) + } + return decodeSMBIOSType4Field(data, smbiosType4ManufacturerOffset) +} + +// CPUVersion implements [HostEnvironmentARM64.CPUVersion]. +func (defaultEnvARM64Impl) CPUVersion() (string, error) { + data, err := osReadFile(dmiProcessorInfoPath) + if err != nil { + return "", fmt.Errorf("cannot read %s: %w", dmiProcessorInfoPath, err) + } + return decodeSMBIOSType4Field(data, smbiosType4VersionOffset) +} + +// ARM64 implements [HostEnvironment.ARM64]. +// 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) ARM64() (HostEnvironmentARM64, error) { + if runtimeGOARCH != "arm64" { + return nil, ErrNotARM64Host + } + return defaultEnvARM64Impl{}, nil +} diff --git a/internal/efi/default_env_amd64.go b/internal/efi/default_env_amd64.go index b9b13917..a73b9aa2 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 +// Unlike the ARM64 implementation (in default_env.go), 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/default_env_test.go b/internal/efi/default_env_test.go index 70f7e69e..c0058bd4 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 @@ -22,6 +22,7 @@ package efi_test import ( "context" "errors" + "fmt" "io" "os" "path/filepath" @@ -638,3 +639,326 @@ func (s *defaultEnvSuite) TestSysfsDeviceParentNoParent(c *C) { c.Check(err, IsNil) c.Check(parent, IsNil) } + +type defaultEnvARM64Suite struct { + snapd_testutil.BaseTest +} + +var _ = Suite(&defaultEnvARM64Suite{}) + +func (s *defaultEnvARM64Suite) SetUpTest(c *C) { + s.BaseTest.SetUpTest(c) + s.AddCleanup(MockRuntimeGOARCH("arm64")) +} + +// buildSMBIOSType4 constructs a synthetic SMBIOS type 4 (Processor Information) +// blob for testing. formattedArea contains the raw formatted area bytes +// (including the 4-byte header: type, length, handle×2); formattedArea[0] +// should be set to the desired type byte and formattedArea[1] is overwritten +// with len(formattedArea). strs are the string-set entries appended in order. +func buildSMBIOSType4(formattedArea []byte, strs ...string) []byte { + fa := make([]byte, len(formattedArea)) + copy(fa, formattedArea) + if len(fa) >= 2 { + fa[1] = byte(len(fa)) + } + out := append([]byte(nil), fa...) + for _, s := range strs { + out = append(out, s...) + out = append(out, 0) + } + out = append(out, 0) // end-of-string-set sentinel + return out +} + +// makeValidType4Blob returns a minimal valid SMBIOS type 4 blob whose +// Manufacturer field (0x07) points to string 1 and Version field (0x10) +// points to string 2. +func makeValidType4Blob(manufacturer, version string) []byte { + fa := make([]byte, 0x11) // 17 bytes: includes offsets 0x07 and 0x10 + fa[0] = 4 // structure type 4 + fa[0x07] = 1 // Manufacturer = string 1 + fa[0x10] = 2 // Version = string 2 + return buildSMBIOSType4(fa, manufacturer, version) +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturer(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + return makeValidType4Blob("NVIDIA", "GB10"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + manufacturer, err := arm64.CPUManufacturer() + c.Check(err, IsNil) + c.Check(manufacturer, Equals, "NVIDIA") +} + +func (s *defaultEnvARM64Suite) TestCPUVersion(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + return makeValidType4Blob("NVIDIA", "GB10"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + version, err := arm64.CPUVersion() + c.Check(err, IsNil) + c.Check(version, Equals, "GB10") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerWhitespaceTrimming(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + return makeValidType4Blob("\t Example Manufacturer \t", "Example Version"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + manufacturer, err := arm64.CPUManufacturer() + c.Check(err, IsNil) + c.Check(manufacturer, Equals, "Example Manufacturer") +} + +func (s *defaultEnvARM64Suite) TestCPUVersionWhitespaceTrimming(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + return makeValidType4Blob("Example Manufacturer", "\t Example Version \t"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + version, err := arm64.CPUVersion() + c.Check(err, IsNil) + c.Check(version, Equals, "Example Version") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerReadError(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + return nil, errors.New("some error") + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + _, err = arm64.CPUManufacturer() + c.Check(err, ErrorMatches, "cannot read /sys/firmware/dmi/entries/4-0/raw: some error") +} + +func (s *defaultEnvARM64Suite) TestCPUVersionReadError(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + return nil, errors.New("some error") + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + _, err = arm64.CPUVersion() + c.Check(err, ErrorMatches, "cannot read /sys/firmware/dmi/entries/4-0/raw: some error") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerWrongStructureType(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + fa := make([]byte, 0x11) + fa[0] = 1 // wrong type (System Information, not Processor Information) + fa[0x07] = 1 // Manufacturer = string 1 + fa[0x10] = 2 // Version = string 2 + return buildSMBIOSType4(fa, "NVIDIA", "GB10"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + _, err = arm64.CPUManufacturer() + c.Check(err, ErrorMatches, "unexpected SMBIOS structure type 1 \\(expected 4\\)") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerTooShortForHeader(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + return []byte{4, 3, 0}, nil // only 3 bytes, not enough for header + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + _, err = arm64.CPUManufacturer() + c.Check(err, ErrorMatches, "SMBIOS structure too short for header: have 3 bytes") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerFormattedAreaTooShort(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + // Formatted area is only 7 bytes; Manufacturer is at 0x07, + // so formattedLen (7) <= fieldOffset (7): field not present. + fa := make([]byte, 7) + fa[0] = 4 + fa[0x06] = 1 // not the manufacturer field, just filler + return buildSMBIOSType4(fa, "NVIDIA"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + _, err = arm64.CPUManufacturer() + c.Check(err, ErrorMatches, "SMBIOS structure too short to contain field at offset 0x07: formatted area length is 7") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerDataTruncated(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + // Length field says 0x11 bytes but we only provide 8. + data := make([]byte, 8) + data[0] = 4 + data[1] = 0x11 // claims 17-byte formatted area + data[0x07] = 1 + return data, nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + _, err = arm64.CPUManufacturer() + c.Check(err, ErrorMatches, "SMBIOS structure data truncated: have 8 bytes, formatted area length is 17") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerOutOfRangeStringIndex(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + fa := make([]byte, 0x11) + fa[0] = 4 + fa[0x07] = 3 // Manufacturer = string 3, but only 2 strings exist + fa[0x10] = 2 + return buildSMBIOSType4(fa, "NVIDIA", "GB10"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + _, err = arm64.CPUManufacturer() + c.Check(err, ErrorMatches, "SMBIOS string index 3 is out of range") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerUnsetStringIndex(c *C) { + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + fa := make([]byte, 0x11) + fa[0] = 4 + fa[0x07] = 0 // Manufacturer unset (index 0) + fa[0x10] = 1 + return buildSMBIOSType4(fa, "GB10"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + _, err = arm64.CPUManufacturer() + c.Check(err, ErrorMatches, "SMBIOS field at offset 0x07 is unset") +} + +// makeRealisticType4Blob returns a SMBIOS type 4 blob laid out like the ones +// observed on real NVIDIA Spark hardware: a 0x32 byte formatted area, with +// Socket Designation as string 1, Manufacturer as string 2, Version as string +// 3, and further strings following Version. +func makeRealisticType4Blob(manufacturer, version string) []byte { + fa := make([]byte, 0x32) // 50 bytes, as reported by dmidecode on DGX Spark and RTX Spark + fa[0] = 4 // structure type 4 + fa[0x04] = 1 // Socket Designation = string 1 + fa[0x07] = 2 // Manufacturer = string 2 + fa[0x10] = 3 // Version = string 3 + return buildSMBIOSType4(fa, "CPU01", manufacturer, version, "NA", "NA", "Spark") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerAndVersionDGXSparkLayout(c *C) { + // Regression test using the structure shape reported by a real DGX Spark, + // where Version is string 3 and is followed by more strings. + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + return makeRealisticType4Blob("NVIDIA", "GB10"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + manufacturer, err := arm64.CPUManufacturer() + c.Check(err, IsNil) + c.Check(manufacturer, Equals, "NVIDIA") + + version, err := arm64.CPUVersion() + c.Check(err, IsNil) + c.Check(version, Equals, "GB10") +} + +func (s *defaultEnvARM64Suite) TestCPUManufacturerAndVersionRTXSparkLayout(c *C) { + // Regression test using the structure shape and version string reported by + // a real RTX Spark. + restore := MockOsReadFile(func(path string) ([]byte, error) { + if path == "/sys/firmware/dmi/entries/4-0/raw" { + return makeRealisticType4Blob("NVIDIA", "NVIDIA RTX Spark N1X (5120-core GPU, 18-core CPU)"), nil + } + return nil, fmt.Errorf("unexpected path: %s", path) + }) + defer restore() + + arm64, err := DefaultEnv.ARM64() + c.Assert(err, IsNil) + + manufacturer, err := arm64.CPUManufacturer() + c.Check(err, IsNil) + c.Check(manufacturer, Equals, "NVIDIA") + + version, err := arm64.CPUVersion() + c.Check(err, IsNil) + c.Check(version, Equals, "NVIDIA RTX Spark N1X (5120-core GPU, 18-core CPU)") +} + +func (s *defaultEnvARM64Suite) TestNotARM64Host(c *C) { + // Override the arm64 mock installed by SetUpTest: on a non-arm64 host + // ARM64() must return ErrNotARM64Host. + restore := MockRuntimeGOARCH("amd64") + defer restore() + + _, err := DefaultEnv.ARM64() + c.Check(err, Equals, ErrNotARM64Host) +} diff --git a/internal/efi/env.go b/internal/efi/env.go index 20b05d52..043d9596 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, @@ -83,6 +93,18 @@ type HostEnvironmentAMD64 interface { ReadMSRs(msr uint32) (map[uint32]uint64, error) } +// HostEnvironmentARM64 is an interface that abstracts out a host environment specific +// to ARM64 platforms. +type HostEnvironmentARM64 interface { + // CPUManufacturer returns the processor manufacturer from the SMBIOS + // type 4 (Processor Information) structure. + CPUManufacturer() (string, error) + + // CPUVersion returns the processor version from the SMBIOS + // type 4 (Processor Information) structure. + CPUVersion() (string, error) +} + // DetectVirtMode controls what type of virtualization to test for. type DetectVirtMode int @@ -113,6 +135,10 @@ var ( // are not AMD64. ErrNotAMD64Host = errors.New("not a AMD64 host") + // ErrNotARM64Host is returned from HostEnvironment.ARM64 on environments that + // are not ARM64. + ErrNotARM64Host = errors.New("not a ARM64 host") + // ErrNoKernelMSRSupport is returned from HostEnvironmentAMD64.ReadMSRs if there is // no support for reading MSRs. ErrNoKernelMSRSupport = errors.New("missing kernel support for reading MSRs") @@ -140,6 +166,10 @@ type HostEnvironment interface { EnumerateDevices(matcher netlink.Matcher) ([]SysfsDevice, error) // AMD64 returns an interface that can be used to mock some parts of an AMD64 platform. - // This will return ErrNotAMD64CPU on non-AMD64 platforms. + // This will return ErrNotAMD64Host on non-AMD64 platforms. AMD64() (HostEnvironmentAMD64, error) + + // ARM64 returns an interface that can be used to mock some parts of an ARM64 platform. + // This will return ErrNotARM64Host on non-ARM64 platforms. + ARM64() (HostEnvironmentARM64, error) } diff --git a/internal/efi/export_test.go b/internal/efi/export_test.go index e2828882..7cd553b2 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,11 @@ func MockOsReadlink(fn func(string) (string, error)) (restore func()) { osReadlink = orig } } + +func MockRuntimeGOARCH(arch string) (restore func()) { + oldRuntimeGOARCH := runtimeGOARCH + runtimeGOARCH = arch + return func() { + runtimeGOARCH = oldRuntimeGOARCH + } +} diff --git a/internal/efitest/hostenv.go b/internal/efitest/hostenv.go index a1773682..bd2f8a45 100644 --- a/internal/efitest/hostenv.go +++ b/internal/efitest/hostenv.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 @@ -48,6 +48,7 @@ type MockHostEnvironment struct { Devices map[string]internal_efi.SysfsDevice AMD64Env internal_efi.HostEnvironmentAMD64 + ARM64Env internal_efi.HostEnvironmentARM64 } func NewMockHostEnvironment(vars MockVars, log *tcglog.Log) *MockHostEnvironment { @@ -149,6 +150,19 @@ func (e *mockHostEnvironmentAMD64) ReadMSRs(msr uint32) (map[uint32]uint64, erro return out, nil } +type mockHostEnvironmentARM64 struct { + cpuManufacturer string + cpuVersion string +} + +func (e *mockHostEnvironmentARM64) CPUManufacturer() (string, error) { + return e.cpuManufacturer, nil +} + +func (e *mockHostEnvironmentARM64) CPUVersion() (string, error) { + return e.cpuVersion, nil +} + // MockSysfsDevice is a mock implementation of [internal_efi.SysfsDevice]. type MockSysfsDevice struct { DevicePath string @@ -221,6 +235,16 @@ func WithAMD64Environment(cpuVendorIdentificator string, family uint32, cpuidFea } } +// WithARM64Environment adds a [github.com/snapcore/secboot/efi/internal.HostEnvironmentARM64] to the [MockHostEnvironment]. +func WithARM64Environment(cpuManufacturer, cpuVersion string) MockHostEnvironmentOption { + return func(env *MockHostEnvironment) { + env.ARM64Env = &mockHostEnvironmentARM64{ + cpuManufacturer: cpuManufacturer, + cpuVersion: cpuVersion, + } + } +} + // NewMockHostEnvironmentWithOpts returns a new MockHostEnvironment. func NewMockHostEnvironmentWithOpts(options ...MockHostEnvironmentOption) *MockHostEnvironment { env := &MockHostEnvironment{ @@ -308,3 +332,11 @@ func (e *MockHostEnvironment) AMD64() (internal_efi.HostEnvironmentAMD64, error) } return e.AMD64Env, nil } + +// ARM64 implements [github.com/snapcore/secboot/internal/efi.HostEnvironment.ARM64]. +func (e *MockHostEnvironment) ARM64() (internal_efi.HostEnvironmentARM64, error) { + if e.ARM64Env == nil { + return nil, internal_efi.ErrNotARM64Host + } + return e.ARM64Env, nil +}