diff --git a/efi/preinstall/check_host_security.go b/efi/preinstall/check_host_security.go index 61c0f9ff..35567ac3 100644 --- a/efi/preinstall/check_host_security.go +++ b/efi/preinstall/check_host_security.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -21,12 +21,20 @@ package preinstall import ( "bytes" + "errors" + "fmt" + "runtime" "github.com/canonical/tcglog-parser" "github.com/pilebones/go-udev/netlink" internal_efi "github.com/snapcore/secboot/internal/efi" ) +// runtimeGOARCH is the architecture that host security checks are performed +// for. It is a variable so that tests can run the checks for architectures +// other than the one the test binary was built for. +var runtimeGOARCH = runtime.GOARCH + // discreteTPMPartialResetAttackMitigationStatus indicates whether a partial mitigation against // discrete TPM reset attacks should be enabled. See the documentation for // RequestPartialDiscreteTPMResetAttackMitigation @@ -145,3 +153,145 @@ Loop: } return nil } + +// Architecture-specific host security checks are dispatched at runtime rather than +// selected by build constraints, so that all architectures' checks are compiled and +// testable everywhere. + +// checkHostSecurity is the main entry point for verifying that the host security +// is sufficient. Errors that can't be resolved or which should prevent further checks from running +// are returned immediately and without any wrapping. Errors that can be resolved and which shouldn't +// prevent further checks from running are returned wrapped in [joinError]. +func checkHostSecurity(env internal_efi.HostEnvironment, log *tcglog.Log) (platformFirmwareIntegrityConfig, error) { + switch runtimeGOARCH { + case "amd64": + return checkHostSecurityAMD64(env, log) + default: + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("checking host security is not implemented on %s", runtimeGOARCH)} + } +} + +// checkDiscreteTPMPartialResetAttackMitigationStatus determines whether a partial mitigation +// against discrete TPM reset attacks should be enabled. See the documentation for +// RequestPartialDiscreteTPMResetAttackMitigation. +func checkDiscreteTPMPartialResetAttackMitigationStatus(env internal_efi.HostEnvironment, logResults *pcrBankResults) (discreteTPMPartialResetAttackMitigationStatus, error) { + switch runtimeGOARCH { + case "amd64": + return checkDiscreteTPMPartialResetAttackMitigationStatusAMD64(env, logResults) + default: + return dtpmPartialResetAttackMitigationNotRequired, nil + } +} + +func checkHostSecurityAMD64(env internal_efi.HostEnvironment, log *tcglog.Log) (platformFirmwareIntegrityConfig, error) { + cpuVendor, err := determineCPUVendor(env) + if err != nil { + return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} + } + + amd64Env, err := env.AMD64() + if err != nil { + return platformFirmwareIntegrityNone, fmt.Errorf("cannot obtain AMD64 environment: %w", err) + } + + var errs []error + + var integrity platformFirmwareIntegrityConfig + switch cpuVendor { + case cpuVendorIntel: + if err := checkHostSecurityIntelBootGuard(env); err != nil { + var nohwrotErr *NoHardwareRootOfTrustError + ctxErr := fmt.Errorf("encountered an error when checking Intel BootGuard configuration: %w", err) + if !errors.As(err, &nohwrotErr) { + return platformFirmwareIntegrityNone, ctxErr + } + errs = append(errs, ctxErr) + } + if err := checkHostSecurityIntelCPUDebuggingLocked(amd64Env); err != nil { + return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error when checking Intel CPU debugging configuration: %w", err) + } + if len(errs) == 0 { + integrity = platformFirmwareIntegrityVerified + } + case cpuVendorAMD: + integrity, err = checkHostSecurityAMDPSP(env) + if err != nil { + ctxErr := fmt.Errorf("encountered an error when checking the AMD PSP configuration: %w", err) + var nohwrotErr *NoHardwareRootOfTrustError + if !errors.As(err, &nohwrotErr) { + return platformFirmwareIntegrityNone, ctxErr + } + errs = append(errs, ctxErr) + } + default: + panic("not reached") + } + + if err := checkSecureBootPolicyPCRForDegradedFirmwareSettings(log); err != nil { + var ce CompoundError + if !errors.As(err, &ce) { + return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error whilst checking the TCG log for degraded firmware settings: %w", err) + } + errs = append(errs, ce.Unwrap()...) + } + if err := checkForKernelIOMMU(env); err != nil { + switch { + case errors.Is(err, ErrNoKernelIOMMU): + errs = append(errs, err) + default: + return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error whilst checking sysfs to determine that kernel IOMMU support is enabled: %w", err) + } + } + + if len(errs) > 0 { + return platformFirmwareIntegrityNone, joinErrors(errs...) + } + + return integrity, nil +} + +func checkDiscreteTPMPartialResetAttackMitigationStatusAMD64(env internal_efi.HostEnvironment, logResults *pcrBankResults) (discreteTPMPartialResetAttackMitigationStatus, error) { + cpuVendor, err := determineCPUVendor(env) + if err != nil { + return dtpmPartialResetAttackMitigationUnknown, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} + } + + if cpuVendor != cpuVendorIntel { + // Only enable this on Intel systems. + return dtpmPartialResetAttackMitigationNotRequired, nil + } + + amd64Env, err := env.AMD64() + if err != nil { + return dtpmPartialResetAttackMitigationUnknown, fmt.Errorf("cannot obtain AMD64 environment: %w", err) + } + + discreteTPM, err := isTPMDiscrete(env) + if err != nil { + return dtpmPartialResetAttackMitigationUnknown, &TPM2DeviceError{err} + } + + switch { + case !discreteTPM: + // Not a discrete TPM. + return dtpmPartialResetAttackMitigationNotRequired, nil + case !logResults.Lookup(internal_efi.PlatformFirmwarePCR).Ok(): + // PCR0 is unusable. + return dtpmPartialResetAttackMitigationUnavailable, nil + } + + restrictedLocalities := restrictedTPMLocalitiesIntel(amd64Env) + for _, locality := range restrictedLocalities.Values() { + if locality == logResults.StartupLocality { + // The startup locality is not available to the OS, so + // we can enable the migitation because PCR0 cannot + // be recreated from the OS. + return dtpmPartialResetAttackMitigationPreferred, nil + } + } + + // The startup locality is available to the OS, so the mitigation + // is unavailable even though it would have been desired because + // PCR0 can be recreated from the OS. + return dtpmPartialResetAttackMitigationUnavailable, nil +} diff --git a/efi/preinstall/check_host_security_amd.go b/efi/preinstall/check_host_security_amd.go index 2e88c2a6..ea38304d 100644 --- a/efi/preinstall/check_host_security_amd.go +++ b/efi/preinstall/check_host_security_amd.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2025 Canonical Ltd + * Copyright (C) 2025-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_amd64.go b/efi/preinstall/check_host_security_amd64.go deleted file mode 100644 index 9571ca12..00000000 --- a/efi/preinstall/check_host_security_amd64.go +++ /dev/null @@ -1,148 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall - -import ( - "errors" - "fmt" - - "github.com/canonical/tcglog-parser" - internal_efi "github.com/snapcore/secboot/internal/efi" -) - -// checkHostSecurity is the main entry point for verifying that the host security -// is sufficient. Errors that can't be resolved or which should prevent further checks from running -// are returned immediately and without any wrapping. Errors that can be resolved and which shouldn't -// prevent further checks from running are returned wrapped in [joinError]. -func checkHostSecurity(env internal_efi.HostEnvironment, log *tcglog.Log) (platformFirmwareIntegrityConfig, error) { - cpuVendor, err := determineCPUVendor(env) - if err != nil { - return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} - } - - amd64Env, err := env.AMD64() - if err != nil { - return platformFirmwareIntegrityNone, fmt.Errorf("cannot obtain AMD64 environment: %w", err) - } - - var errs []error - - var integrity platformFirmwareIntegrityConfig - switch cpuVendor { - case cpuVendorIntel: - if err := checkHostSecurityIntelBootGuard(env); err != nil { - var nohwrotErr *NoHardwareRootOfTrustError - ctxErr := fmt.Errorf("encountered an error when checking Intel BootGuard configuration: %w", err) - if !errors.As(err, &nohwrotErr) { - return platformFirmwareIntegrityNone, ctxErr - } - errs = append(errs, ctxErr) - } - if err := checkHostSecurityIntelCPUDebuggingLocked(amd64Env); err != nil { - return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error when checking Intel CPU debugging configuration: %w", err) - } - if len(errs) == 0 { - integrity = platformFirmwareIntegrityVerified - } - case cpuVendorAMD: - integrity, err = checkHostSecurityAMDPSP(env) - if err != nil { - ctxErr := fmt.Errorf("encountered an error when checking the AMD PSP configuration: %w", err) - var nohwrotErr *NoHardwareRootOfTrustError - if !errors.As(err, &nohwrotErr) { - return platformFirmwareIntegrityNone, ctxErr - } - errs = append(errs, ctxErr) - } - default: - panic("not reached") - } - - if err := checkSecureBootPolicyPCRForDegradedFirmwareSettings(log); err != nil { - var ce CompoundError - if !errors.As(err, &ce) { - return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error whilst checking the TCG log for degraded firmware settings: %w", err) - } - errs = append(errs, ce.Unwrap()...) - } - if err := checkForKernelIOMMU(env); err != nil { - switch { - case errors.Is(err, ErrNoKernelIOMMU): - errs = append(errs, err) - default: - return platformFirmwareIntegrityNone, fmt.Errorf("encountered an error whilst checking sysfs to determine that kernel IOMMU support is enabled: %w", err) - } - } - - if len(errs) > 0 { - return platformFirmwareIntegrityNone, joinErrors(errs...) - } - - return integrity, nil -} - -// checkDiscreteTPMPartialResetAttackMitigationStatus determines whether a partial mitigation -// against discrete TPM reset attacks should be enabled. See the documentation for -// RequestPartialDiscreteTPMResetAttackMitigation. -func checkDiscreteTPMPartialResetAttackMitigationStatus(env internal_efi.HostEnvironment, logResults *pcrBankResults) (discreteTPMPartialResetAttackMitigationStatus, error) { - cpuVendor, err := determineCPUVendor(env) - if err != nil { - return dtpmPartialResetAttackMitigationUnknown, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} - } - - if cpuVendor != cpuVendorIntel { - // Only enable this on Intel systems. - return dtpmPartialResetAttackMitigationNotRequired, nil - } - - amd64Env, err := env.AMD64() - if err != nil { - return dtpmPartialResetAttackMitigationUnknown, fmt.Errorf("cannot obtain AMD64 environment: %w", err) - } - - discreteTPM, err := isTPMDiscrete(env) - if err != nil { - return dtpmPartialResetAttackMitigationUnknown, &TPM2DeviceError{err} - } - - switch { - case !discreteTPM: - // Not a discrete TPM. - return dtpmPartialResetAttackMitigationNotRequired, nil - case !logResults.Lookup(internal_efi.PlatformFirmwarePCR).Ok(): - // PCR0 is unusable. - return dtpmPartialResetAttackMitigationUnavailable, nil - } - - restrictedLocalities := restrictedTPMLocalitiesIntel(amd64Env) - for _, locality := range restrictedLocalities.Values() { - if locality == logResults.StartupLocality { - // The startup locality is not available to the OS, so - // we can enable the migitation because PCR0 cannot - // be recreated from the OS. - return dtpmPartialResetAttackMitigationPreferred, nil - } - } - - // The startup locality is available to the OS, so the mitigation - // is unavailable even though it would have been desired because - // PCR0 can be recreated from the OS. - return dtpmPartialResetAttackMitigationUnavailable, nil -} diff --git a/efi/preinstall/check_host_security_amd64_test.go b/efi/preinstall/check_host_security_amd64_test.go deleted file mode 100644 index 2ea4892e..00000000 --- a/efi/preinstall/check_host_security_amd64_test.go +++ /dev/null @@ -1,430 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall_test - -import ( - "errors" - - . "gopkg.in/check.v1" - - "github.com/canonical/cpuid" - "github.com/canonical/go-tpm2" - . "github.com/snapcore/secboot/efi/preinstall" - internal_efi "github.com/snapcore/secboot/internal/efi" - "github.com/snapcore/secboot/internal/efitest" - "github.com/snapcore/secboot/internal/testutil" -) - -type hostSecurityAMD64Suite struct{} - -var _ = Suite(&hostSecurityAMD64Suite{}) - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelGood(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - integrity, err := CheckHostSecurity(env, log) - c.Check(err, IsNil) - c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityErrNotAMD64(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts() - - _, err := CheckHostSecurity(env, nil) - c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: not a AMD64 host`) - - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDGoodVerified(c *C) { - pspAttrs := map[string][]byte{ - "boot_integrity": []byte(`1 -`), - "debug_lock_on": []byte(`1 -`), - "fused_part": []byte(`1 -`), - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", pspAttrs, nil), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - integrity, err := CheckHostSecurity(env, log) - c.Check(err, IsNil) - c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDGoodMeasured(c *C) { - pspAttrs := map[string][]byte{ - "boot_integrity": []byte(`0 -`), - "debug_lock_on": []byte(`1 -`), - "fused_part": []byte(`1 -`), - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", pspAttrs, nil), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - integrity, err := CheckHostSecurity(env, log) - c.Check(err, IsNil) - c.Check(integrity, Equals, PlatformFirmwareIntegrityMeasured) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityErrUnrecognizedCpuVendor(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 0, nil), - ) - - _, err := CheckHostSecurity(env, nil) - c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) - - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelErrMEI(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 0, nil), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) - - // Check that there is a NoHardwareRootOfTrustError - // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. - var nhrotErr *NoHardwareRootOfTrustError - var cErr CompoundError - c.Check(errors.As(err, &cErr), testutil.IsTrue) - foundNhrot := false - for _, e := range cErr.Unwrap() { - if errors.As(e, &nhrotErr) { - foundNhrot = true - } - } - c.Check(foundNhrot, testutil.IsTrue) - c.Check(nhrotErr, ErrorMatches, `no hardware root-of-trust properly configured: system is in manufacturing mode`) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDErrPSP(c *C) { - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", nil, nil), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `encountered an error when checking the AMD PSP configuration: no hardware root-of-trust properly configured: PSP security reporting not available`) - - // Check that there is a NoHardwareRootOfTrustError - // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. - var nhrotErr *NoHardwareRootOfTrustError - var cErr CompoundError - c.Check(errors.As(err, &cErr), testutil.IsTrue) - foundNhrot := false - for _, e := range cErr.Unwrap() { - if errors.As(e, &nhrotErr) { - foundNhrot = true - } - } - c.Check(foundNhrot, testutil.IsTrue) - c.Check(nhrotErr, ErrorMatches, `no hardware root-of-trust properly configured: PSP security reporting not available`) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecuritySecureBootPolicyFirmwareDebugging(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `the platform firmware contains a debugging endpoint enabled`) - var tmpl CompoundError - c.Assert(err, Implements, &tmpl) - c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled}) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityNoIOMMU(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `no kernel IOMMU support was detected`) - var tmpl CompoundError - c.Assert(err, Implements, &tmpl) - c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrNoKernelIOMMU}) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecuritySecureBootPolicyFirmwareDebuggingAndNoIOMMU(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `2 errors detected: -- the platform firmware contains a debugging endpoint enabled -- no kernel IOMMU support was detected -`) - var tmpl CompoundError - c.Assert(err, Implements, &tmpl) - c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled, ErrNoKernelIOMMU}) -} - -func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelErrCPUDebuggingUnlocked(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithSysfsDevices(devices...), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0x0}), - ) - log := efitest.NewLog(c, &efitest.LogOptions{}) - - _, err := CheckHostSecurity(env, log) - c.Check(err, ErrorMatches, `encountered an error when checking Intel CPU debugging configuration: CPU debugging features are not disabled and locked`) - c.Check(errors.Is(err, ErrCPUDebuggingNotLocked), testutil.IsTrue) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusNotRequiredAMD(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelNotDiscrete(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableInvalidPCR0(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelPreferred(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationPreferred) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableSL0(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableNoTXT(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 4, map[uint32]uint64{0x13a: (2 << 1)}), - ) - - status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ - MakePCRResults( - false, - make(tpm2.Digest, 32), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), - nil, - ), - })) - c.Check(err, IsNil) - c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) -} - -func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusErrUnsupportedCpuVendor(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 0, nil), - ) - - _, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{})) - c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} diff --git a/efi/preinstall/check_host_security_amd_test.go b/efi/preinstall/check_host_security_amd_test.go index 8b3c0ddd..9a69c70c 100644 --- a/efi/preinstall/check_host_security_amd_test.go +++ b/efi/preinstall/check_host_security_amd_test.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2025 Canonical Ltd + * Copyright (C) 2025-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel.go b/efi/preinstall/check_host_security_intel.go index bedd4f92..3889208f 100644 --- a/efi/preinstall/check_host_security_intel.go +++ b/efi/preinstall/check_host_security_intel.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -26,7 +24,6 @@ import ( "errors" "fmt" - "github.com/canonical/cpuid" "github.com/canonical/go-tpm2" "github.com/pilebones/go-udev/netlink" internal_efi "github.com/snapcore/secboot/internal/efi" @@ -346,7 +343,7 @@ const ( func checkHostSecurityIntelCPUDebuggingLocked(env internal_efi.HostEnvironmentAMD64) error { // Check for "Silicon Debug Interface", returned in bit 11 of %ecx when calling // cpuid with %eax=1. - debugSupported := env.HasCPUIDFeature(cpuid.SDBG) + debugSupported := env.HasCPUIDFeature(internal_efi.CPUIDFeatureSDBG) if !debugSupported { return nil } @@ -374,7 +371,7 @@ func checkHostSecurityIntelCPUDebuggingLocked(env internal_efi.HostEnvironmentAM // restrictedTPMLocalitiesIntel returns the TPM localities with access restricted // from the OS. func restrictedTPMLocalitiesIntel(env internal_efi.HostEnvironmentAMD64) tpm2.Locality { - if env.HasCPUIDFeature(cpuid.SMX) { + if env.HasCPUIDFeature(internal_efi.CPUIDFeatureSMX) { // The Intel TXT spec says that locality 4 is only available to microcode, // and is locked before handing over to an ACM which has access to locality // 3. The SINIT ACM uses this to establish a D-RTM and then locks access to diff --git a/efi/preinstall/check_host_security_intel_btgmsr.go b/efi/preinstall/check_host_security_intel_btgmsr.go index d64a65bb..c408a9b7 100644 --- a/efi/preinstall/check_host_security_intel_btgmsr.go +++ b/efi/preinstall/check_host_security_intel_btgmsr.go @@ -1,5 +1,3 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* diff --git a/efi/preinstall/check_host_security_intel_btgmsr_test.go b/efi/preinstall/check_host_security_intel_btgmsr_test.go index 0025edf7..27faea03 100644 --- a/efi/preinstall/check_host_security_intel_btgmsr_test.go +++ b/efi/preinstall/check_host_security_intel_btgmsr_test.go @@ -1,5 +1,3 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* diff --git a/efi/preinstall/check_host_security_intel_csme11.go b/efi/preinstall/check_host_security_intel_csme11.go index 806cd6bb..b1a03e15 100644 --- a/efi/preinstall/check_host_security_intel_csme11.go +++ b/efi/preinstall/check_host_security_intel_csme11.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel_csme11_test.go b/efi/preinstall/check_host_security_intel_csme11_test.go index 74eea31e..e74fb6e9 100644 --- a/efi/preinstall/check_host_security_intel_csme11_test.go +++ b/efi/preinstall/check_host_security_intel_csme11_test.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel_csme18.go b/efi/preinstall/check_host_security_intel_csme18.go index 4693e4e4..7ceb2bf6 100644 --- a/efi/preinstall/check_host_security_intel_csme18.go +++ b/efi/preinstall/check_host_security_intel_csme18.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2025 Canonical Ltd + * Copyright (C) 2025-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel_csme18_test.go b/efi/preinstall/check_host_security_intel_csme18_test.go index 56339779..54f118aa 100644 --- a/efi/preinstall/check_host_security_intel_csme18_test.go +++ b/efi/preinstall/check_host_security_intel_csme18_test.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_host_security_intel_test.go b/efi/preinstall/check_host_security_intel_test.go index 7ede04e8..8ff36770 100644 --- a/efi/preinstall/check_host_security_intel_test.go +++ b/efi/preinstall/check_host_security_intel_test.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -28,7 +26,6 @@ import ( . "gopkg.in/check.v1" - "github.com/canonical/cpuid" "github.com/canonical/go-tpm2" . "github.com/snapcore/secboot/efi/preinstall" internal_efi "github.com/snapcore/secboot/internal/efi" @@ -730,7 +727,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDis } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDisabledMSR(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0x40000000})) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 0x40000000})) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -738,7 +735,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDis } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDisabledAvailable(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0})) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 0})) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -746,7 +743,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedDis } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedEnabled(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 1})) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 1})) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -754,7 +751,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedEna } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedErrMissingMSR(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{})) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{})) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -764,7 +761,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedErr } func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedErrNoMSRSupport(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 0, nil)) + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 0, nil)) amd64Env, err := env.AMD64() c.Assert(err, IsNil) @@ -775,7 +772,7 @@ func (s *hostSecurityIntelSuite) TestCheckHostSecurityIntelCPUDebuggingLockedErr func (s *hostSecurityIntelSuite) TestRestrictedTPMLocalitiesIntel(c *C) { env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SMX}, 0, nil), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 0, nil), ) amd64Env, err := env.AMD64() c.Assert(err, IsNil) diff --git a/efi/preinstall/check_host_security_null.go b/efi/preinstall/check_host_security_null.go deleted file mode 100644 index ecaca284..00000000 --- a/efi/preinstall/check_host_security_null.go +++ /dev/null @@ -1,39 +0,0 @@ -//go:build !amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall - -import ( - "fmt" - "runtime" - - "github.com/canonical/tcglog-parser" - - internal_efi "github.com/snapcore/secboot/internal/efi" -) - -func checkHostSecurity(env internal_efi.HostEnvironment, log *tcglog.Log) (platformFirmwareIntegrityConfig, error) { - return platformFirmwareIntegrityNone, &UnsupportedPlatformError{fmt.Errorf("checking host security is not implemented on %s", runtime.GOARCH)} -} - -func checkDiscreteTPMPartialResetAttackMitigationStatus(env internal_efi.HostEnvironment, logResults *pcrBankResults) (discreteTPMPartialResetAttackMitigationStatus, error) { - return dtpmPartialResetAttackMitigationNotRequired, nil -} diff --git a/efi/preinstall/check_host_security_test.go b/efi/preinstall/check_host_security_test.go index 404877db..1ca94879 100644 --- a/efi/preinstall/check_host_security_test.go +++ b/efi/preinstall/check_host_security_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -20,10 +20,15 @@ package preinstall_test import ( - . "gopkg.in/check.v1" + "errors" + "github.com/canonical/go-tpm2" . "github.com/snapcore/secboot/efi/preinstall" + internal_efi "github.com/snapcore/secboot/internal/efi" "github.com/snapcore/secboot/internal/efitest" + "github.com/snapcore/secboot/internal/testutil" + snapd_testutil "github.com/snapcore/snapd/testutil" + . "gopkg.in/check.v1" ) type hostSecuritySuite struct{} @@ -125,3 +130,428 @@ func (s *hostSecuritySuite) TestCheckSecureBootPolicyPCRForDegradedSettingsFirmw c.Assert(err, Implements, &tmpl) c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled, ErrInsufficientDMAProtection}) } + +type hostSecurityAMD64Suite struct { + snapd_testutil.BaseTest +} + +func (s *hostSecurityAMD64Suite) SetUpTest(c *C) { + s.BaseTest.SetUpTest(c) + s.AddCleanup(MockRuntimeGOARCH("amd64")) +} + +var _ = Suite(&hostSecurityAMD64Suite{}) + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelGood(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(err, IsNil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityErrNotAMD64(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts() + + _, err := CheckHostSecurity(env, nil) + c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: not a AMD64 host`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDGoodVerified(c *C) { + pspAttrs := map[string][]byte{ + "boot_integrity": []byte(`1 +`), + "debug_lock_on": []byte(`1 +`), + "fused_part": []byte(`1 +`), + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", pspAttrs, nil), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(err, IsNil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityVerified) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDGoodMeasured(c *C) { + pspAttrs := map[string][]byte{ + "boot_integrity": []byte(`0 +`), + "debug_lock_on": []byte(`1 +`), + "fused_part": []byte(`1 +`), + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", pspAttrs, nil), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + integrity, err := CheckHostSecurity(env, log) + c.Check(err, IsNil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityMeasured) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityErrUnrecognizedCpuVendor(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 0, nil), + ) + + _, err := CheckHostSecurity(env, nil) + c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelErrMEI(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusManufacturingMode, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 0, nil), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) + + // Check that there is a NoHardwareRootOfTrustError + // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. + var nhrotErr *NoHardwareRootOfTrustError + var cErr CompoundError + c.Check(errors.As(err, &cErr), testutil.IsTrue) + foundNhrot := false + for _, e := range cErr.Unwrap() { + if errors.As(e, &nhrotErr) { + foundNhrot = true + } + } + c.Check(foundNhrot, testutil.IsTrue) + c.Check(nhrotErr, ErrorMatches, `no hardware root-of-trust properly configured: system is in manufacturing mode`) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityAMDErrPSP(c *C) { + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:08.1/0000:c1:00.2", map[string]string{"DRIVER": "ccp"}, "pci", nil, nil), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `encountered an error when checking the AMD PSP configuration: no hardware root-of-trust properly configured: PSP security reporting not available`) + + // Check that there is a NoHardwareRootOfTrustError + // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. + var nhrotErr *NoHardwareRootOfTrustError + var cErr CompoundError + c.Check(errors.As(err, &cErr), testutil.IsTrue) + foundNhrot := false + for _, e := range cErr.Unwrap() { + if errors.As(e, &nhrotErr) { + foundNhrot = true + } + } + c.Check(foundNhrot, testutil.IsTrue) + c.Check(nhrotErr, ErrorMatches, `no hardware root-of-trust properly configured: PSP security reporting not available`) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecuritySecureBootPolicyFirmwareDebugging(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `the platform firmware contains a debugging endpoint enabled`) + var tmpl CompoundError + c.Assert(err, Implements, &tmpl) + c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled}) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityNoIOMMU(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `no kernel IOMMU support was detected`) + var tmpl CompoundError + c.Assert(err, Implements, &tmpl) + c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrNoKernelIOMMU}) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecuritySecureBootPolicyFirmwareDebuggingAndNoIOMMU(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{FirmwareDebugger: true}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `2 errors detected: +- the platform firmware contains a debugging endpoint enabled +- no kernel IOMMU support was detected +`) + var tmpl CompoundError + c.Assert(err, Implements, &tmpl) + c.Check(err.(CompoundError).Unwrap(), DeepEquals, []error{ErrUEFIDebuggingEnabled, ErrNoKernelIOMMU}) +} + +func (s *hostSecurityAMD64Suite) TestCheckHostSecurityIntelErrCPUDebuggingUnlocked(c *C) { + meiAttrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": fwStatusBase, + } + devices := []internal_efi.SysfsDevice{ + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + )), + } + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithSysfsDevices(devices...), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 0x0}), + ) + log := efitest.NewLog(c, &efitest.LogOptions{}) + + _, err := CheckHostSecurity(env, log) + c.Check(err, ErrorMatches, `encountered an error when checking Intel CPU debugging configuration: CPU debugging features are not disabled and locked`) + c.Check(errors.Is(err, ErrCPUDebuggingNotLocked), testutil.IsTrue) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusNotRequiredAMD(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 0, nil), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelNotDiscrete(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (3 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableInvalidPCR0(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelPreferred(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationPreferred) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableSL0(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (2 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusIntelUnavailableNoTXT(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 4, map[uint32]uint64{0x13a: (2 << 1)}), + ) + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 3, [8]PcrResults{ + MakePCRResults( + false, + make(tpm2.Digest, 32), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + testutil.DecodeHexString(c, "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5"), + nil, + ), + })) + c.Check(err, IsNil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationUnavailable) +} + +func (s *hostSecurityAMD64Suite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusErrUnsupportedCpuVendor(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 0, nil), + ) + + _, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(env, NewPCRBankResults(tpm2.HashAlgorithmSHA256, 0, [8]PcrResults{})) + c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecuritySuite) TestCheckHostSecurityUnsupportedArchitecture(c *C) { + restore := MockRuntimeGOARCH("ppc64le") + defer restore() + + integrity, err := CheckHostSecurity(nil, nil) + c.Check(integrity, Equals, PlatformFirmwareIntegrityNone) + c.Check(err, ErrorMatches, `unsupported platform: checking host security is not implemented on ppc64le`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *hostSecuritySuite) TestCheckDiscreteTPMPartialResetAttackMitigationStatusUnsupportedArchitecture(c *C) { + restore := MockRuntimeGOARCH("ppc64le") + defer restore() + + status, err := CheckDiscreteTPMPartialResetAttackMitigationStatus(nil, nil) + c.Check(status, Equals, DtpmPartialResetAttackMitigationNotRequired) + c.Check(err, IsNil) +} diff --git a/efi/preinstall/check_tpm.go b/efi/preinstall/check_tpm.go index 55ba7e13..4a39e7b1 100644 --- a/efi/preinstall/check_tpm.go +++ b/efi/preinstall/check_tpm.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -21,6 +21,7 @@ package preinstall import ( "bytes" + "errors" "fmt" "github.com/canonical/go-tpm2" @@ -467,3 +468,42 @@ func openAndCheckTPM2Device(env internal_efi.HostEnvironment, flags checkTPM2Dev return tpm, nil } + +// Architecture-specific TPM discreteness checks are dispatched at runtime rather than +// selected by build constraints, so that all architectures' checks are compiled and +// testable everywhere. + +// isTPMDiscrete determines whether the default TPM is discrete. +func isTPMDiscrete(env internal_efi.HostEnvironment) (bool, error) { + switch runtimeGOARCH { + case "amd64": + return isTPMDiscreteAMD64(env) + default: + return false, &UnsupportedPlatformError{fmt.Errorf("checking for TPM discreteness is not implemented on %s", runtimeGOARCH)} + } +} + +func isTPMDiscreteAMD64(env internal_efi.HostEnvironment) (bool, error) { + amd64, err := env.AMD64() + if err != nil { + return false, err + } + + cpuVendor, err := determineCPUVendor(env) + if err != nil { + return false, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} + } + + switch cpuVendor { + case cpuVendorIntel: + discrete, err := isTPMDiscreteFromIntelBootGuard(amd64) + if err != nil { + return false, fmt.Errorf("cannot check TPM discreteness using Intel BootGuard status: %w", err) + } + return discrete, nil + case cpuVendorAMD: + return false, &UnsupportedPlatformError{errors.New("cannot check TPM discreteness on AMD systems")} + default: + panic("not reached") + } +} diff --git a/efi/preinstall/check_tpm_amd64.go b/efi/preinstall/check_tpm_amd64.go deleted file mode 100644 index bb0fecaf..00000000 --- a/efi/preinstall/check_tpm_amd64.go +++ /dev/null @@ -1,53 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall - -import ( - "errors" - "fmt" - - internal_efi "github.com/snapcore/secboot/internal/efi" -) - -// isTPMDiscrete determines whether the TPM is discrete -func isTPMDiscrete(env internal_efi.HostEnvironment) (bool, error) { - amd64, err := env.AMD64() - if err != nil { - return false, err - } - - cpuVendor, err := determineCPUVendor(env) - if err != nil { - return false, &UnsupportedPlatformError{fmt.Errorf("cannot determine CPU vendor: %w", err)} - } - - switch cpuVendor { - case cpuVendorIntel: - discrete, err := isTPMDiscreteFromIntelBootGuard(amd64) - if err != nil { - return false, fmt.Errorf("cannot check TPM discreteness using Intel BootGuard status: %w", err) - } - return discrete, nil - case cpuVendorAMD: - return false, &UnsupportedPlatformError{errors.New("cannot check TPM discreteness on AMD systems")} - default: - panic("not reached") - } -} diff --git a/efi/preinstall/check_tpm_amd64_test.go b/efi/preinstall/check_tpm_amd64_test.go deleted file mode 100644 index a6a8ea90..00000000 --- a/efi/preinstall/check_tpm_amd64_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall_test - -import ( - "errors" - - . "github.com/snapcore/secboot/efi/preinstall" - "github.com/snapcore/secboot/internal/efitest" - "github.com/snapcore/secboot/internal/testutil" - . "gopkg.in/check.v1" -) - -type tpmAmd64Suite struct{} - -var _ = Suite(&tpmAmd64Suite{}) - -func (s *tpmIntelSuite) TestIsTPMDiscreteIntelYes(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (2 << 1)}), - ) - discrete, err := IsTPMDiscrete(env) - c.Check(err, IsNil) - c.Check(discrete, testutil.IsTrue) -} - -func (s *tpmIntelSuite) TestIsTPMDiscreteIntelNo(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (3 << 1)}), - ) - discrete, err := IsTPMDiscrete(env) - c.Check(err, IsNil) - c.Check(discrete, testutil.IsFalse) -} - -func (s *tpmIntelSuite) TestIsTPMDiscreteIntelNoTPM2(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts( - efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (0 << 1)}), - ) - _, err := IsTPMDiscrete(env) - c.Check(err, ErrorMatches, `cannot check TPM discreteness using Intel BootGuard status: no TPM2 device is available`) - c.Check(errors.Is(err, ErrNoTPM2Device), testutil.IsTrue) -} - -func (s *tpmIntelSuite) TestIsTPMDiscreteAMD(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 1, nil)) - _, err := IsTPMDiscrete(env) - c.Check(err, ErrorMatches, `unsupported platform: cannot check TPM discreteness on AMD systems`) - - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} - -func (s *tpmIntelSuite) TestIsTPMDiscreteUnrecognizedCPUVendor(c *C) { - env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 1, nil)) - _, err := IsTPMDiscrete(env) - c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) - - var upe *UnsupportedPlatformError - c.Check(errors.As(err, &upe), testutil.IsTrue) -} diff --git a/efi/preinstall/check_tpm_intel.go b/efi/preinstall/check_tpm_intel.go index 1a5d9fe0..5a8cc8c2 100644 --- a/efi/preinstall/check_tpm_intel.go +++ b/efi/preinstall/check_tpm_intel.go @@ -1,9 +1,7 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/check_tpm_intel_test.go b/efi/preinstall/check_tpm_intel_test.go index 7c76081c..222458d0 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,19 @@ 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) + // All Intel TPM tests assume an amd64 host + s.AddCleanup(MockRuntimeGOARCH("amd64")) +} var _ = Suite(&tpmIntelSuite{}) diff --git a/efi/preinstall/check_tpm_test.go b/efi/preinstall/check_tpm_test.go index 93a7e43c..bdeb03b5 100644 --- a/efi/preinstall/check_tpm_test.go +++ b/efi/preinstall/check_tpm_test.go @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -30,6 +30,7 @@ import ( "github.com/snapcore/secboot/internal/efitest" "github.com/snapcore/secboot/internal/testutil" "github.com/snapcore/secboot/internal/tpm2_device" + snapd_testutil "github.com/snapcore/snapd/testutil" . "gopkg.in/check.v1" ) @@ -1149,3 +1150,70 @@ func (s *tpmSuite) TestOpenAndCheckTPM2DeviceLockoutAvailabilitySkipped(c *C) { c.Assert(tpm, NotNil) c.Check(dev.NumberOpen(), Equals, int(1)) } + +type tpmAmd64Suite struct { + snapd_testutil.BaseTest +} + +func (s *tpmAmd64Suite) SetUpTest(c *C) { + s.BaseTest.SetUpTest(c) + s.AddCleanup(MockRuntimeGOARCH("amd64")) +} + +var _ = Suite(&tpmAmd64Suite{}) + +func (s *tpmIntelSuite) TestIsTPMDiscreteIntelYes(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (2 << 1)}), + ) + discrete, err := IsTPMDiscrete(env) + c.Check(err, IsNil) + c.Check(discrete, testutil.IsTrue) +} + +func (s *tpmIntelSuite) TestIsTPMDiscreteIntelNo(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (3 << 1)}), + ) + discrete, err := IsTPMDiscrete(env) + c.Check(err, IsNil) + c.Check(discrete, testutil.IsFalse) +} + +func (s *tpmIntelSuite) TestIsTPMDiscreteIntelNoTPM2(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts( + efitest.WithAMD64Environment("GenuineIntel", 0x6, nil, 1, map[uint32]uint64{0x13a: (0 << 1)}), + ) + _, err := IsTPMDiscrete(env) + c.Check(err, ErrorMatches, `cannot check TPM discreteness using Intel BootGuard status: no TPM2 device is available`) + c.Check(errors.Is(err, ErrNoTPM2Device), testutil.IsTrue) +} + +func (s *tpmIntelSuite) TestIsTPMDiscreteAMD(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("AuthenticAMD", 0x1a, nil, 1, nil)) + _, err := IsTPMDiscrete(env) + c.Check(err, ErrorMatches, `unsupported platform: cannot check TPM discreteness on AMD systems`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *tpmIntelSuite) TestIsTPMDiscreteUnrecognizedCPUVendor(c *C) { + env := efitest.NewMockHostEnvironmentWithOpts(efitest.WithAMD64Environment("GenuineInte", 0x6, nil, 1, nil)) + _, err := IsTPMDiscrete(env) + c.Check(err, ErrorMatches, `unsupported platform: cannot determine CPU vendor: unknown CPU vendor: GenuineInte`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} + +func (s *tpmSuite) TestIsTPMDiscreteUnsupportedArchitecture(c *C) { + restore := MockRuntimeGOARCH("ppc64le") + defer restore() + + _, err := IsTPMDiscrete(nil) + c.Check(err, ErrorMatches, `unsupported platform: checking for TPM discreteness is not implemented on ppc64le`) + + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) +} diff --git a/efi/preinstall/checks_context_test.go b/efi/preinstall/checks_context_test.go index e7ed9448..1f37b612 100644 --- a/efi/preinstall/checks_context_test.go +++ b/efi/preinstall/checks_context_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -28,7 +28,6 @@ import ( "io" "time" - "github.com/canonical/cpuid" efi "github.com/canonical/go-efilib" "github.com/canonical/go-tpm2" "github.com/canonical/go-tpm2/objectutil" @@ -90,6 +89,7 @@ type testRunChecksContextRunParams struct { } func (s *runChecksContextSuite) testRun(c *C, params *testRunChecksContextRunParams) (errs []*WithKindAndActionsError) { + s.ResetAndClearTPMSimulatorUsingPlatformHierarchy(c) dev, err := params.env.TPMDevice() if err == nil { s.allocatePCRBanks(c, params.enabledBanks...) @@ -215,182 +215,143 @@ func (s *runChecksContextSuite) testRun(c *C, params *testRunChecksContextRunPar func (s *runChecksContextSuite) TestRunGood(c *C) { // Good test on a fTPM with a single run - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodSHA384(c *C) { // Good test on a fTPM with a single run and SHA384 selected as the PCR bank - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "030ac3c913dab858f1d69239115545035cff671d6229f95577bb0ffbd827b35abaf6af6bfd223e04ecc9b60a9803642d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "030ac3c913dab858f1d69239115545035cff671d6229f95577bb0ffbd827b35abaf6af6bfd223e04ecc9b60a9803642d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "6c2df9007211786438be210b6908f2935d0b25ebdcd2c65621826fd2ec55fb9fbacbfe080d48db98f0ef970273b8254a")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "42f61b3089f5ce0646b422a59c9632065db2630f3e5b01690e63c41420ed31f10ff2a191f3440f9501109fc85f7fb00f")}, }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "6c2df9007211786438be210b6908f2935d0b25ebdcd2c65621826fd2ec55fb9fbacbfe080d48db98f0ef970273b8254a")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "42f61b3089f5ce0646b422a59c9632065db2630f3e5b01690e63c41420ed31f10ff2a191f3440f9501109fc85f7fb00f")}, - }, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA384, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA384, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodSHA1FromInitialFlags(c *C) { // Good test on a fTPM with a single run and SHA1 as the selected algorithm, // permitted by passing the PermitWeakPCRBanks flag as an initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, - initialFlags: PermitWeakPCRBanks, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, + initialFlags: PermitWeakPCRBanks, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, - }, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA1, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA1, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Test a good case that selects SHA1 without supplying the initial flag when we have an action to enable PermitWeakPCRBanks. @@ -398,544 +359,440 @@ func (s *runChecksContextSuite) TestRunGoodSHA1FromInitialFlags(c *C) { func (s *runChecksContextSuite) TestRunGoodPermitInsufficientDMAProtectionFromInitialFlags(c *C) { // Test case where there is an empty PCR bank, but it is permitted by // supplying PermitInsufficientDMAProtection as an initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitInsufficientDMAProtection, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindInsufficientDMAProtection: nil, - ErrorKindNoKernelIOMMU: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitInsufficientDMAProtection, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindInsufficientDMAProtection: nil, + ErrorKindNoKernelIOMMU: nil, + }, + expectedWarningsMatch: `4 errors detected: - the platform firmware indicates that DMA protections are insufficient - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 0) + }) + c.Assert(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitInsufficientDMAProtection(c *C) { // Test that ActionProceed enables PermitInsufficientDMAProtection. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - errs[0].Unwrap(), - )) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindInsufficientDMAProtection: nil, - ErrorKindNoKernelIOMMU: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + errs[0].Unwrap(), + )) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindInsufficientDMAProtection: nil, + ErrorKindNoKernelIOMMU: nil, + }, + expectedWarningsMatch: `4 errors detected: - the platform firmware indicates that DMA protections are insufficient - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 0) + }) + c.Assert(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitNoHardwareRootOfTrust(c *C) { // Test that ActionProceed enables PermitNoHardwareRootOfTrust. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindNoHardwareRootOfTrust, - nil, - []Action{ActionProceed}, - errs[0].Unwrap(), - )) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindNoHardwareRootOfTrust: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityInsufficientHWRootOfTrust + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindNoHardwareRootOfTrust, + nil, + []Action{ActionProceed}, + errs[0].Unwrap(), + )) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindNoHardwareRootOfTrust: nil, + }, + expectedWarningsMatch: `4 errors detected: - encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodPostInstall(c *C) { // Test good post-install scenario on a fTPM, which skips some tests related to // TPM ownership, lockout status and checking the number of available // NV counters. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PostInstallChecks, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PostInstallChecks, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodPreAndPostInstall(c *C) { // Test good pre-install and post-install scenario on a fTPM. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 4, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: +- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 +- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 +- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 +`, + }) + c.Check(errs, HasLen, 0) + + errs = s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + tpm2.PropertyPermanent: uint32(tpm2.AttrLockoutAuthSet), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PostInstallChecks, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: +- availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set +- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 +- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 +- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 +`, + }) + c.Check(errs, HasLen, 0) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 4, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: -- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 -- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 -- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 -`, - }) - c.Check(errs, HasLen, 0) - - errs = s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - tpm2.PropertyPermanent: uint32(tpm2.AttrLockoutAuthSet), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PostInstallChecks, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: -- availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set -- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 -- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 -- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 -`, - }) - c.Check(errs, HasLen, 0) } func (s *runChecksContextSuite) TestRunGoodPermitVirtualMachineFromInitialFlags(c *C) { // Test on a virtual machine, wehere PermitVirtualMachine is supplied via // the initial flags to permit it. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitVirtualMachine, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindRunningInVM: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitVirtualMachine, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindRunningInVM: nil, + }, + expectedWarningsMatch: `4 errors detected: - virtual machine environment detected - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitVirtualMachine(c *C) { // Test that ActionProceed turns on PermitVirtualMachine. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindRunningInVM, - nil, - []Action{ActionProceed}, - ErrVirtualMachineDetected, - )) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindRunningInVM: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindRunningInVM, + nil, + []Action{ActionProceed}, + ErrVirtualMachineDetected, + )) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindRunningInVM: nil, + }, + expectedWarningsMatch: `4 errors detected: - virtual machine environment detected - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodDiscreteTPMDetectedSL3(c *C) { // Test a good case on a dTPM where the startup locality is 3 and // access to locality 3 is restricted to ring 0 code. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation, - expectedWarningsMatch: `3 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality3InaccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Test a good case with a discrete TPM where the startup locality is 3, but not protected, when we have an action to turn on the PermitNoDiscreteTPMResetMitigation flag. @@ -943,57 +800,47 @@ func (s *runChecksContextSuite) TestRunGoodDiscreteTPMDetectedSL3(c *C) { func (s *runChecksContextSuite) TestRunGoodDiscreteTPMDetectedHCRTM(c *C) { // Test a good case on a dTPM where there is a H-CRTM event and // access to locality 4 is restricted to ring 0 code. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 4, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation, - expectedWarningsMatch: `3 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality4InaccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 4, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Test a good case with a discrete TPM where there is a HCRTM event but startup locality is 4 is not protected, when we have an action to turn on the PermitNoDiscreteTPMResetMitigation flag. @@ -1002,125 +849,111 @@ func (s *runChecksContextSuite) TestRunGoodInvalidPCR0Value(c *C) { // Test a good case where the value of PCR0 is inconsistent with the log, // but in a configuration where PCR0 isn't required because the system is // configured with verified boot and there is a fTPM. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\) - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + if fixture.additionalExpectedFlags&RequireLockToPlatformFirmware != 0 { + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) + continue + } + c.Check(errs, HasLen, 0) + } } -// TODO: Good test case for invalid PCR1 when we support it. - func (s *runChecksContextSuite) TestRunGoodInvalidPCR2ValueWhenOmittedFromPCRProfileOpts(c *C) { // Test a good case on a fTPM where the value of PCR2 is inconsistent // with the log, but PCR2 isn't required for the specified profile options. - restore := MockKnownCAs(AuthorityTrustDataSet{ - {internal_efi.MSUefiCA2011, AuthorityTrustDrivers}, - {internal_efi.MSUefiCA2023, 0}, - }) - defer restore() - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForAddonDrivers, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + func() { + restore := MockKnownCAs(AuthorityTrustDataSet{ + {internal_efi.MSUefiCA2011, AuthorityTrustDrivers}, + {internal_efi.MSUefiCA2023, 0}, + }) + defer restore() + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForAddonDrivers, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\) - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + }() + } } // TODO: Good test case for invalid PCR3 when we support it. @@ -1128,65 +961,54 @@ func (s *runChecksContextSuite) TestRunGoodInvalidPCR2ValueWhenOmittedFromPCRPro func (s *runChecksContextSuite) TestRunGoodInvalidPCR4ValueWhenOmittedFromPCRProfileOpts(c *C) { // Test a good case on a fTPM where the value of PCR4 is inconsistent // with the log, but PCR4 isn't required for the specified profile options. - restore := MockKnownCAs(AuthorityTrustDataSet{ - {internal_efi.MSUefiCA2011, AuthorityTrustBootCode}, - {internal_efi.MSUefiCA2023, 0}, - }) - defer restore() - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForBootCode, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + func() { + restore := MockKnownCAs(AuthorityTrustDataSet{ + {internal_efi.MSUefiCA2011, AuthorityTrustBootCode}, + {internal_efi.MSUefiCA2023, 0}, + }) + defer restore() + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForBootCode, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\) - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + }() + } } // TODO: Good test case for invalid PCR5 when we support it. @@ -1196,336 +1018,235 @@ func (s *runChecksContextSuite) TestRunGoodAddonDriversPresentFromInitialFlags(c // Test good case on a fTPM where there are value-added-retailer drivers // detected, and these are permitted with the PermitAddonDrivers // initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitAddonDrivers, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitAddonDrivers, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Test the above case without the initial flag when we have an action to set PermitAddonDrivers. func (s *runChecksContextSuite) TestRunGoodActionProceedPermitAddonDrivers(c *C) { // Test that ActionProceed turns on PermitAddonDrivers. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodSysPrepAppsPresentFromInitialFlags(c *C) { // Test good case on a fTPM where there are system preparation applications // detected, and these are permitted with the PermitSysPrepApplications // initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitSysPrepApplications, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindSysPrepApplicationsPresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitSysPrepApplications, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindSysPrepApplicationsPresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - system preparation applications were detected: - Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitSysPrepApplications(c *C) { // Test that ActionProceed enables PermitSysPrepApplications. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `system preparation applications were detected: -- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 -`) - imageInfo := []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ &efi.HardDriveDevicePathNode{ PartitionNumber: 1, PartitionStart: 0x800, @@ -1534,306 +1255,304 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedPermitSysPrepApplication MBRType: efi.GPT}, efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - } + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindSysPrepApplicationsPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &SysPrepApplicationsPresentError{ - Apps: imageInfo, - }, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindSysPrepApplicationsPresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + c.Check(errs[0], ErrorMatches, `system preparation applications were detected: +- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 +`) + imageInfo := []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), + }, + } + + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindSysPrepApplicationsPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &SysPrepApplicationsPresentError{ + Apps: imageInfo, + }, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindSysPrepApplicationsPresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - system preparation applications were detected: - Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 0) + }) + c.Assert(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodAbsoluteActiveFromInitialFlags(c *C) { // Test good case on a fTPM where Absolute is detected, and this is // permitted with the PermitAbsoluteComputrace initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - initialFlags: PermitAbsoluteComputrace, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAbsolutePresent: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + initialFlags: PermitAbsoluteComputrace, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAbsolutePresent: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - Absolute was detected to be active and it is advised that this is disabled - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitAbsolute(c *C) { // Test that ActionProceed enables PermitAbsoluteComputrace. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAbsolutePresent, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + ErrAbsoluteComputraceActive, + )) + } + }, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAbsolutePresent: nil, + }, + expectedWarningsMatch: `4 errors detected: +- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 +- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 +- Absolute was detected to be active and it is advised that this is disabled +- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 +`, + }) + c.Check(errs, HasLen, 0) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAbsolutePresent, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - ErrAbsoluteComputraceActive, - )) - } - }, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAbsolutePresent: nil, - }, - expectedWarningsMatch: `4 errors detected: -- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 -- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 -- Absolute was detected to be active and it is advised that this is disabled -- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 -`, - }) - c.Check(errs, HasLen, 0) -} +} // TODO: Test the above case without the initial flag when we have an action to set PermitAbsoluteComputrace. func (s *runChecksContextSuite) TestRunGoodNoBootManagerCodeProfileSupportWhenOmittedFromPCRProfileOpts(c *C) { // Test a good case on a fTPM where the launch digests in the log for OS components // are invalid, but the profile options permits the omission of PCR4. - restore := MockKnownCAs(AuthorityTrustDataSet{ - {internal_efi.MSUefiCA2011, AuthorityTrustBootCode}, - {internal_efi.MSUefiCA2023, 0}, - }) - defer restore() - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + func() { + restore := MockKnownCAs(AuthorityTrustDataSet{ + {internal_efi.MSUefiCA2011, AuthorityTrustBootCode}, + {internal_efi.MSUefiCA2023, 0}, + }) + defer restore() + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - }, - // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test - // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in - // the log so the test thinks that the log contains the flat file digest. - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, - }, - profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForBootCode, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test + // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in + // the log so the test thinks that the log contains the flat file digest. + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, + }, + profileOpts: PCRProfileOptionTrustSecureBootAuthoritiesForBootCode, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and/or the PE_COFF_IMAGE flag - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + }() + } } func (s *runChecksContextSuite) TestRunGoodPreOSSecureBootAuthByEnrolledDigestsFromInitialFlags(c *C) { // Test a good case where there are value-added-retailer drivers being loaded, // authenticated by way of a digest in db, permitted by supplying PermitPreOSSecureBootAuthByEnrolledDigests // as one of the initial flags. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `5 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `5 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -1841,254 +1560,215 @@ func (s *runChecksContextSuite) TestRunGoodPreOSSecureBootAuthByEnrolledDigestsF - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitSecureBootUserMode(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `secure boot is enabled but not in deployed mode`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidSecureBootMode, - SecureBootModeArg{ - Enabled: true, - Mode: efi.UserMode, - }, - []Action{ActionRebootToFWSettings, ActionProceed}, - ErrNoDeployedMode, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindInvalidSecureBootMode: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `secure boot is enabled but not in deployed mode`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidSecureBootMode, + SecureBootModeArg{ + Enabled: true, + Mode: efi.UserMode, + }, + []Action{ActionRebootToFWSettings, ActionProceed}, + ErrNoDeployedMode, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindInvalidSecureBootMode: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 - secure boot is enabled but not in deployed mode `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodPermitSecureBootUserModeFromInitialFlags(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitSecureBootUserMode, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindInvalidSecureBootMode: nil, - }, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitSecureBootUserMode, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindInvalidSecureBootMode: nil, + }, + expectedWarningsMatch: `4 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 - secure boot is enabled but not in deployed mode `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitPreOSSecureBootAuthByEnrolledDigests(c *C) { // Test that ActionProceed enables the PermitPreOSSecureBootAuthByEnrolledDigests flag. As // this test generates 2 errors, it also tests the case where ActionProceed can // be used to ignore multiple errors. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 2) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 2) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `5 errors detected: + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `5 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -2096,66 +1776,53 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedPermitPreOSSecureBootAut - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodWeakSecureBootAlgsFromInitialFlags(c *C) { // Test a good case on a fTPM where there are weak secure boot algorithms // detected, but this is permitted because PermitWeakSecureBootAlgorithms // was supplied as an initial flag. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - initialFlags: PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindWeakSecureBootAlgorithmsDetected: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `6 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + initialFlags: PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindWeakSecureBootAlgorithmsDetected: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `6 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -2164,126 +1831,113 @@ func (s *runChecksContextSuite) TestRunGoodWeakSecureBootAlgsFromInitialFlags(c - a weak cryptographic algorithm was detected during secure boot verification - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionProceedPermitWeakSecureBootAlgs(c *C) { // Test that ActionProceed enables PermitWeakSecureBootAlgorithms. As // this test generates 3 errors, it also tests the case where ActionProceed // can be used to ignore multiple errors. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 3) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 3) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindWeakSecureBootAlgorithmsDetected, - nil, - []Action{ActionProceed}, - ErrWeakSecureBootAlgorithmDetected, - )) - - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindWeakSecureBootAlgorithmsDetected: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `6 errors detected: + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindWeakSecureBootAlgorithmsDetected, + nil, + []Action{ActionProceed}, + ErrWeakSecureBootAlgorithmDetected, + )) + + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindWeakSecureBootAlgorithmsDetected: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `6 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -2292,8 +1946,9 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedPermitWeakSecureBootAlgs - a weak cryptographic algorithm was detected during secure boot verification - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } // TODO: Good test case for invalid secure boot config (eg, no DeployedMode) when PCRProfileOptionPermitNoSecureBootPolicyProfile is supported. @@ -2301,143 +1956,129 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedPermitWeakSecureBootAlgs func (s *runChecksContextSuite) TestRunGoodActionProceedIndividualWithMultipleErrors(c *C) { // Test that ActionProceed can be used to ignore individual errors when // multiple errors are reported. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 4, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindWeakSecureBootAlgorithmsDetected}}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindPreOSSecureBootAuthByEnrolledDigests}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 3) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 4, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindWeakSecureBootAlgorithmsDetected}}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindPreOSSecureBootAuthByEnrolledDigests}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 3) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindWeakSecureBootAlgorithmsDetected, - nil, - []Action{ActionProceed}, - ErrWeakSecureBootAlgorithmDetected, - )) - - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - case 1: - c.Check(errs, HasLen, 2) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindWeakSecureBootAlgorithmsDetected, - nil, - []Action{ActionProceed}, - ErrWeakSecureBootAlgorithmDetected, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - case 2: - c.Check(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ - ErrorKindAddonDriversPresent: nil, - ErrorKindWeakSecureBootAlgorithmsDetected: nil, - ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, - }, - expectedWarningsMatch: `6 errors detected: + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindWeakSecureBootAlgorithmsDetected, + nil, + []Action{ActionProceed}, + ErrWeakSecureBootAlgorithmDetected, + )) + + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + case 1: + c.Check(errs, HasLen, 2) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindWeakSecureBootAlgorithmsDetected, + nil, + []Action{ActionProceed}, + ErrWeakSecureBootAlgorithmDetected, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + case 2: + c.Check(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedAcceptedErrors: map[ErrorKind]json.RawMessage{ + ErrorKindAddonDriversPresent: nil, + ErrorKindWeakSecureBootAlgorithmsDetected: nil, + ErrorKindPreOSSecureBootAuthByEnrolledDigests: nil, + }, + expectedWarningsMatch: `6 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 @@ -2446,8 +2087,9 @@ func (s *runChecksContextSuite) TestRunGoodActionProceedIndividualWithMultipleEr - a weak cryptographic algorithm was detected during secure boot verification - some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodPostInstallTPMDeviceLockedOut(c *C) { @@ -2456,1231 +2098,1774 @@ func (s *runChecksContextSuite) TestRunGoodPostInstallTPMDeviceLockedOut(c *C) { // hierarchy has an authorization value. The TPM lockout is returned as // a warning because it's normally cleared during a successful boot and // it will be cleared during a reprovision as well. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - initialFlags: PostInstallChecks, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Trip the DA logic by triggering an auth failure with a DA protected - // resource. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) - pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) - c.Assert(err, IsNil) - key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) - c.Assert(err, IsNil) - key.SetAuthValue(nil) - _, err = s.TPM.Unseal(key, nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) - - // Take ownership of the lockout hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `5 errors detected: + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + initialFlags: PostInstallChecks, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Trip the DA logic by triggering an auth failure with a DA protected + // resource. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) + pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) + c.Assert(err, IsNil) + key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) + c.Assert(err, IsNil) + key.SetAuthValue(nil) + _, err = s.TPM.Unseal(key, nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) + + // Take ownership of the lockout hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `5 errors detected: - availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set - error with TPM2 device: TPM is in DA lockout mode - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodActionClearTPMSimple(c *C) { // Test that ActionClearTPMSimple works. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMSimple}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMSimple}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) - val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) - c.Assert(err, IsNil) - c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) + c.Assert(err, IsNil) + c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + } } func (s *runChecksContextSuite) TestRunGoodActionClearTPM(c *C) { // Test that ActionClearTPM works. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the lockout hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg("1234")}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the lockout hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg("1234")}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) - val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) - c.Assert(err, IsNil) - c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) + c.Assert(err, IsNil) + c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + } } func (s *runChecksContextSuite) TestRunGoodActionClearTPMMissingAuthValueArg(c *C) { // Test that ActionClearTPM works if the lockout hierarchy has no authorization - // value and no arguments are suppled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + // value and no arguments are supplied. + required := runChecksHostCapabilityValid | runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) - val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) - c.Assert(err, IsNil) - c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + val, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyPermanent) + c.Assert(err, IsNil) + c.Check(tpm2.PermanentAttributes(val)&(tpm2.AttrOwnerAuthSet|tpm2.AttrEndorsementAuthSet|tpm2.AttrLockoutAuthSet), Equals, tpm2.PermanentAttributes(0)) + } } func (s *runChecksContextSuite) TestRunGoodStartupLocalityNotProtected(c *C) { // Test the case where there is a dTPM and the startup locality // is not protected from ring 0 access. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `4 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality0AccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `4 errors detected: - error with system security: cannot enable partial mitigation against discrete TPM reset attacks - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Check(errs, HasLen, 0) + }) + c.Check(errs, HasLen, 0) + } } func (s *runChecksContextSuite) TestRunGoodInvalidPCR0ValueDiscreteTPM(c *C) { // Test the case where there is a dTPM and PCR0 is inconsistent with // the log. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `5 errors detected: + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `5 errors detected: - error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0x420bd3899738e6b41dccd18253a556e152e2b107559b89cbf0cbf1661ff6ee55, reconstructed from log 0xb0d6d5f50852be1524306ad88b928605c14338e56a1b8c0dc211a144524df2ef\) - error with system security: cannot enable partial mitigation against discrete TPM reset attacks - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 0) + }) + if fixture.additionalExpectedFlags&RequireLockToPlatformFirmware != 0 { + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0x420bd3899738e6b41dccd18253a556e152e2b107559b89cbf0cbf1661ff6ee55, reconstructed from log 0xb0d6d5f50852be1524306ad88b928605c14338e56a1b8c0dc211a144524df2ef\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) + continue + } + c.Assert(errs, HasLen, 0) + } } // **End of good cases ** // func (s *runChecksContextSuite) TestRunBadUnexpectedAction(c *C) { - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionClearTPMViaFirmware}}, - }) - c.Assert(errs, HasLen, 1) - c.Assert(errs[0], ErrorMatches, `specified action is not expected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindUnexpectedAction, nil, nil, errs[0].Unwrap())) + required := runChecksHostCapabilities(0) + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionClearTPMViaFirmware}}, + }) + c.Assert(errs, HasLen, 1) + c.Assert(errs[0], ErrorMatches, `specified action is not expected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindUnexpectedAction, nil, nil, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadExternalAction(c *C) { - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionRebootToFWSettings}, - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `specified action is not implemented directly by this package`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindUnexpectedAction, nil, nil, errs[0].Unwrap())) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionRebootToFWSettings}, + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `specified action is not implemented directly by this package`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindUnexpectedAction, nil, nil, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadVirtualMachine(c *C) { // Test the error case where a virtualized environment // is detected. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Assert(errs[0], ErrorMatches, `virtual machine environment detected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindRunningInVM, - nil, - []Action{ActionProceed}, - ErrVirtualMachineDetected, - )) + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Assert(errs[0], ErrorMatches, `virtual machine environment detected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindRunningInVM, + nil, + []Action{ActionProceed}, + ErrVirtualMachineDetected, + )) + } } func (s *runChecksContextSuite) TestRunBadNotEFI(c *C) { // Test the error case where the host system is not EFI - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Assert(errs[0], ErrorMatches, `host system is not an EFI system`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindSystemNotEFI, nil, nil, ErrSystemNotEFI)) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Assert(errs[0], ErrorMatches, `host system is not an EFI system`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindSystemNotEFI, nil, nil, ErrSystemNotEFI)) + } } func (s *runChecksContextSuite) TestRunBadEFIVariableAccessError(c *C) { // Test the error case where an EFI variable access fails - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Err: efi.ErrVarDeviceError}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Assert(errs[0], ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read AuditMode variable: variable access failed because of a hardware error`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindEFIVariableAccess, EFIVarDeviceError, []Action{ActionContactOEM}, errs[0].Unwrap())) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Err: efi.ErrVarDeviceError}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Assert(errs[0], ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read AuditMode variable: variable access failed because of a hardware error`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindEFIVariableAccess, EFIVarDeviceError, []Action{ActionContactOEM}, errs[0].Unwrap())) } func (s *runChecksContextSuite) TestRunBadNoTPM2Device(c *C) { // Test the error case where no valid TPM2 device is detected. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: cannot open TPM device: cannot obtain TPM device: no TPM2 device is available`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitableTPM2Device, nil, nil, errs[0].Unwrap())) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: cannot open TPM device: cannot obtain TPM device: no TPM2 device is available`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitableTPM2Device, nil, nil, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadTPMDeviceFailure(c *C) { // Test the error case where the TPM device is in failure mode. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // The next command following this is inside openAndCheckTPM2Device - // which runs TPM2_SelfTest(false) and will trigger the device's - // failure mode. - s.Mssim(c).TestFailureMode() - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is in failure mode`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceFailure, nil, []Action{ActionReboot, ActionContactOEM}, errs[0].Unwrap())) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // The next command following this is inside openAndCheckTPM2Device + // which runs TPM2_SelfTest(false) and will trigger the device's + // failure mode. + s.Mssim(c).TestFailureMode() + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is in failure mode`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceFailure, nil, []Action{ActionReboot, ActionContactOEM}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadNoPCClientTPMDevice(c *C) { // Test the error case where there is a TPM2 device, but it isn't // a PC Client device. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 2, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but it is not a PC-Client TPM`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitableTPM2Device, nil, nil, errs[0].Unwrap())) + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 2, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but it is not a PC-Client TPM`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitableTPM2Device, nil, nil, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadTPM2DeviceDisabled(c *C) { // Test the error case where the TPM has been disabled by firmware. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + nil, + )), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadTPM2DeviceDisabledRunEnableTPMViaFirmwareAction(c *C) { // Test the error case where the TPM has been disabled by firmware, and // we run the ActionEnableTPMViaFirmware action. + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Disable owner and endorsement hierarchies on the first iteration + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + } + }, + iterations: 2, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"EnableTPM()"}) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Disable owner and endorsement hierarchies on the first iteration - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - } - }, - iterations: 2, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) - } - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - - c.Check(p.called, DeepEquals, []string{"EnableTPM()"}) -} +} func (s *runChecksContextSuite) TestRunBadTPM2DeviceDisabledRunEnableAndClearTPMViaFirmwareAction(c *C) { // Test the error case where the TPM has been disabled by firmware, and // we run the ActionEnableAndClearTPMViaFirmware action. + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Disable owner and endorsement hierarchies on the first iteration - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - } - }, - iterations: 2, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableAndClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) - } - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Disable owner and endorsement hierarchies on the first iteration + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + } + }, + iterations: 2, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableAndClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + } } func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwned(c *C) { // Test the error case where one or more hierarchies of the TPM are already owned. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the endorsement hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the endorsement hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_ENDORSEMENT has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedRunActionClearTPMViaFirmware(c *C) { // Test the error case where one or more hierarchies of the TPM are already owned, and // we run the ActionClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the endorsement hierarchy on the + // first iteration. + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedRunActionEnableAndClearTPMViaFirmware(c *C) { + // Test the error case where one or more hierarchies of the TPM are already owned, and + // we run the ActionEnableAndClearTPMViaFirmware action. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the endorsement hierarchy on the first iteration. + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableAndClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) } +} - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, +func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOut(c *C) { + // Test the error case where the TPM's lockout hierarchy is locked out. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) + + // Disable the lockout hierarchy by authorizing it incorrectly + s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) + err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM's lockout hierarchy is unavailable because it is locked out`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMDeviceLockoutLockedOut, + TPMDeviceLockoutRecoveryArg(24*time.Hour), + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) } +} - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the endorsement hierarchy on the - // first iteration. - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: +func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionClearTPMViaFirmware(c *C) { + // Test the error case where the TPM's lockout hierarchy is locked out, and + // we run the ActionClearTPMViaFirmware action. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Disable the lockout hierarchy on the first iteration. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) + + // Disable the lockout hierarchy by authorizing it incorrectly + s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) + err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMDeviceLockoutLockedOut, + TPMDeviceLockoutRecoveryArg(24*time.Hour), + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) + } +} + +func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionEnableAndClearTPMViaFirmware(c *C) { + // Test the error case where the TPM's lockout hierarchy is locked out, and + // we run the ActionEnableAndClearTPMViaFirmware action. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Disable the lockout hierarchy on the first iteration. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) + + // Disable the lockout hierarchy by authorizing it incorrectly + s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) + err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableAndClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMDeviceLockoutLockedOut, + TPMDeviceLockoutRecoveryArg(24*time.Hour), + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + + c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + } +} + +func (s *runChecksContextSuite) TestRunBadTPMInsufficientCounters(c *C) { + // Test the error case where there appears to be too few NV counters. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: insufficient NV counters available`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientTPMStorage, + nil, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } +} + +func (s *runChecksContextSuite) TestRunBadTPMInsufficientCountersRunActionClearTPMViaFirmware(c *C) { + // Test the error case where there appears to be too few NV counters, and + // we run the ActionClearTPMViaFirmware action. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { c.Assert(errs, HasLen, 1) c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + ErrorKindInsufficientTPMStorage, + nil, []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, errs[0].Unwrap(), )) - } - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) + c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) + } } -func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedRunActionEnableAndClearTPMViaFirmware(c *C) { - // Test the error case where one or more hierarchies of the TPM are already owned, and +func (s *runChecksContextSuite) TestRunBadTPMInsufficientCountersRunActionEnableAndClearTPMViaFirmware(c *C) { + // Test the error case where there appears to be too few NV counters, and // we run the ActionEnableAndClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - } + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + p := &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + } - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the endorsement hierarchy on the first iteration. - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableAndClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableAndClearTPMViaFirmware}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { c.Assert(errs, HasLen, 1) c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + ErrorKindInsufficientTPMStorage, + nil, []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, errs[0].Unwrap(), )) - } - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + } } -func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOut(c *C) { - // Test the error case where the TPM's lockout hierarchy is locked out. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedAndLockedOut(c *C) { + // Test case with more than one TPM error - in this case, one of the errors + // is ErrTPMLockout which is converted to a warning and suppressed unless + // RunChecks completes with success. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Trip the DA logic by triggering an auth failure with a DA protected + // resource. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) + pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) + c.Assert(err, IsNil) + key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) + c.Assert(err, IsNil) + key.SetAuthValue(nil) + _, err = s.TPM.Unseal(key, nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) + + // Take ownership of the lockout hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: +- TPM_RH_LOCKOUT has an authorization value +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksContextSuite) TestRunBadTCGLog(c *C) { + // Test the error case where the TCG log cannot be decoded. + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: nil log`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindMeasuredBoot, nil, nil, errs[0].Unwrap())) } - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) - - // Disable the lockout hierarchy by authorizing it incorrectly - s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) - err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM's lockout hierarchy is unavailable because it is locked out`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMDeviceLockoutLockedOut, - TPMDeviceLockoutRecoveryArg(24*time.Hour), - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) } -func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionClearTPMViaFirmware(c *C) { - // Test the error case where the TPM's lockout hierarchy is locked out, and - // we run the ActionClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +// TODO: Test another bad case where PCR0 is mandatory but unusable, but is mandatory +// because the firmware is only protected with measured boot (this isn't supported yet, +// but it would result in the "no-suitable-pcr-bank" error kind). + +func (s *runChecksContextSuite) TestRunBadInvalidPCR2Value(c *C) { + // Test the error case where PCR2 is inconsistent with the log, but it + // has been marked as mandatory due to the usage of the Microsoft UEFI CA. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksContextSuite) TestRunBadInvalidPCR4Value(c *C) { + // Test the error case where PCR4 is inconsistent with the log, but it + // has been marked as mandatory due to the usage of the Microsoft UEFI CA. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) } +} - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, +func (s *runChecksContextSuite) TestRunBadInvalidPCR7Value(c *C) { + // Test the error case where PCR7 is inconsistent with the log, but it + // has been marked as mandatory because the default profile options + // require it. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\). +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) } +} - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Disable the lockout hierarchy on the first iteration. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) +// TODO: Add a test for ErrorKindUnsupportedPlatform - // Disable the lockout hierarchy by authorizing it incorrectly - s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) - err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMDeviceLockoutLockedOut, - TPMDeviceLockoutRecoveryArg(24*time.Hour), - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) +func (s *runChecksContextSuite) TestRunBadUEFIDebuggingEnabled(c *C) { + // Test the error case where a UEFI debugger is enabled. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + FirmwareDebugger: true, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware contains a debugging endpoint enabled`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindHostSecurity, nil, []Action{ActionContactOEM}, errs[0].Unwrap())) + } +} - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) +func (s *runChecksContextSuite) TestRunBadInsufficientDMAProtection(c *C) { + // Test the error case where DMA protection is disabled. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + errs[0].Unwrap(), + )) + } +} - c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) +func (s *runChecksContextSuite) TestRunBadNoKernelIOMMU(c *C) { + // Test the error case where the kernel doesn't enable a IOMMU + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindNoKernelIOMMU, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOSVendor}, + errs[0].Unwrap(), + )) + } } -func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionEnableAndClearTPMViaFirmware(c *C) { - // Test the error case where the TPM's lockout hierarchy is locked out, and - // we run the ActionEnableAndClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksContextSuite) TestRunChecksBadTPMHierarchiesOwnedAndNoKernelIOMMU(c *C) { + // Test case where a TPM hierarchy is owned and there is a host security error. + // This tests the case where ActionProceed is suppressed because one of the returned + // errors doesn't permit it. + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + prepare: func(_ int) { + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 2) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: +- TPM_RH_OWNER has an authorization value +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + c.Check(errs[1], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindNoKernelIOMMU, + nil, + []Action{ActionRebootToFWSettings, ActionContactOSVendor}, + errs[1].Unwrap(), + )) + } +} + +func (s *runChecksContextSuite) TestRunBadNoHardwareRootOfTrust(c *C) { + // Test the error case where the hardware root of trust is insufficient. + required := runChecksHostCapabilityInsufficientHWRootOfTrust + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoHardwareRootOfTrust, nil, []Action{ActionProceed}, errs[0].Unwrap())) } +} + +func (s *runChecksContextSuite) TestRunBadHostSecurityErrorMissingIntelMEModule(c *C) { + s.AddCleanup(MockRuntimeGOARCH("amd64")) + + // Test case where host security checks fail because the intel ME kernel module is missing. devices := []internal_efi.SysfsDevice{ efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00:16:0", map[string]string{"PCI_CLASS": "78000", "PCI_ID": "8086:7E70"}, "pci", nil, nil), } errs := s.testRun(c, &testRunChecksContextRunParams{ env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ tpm2.PropertyNVCountersMax: 0, @@ -3688,49 +3873,18 @@ func (s *runChecksContextSuite) TestRunBadTPMDeviceLockoutLockedOutRunActionEnab tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Disable the lockout hierarchy on the first iteration. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 32, 7200, 86400, nil), IsNil) - - // Disable the lockout hierarchy by authorizing it incorrectly - s.TPM.LockoutHandleContext().SetAuthValue([]byte("1234")) - err := s.TPM.DictionaryAttackLockReset(s.TPM.LockoutHandleContext(), nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandDictionaryAttackLockReset, 1), testutil.IsTrue) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableAndClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMDeviceLockoutLockedOut, - TPMDeviceLockoutRecoveryArg(24*time.Hour), - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, + actions: []actionAndArgs{{action: ActionNone}}, }) c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - - c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) + c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: the kernel module "mei_me" must be loaded`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindInternal, nil, nil, errs[0].Unwrap())) + c.Check(errors.Is(errs[0], MissingKernelModuleError("mei_me")), testutil.IsTrue) } -func (s *runChecksContextSuite) TestRunBadTPMInsufficientCounters(c *C) { - // Test the error case where there appears to be too few NV counters. +func (s *runChecksContextSuite) TestRunBadHostSecurityErrorMissingMSR(c *C) { + s.AddCleanup(MockRuntimeGOARCH("amd64")) + + // Test case where host security checks fail because the MSR kernel module is missing. meiAttrs := map[string][]byte{ "fw_ver": []byte(`0:16.1.27.2176 0:16.1.27.2176 @@ -3745,1210 +3899,374 @@ func (s *runChecksContextSuite) TestRunBadTPMInsufficientCounters(c *C) { "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, )), } + errs := s.testRun(c, &testRunChecksContextRunParams{ env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 0, nil), efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, + tpm2.PropertyNVCountersMax: 0, tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, actions: []actionAndArgs{{action: ActionNone}}, }) c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: insufficient NV counters available`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientTPMStorage, - nil, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel CPU debugging configuration: the kernel module "msr" must be loaded`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindInternal, nil, nil, errs[0].Unwrap())) + c.Check(errors.Is(errs[0], MissingKernelModuleError("msr")), testutil.IsTrue) } -func (s *runChecksContextSuite) TestRunBadTPMInsufficientCountersRunActionClearTPMViaFirmware(c *C) { - // Test the error case where there appears to be too few NV counters, and - // we run the ActionClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +func (s *runChecksContextSuite) TestRunBadSHA1(c *C) { + // Test the error case where there is no suitable PCR bank other + // than SHA1, but SHA1 is disallowed by default. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, + }, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA1, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: the PCR bank is missing from the TCG log. +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) } +} - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, +func (s *runChecksContextSuite) TestRunBadPCRProfileMostSecure(c *C) { + // Test the error case where the profile options are set to "most secure". + // This is currently unsupported because of a lack of source for some + // PCRs - it is intended that this will work eventually. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionMostSecure, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 3) + c.Check(errs[0], ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(1), nil, errs[0].Unwrap())) + + c.Check(errs[1], ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(3), nil, errs[1].Unwrap())) + + c.Check(errs[2], ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(5), nil, errs[2].Unwrap())) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientTPMStorage, - nil, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - - c.Check(p.called, DeepEquals, []string{"ClearTPM()"}) -} - -func (s *runChecksContextSuite) TestRunBadTPMInsufficientCountersRunActionEnableAndClearTPMViaFirmware(c *C) { - // Test the error case where there appears to be too few NV counters, and - // we run the ActionEnableAndClearTPMViaFirmware action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - p := &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), p, nil)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableAndClearTPMViaFirmware}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientTPMStorage, - nil, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a reboot is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindRebootRequired, nil, []Action{ActionReboot}, errs[0].Unwrap())) - - c.Check(p.called, DeepEquals, []string{"EnableAndClearTPM()"}) -} - -func (s *runChecksContextSuite) TestRunBadTPMHierarchiesOwnedAndLockedOut(c *C) { - // Test case with more than one TPM error - in this case, one of the errors - // is ErrTPMLockout which is converted to a warning and suppressed unless - // RunChecks completes with success. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Trip the DA logic by triggering an auth failure with a DA protected - // resource. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) - pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) - c.Assert(err, IsNil) - key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) - c.Assert(err, IsNil) - key.SetAuthValue(nil) - _, err = s.TPM.Unseal(key, nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) - - // Take ownership of the lockout hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: -- TPM_RH_LOCKOUT has an authorization value -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunBadTCGLog(c *C) { - // Test the error case where the TCG log cannot be decoded. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: nil log`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindMeasuredBoot, nil, nil, errs[0].Unwrap())) -} - -// TODO: Test another bad case where PCR0 is mandatory but unusable, but is mandatory -// because the firmware is only protected with measured boot (this isn't supported yet, -// but it would result in the "no-suitable-pcr-bank" error kind). - -func (s *runChecksContextSuite) TestRunBadInvalidPCR2Value(c *C) { - // Test the error case where PCR2 is inconsistent with the log, but it - // has been marked as mandatory due to the usage of the Microsoft UEFI CA. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\). -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadInvalidPCR4Value(c *C) { - // Test the error case where PCR4 is inconsistent with the log, but it - // has been marked as mandatory due to the usage of the Microsoft UEFI CA. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\). -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadInvalidPCR7Value(c *C) { - // Test the error case where PCR7 is inconsistent with the log, but it - // has been marked as mandatory because the default profile options - // require it. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\). -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) -} - -// TODO: Add a test for ErrorKindUnsupportedPlatform - -func (s *runChecksContextSuite) TestRunBadUEFIDebuggingEnabled(c *C) { - // Test the error case where a UEFI debugger is enabled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - FirmwareDebugger: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware contains a debugging endpoint enabled`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindHostSecurity, nil, []Action{ActionContactOEM}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadInsufficientDMAProtection(c *C) { - // Test the error case where DMA protection is disabled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunBadNoKernelIOMMU(c *C) { - // Test the error case where the kernel doesn't enable a IOMMU - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindNoKernelIOMMU, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOSVendor}, - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunChecksBadTPMHierarchiesOwnedAndNoKernelIOMMU(c *C) { - // Test case where a TPM hierarchy is owned and there is a host security error. - // This tests the case where ActionProceed is suppressed because one of the returned - // errors doesn't permit it. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (2 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - prepare: func(_ int) { - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 2) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: -- TPM_RH_OWNER has an authorization value -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - - c.Check(errs[1], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindNoKernelIOMMU, - nil, - []Action{ActionRebootToFWSettings, ActionContactOSVendor}, - errs[1].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunBadHostSecurityErrorMissingIntelMEModule(c *C) { - // Test case where host security checks fail because the intel ME kernel module is missing. - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00:16:0", map[string]string{"PCI_CLASS": "78000", "PCI_ID": "8086:7E70"}, "pci", nil, nil), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: the kernel module "mei_me" must be loaded`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindInternal, nil, nil, errs[0].Unwrap())) - c.Check(errors.Is(errs[0], MissingKernelModuleError("mei_me")), testutil.IsTrue) -} - -func (s *runChecksContextSuite) TestRunBadHostSecurityErrorMissingMSR(c *C) { - // Test case where host security checks fail because the MSR kernel module is missing. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 0, nil), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel CPU debugging configuration: the kernel module "msr" must be loaded`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindInternal, nil, nil, errs[0].Unwrap())) - c.Check(errors.Is(errs[0], MissingKernelModuleError("msr")), testutil.IsTrue) -} - -func (s *runChecksContextSuite) TestRunBadNoHardwareRootOfTrust(c *C) { - // Test the error case where we're running on an Intel based device - // and BootGuard is mis-configured. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoHardwareRootOfTrust, nil, []Action{ActionProceed}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadSHA1(c *C) { - // Test the error case where there is no suitable PCR bank other - // than SHA1, but SHA1 is disallowed by default. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), - }, - }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, - }, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA1, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: the PCR bank is missing from the TCG log. -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindNoSuitablePCRBank, nil, []Action{ActionRebootToFWSettings, ActionContactOEM}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunBadPCRProfileMostSecure(c *C) { - // Test the error case where the profile options are set to "most secure". - // This is currently unsupported because of a lack of source for some - // PCRs - it is intended that this will work eventually. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionMostSecure, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 3) - c.Check(errs[0], ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(1), nil, errs[0].Unwrap())) - - c.Check(errs[1], ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(3), nil, errs[1].Unwrap())) - - c.Check(errs[2], ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(5), nil, errs[2].Unwrap())) -} +} func (s *runChecksContextSuite) TestRunBadInvalidPCR7ValuePCRProfilePermitNoSecureBoot(c *C) { // Test the error case where PCR7 is unusable and the profile options are set // to permit policies without PCR7, but this fails due to a lack of support // for some mandatory alternative PCRs - it is intended that this case will // work in the future. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionPermitNoSecureBootPolicyProfile, - prepare: func(_ int) { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 3) - c.Check(errs[0], ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(1), nil, errs[0].Unwrap())) + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionPermitNoSecureBootPolicyProfile, + prepare: func(_ int) { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 3) + c.Check(errs[0], ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(1), nil, errs[0].Unwrap())) - c.Check(errs[1], ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(3), nil, errs[1].Unwrap())) + c.Check(errs[1], ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(3), nil, errs[1].Unwrap())) - c.Check(errs[2], ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(5), nil, errs[2].Unwrap())) + c.Check(errs[2], ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(5), nil, errs[2].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadAddonDriversPresent(c *C) { // Test the error case where value-added-retailer drivers have been detected // but the initial flags do not permit these. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + } } func (s *runChecksContextSuite) TestRunBadSysPrepAppsPresent(c *C) { // Test the error case where system preparations have been detected // but the initial flags do not permit these. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `system preparation applications were detected: + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `system preparation applications were detected: - Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 `) - imageInfo := []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - } + imageInfo := []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), + }, + } - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindSysPrepApplicationsPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &SysPrepApplicationsPresentError{ - Apps: imageInfo, - }, - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindSysPrepApplicationsPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &SysPrepApplicationsPresentError{ + Apps: imageInfo, + }, + )) + } } func (s *runChecksContextSuite) TestRunBadAbsoluteActive(c *C) { // Test the error case where Absolute has been detected but the initial // flags do not permit this. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `Absolute was detected to be active and it is advised that this is disabled`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAbsolutePresent, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + ErrAbsoluteComputraceActive, + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `Absolute was detected to be active and it is advised that this is disabled`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAbsolutePresent, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - ErrAbsoluteComputraceActive, - )) } func (s *runChecksContextSuite) TestRunBadNotAllBootManagerCodeDigestsVerified(c *C) { @@ -4957,411 +4275,333 @@ func (s *runChecksContextSuite) TestRunBadNotAllBootManagerCodeDigestsVerified(c // profile options were supplied, but where PCR4 is marked unusable because // not all of the EFI applications that were part of the current boot were // supplied when creating the RunChecksContext. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: grubDigestDefault}, }, - &mockImage{contents: []byte("mock grub executable"), digest: grubDigestDefault}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with boot manager code \(PCR4\) measurements: cannot verify correctness of EV_EFI_BOOT_SERVICES_APPLICATION event digest: not enough images supplied`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(4), []Action{ActionContactOEM}, errs[0].Unwrap())) + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with boot manager code \(PCR4\) measurements: cannot verify correctness of EV_EFI_BOOT_SERVICES_APPLICATION event digest: not enough images supplied`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(4), []Action{ActionContactOEM}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeSecureBootDisabled(c *C) { // Test the error case where PCR7 is mandatory with the supplied profile options, // but is marked invalid because secure boot is disabled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + SecureBootDisabled: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidSecureBootMode, + SecureBootModeArg{ + Enabled: false, + Mode: efi.UserMode, + }, + []Action{ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - SecureBootDisabled: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidSecureBootMode, - SecureBootModeArg{ - Enabled: false, - Mode: efi.UserMode, - }, - []Action{ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) } func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeSecureBootDisabledAndNoSBATLevel(c *C) { // Simulate running on a machine with secure boot disabled and running // shim on a system with an empty SbatLevel variable. In this case, // there are no EV_EFI_VARIABLE_AUTHORITY events which caused - // https://launchpad.net/bugs/2125439 - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - SecureBootDisabled: true, - NoSBAT: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidSecureBootMode, - SecureBootModeArg{ - Enabled: false, - Mode: efi.UserMode, - }, - []Action{ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + // https://launchpad.net/bugs/2125439 + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + SecureBootDisabled: true, + NoSBAT: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidSecureBootMode, + SecureBootModeArg{ + Enabled: false, + Mode: efi.UserMode, + }, + []Action{ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadNoSecureBootPolicySupport(c *C) { // Test the error case where PCR7 is mandatory but the secure boot checks fail // because dbx is measured twice. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}}) - var eventsCopy []*tcglog.Event - for _, ev := range log.Events { - eventsCopy = append(eventsCopy, ev) - - if ev.PCRIndex != internal_efi.SecureBootPolicyPCR { - continue - } - if ev.EventType != tcglog.EventTypeEFIVariableDriverConfig { - continue - } - data, ok := ev.Data.(*tcglog.EFIVariableData) - c.Assert(ok, testutil.IsTrue) - if data.UnicodeName == "dbx" { - // Measure dbx twice + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + log := efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}}) + var eventsCopy []*tcglog.Event + for _, ev := range log.Events { eventsCopy = append(eventsCopy, ev) + + if ev.PCRIndex != internal_efi.SecureBootPolicyPCR { + continue + } + if ev.EventType != tcglog.EventTypeEFIVariableDriverConfig { + continue + } + data, ok := ev.Data.(*tcglog.EFIVariableData) + c.Assert(ok, testutil.IsTrue) + if data.UnicodeName == "dbx" { + // Measure dbx twice + eventsCopy = append(eventsCopy, ev) + } } + log.Events = eventsCopy + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(log), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: unexpected EV_EFI_VARIABLE_DRIVER_CONFIG event: all expected secure boot variable have been measured`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(7), []Action{ActionContactOEM}, errs[0].Unwrap())) } - log.Events = eventsCopy - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(log), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with secure boot policy \(PCR7\) measurements: unexpected EV_EFI_VARIABLE_DRIVER_CONFIG event: all expected secure boot variable have been measured`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindPCRUnusable, PCRUnusableArg(7), []Action{ActionContactOEM}, errs[0].Unwrap())) } func (s *runChecksContextSuite) TestRunBadWeakSecureBootAlgs(c *C) { // Test the error case where PCR7 is mandatory with the supplied profile options, // but is marked invalid because the use of weak algorithms were detected during // the current boot. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(errs, HasLen, 3) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(errs, HasLen, 3) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], ErrorMatches, `a weak cryptographic algorithm was detected during secure boot verification`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindWeakSecureBootAlgorithmsDetected, - nil, - []Action{ActionProceed}, - ErrWeakSecureBootAlgorithmDetected, - )) - - c.Check(errs[2], ErrorMatches, `some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest`) - c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], ErrorMatches, `a weak cryptographic algorithm was detected during secure boot verification`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindWeakSecureBootAlgorithmsDetected, + nil, + []Action{ActionProceed}, + ErrWeakSecureBootAlgorithmDetected, + )) + + c.Check(errs[2], ErrorMatches, `some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest`) + c.Check(errs[2], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } } func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeNoDeployedMode(c *C) { // Test the error case where PCR7 is mandatory with the supplied profile options, // but is marked invalid because the system is not in deployed mode. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `secure boot is enabled but not in deployed mode`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidSecureBootMode, + SecureBootModeArg{ + Enabled: true, + Mode: efi.UserMode, + }, + []Action{ActionRebootToFWSettings, ActionProceed}, + ErrNoDeployedMode, + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `secure boot is enabled but not in deployed mode`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidSecureBootMode, - SecureBootModeArg{ - Enabled: true, - Mode: efi.UserMode, - }, - []Action{ActionRebootToFWSettings, ActionProceed}, - ErrNoDeployedMode, - )) } // TODO: This is disabled temporarily until a follow-up PR which adds warnings to the returned errors @@ -5396,7 +4636,7 @@ func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeNoDeployedMode(c // efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ // Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, // })), -// efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), +// efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), // efitest.WithSysfsDevices(devices...), // efitest.WithMockVars(efitest.MockVars{ // {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, @@ -5463,7 +4703,7 @@ func (s *runChecksContextSuite) TestRunBadInvalidSecureBootModeNoDeployedMode(c // efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ // Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, // })), -// efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), +// efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), // efitest.WithSysfsDevices(devices...), // efitest.WithMockVars(efitest.MockVars{ // {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, @@ -5510,1696 +4750,1492 @@ func (s *runChecksContextSuite) TestRunChecksBadInsufficientDMAProtectionAndNoKe // Test with a system that has insufficient DMA protection and no kernel IOMMU. // As both errors support ActionProceed, it is a valid action for // both of the returned errors. - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{{action: ActionNone}}, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 2) + + c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, + errs[0].Unwrap(), + )) + + c.Check(errs[1], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindNoKernelIOMMU, + nil, + []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOSVendor}, + errs[1].Unwrap(), + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{{action: ActionNone}}, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 2) - - c.Check(errs[0], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOEM}, - errs[0].Unwrap(), - )) - - c.Check(errs[1], ErrorMatches, `error with system security: no kernel IOMMU support was detected`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindNoKernelIOMMU, - nil, - []Action{ActionRebootToFWSettings, ActionProceed, ActionContactOSVendor}, - errs[1].Unwrap(), - )) } func (s *runChecksContextSuite) TestRunChecksActionEnableTPMViaFirmwareNotAvailable(c *C) { // Generate an error that could be fixed by ActionEnableTPMViaFirmware when // this action is not available. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + nil, + )), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunChecksActionEnableAndClearTPMViaFirmwareNotAvailable(c *C) { // Generate an error that could be fixed by ActionEnableAndClearTPMViaFirmware when // this action is not available. - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionShutdownRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionShutdownRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + nil, + )), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindTPMDeviceDisabled, nil, []Action{ActionEnableTPMViaFirmware, ActionRebootToFWSettings}, errs[0].Unwrap())) + } } func (s *runChecksContextSuite) TestRunChecksActionClearTPMViaFirmwareNotAvailable(c *C) { // Generate an error that could be fixed by ActionClearTPMViaFirmware when this action // is not available. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the endorsement hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the endorsement hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_ENDORSEMENT has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, - []Action{ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksPPIActionWithShutdownTransition(c *C) { // Generate an error that can be resolve using a PPI action, with the // state transition action being "shutdown" rather than the more common - // "reboot". - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionShutdownRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyPSFamilyIndicator: 1, - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - iterations: 2, - prepare: func(i int) { - switch i { - case 0: - // Disable owner and endorsement hierarchies on the first iteration - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionEnableTPMViaFirmware}, - }, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `a shutdown is required to complete the action`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindShutdownRequired, nil, []Action{ActionShutdown}, errs[0].Unwrap())) -} - -func (s *runChecksContextSuite) TestRunChecksActionProceedUnavailable(c *C) { - // Return 2 errors where only 1 supports ActionProceed. It should - // be suppressed in this case. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + // "reboot". + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionShutdownRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyPSFamilyIndicator: 1, + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + iterations: 2, + prepare: func(i int) { + switch i { + case 0: + // Disable owner and endorsement hierarchies on the first iteration + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionEnableTPMViaFirmware}, + }, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `a shutdown is required to complete the action`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError(ErrorKindShutdownRequired, nil, []Action{ActionShutdown}, errs[0].Unwrap())) } +} - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationClearTPM: ppi.OperationPPRequired, +func (s *runChecksContextSuite) TestRunChecksActionProceedUnavailable(c *C) { + // Return 2 errors where only 1 supports ActionProceed. It should + // be suppressed in this case. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the endorsement hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 2) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the endorsement hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleEndorsement, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 2) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_ENDORSEMENT has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, - []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - - c.Check(errs[1], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionContactOEM}, - errs[1].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleEndorsement}}, + []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + c.Check(errs[1], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionContactOEM}, + errs[1].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksActionProceedErrorsOrderedAfterOtherErrors(c *C) { // Ensure that errors which support ActionProceed get reordered to be // returned after other errors. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func(_ int) { - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 2) + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func(_ int) { + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 2) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_OWNER has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - - c.Check(errs[1], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindInsufficientDMAProtection, - nil, - []Action{ActionRebootToFWSettings, ActionContactOEM}, - errs[1].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + + c.Check(errs[1], ErrorMatches, `error with system security: the platform firmware indicates that DMA protections are insufficient`) + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindInsufficientDMAProtection, + nil, + []Action{ActionRebootToFWSettings, ActionContactOEM}, + errs[1].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksActionProceedUnsupportedArgumentType(c *C) { // Test that passing an unsupported type as an argument to ActionProceed // generates an error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed, args: map[string]any{"error-kinds": 1}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 1) - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed, args: map[string]any{"error-kinds": 1}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 1) + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `cannot deserialize argument map from JSON to type preinstall.ActionProceedArgs: json: cannot unmarshal number into Go value of type \[\]preinstall.ErrorKind`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "error-kinds", - Reason: InvalidActionArgumentReasonType, - }, - nil, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `cannot deserialize argument map from JSON to type preinstall.ActionProceedArgs: json: cannot unmarshal number into Go value of type \[\]preinstall.ErrorKind`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "error-kinds", + Reason: InvalidActionArgumentReasonType, + }, + nil, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksActionProceedUnexpectedErrorKind1(c *C) { // Test that passing an unexpected ErrorKind as an argument to ActionProceed // generates an error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindPreOSSecureBootAuthByEnrolledDigests}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 1) - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindPreOSSecureBootAuthByEnrolledDigests}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 1) + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `invalid value for argument "error-kinds" at index 0: "pre-os-secure-boot-auth-by-enrolled-digests" is not expected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "error-kinds", - Reason: InvalidActionArgumentReasonValue, - }, - nil, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `invalid value for argument "error-kinds" at index 0: "pre-os-secure-boot-auth-by-enrolled-digests" is not expected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "error-kinds", + Reason: InvalidActionArgumentReasonValue, + }, + nil, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksActionProceedUnexpectedErrorKind2(c *C) { // Test that passing the same ErrorKind as an argument to ActionProceed // more than once generates an error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 3, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 2) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, - }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } - - c.Check(errs[0], ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 -`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) - - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - case 1: - c.Check(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `invalid value for argument "error-kinds" at index 0: "addon-drivers-present" is not expected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "error-kinds", - Reason: InvalidActionArgumentReasonValue, - }, - nil, - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunChecksActionProceedUnexpectedErrorKind3(c *C) { - // Test that passing any ErrorKind as an argument to ActionProceed after - // already accepting all errors generates an error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 3, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionProceed}, - {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Check(errs, HasLen, 2) - - imageInfo := []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 3, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 2) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - } + } - c.Check(errs[0], ErrorMatches, `addon drivers were detected: + c.Check(errs[0], ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindAddonDriversPresent, - LoadedImagesInfoArg(imageInfo), - []Action{ActionProceed}, - &AddonDriversPresentError{ - Drivers: imageInfo, - }, - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + case 1: + c.Check(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `invalid value for argument "error-kinds" at index 0: "addon-drivers-present" is not expected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "error-kinds", + Reason: InvalidActionArgumentReasonValue, + }, + nil, + errs[0].Unwrap(), + )) + } +} - c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( - ErrorKindPreOSSecureBootAuthByEnrolledDigests, - nil, - []Action{ActionProceed}, - ErrPreOSSecureBootAuthByEnrolledDigests, - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `specified action is not expected`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindUnexpectedAction, - nil, - nil, - errs[0].Unwrap(), - )) +func (s *runChecksContextSuite) TestRunChecksActionProceedUnexpectedErrorKind3(c *C) { + // Test that passing any ErrorKind as an argument to ActionProceed after + // already accepting all errors generates an error. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 3, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionProceed}, + {action: ActionProceed, args: ActionProceedArgs{ErrorKindAddonDriversPresent}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Check(errs, HasLen, 2) + + imageInfo := []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), + }, + } + + c.Check(errs[0], ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindAddonDriversPresent, + LoadedImagesInfoArg(imageInfo), + []Action{ActionProceed}, + &AddonDriversPresentError{ + Drivers: imageInfo, + }, + )) + + c.Check(errs[1], DeepEquals, NewWithKindAndActionsError( + ErrorKindPreOSSecureBootAuthByEnrolledDigests, + nil, + []Action{ActionProceed}, + ErrPreOSSecureBootAuthByEnrolledDigests, + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `specified action is not expected`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindUnexpectedAction, + nil, + nil, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksClearTPMNotAvailable(c *C) { // Test the case where neither ActionClearTPMSimple and ActionClearTPM are // not available because owner clear is disabled. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - // Disable owner clear. - c.Assert(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + // Disable owner clear. + c.Assert(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_OWNER has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunChecksClearTPMSimpleNotAvailable(c *C) { // Test the case where ActionClearTPMSimple is not available because the // lockout hierarchy has a non-empty authorization value. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - profileOpts: PCRProfileOptionsDefault, - prepare: func(_ int) { - // Set an authorization value for the lockout hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - actions: []actionAndArgs{{action: ActionNone}}, - }) - c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + profileOpts: PCRProfileOptionsDefault, + prepare: func(_ int) { + // Set an authorization value for the lockout hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + actions: []actionAndArgs{{action: ActionNone}}, + }) + c.Assert(errs, HasLen, 1) + c.Check(errs[0], ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_LOCKOUT has an authorization value `) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleFailsInvalidAuthValue(c *C) { // Test that ActionClearTPMSimple returns an error if something sets // the authorization value for the lockout hierarchy in between // receiving the first error and submitting the action. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - case 1: - // Set an authorization value for the lockout hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMSimple}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: -- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 -- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 -- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 -`, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `specified action is no longer available because the TPM's lockout hierarchy now has a non-empty auth value: use "clear-tpm" action instead`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindUnexpectedAction, - nil, nil, // args, actions - errs[0].Unwrap(), - )) -} - -func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleFailsWithError(c *C) { - // Test that ActionClearTPMSimple returns an error if clearing the - // TPM fails for some reason. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - case 1: - // Disable owner clear - c.Check(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPMSimple}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + case 1: + // Set an authorization value for the lockout hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMSimple}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `cannot clear TPM: TPM returned an error whilst executing command TPM_CC_Clear: TPM_RC_DISABLED \(the command is disabled\)`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindActionFailed, - nil, nil, // args, actions - errs[0].Unwrap(), - )) -} + }) + c.Assert(errs, HasLen, 1) -func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleBecomesUnavailableAfterLockoutAuthFailure(c *C) { - // Test that ActionClearTPMSimple becomes unavailable if the lockout - // hierarchy is used with an invalid auth value. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + c.Check(errs[0], ErrorMatches, `specified action is no longer available because the TPM's lockout hierarchy now has a non-empty auth value: use "clear-tpm" action instead`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindUnexpectedAction, + nil, nil, // args, actions + errs[0].Unwrap(), + )) } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 3, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - case 1: - // Set an authorization value for the lockout hierarchy, - // so that we can run ActionClearTPM with the wrong value. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg("5678")}, - {action: ActionClearTPMSimple}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - case 1: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "auth-value", - Reason: InvalidActionArgumentReasonValue, +} + +func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleFailsWithError(c *C) { + // Test that ActionClearTPMSimple returns an error if clearing the + // TPM fails for some reason. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - nil, // actions, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + case 1: + // Disable owner clear + c.Check(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPMSimple}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `cannot clear TPM: TPM returned an error whilst executing command TPM_CC_Clear: TPM_RC_DISABLED \(the command is disabled\)`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindActionFailed, + nil, nil, // args, actions + errs[0].Unwrap(), + )) + } +} + +func (s *runChecksContextSuite) TestRunBadActionClearTPMSimpleBecomesUnavailableAfterLockoutAuthFailure(c *C) { + // Test that ActionClearTPMSimple becomes unavailable if the lockout + // hierarchy is used with an invalid auth value. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, + }, + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 3, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + case 1: + // Set an authorization value for the lockout hierarchy, + // so that we can run ActionClearTPM with the wrong value. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg("5678")}, + {action: ActionClearTPMSimple}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + case 1: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "auth-value", + Reason: InvalidActionArgumentReasonValue, + }, + nil, // actions, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: +- error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 +- error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 +- error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 +`, + }) + c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `specified action is no longer available`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindUnexpectedAction, - nil, nil, // args, actions - errs[0].Unwrap(), - )) + c.Check(errs[0], ErrorMatches, `specified action is no longer available`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindUnexpectedAction, + nil, nil, // args, actions + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMInvalidAuthValueArgumentType(c *C) { // Test that ActionClearTPM returns an error if the supplied lockout // hierarchy authorization value argument is the wrong type. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: map[string]any{"auth-value": 1}}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: map[string]any{"auth-value": 1}}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `cannot deserialize argument map from JSON to type preinstall.TPMAuthValueArg: json: cannot unmarshal number into Go value of type \[\]uint8`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "auth-value", - Reason: InvalidActionArgumentReasonType, - }, - nil, // actions - errs[0].Unwrap(), - )) + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `cannot deserialize argument map from JSON to type preinstall.TPMAuthValueArg: json: cannot unmarshal number into Go value of type \[\]uint8`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "auth-value", + Reason: InvalidActionArgumentReasonType, + }, + nil, // actions + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMInvalidAuthValue(c *C) { // Test that ActionClearTPM returns an error if the supplied lockout // hierarchy authorization value is inconsistent with the value of // the lockoutAuthSet attribute. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg("1234")}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg("1234")}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) - - c.Check(errs[0], ErrorMatches, `supplied TPM lockout hierarchy authorization value is inconsistent with the value of the TPM_PT_PERMANENT lockoutAuthSet attribute`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "auth-value", - Reason: InvalidActionArgumentReasonValue, - }, - nil, // actions - errs[0].Unwrap(), - )) + }) + c.Assert(errs, HasLen, 1) + + c.Check(errs[0], ErrorMatches, `supplied TPM lockout hierarchy authorization value is inconsistent with the value of the TPM_PT_PERMANENT lockoutAuthSet attribute`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "auth-value", + Reason: InvalidActionArgumentReasonValue, + }, + nil, // actions + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMFailsWithError(c *C) { // Test that ActionClearTPM returns an error if clearing the // TPM fails for some reason. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 2, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the storage hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) - case 1: - // Disable owner clear - c.Check(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg(nil)}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 2, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the storage hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleOwner, []byte("1234")) + case 1: + // Disable owner clear + c.Check(s.TPM.ClearControl(s.TPM.LockoutHandleContext(), true, nil), IsNil) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg(nil)}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleOwner}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPMSimple, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) + }) + c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `cannot clear TPM: TPM returned an error whilst executing command TPM_CC_Clear: TPM_RC_DISABLED \(the command is disabled\)`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindActionFailed, - nil, nil, // args, actions - errs[0].Unwrap(), - )) + c.Check(errs[0], ErrorMatches, `cannot clear TPM: TPM returned an error whilst executing command TPM_CC_Clear: TPM_RC_DISABLED \(the command is disabled\)`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindActionFailed, + nil, nil, // args, actions + errs[0].Unwrap(), + )) + } } func (s *runChecksContextSuite) TestRunBadActionClearTPMBecomesUnavailableAfterLockoutAuthFailure(c *C) { // Test that ActionClearTPM becomes unavailable if the lockout // hierarchy is used with an invalid auth value. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - errs := s.testRun(c, &testRunChecksContextRunParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice( - tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), - &mockPPI{ - sta: ppi.StateTransitionRebootRequired, - ops: map[ppi.OperationId]ppi.OperationStatus{ - ppi.OperationEnableTPM: ppi.OperationPPRequired, - ppi.OperationClearTPM: ppi.OperationPPRequired, - ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, - }, - }, - nil, - )), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0x13a: (3 << 1), 0xc80: 0x40000000}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - iterations: 3, - loadedImages: efiImagesDefault(), - profileOpts: PCRProfileOptionsDefault, - prepare: func(i int) { - switch i { - case 0: - // Set an authorization value for the lockout hierarchy. - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - } - }, - actions: []actionAndArgs{ - {action: ActionNone}, - {action: ActionClearTPM, args: TPMAuthValueArg("5678")}, - {action: ActionClearTPM}, - }, - checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { - switch i { - case 0: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindTPMHierarchiesOwned, - &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, - []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, - errs[0].Unwrap(), - )) - case 1: - c.Assert(errs, HasLen, 1) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindInvalidArgument, - InvalidActionArgumentDetails{ - Field: "auth-value", - Reason: InvalidActionArgumentReasonValue, + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + errs := s.testRun(c, &testRunChecksContextRunParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice( + tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), + &mockPPI{ + sta: ppi.StateTransitionRebootRequired, + ops: map[ppi.OperationId]ppi.OperationStatus{ + ppi.OperationEnableTPM: ppi.OperationPPRequired, + ppi.OperationClearTPM: ppi.OperationPPRequired, + ppi.OperationEnableAndClearTPM: ppi.OperationPPRequired, + }, }, - nil, // actions, - errs[0].Unwrap(), - )) - } - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - expectedWarningsMatch: `3 errors detected: + nil, + )), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + iterations: 3, + loadedImages: efiImagesDefault(), + profileOpts: PCRProfileOptionsDefault, + prepare: func(i int) { + switch i { + case 0: + // Set an authorization value for the lockout hierarchy. + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + } + }, + actions: []actionAndArgs{ + {action: ActionNone}, + {action: ActionClearTPM, args: TPMAuthValueArg("5678")}, + {action: ActionClearTPM}, + }, + checkIntermediateErrs: func(i int, errs []*WithKindAndActionsError) { + switch i { + case 0: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindTPMHierarchiesOwned, + &TPM2OwnedHierarchiesError{WithAuthValue: tpm2.HandleList{tpm2.HandleLockout}}, + []Action{ActionClearTPMViaFirmware, ActionEnableAndClearTPMViaFirmware, ActionClearTPM, ActionRebootToFWSettings}, + errs[0].Unwrap(), + )) + case 1: + c.Assert(errs, HasLen, 1) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindInvalidArgument, + InvalidActionArgumentDetails{ + Field: "auth-value", + Reason: InvalidActionArgumentReasonValue, + }, + nil, // actions, + errs[0].Unwrap(), + )) + } + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + expectedWarningsMatch: `3 errors detected: - error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322 - error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341 - error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323 `, - }) - c.Assert(errs, HasLen, 1) + }) + c.Assert(errs, HasLen, 1) - c.Check(errs[0], ErrorMatches, `specified action is no longer available`) - c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( - ErrorKindUnexpectedAction, - nil, nil, // args, actions - errs[0].Unwrap(), - )) + c.Check(errs[0], ErrorMatches, `specified action is no longer available`) + c.Check(errs[0], DeepEquals, NewWithKindAndActionsError( + ErrorKindUnexpectedAction, + nil, nil, // args, actions + errs[0].Unwrap(), + )) + } } type insertActionProceedTestSuite struct{} diff --git a/efi/preinstall/checks_fixture_test.go b/efi/preinstall/checks_fixture_test.go new file mode 100644 index 00000000..d40de2de --- /dev/null +++ b/efi/preinstall/checks_fixture_test.go @@ -0,0 +1,213 @@ +// -*- 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 +) + +// runChecksHostFixture abstracts host-specific details from scenario logic in +// the shared RunChecks and RunChecksContext tests. +type runChecksHostFixture struct { + name string + // capabilities represent high level abstractions of one or more aspects of a host fixture + // that tests can use to determine if the fixture meets the requirements for a given scenario. + // + // For example, a scenario that tests fTPM-specific behavior may fail when run on a fixture + // with a dTPM. Depending on the level of the behavior being tested, this failure may not be + // particularly meaningful, and it may make more sense for the test to only run on fixtures + // that actually provide an fTPM. + // + // Capabilities simply summarize and label information encoded in other fields of the fixture. + // Declaring a capability by itself does not instantiate any mock behaviors, and it is the + // responsibility of the author to make sure that the capabilities are a faithful reflection + // of the actual behavior of the fixture. + capabilities runChecksHostCapabilities + environment efitest.MockHostEnvironmentOption + virtualizationMode string + virtualizationDetection internal_efi.DetectVirtMode + sysfsDevices []internal_efi.SysfsDevice + + // arch is the GOARCH that this fixture emulates; host security checks dispatch on it at runtime. + arch string + + // additionalExpectedFlags allows a host fixture to inject fixture-specific + // CheckResultFlags to the expected value. For example, platforms that validate + // platformFirmwareIntegrity via measured boot instead of reading a fused key will + // report RequireLockToPlatformFirmware, which needs to be OR'd against the + // test-specific expected flags. + additionalExpectedFlags CheckResultFlags +} + +func runChecksHostFixturesFor(c *C, required runChecksHostCapabilities) []runChecksHostFixture { + var matches []runChecksHostFixture + for _, fixture := range runChecksPlatformHostFixtures() { + if fixture.capabilities&required == required { + matches = append(matches, fixture) + } + } + if len(matches) == 0 { + c.Skip("no platform fixture provides the required host capabilities") + } + return matches +} + +func (f *runChecksHostFixture) newEnvironment(options ...efitest.MockHostEnvironmentOption) internal_efi.HostEnvironment { + base := []efitest.MockHostEnvironmentOption{ + f.environment, + efitest.WithVirtMode(f.virtualizationMode, f.virtualizationDetection), + } + devices := append([]internal_efi.SysfsDevice(nil), f.sysfsDevices...) + base = append(base, efitest.WithSysfsDevices(devices...)) + return efitest.NewMockHostEnvironmentWithOpts(append(base, options...)...) +} + +func (f *runChecksHostFixture) mockRuntimeGOARCH(s interface{ AddCleanup(func()) }) { + s.AddCleanup(MockRuntimeGOARCH(f.arch)) +} + +// runChecksPlatformHostFixtures returns an array of mock platform host configurations +// for testing. Each fixture can define an EFI environment with CPU features, a set of sysfs +// devices, virtualization information, and host ISA. Each fixture also includes a set of +// "capabilities" which can be used by tests to decide whether they should expect a +// certain fixture to work for a given test scenario or not. +// +// To add fixtures, append them to the array returned by this function. To add capabilities, +// add them to the const block at the top of this file and then audit the existing fixtures +// and add the new capability to any existing fixtures to which it might apply. +func runChecksPlatformHostFixtures() []runChecksHostFixture { + intelDevices := func(status []byte, withIOMMU bool) []internal_efi.SysfsDevice { + attrs := map[string][]byte{ + "fw_ver": []byte(`0:16.1.27.2176 +0:16.1.27.2176 +0:16.0.15.1624 +`), + "fw_status": status, + } + var devices []internal_efi.SysfsDevice + if withIOMMU { + devices = append(devices, + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), + efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), + ) + } + return append(devices, efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", attrs, efitest.NewMockSysfsDevice( + "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, + ))) + } + + return []runChecksHostFixture{ + // amd64 fixtures + { + name: "intel-ptt", + capabilities: runChecksHostCapabilityValid | + runChecksHostCapabilityNotVirtualMachine | + runChecksHostCapabilityFirmwareTPM, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusBase, true), + arch: "amd64", + }, + { + name: "intel-dtpm-smx", + capabilities: runChecksHostCapabilityValid | + runChecksHostCapabilityNotVirtualMachine | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality0AccessibleFromOS | + runChecksHostCapabilityStartupLocality3InaccessibleFromOS | + runChecksHostCapabilityStartupLocality4InaccessibleFromOS, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusBase, true), + arch: "amd64", + }, + { + name: "intel-dtpm-no-smx", + capabilities: runChecksHostCapabilityValid | + runChecksHostCapabilityNotVirtualMachine | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality0AccessibleFromOS | + runChecksHostCapabilityStartupLocality3AccessibleFromOS | + runChecksHostCapabilityStartupLocality4AccessibleFromOS, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusBase, true), + arch: "amd64", + }, + { + name: "intel-ptt-no-kernel-iommu", + capabilities: runChecksHostCapabilityNotVirtualMachine | runChecksHostCapabilityNoKernelIOMMU | runChecksHostCapabilityFirmwareTPM, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusBase, false), + arch: "amd64", + }, + { + name: "intel-mfg-mode", + capabilities: runChecksHostCapabilityNotVirtualMachine | runChecksHostCapabilityInsufficientHWRootOfTrust, + environment: efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + virtualizationMode: internal_efi.VirtModeNone, + virtualizationDetection: internal_efi.DetectVirtModeAll, + sysfsDevices: intelDevices(fwStatusManufacturingMode, true), + arch: "amd64", + }, + // RunChecks skips host security checks inside a VM, so the emulated + // architecture is irrelevant here; we keep exactly one virtual-machine + // fixture rather than duplicating it per-arch. + { + name: "virtual-machine", + capabilities: runChecksHostCapabilityVirtualMachine, + environment: func(*efitest.MockHostEnvironment) {}, + virtualizationMode: "qemu", + virtualizationDetection: internal_efi.DetectVirtModeVM, + arch: "amd64", + }, + } +} diff --git a/efi/preinstall/checks_test.go b/efi/preinstall/checks_test.go index 834f14f9..088a427d 100644 --- a/efi/preinstall/checks_test.go +++ b/efi/preinstall/checks_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -26,7 +26,6 @@ import ( "errors" "io" - "github.com/canonical/cpuid" efi "github.com/canonical/go-efilib" "github.com/canonical/go-tpm2" "github.com/canonical/go-tpm2/objectutil" @@ -73,6 +72,7 @@ type testRunChecksParams struct { } func (s *runChecksSuite) testRunChecks(c *C, params *testRunChecksParams) (warnings []error, err error) { + s.ResetAndClearTPMSimulatorUsingPlatformHierarchy(c) s.allocatePCRBanks(c, params.enabledBanks...) log, err := params.env.ReadEventLog() c.Assert(err, IsNil) @@ -131,3332 +131,2445 @@ func (s *runChecksSuite) testRunChecks(c *C, params *testRunChecksParams) (warni } func (s *runChecksSuite) TestRunChecksGood(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodSHA384(c *C) { - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "030ac3c913dab858f1d69239115545035cff671d6229f95577bb0ffbd827b35abaf6af6bfd223e04ecc9b60a9803642d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), +func (s *runChecksSuite) TestRunChecksGoodSHA384(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "030ac3c913dab858f1d69239115545035cff671d6229f95577bb0ffbd827b35abaf6af6bfd223e04ecc9b60a9803642d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "6c2df9007211786438be210b6908f2935d0b25ebdcd2c65621826fd2ec55fb9fbacbfe080d48db98f0ef970273b8254a")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "42f61b3089f5ce0646b422a59c9632065db2630f3e5b01690e63c41420ed31f10ff2a191f3440f9501109fc85f7fb00f")}, }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "6c2df9007211786438be210b6908f2935d0b25ebdcd2c65621826fd2ec55fb9fbacbfe080d48db98f0ef970273b8254a")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "42f61b3089f5ce0646b422a59c9632065db2630f3e5b01690e63c41420ed31f10ff2a191f3440f9501109fc85f7fb00f")}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA384, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + expectedPcrAlg: tpm2.HashAlgorithmSHA384, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) -func (s *runChecksSuite) TestRunChecksGoodSHA1(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitWeakPCRBanks, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), +func (s *runChecksSuite) TestRunChecksGoodSHA1(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitWeakPCRBanks, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA1, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + expectedPcrAlg: tpm2.HashAlgorithmSHA1, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodEmptySHA384(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `the PCR bank for TPM_ALG_SHA384 is missing from the TCG log but active and with one or more empty PCRs on the TPM`) + var epbe *EmptyPCRBanksError + c.Check(errors.As(warning, &epbe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256, tpm2.HashAlgorithmSHA384}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `the PCR bank for TPM_ALG_SHA384 is missing from the TCG log but active and with one or more empty PCRs on the TPM`) - var epbe *EmptyPCRBanksError - c.Check(errors.As(warning, &epbe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) } func (s *runChecksSuite) TestRunChecksGoodPostInstall(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 6, + tpm2.PropertyNVCounters: 5, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PostInstallChecks, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 6, - tpm2.PropertyNVCounters: 5, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PostInstallChecks, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodVirtualMachine(c *C) { - family, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyFamilyIndicator) - c.Assert(err, IsNil) - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: family, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerMSFT), - tpm2.PropertyHRPersistentMin: 7, // The simulator seems to set this to 2 - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitVirtualMachine, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + family, err := s.TPM.GetCapabilityTPMProperty(tpm2.PropertyFamilyIndicator) + c.Assert(err, IsNil) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: family, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerMSFT), + tpm2.PropertyHRPersistentMin: 7, // The simulator seems to set this to 2 + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitVirtualMachine, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warning := warnings[0] - c.Check(warning, Equals, ErrVirtualMachineDetected) + warning := warnings[0] + c.Check(warning, Equals, ErrVirtualMachineDetected) - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetected(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality0AccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) + var hse *HostSecurityError + c.Assert(errors.As(warning, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) - var hse *HostSecurityError - c.Assert(errors.As(warning, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetectedSL3(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality3InaccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetectedSL3NotProtected(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality3AccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 3, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) + var hse *HostSecurityError + c.Assert(errors.As(warning, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 3, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) - var hse *HostSecurityError - c.Assert(errors.As(warning, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetectedHCRTM(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality4InaccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 4, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 3) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 4, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | RequestPartialDiscreteTPMResetAttackMitigation, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 3) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodDiscreteTPMDetectedHCRTMLocality4NotProtected(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM | + runChecksHostCapabilityStartupLocality4AccessibleFromOS + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + StartupLocality: 4, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) + var hse *HostSecurityError + c.Assert(errors.As(warning, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - StartupLocality: 4, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerNTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) - var hse *HostSecurityError - c.Assert(errors.As(warning, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) } func (s *runChecksSuite) TestRunChecksGoodInvalidPCR0Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformFirmwareProfileSupport | PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformFirmwareProfileSupport | PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\)`) - var pfe *PlatformFirmwarePCRError - c.Check(errors.As(warning, &pfe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\)`) + var pfe *PlatformFirmwarePCRError + c.Check(errors.As(warning, &pfe), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodInvalidPCR0ValueWithDiscreteTPM(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (2 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformFirmwareProfileSupport | PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\)`) - var pfe *PlatformFirmwarePCRError - c.Check(errors.As(warning, &pfe), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } +} - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) - var hse *HostSecurityError - c.Assert(errors.As(warning, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) +func (s *runChecksSuite) TestRunChecksGoodInvalidPCR0ValueWithDiscreteTPM(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityDiscreteTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformFirmwareProfileSupport | PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformFirmwareProfileSupport | NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\)`) + var pfe *PlatformFirmwarePCRError + c.Check(errors.As(warning, &pfe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with system security: cannot enable partial mitigation against discrete TPM reset attacks`) + var hse *HostSecurityError + c.Assert(errors.As(warning, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoPartialDiscreteTPMResetAttackMitigation), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } // TODO: Good test case for invalid PCR1 when we support it. func (s *runChecksSuite) TestRunChecksGoodInvalidPCR2Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\)`) - var de *DriversAndAppsPCRError - c.Check(errors.As(warning, &de), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\)`) + var de *DriversAndAppsPCRError + c.Check(errors.As(warning, &de), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } // TODO: Good test case for invalid PCR3 when we support it. func (s *runChecksSuite) TestRunChecksGoodInvalidPCR4Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\)`) - var bme *BootManagerCodePCRError - c.Check(errors.As(warning, &bme), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\)`) + var bme *BootManagerCodePCRError + c.Check(errors.As(warning, &bme), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } // TODO: Good test case for invalid PCR5 when we support it. func (s *runChecksSuite) TestRunChecksGoodInvalidPCR7Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport | fixture.additionalExpectedFlags, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\)`) - var sbe *SecureBootPolicyPCRError - c.Check(errors.As(warning, &sbe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\)`) + var sbe *SecureBootPolicyPCRError + c.Check(errors.As(warning, &sbe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksGoodAddonDriversPresent(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +`) + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), + }, + }) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: +func (s *runChecksSuite) TestRunChecksGoodVARDriversPresentWithInvalidPCR2Value(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0x33da7dc7c748c1767c14a1328487ad2f1a058cda30956405bc9ccf02a75bcfb9, reconstructed from log 0x6a16b79136a20b5fa1d3d3812165fddf6e2a4d9c5a682e15f26c6e4fbc8f4d04\)`) + var de *DriversAndAppsPCRError + c.Check(errors.As(warning, &de), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) + }) - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodVARDriversPresentWithInvalidPCR2Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0x33da7dc7c748c1767c14a1328487ad2f1a058cda30956405bc9ccf02a75bcfb9, reconstructed from log 0x6a16b79136a20b5fa1d3d3812165fddf6e2a4d9c5a682e15f26c6e4fbc8f4d04\)`) - var de *DriversAndAppsPCRError - c.Check(errors.As(warning, &de), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +func (s *runChecksSuite) TestRunChecksGoodSysPrepAppsPresent(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSysPrepApplications, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `system preparation applications were detected: +- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 `) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + var spape *SysPrepApplicationsPresentError + c.Check(errors.As(warning, &spape), testutil.IsTrue) + c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + }) -func (s *runChecksSuite) TestRunChecksGoodSysPrepAppsPresent(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSysPrepApplications, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `system preparation applications were detected: +func (s *runChecksSuite) TestRunChecksGoodSysPrepAppsPresentWithInvalidPCR4Value(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSysPrepApplications, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoBootManagerCodeProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0xe17df8a36f5af4ae49c1ca567f6194bb06269c81339d87be07a3b3993edc6773, reconstructed from log 0x37704821d1e3005e2b31a7011ae80beec847c639699ed234bcaf9e0dd2fe47fe\)`) + var bme *BootManagerCodePCRError + c.Check(errors.As(warning, &bme), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `system preparation applications were detected: - Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 `) - var spape *SysPrepApplicationsPresentError - c.Check(errors.As(warning, &spape), testutil.IsTrue) - c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + var spape *SysPrepApplicationsPresentError + c.Check(errors.As(warning, &spape), testutil.IsTrue) + c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - }) + }) - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksGoodSysPrepAppsPresentWithInvalidPCR4Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } +func (s *runChecksSuite) TestRunChecksGoodAbsoluteActive(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAbsoluteComputrace, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSysPrepApplications, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoBootManagerCodeProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0xe17df8a36f5af4ae49c1ca567f6194bb06269c81339d87be07a3b3993edc6773, reconstructed from log 0x37704821d1e3005e2b31a7011ae80beec847c639699ed234bcaf9e0dd2fe47fe\)`) - var bme *BootManagerCodePCRError - c.Check(errors.As(warning, &bme), testutil.IsTrue) + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) + warning = warnings[2] + c.Check(warning, Equals, ErrAbsoluteComputraceActive) - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } +} - warning = warnings[3] - c.Check(warning, ErrorMatches, `system preparation applications were detected: -- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 -`) - var spape *SysPrepApplicationsPresentError - c.Check(errors.As(warning, &spape), testutil.IsTrue) - c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), +func (s *runChecksSuite) TestRunChecksGoodAbsoluteActiveWithInvalidPCR4Value(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - }) + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAbsoluteComputrace, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x7b023f4133ed7e29f9445fa186592378dbaac21c2a9737f37e170b3062e174cb, reconstructed from log 0xf9464e8dcd68eddcaa704e885ba08a129bc4d0178f7f88593c68be8a27bc5f01\)`) + var bme *BootManagerCodePCRError + c.Check(errors.As(warning, &bme), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodAbsoluteActive(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAbsoluteComputrace, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, Equals, ErrAbsoluteComputraceActive) - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } +} - warning = warnings[2] - c.Check(warning, Equals, ErrAbsoluteComputraceActive) +func (s *runChecksSuite) TestRunChecksGoodNoBootManagerCodeProfileSupport(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test + // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in + // the log so the test thinks that the log contains the flat file digest. + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodAbsoluteActiveWithInvalidPCR4Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAbsoluteComputrace, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x7b023f4133ed7e29f9445fa186592378dbaac21c2a9737f37e170b3062e174cb, reconstructed from log 0xf9464e8dcd68eddcaa704e885ba08a129bc4d0178f7f88593c68be8a27bc5f01\)`) - var bme *BootManagerCodePCRError - c.Check(errors.As(warning, &bme), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, Equals, ErrAbsoluteComputraceActive) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and\/or the PE_COFF_IMAGE flag`) + var bme *BootManagerCodePCRError + c.Check(errors.As(warning, &bme), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksGoodNoBootManagerCodeProfileSupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), +func (s *runChecksSuite) TestRunChecksGoodPreOSSecureBootAuthByEnrolledDigests(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +`) + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test - // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in - // the log so the test thinks that the log contains the flat file digest. - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerCodeProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and\/or the PE_COFF_IMAGE flag`) - var bme *BootManagerCodePCRError - c.Check(errors.As(warning, &bme), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} + }) -func (s *runChecksSuite) TestRunChecksGoodPreOSSecureBootAuthByEnrolledDigests(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 -`) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, - }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) - warning = warnings[4] - c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) + warning = warnings[4] + c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) + } } func (s *runChecksSuite) TestRunChecksGoodPreOSSecureBootAuthByEnrolledDigestsWithInvalidPCR7Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport | PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 6) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0x41cc3a26db1bf43609d3fb0b15b1e87a3f68822a6770ab1b912e1b07e6e49952, reconstructed from log 0x3cb6f84240068b76a933839a170565fdf5de48ff7d6ef361b6474a41e2cd60af\)`) - var sbe *SecureBootPolicyPCRError - c.Check(errors.As(warning, &sbe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 -`) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[5] - c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) -} - -func (s *runChecksSuite) TestRunChecksGoodWeakSecureBootAlgs(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 6) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 -`) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, Equals, ErrWeakSecureBootAlgorithmDetected) - - warning = warnings[5] - c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) -} - -func (s *runChecksSuite) TestRunChecksGoodWeakSecureBootAlgsWithInvalidPCR7Value(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport | PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 7) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0x97fe6e8a33309869583ba98ecc25b5c528270db96e41dfdd75ebf20eb7562441, reconstructed from log 0x5e99922ef40f9e7e64ca71f1128423e8400c9e5fe60cfbad3d905bb91b9e8949\)`) - var sbe *SecureBootPolicyPCRError - c.Check(errors.As(warning, &sbe), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - var adpe *AddonDriversPresentError - c.Check(warning, ErrorMatches, `addon drivers were detected: + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport | PermitAddonDrivers | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 6) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0x41cc3a26db1bf43609d3fb0b15b1e87a3f68822a6770ab1b912e1b07e6e49952, reconstructed from log 0x3cb6f84240068b76a933839a170565fdf5de48ff7d6ef361b6474a41e2cd60af\)`) + var sbe *SecureBootPolicyPCRError + c.Check(errors.As(warning, &sbe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: - \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) - c.Check(errors.As(warning, &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[5] - c.Check(warning, Equals, ErrWeakSecureBootAlgorithmDetected) - - warning = warnings[6] - c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) -} - -func (s *runChecksSuite) TestRunChecksGoodNoSecureBootPolicyProfileSupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) - var sbpe *SecureBootPolicyPCRError - c.Assert(errors.As(warning, &sbpe), testutil.IsTrue) - c.Check(errors.Is(sbpe, ErrNoSecureBoot), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksGoodNoSecureBootDeployedMode(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSecureBootUserMode, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `secure boot is enabled but not in deployed mode`) - c.Check(errors.Is(warning, ErrNoDeployedMode), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksGoodTPMLockout(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - // Trip the DA logic by setting newMaxTries to 0. This also prevents - // the lockout hierarchy availability test from clearing the lockout, - // although that test does still run. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 0, 10000, 10000, nil), IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `error with TPM2 device: TPM is in DA lockout mode`) - var tde *TPM2DeviceError - c.Assert(errors.As(warning, &tde), testutil.IsTrue) - c.Check(errors.Is(tde, ErrTPMLockout), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksGoodPostInstallLockoutAvailabilityCheckSkipped(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - // Take ownership of the lockout hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PostInstallChecks, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set`) - c.Check(errors.Is(warning, ErrTPMLockoutAvailabilityNotChecked), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadVirtualMachine(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode("qemu", internal_efi.DetectVirtModeVM), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - }) - c.Check(err, Equals, ErrVirtualMachineDetected) -} - -func (s *runChecksSuite) TestRunChecksBadNotEFI(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - ), - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - }) - c.Check(err, Equals, ErrSystemNotEFI) -} - -func (s *runChecksSuite) TestRunChecksBadTPM2DeviceDisabled(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - // Disable owner and endorsement hierarchies - c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) - c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) - }, - }) - c.Check(err, ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) - c.Check(errors.Is(err, ErrTPMDisabled), testutil.IsTrue) - var te *TPM2DeviceError - c.Check(errors.As(err, &te), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadTPMOwnedHierarchiesAndLockedOut(c *C) { - // Test case with more than one TPM error - in this case, one of the errors - // is ErrTPMLockout which is converted to a warning and suppressed unless - // RunChecks completes with success. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - // Trip the DA logic by triggering an auth failure with a DA protected - // resource. - c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) - pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) - c.Assert(err, IsNil) - key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) - c.Assert(err, IsNil) - key.SetAuthValue(nil) - _, err = s.TPM.Unseal(key, nil) - c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) - - // Take ownership of the lockout hierarchy - s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, - }) - c.Check(err, ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: -- TPM_RH_LOCKOUT has an authorization value -`) - - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) - - var te *TPM2DeviceError - c.Assert(errors.As(errs[0], &te), testutil.IsTrue) - var ohe *TPM2OwnedHierarchiesError - c.Check(errors.As(te, &ohe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadInvalidPCR0Value(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{}, 1, map[uint32]uint64{0x13a: (3 << 1)}), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\). -`) - var te *MeasuredBootError - c.Assert(errors.As(err, &te), testutil.IsTrue) - var pe *NoSuitablePCRAlgorithmError - c.Check(errors.As(te, &pe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadInvalidPCR2Value(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{}, 1, map[uint32]uint64{0x13a: (3 << 1)}), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\). -`) - var te *MeasuredBootError - c.Assert(errors.As(err, &te), testutil.IsTrue) - var pe *NoSuitablePCRAlgorithmError - c.Check(errors.As(te, &pe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadInvalidPCR4Value(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{}, 1, map[uint32]uint64{0x13a: (3 << 1)}), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\). -`) - var te *MeasuredBootError - c.Assert(errors.As(err, &te), testutil.IsTrue) - var pe *NoSuitablePCRAlgorithmError - c.Check(errors.As(te, &pe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadInvalidPCR7Value(c *C) { - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{}, 1, map[uint32]uint64{0x13a: (3 << 1)}), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) - c.Check(err, IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\). -`) - var te *MeasuredBootError - c.Assert(errors.As(err, &te), testutil.IsTrue) - var pe *NoSuitablePCRAlgorithmError - c.Check(errors.As(te, &pe), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadNoHardwareRootOfTrustError(c *C) { - // Test case with no hardware root-of-trust configured. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - - c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) - - // Check that there is a NoHardwareRootOfTrustError wrapped in a HostSecurityError - // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. - var hse *HostSecurityError - var cErr CompoundError - c.Check(errors.As(err, &cErr), testutil.IsTrue) - foundHse := false - for _, e := range cErr.Unwrap() { - if errors.As(e, &hse) { - foundHse = true - } - } - c.Check(foundHse, testutil.IsTrue) - var rote *NoHardwareRootOfTrustError - c.Check(errors.As(hse, &rote), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadHostSecurityMissingIntelMEModule(c *C) { - // Test case where host security checks fail because the intel ME kernel module is missing. - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0", map[string]string{"PCI_CLASS": "78000", "PCI_ID": "8086:7E70"}, "pci", nil, nil), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: the kernel module "mei_me" must be loaded`) - var hse *HostSecurityError - c.Assert(errors.As(err, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, MissingKernelModuleError("mei_me")), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadHostSecurityMissingMSR(c *C) { - // Test case where host security checks fail because the MSR kernel module is missing. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 0, nil), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - }) - c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel CPU debugging configuration: the kernel module "msr" must be loaded`) - var hse *HostSecurityError - c.Assert(errors.As(err, &hse), testutil.IsTrue) - c.Check(errors.Is(hse, MissingKernelModuleError("msr")), testutil.IsTrue) -} - -func (s *runChecksSuite) TestRunChecksBadUEFIDebuggingEnabledAndNoKernelIOMMU(c *C) { - // Test case with more than one host security error. - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + }) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + + warning = warnings[5] + c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - FirmwareDebugger: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, - }) - c.Check(err, ErrorMatches, `2 errors detected: -- error with system security: the platform firmware contains a debugging endpoint enabled -- error with system security: no kernel IOMMU support was detected +func (s *runChecksSuite) TestRunChecksGoodWeakSecureBootAlgs(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 6) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), + }, + }) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 2) + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - var hse *HostSecurityError - c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrUEFIDebuggingEnabled), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) - c.Assert(errors.As(errs[1], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoKernelIOMMU), testutil.IsTrue) -} + warning = warnings[4] + c.Check(warning, Equals, ErrWeakSecureBootAlgorithmDetected) -func (s *runChecksSuite) TestRunChecksBadSHA1(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + warning = warnings[5] + c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), - }, +func (s *runChecksSuite) TestRunChecksGoodWeakSecureBootAlgsWithInvalidPCR7Value(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, - }, - }) - c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: -- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. -- TPM_ALG_SHA256: the PCR bank is missing from the TCG log. + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport | PermitAddonDrivers | PermitWeakSecureBootAlgorithms | PermitPreOSSecureBootAuthByEnrolledDigests, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 7) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0x97fe6e8a33309869583ba98ecc25b5c528270db96e41dfdd75ebf20eb7562441, reconstructed from log 0x5e99922ef40f9e7e64ca71f1128423e8400c9e5fe60cfbad3d905bb91b9e8949\)`) + var sbe *SecureBootPolicyPCRError + c.Check(errors.As(warning, &sbe), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + var adpe *AddonDriversPresentError + c.Check(warning, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 `) + c.Check(errors.As(warning, &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), + }, + }) - var e *NoSuitablePCRAlgorithmError - c.Assert(errors.As(err, &e), testutil.IsTrue) + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) - // Test that we can access individual errors. - c.Check(e.Errs[tpm2.HashAlgorithmSHA512], DeepEquals, []error{ErrPCRBankMissingFromLog}) - c.Check(e.Errs[tpm2.HashAlgorithmSHA384], DeepEquals, []error{ErrPCRBankMissingFromLog}) - c.Check(e.Errs[tpm2.HashAlgorithmSHA256], DeepEquals, []error{ErrPCRBankMissingFromLog}) -} + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksBadMandatoryPCR1(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, + warning = warnings[5] + c.Check(warning, Equals, ErrWeakSecureBootAlgorithmDetected) + + warning = warnings[6] + c.Check(warning, Equals, ErrPreOSSecureBootAuthByEnrolledDigests) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksGoodNoSecureBootPolicyProfileSupport(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | NoSecureBootPolicyProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + var sbpe *SecureBootPolicyPCRError + c.Assert(errors.As(warning, &sbpe), testutil.IsTrue) + c.Check(errors.Is(sbpe, ErrNoSecureBoot), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) +func (s *runChecksSuite) TestRunChecksGoodNoSecureBootDeployedMode(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitSecureBootUserMode, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) - var pce *PlatformConfigPCRError - c.Check(errors.As(errs[0], &pce), testutil.IsTrue) -} + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksBadMandatoryPCR3(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `secure boot is enabled but not in deployed mode`) + c.Check(errors.Is(warning, ErrNoDeployedMode), testutil.IsTrue) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksGoodTPMLockout(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + // Trip the DA logic by setting newMaxTries to 0. This also prevents + // the lockout hierarchy availability test from clearing the lockout, + // although that test does still run. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 0, 10000, 10000, nil), IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, `error with TPM2 device: TPM is in DA lockout mode`) + var tde *TPM2DeviceError + c.Assert(errors.As(warning, &tde), testutil.IsTrue) + c.Check(errors.Is(tde, ErrTPMLockout), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) +func (s *runChecksSuite) TestRunChecksGoodPostInstallLockoutAvailabilityCheckSkipped(c *C) { + required := runChecksHostCapabilityValid | + runChecksHostCapabilityFirmwareTPM + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + // Take ownership of the lockout hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PostInstallChecks, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + warning := warnings[0] + c.Check(warning, ErrorMatches, `availability of TPM's lockout hierarchy was not checked because the lockout hierarchy has an authorization value set`) + c.Check(errors.Is(warning, ErrTPMLockoutAvailabilityNotChecked), testutil.IsTrue) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(errs[0], &dce), testutil.IsTrue) + warning = warnings[1] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadMandatoryPCR5(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksSuite) TestRunChecksBadVirtualMachine(c *C) { + required := runChecksHostCapabilityVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + }) + c.Check(err, Equals, ErrVirtualMachineDetected) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksBadNotEFI(c *C) { + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + ), + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + }) + c.Check(err, Equals, ErrSystemNotEFI) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) +func (s *runChecksSuite) TestRunChecksBadTPM2DeviceDisabled(c *C) { + required := runChecksHostCapabilityNotVirtualMachine + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + // Disable owner and endorsement hierarchies + c.Assert(s.TPM.HierarchyControl(s.TPM.OwnerHandleContext(), tpm2.HandleOwner, false, nil), IsNil) + c.Assert(s.TPM.HierarchyControl(s.TPM.EndorsementHandleContext(), tpm2.HandleEndorsement, false, nil), IsNil) + }, + }) + c.Check(err, ErrorMatches, `error with TPM2 device: TPM2 device is present but is currently disabled by the platform firmware`) + c.Check(errors.Is(err, ErrTPMDisabled), testutil.IsTrue) + var te *TPM2DeviceError + c.Check(errors.As(err, &te), testutil.IsTrue) + } +} - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) +func (s *runChecksSuite) TestRunChecksBadTPMOwnedHierarchiesAndLockedOut(c *C) { + // Test case with more than one TPM error - in this case, one of the errors + // is ErrTPMLockout which is converted to a warning and suppressed unless + // RunChecks completes with success. + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + // Trip the DA logic by triggering an auth failure with a DA protected + // resource. + c.Assert(s.TPM.DictionaryAttackParameters(s.TPM.LockoutHandleContext(), 1, 10000, 10000, nil), IsNil) + pub, sensitive, err := objectutil.NewSealedObject(rand.Reader, []byte("foo"), []byte("5678")) + c.Assert(err, IsNil) + key, err := s.TPM.LoadExternal(sensitive, pub, tpm2.HandleNull) + c.Assert(err, IsNil) + key.SetAuthValue(nil) + _, err = s.TPM.Unseal(key, nil) + c.Check(tpm2.IsTPMSessionError(err, tpm2.ErrorAuthFail, tpm2.CommandUnseal, 1), testutil.IsTrue) + + // Take ownership of the lockout hierarchy + s.HierarchyChangeAuth(c, tpm2.HandleLockout, []byte("1234")) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, + }) + c.Check(err, ErrorMatches, `error with TPM2 device: one or more of the TPM hierarchies is already owned: +- TPM_RH_LOCKOUT has an authorization value +`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(errs[0], &bmce), testutil.IsTrue) -} + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) -func (s *runChecksSuite) TestRunChecksBadAddonDriversPresent(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + var te *TPM2DeviceError + c.Assert(errors.As(errs[0], &te), testutil.IsTrue) + var ohe *TPM2OwnedHierarchiesError + c.Check(errors.As(te, &ohe), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `addon drivers were detected: -- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +func (s *runChecksSuite) TestRunChecksBadInvalidPCR0Value(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(0), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with platform firmware \(PCR0\) measurements: PCR value mismatch \(actual from TPM 0xe9995745ca25279ec699688b70488116fe4d9f053cb0991dd71e82e7edfa66b5, reconstructed from log 0xa6602a7a403068b5556e78cc3f5b00c9c76d33d514093ca9b584dce7590e6c69\). `) + var te *MeasuredBootError + c.Assert(errors.As(err, &te), testutil.IsTrue) + var pe *NoSuitablePCRAlgorithmError + c.Check(errors.As(te, &pe), testutil.IsTrue) + } +} - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) - - var adpe *AddonDriversPresentError - c.Check(errors.As(errs[0], &adpe), testutil.IsTrue) - c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ - { - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0, - }, - &efi.PCIDevicePathNode{ - Function: 0x1c, - Device: 0x2, - }, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0, - }, - &efi.MediaRelOffsetRangeDevicePathNode{ - StartingOffset: 0x38, - EndingOffset: 0x11dff, - }, +func (s *runChecksSuite) TestRunChecksBadInvalidPCR2Value(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), - }, - }) + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(2), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with drivers and apps \(PCR2\) measurements: PCR value mismatch \(actual from TPM 0xfa734a6a4d262d7405d47d48c0a1b127229ca808032555ad919ed5dd7c1f6519, reconstructed from log 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969\). +`) + var te *MeasuredBootError + c.Assert(errors.As(err, &te), testutil.IsTrue) + var pe *NoSuitablePCRAlgorithmError + c.Check(errors.As(te, &pe), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadSysPrepAppsPresent(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +func (s *runChecksSuite) TestRunChecksBadInvalidPCR4Value(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(4), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with boot manager code \(PCR4\) measurements: PCR value mismatch \(actual from TPM 0x1c93930d6b26232e061eaa33ecf6341fae63ce598a0c6a26ee96a0828639c044, reconstructed from log 0x4bc74f3ffe49b4dd275c9f475887b68193e2db8348d72e1c3c9099c2dcfa85b0\). +`) + var te *MeasuredBootError + c.Assert(errors.As(err, &te), testutil.IsTrue) + var pe *NoSuitablePCRAlgorithmError + c.Check(errors.As(te, &pe), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeSysPrepAppLaunch: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, - {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ - Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, - Description: "Mock sysprep app", - FilePath: efi.DevicePath{ - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), - }, - })}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `system preparation applications were detected: -- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 +func (s *runChecksSuite) TestRunChecksBadInvalidPCR7Value(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + _, err := s.TPM.PCREvent(s.TPM.PCRHandleContext(7), []byte("foo"), nil) + c.Check(err, IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: error with secure boot policy \(PCR7\) measurements: PCR value mismatch \(actual from TPM 0xdf7b5d709755f1bd7142dd2f8c2d1195fc6b4dab5c78d41daf5c795da55db5f2, reconstructed from log 0xafc99bd8b298ea9b70d2796cb0ca22fe2b70d784691a1cae2aa3ba55edc365dc\). `) + var te *MeasuredBootError + c.Assert(errors.As(err, &te), testutil.IsTrue) + var pe *NoSuitablePCRAlgorithmError + c.Check(errors.As(te, &pe), testutil.IsTrue) + } +} - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) - - var spape *SysPrepApplicationsPresentError - c.Check(errors.As(errs[0], &spape), testutil.IsTrue) - c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ - { - Description: "Mock sysprep app", - LoadOptionName: "SysPrep0001", - DevicePath: efi.DevicePath{ - &efi.ACPIDevicePathNode{ - HID: 0x0a0341d0, - UID: 0x0}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x1d}, - &efi.PCIDevicePathNode{ - Function: 0x0, - Device: 0x0}, - &efi.NVMENamespaceDevicePathNode{ - NamespaceID: 0x1, - NamespaceUUID: efi.EUI64{}}, - &efi.HardDriveDevicePathNode{ - PartitionNumber: 1, - PartitionStart: 0x800, - PartitionSize: 0x100000, - Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), - MBRType: efi.GPT}, - efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), +func (s *runChecksSuite) TestRunChecksBadNoHardwareRootOfTrustError(c *C) { + // Test case with no hardware root-of-trust configured. + required := runChecksHostCapabilityInsufficientHWRootOfTrust + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - DigestAlg: tpm2.HashAlgorithmSHA256, - Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), - }, - }) + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + + c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode`) + + // Check that there is a NoHardwareRootOfTrustError wrapped in a HostSecurityError + // While with go1.23 errors.As() can unwrap automatically, with go1.18 we need to unwrap manually. + var hse *HostSecurityError + var cErr CompoundError + c.Check(errors.As(err, &cErr), testutil.IsTrue) + foundHse := false + for _, e := range cErr.Unwrap() { + if errors.As(e, &hse) { + foundHse = true + } + } + c.Check(foundHse, testutil.IsTrue) + var rote *NoHardwareRootOfTrustError + c.Check(errors.As(hse, &rote), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadAbsoluteActive(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } +func (s *runChecksSuite) TestRunChecksBadHostSecurityMissingIntelMEModule(c *C) { + s.AddCleanup(MockRuntimeGOARCH("amd64")) + + // Test case where host security checks fail because the intel ME kernel module is missing. devices := []internal_efi.SysfsDevice{ efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0", map[string]string{"PCI_CLASS": "78000", "PCI_ID": "8086:7E70"}, "pci", nil, nil), } _, err := s.testRunChecks(c, &testRunChecksParams{ env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ tpm2.PropertyNVCountersMax: 0, tpm2.PropertyPSFamilyIndicator: 1, tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, }) - c.Check(err, ErrorMatches, `Absolute was detected to be active and it is advised that this is disabled`) - - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) - - c.Check(errors.Is(errs[0], ErrAbsoluteComputraceActive), testutil.IsTrue) + c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel BootGuard configuration: the kernel module "mei_me" must be loaded`) + var hse *HostSecurityError + c.Assert(errors.As(err, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, MissingKernelModuleError("mei_me")), testutil.IsTrue) } -func (s *runChecksSuite) TestRunChecksBadWeakSecureBootAlgs(c *C) { +func (s *runChecksSuite) TestRunChecksBadHostSecurityMissingMSR(c *C) { + s.AddCleanup(MockRuntimeGOARCH("amd64")) + + // Test case where host security checks fail because the MSR kernel module is missing. meiAttrs := map[string][]byte{ "fw_ver": []byte(`0:16.1.27.2176 0:16.1.27.2176 @@ -3476,363 +2589,716 @@ func (s *runChecksSuite) TestRunChecksBadWeakSecureBootAlgs(c *C) { env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA1, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{internal_efi.CPUIDFeatureSDBG, internal_efi.CPUIDFeatureSMX}, 0, nil), efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ tpm2.PropertyNVCountersMax: 0, tpm2.PropertyPSFamilyIndicator: 1, tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, }) - c.Check(err, ErrorMatches, `2 errors detected: -- a weak cryptographic algorithm was detected during secure boot verification -- some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest + c.Check(err, ErrorMatches, `error with system security: encountered an error when checking Intel CPU debugging configuration: the kernel module "msr" must be loaded`) + var hse *HostSecurityError + c.Assert(errors.As(err, &hse), testutil.IsTrue) + c.Check(errors.Is(hse, MissingKernelModuleError("msr")), testutil.IsTrue) +} + +func (s *runChecksSuite) TestRunChecksBadUEFIDebuggingEnabledAndNoKernelIOMMU(c *C) { + // Test case with more than one host security error. + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + FirmwareDebugger: true, + })), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerCodeProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoSecureBootPolicyProfileSupport, + }) + c.Check(err, ErrorMatches, `2 errors detected: +- error with system security: the platform firmware contains a debugging endpoint enabled +- error with system security: no kernel IOMMU support was detected `) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 2) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 2) - c.Check(errors.Is(errs[0], ErrWeakSecureBootAlgorithmDetected), testutil.IsTrue) - c.Check(errors.Is(errs[1], ErrPreOSSecureBootAuthByEnrolledDigests), testutil.IsTrue) -} + var hse *HostSecurityError + c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrUEFIDebuggingEnabled), testutil.IsTrue) -func (s *runChecksSuite) TestRunChecksBadPreOSSecureBootAuthByEnrolledDigests(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + c.Assert(errors.As(errs[1], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoKernelIOMMU), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - IncludeDriverLaunch: true, - PreOSVerificationUsesDigests: crypto.SHA256, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest`) +func (s *runChecksSuite) TestRunChecksBadSHA1(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA1}, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: testutil.DecodeHexString(c, "25b4e4624ea1f2144a90d7de7aff87b23de0457d"), + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "1dc8bcbdb8b5ee60e87281e36161ec1f923f53b7")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "fc7840d38322a595e50a6b477685fdd2244f9292")}, + }, + }) + c.Check(err, ErrorMatches, `error with or detected from measurement log: no suitable PCR algorithm available: +- TPM_ALG_SHA512: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA384: the PCR bank is missing from the TCG log. +- TPM_ALG_SHA256: the PCR bank is missing from the TCG log. +`) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + var e *NoSuitablePCRAlgorithmError + c.Assert(errors.As(err, &e), testutil.IsTrue) - c.Check(errors.Is(errs[0], ErrPreOSSecureBootAuthByEnrolledDigests), testutil.IsTrue) + // Test that we can access individual errors. + c.Check(e.Errs[tpm2.HashAlgorithmSHA512], DeepEquals, []error{ErrPCRBankMissingFromLog}) + c.Check(e.Errs[tpm2.HashAlgorithmSHA384], DeepEquals, []error{ErrPCRBankMissingFromLog}) + c.Check(e.Errs[tpm2.HashAlgorithmSHA256], DeepEquals, []error{ErrPCRBankMissingFromLog}) + } } -func (s *runChecksSuite) TestRunChecksBadEFIVariableAccessError(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } +func (s *runChecksSuite) TestRunChecksBadMandatoryPCR1(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Err: efi.ErrVarDeviceError}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read AuditMode variable: variable access failed because of a hardware error`) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) - var e *EFIVariableAccessError - c.Assert(errors.As(err, &e), testutil.IsTrue) - c.Check(errors.Is(e, efi.ErrVarDeviceError), testutil.IsTrue) + var pce *PlatformConfigPCRError + c.Check(errors.As(errs[0], &pce), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadNoBootManagerCodeProfileSupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksSuite) TestRunChecksBadMandatoryPCR3(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(errs[0], &dce), testutil.IsTrue) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksBadMandatoryPCR5(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var bmce *BootManagerConfigPCRError + c.Check(errors.As(errs[0], &bmce), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), +func (s *runChecksSuite) TestRunChecksBadAddonDriversPresent(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `addon drivers were detected: +- \[no description\] path=\\PciRoot\(0x0\)\\Pci\(0x2,0x1c\)\\Pci\(0x0,0x0\)\\Offset\(0x38,0x11dff\) authenticode-digest=TPM_ALG_SHA256:1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6 +`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var adpe *AddonDriversPresentError + c.Check(errors.As(errs[0], &adpe), testutil.IsTrue) + c.Check(adpe.Drivers, DeepEquals, []*LoadedImageInfo{ + { + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0, + }, + &efi.PCIDevicePathNode{ + Function: 0x1c, + Device: 0x2, + }, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0, + }, + &efi.MediaRelOffsetRangeDevicePathNode{ + StartingOffset: 0x38, + EndingOffset: 0x11dff, + }, }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "1e94aaed2ad59a4409f3230dca2ad8c03ef8e3fde77cc47dc7b81bb8b242f3e6"), }, - // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test - // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in - // the log so the test thinks that the log contains the flat file digest. - &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, - &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and\/or the PE_COFF_IMAGE flag`) + }) + } +} - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) +func (s *runChecksSuite) TestRunChecksBadSysPrepAppsPresent(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeSysPrepAppLaunch: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {Name: "SysPrepOrder", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1, 0x0}}, + {Name: "SysPrep0001", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: efitest.MakeVarPayload(c, &efi.LoadOption{ + Attributes: efi.LoadOptionActive | efi.LoadOptionCategoryApp, + Description: "Mock sysprep app", + FilePath: efi.DevicePath{ + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + })}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `system preparation applications were detected: +- Mock sysprep app path=\\PciRoot\(0x0\)\\Pci\(0x1d,0x0\)\\Pci\(0x0,0x0\)\\NVMe\(0x1,00-00-00-00-00-00-00-00\)\\HD\(1,GPT,66de947b-fdb2-4525-b752-30d66bb2b960\)\\\\EFI\\Dell\\sysprep.efi authenticode-digest=TPM_ALG_SHA256:11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4 load-option=SysPrep0001 +`) - var bce *BootManagerCodePCRError - c.Check(errors.As(errs[0], &bce), testutil.IsTrue) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var spape *SysPrepApplicationsPresentError + c.Check(errors.As(errs[0], &spape), testutil.IsTrue) + c.Check(spape.Apps, DeepEquals, []*LoadedImageInfo{ + { + Description: "Mock sysprep app", + LoadOptionName: "SysPrep0001", + DevicePath: efi.DevicePath{ + &efi.ACPIDevicePathNode{ + HID: 0x0a0341d0, + UID: 0x0}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x1d}, + &efi.PCIDevicePathNode{ + Function: 0x0, + Device: 0x0}, + &efi.NVMENamespaceDevicePathNode{ + NamespaceID: 0x1, + NamespaceUUID: efi.EUI64{}}, + &efi.HardDriveDevicePathNode{ + PartitionNumber: 1, + PartitionStart: 0x800, + PartitionSize: 0x100000, + Signature: efi.GUIDHardDriveSignature(efi.MakeGUID(0x66de947b, 0xfdb2, 0x4525, 0xb752, [...]uint8{0x30, 0xd6, 0x6b, 0xb2, 0xb9, 0x60})), + MBRType: efi.GPT}, + efi.FilePathDevicePathNode("\\EFI\\Dell\\sysprep.efi"), + }, + DigestAlg: tpm2.HashAlgorithmSHA256, + Digest: testutil.DecodeHexString(c, "11b68a5ce0facfa4233cb71140e3d59c686bc7a176a49a520947c57247fe86f4"), + }, + }) + } } -func (s *runChecksSuite) TestRunChecksBadEFIVariableAccessErrorSetupMode(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +func (s *runChecksSuite) TestRunChecksBadAbsoluteActive(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeOSPresentFirmwareAppLaunch: efi.MakeGUID(0x821aca26, 0x29ea, 0x4993, 0x839f, [...]byte{0x59, 0x7f, 0xc0, 0x21, 0x70, 0x8d}), + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `Absolute was detected to be active and it is advised that this is disabled`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + c.Check(errors.Is(errs[0], ErrAbsoluteComputraceActive), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read SetupMode variable: variable does not exist`) +func (s *runChecksSuite) TestRunChecksBadWeakSecureBootAlgs(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA1, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `2 errors detected: +- a weak cryptographic algorithm was detected during secure boot verification +- some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest +`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 2) - var e *EFIVariableAccessError - c.Assert(errors.As(err, &e), testutil.IsTrue) + c.Check(errors.Is(errs[0], ErrWeakSecureBootAlgorithmDetected), testutil.IsTrue) + c.Check(errors.Is(errs[1], ErrPreOSSecureBootAuthByEnrolledDigests), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksSuite) TestRunChecksBadPreOSSecureBootAuthByEnrolledDigests(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + IncludeDriverLaunch: true, + PreOSVerificationUsesDigests: crypto.SHA256, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitAddonDrivers, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `some pre-OS components were authenticated from the authorized signature database using an enrolled Authenticode digest`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + c.Check(errors.Is(errs[0], ErrPreOSSecureBootAuthByEnrolledDigests), testutil.IsTrue) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksBadEFIVariableAccessError(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Err: efi.ErrVarDeviceError}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read AuditMode variable: variable access failed because of a hardware error`) + + var e *EFIVariableAccessError + c.Assert(errors.As(err, &e), testutil.IsTrue) + c.Check(errors.Is(e, efi.ErrVarDeviceError), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) +func (s *runChecksSuite) TestRunChecksBadNoBootManagerCodeProfileSupport(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, + }, + // We have to cheat a bit here because the digest is hardcoded in the test log. We set an invalid Authenticode digest for the mock image so the intial test + // fails and then have the following code digest the same string that produces the log digest ("mock grub executable"), to get a digest that matches what's in + // the log so the test thinks that the log contains the flat file digest. + &mockImage{contents: []byte("mock grub executable"), digest: testutil.DecodeHexString(c, "80fd5a9364df79953369758a419f7cb167201cf580160b91f837aad455c55bcd")}, + &mockImage{contents: []byte("mock kernel executable"), digest: testutil.DecodeHexString(c, "c49a23d0315fa446781686de3ee5c04288078911c89c39618c6a54d5fedddf44")}, + }, + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with boot manager code \(PCR4\) measurements: log contains unexpected EV_EFI_BOOT_SERVICES_APPLICATION digest for OS-present application mock image: log digest matches flat file digest \(0xd5a9780e9f6a43c2e53fe9fda547be77f7783f31aea8013783242b040ff21dc0\) which suggests an image loaded outside of the LoadImage API and firmware lacking support for the EFI_TCG2_PROTOCOL and\/or the PE_COFF_IMAGE flag`) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) - var sbe *SecureBootPolicyPCRError - c.Assert(errors.As(errs[0], &sbe), testutil.IsTrue) - c.Check(errors.Is(sbe, ErrNoSecureBoot), testutil.IsTrue) + var bce *BootManagerCodePCRError + c.Check(errors.As(errs[0], &bce), testutil.IsTrue) + } } -func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupportNoDeployedMode(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, +func (s *runChecksSuite) TestRunChecksBadEFIVariableAccessErrorSetupMode(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `cannot access EFI variable: cannot compute secure boot mode: cannot read SetupMode variable: variable does not exist`) + + var e *EFIVariableAccessError + c.Assert(errors.As(err, &e), testutil.IsTrue) } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), +} + +func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupport(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) + + var sbe *SecureBootPolicyPCRError + c.Assert(errors.As(errs[0], &sbe), testutil.IsTrue) + c.Check(errors.Is(sbe, ErrNoSecureBoot), testutil.IsTrue) } +} - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `secure boot is enabled but not in deployed mode`) +func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupportNoDeployedMode(c *C) { + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `secure boot is enabled but not in deployed mode`) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) - c.Check(errors.Is(errs[0], ErrNoDeployedMode), testutil.IsTrue) + c.Check(errors.Is(errs[0], ErrNoDeployedMode), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupportSecureBootDisabledAndNoSBATLevel(c *C) { @@ -3840,407 +3306,355 @@ func (s *runChecksSuite) TestRunChecksBadNoSecureBootPolicyProfileSupportSecureB // shim on a system with an empty SbatLevel variable. In this case, // there are no EV_EFI_VARIABLE_AUTHORITY events which caused // https://launchpad.net/bugs/2125439 - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - SecureBootDisabled: true, - NoSBAT: true, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - }) - c.Check(err, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + SecureBootDisabled: true, + NoSBAT: true, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + }) + c.Check(err, ErrorMatches, `error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles`) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 1) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 1) - var sbe *SecureBootPolicyPCRError - c.Assert(errors.As(errs[0], &sbe), testutil.IsTrue) - c.Check(errors.Is(sbe, ErrNoSecureBoot), testutil.IsTrue) + var sbe *SecureBootPolicyPCRError + c.Assert(errors.As(errs[0], &sbe), testutil.IsTrue) + c.Check(errors.Is(sbe, ErrNoSecureBoot), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksBadTPMHierarchiesOwnedAndNoSecureBootPolicySupport(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - prepare: func() { - c.Assert(s.TPM.HierarchyChangeAuth(s.TPM.LockoutHandleContext(), []byte{1, 2, 3, 4}, nil), IsNil) - }, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, ErrorMatches, `2 errors detected: + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(false).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + prepare: func() { + c.Assert(s.TPM.HierarchyChangeAuth(s.TPM.LockoutHandleContext(), []byte{1, 2, 3, 4}, nil), IsNil) + }, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + c.Assert(err, ErrorMatches, `2 errors detected: - error with TPM2 device: one or more of the TPM hierarchies is already owned: - TPM_RH_LOCKOUT has an authorization value - error with secure boot policy \(PCR7\) measurements: secure boot should be enabled in order to generate secure boot profiles `) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 2) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 2) - var te *TPM2DeviceError - c.Assert(errors.As(errs[0], &te), testutil.IsTrue) - var ohe *TPM2OwnedHierarchiesError - c.Check(errors.As(te, &ohe), testutil.IsTrue) + var te *TPM2DeviceError + c.Assert(errors.As(errs[0], &te), testutil.IsTrue) + var ohe *TPM2OwnedHierarchiesError + c.Check(errors.As(te, &ohe), testutil.IsTrue) - var sbpe *SecureBootPolicyPCRError - c.Check(errors.As(errs[1], &sbpe), testutil.IsTrue) - c.Check(errors.Is(sbpe, ErrNoSecureBoot), testutil.IsTrue) + var sbpe *SecureBootPolicyPCRError + c.Check(errors.As(errs[1], &sbpe), testutil.IsTrue) + c.Check(errors.Is(sbpe, ErrNoSecureBoot), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksBadInsufficientDMAProtectionAndNoBootManagerCodeProfileSupport(c *C) { - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: []secboot_efi.Image{ - &mockImage{ - contents: []byte("mock shim executable"), - digest: shimDigestDefault, - signatures: []*efi.WinCertificateAuthenticode{ - efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + required := runChecksHostCapabilityValid + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: []secboot_efi.Image{ + &mockImage{ + contents: []byte("mock shim executable"), + digest: shimDigestDefault, + signatures: []*efi.WinCertificateAuthenticode{ + efitest.ReadWinCertificateAuthenticodeDetached(c, shimUbuntuSig4), + }, }, + &mockImage{contents: []byte("mock grub executable"), digest: grubDigestDefault}, }, - &mockImage{contents: []byte("mock grub executable"), digest: grubDigestDefault}, - }, - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, ErrorMatches, `3 errors detected: + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + c.Assert(err, ErrorMatches, `3 errors detected: - error with system security: the platform firmware indicates that DMA protections are insufficient - error with boot manager code \(PCR4\) measurements: cannot verify correctness of EV_EFI_BOOT_SERVICES_APPLICATION event digest: not enough images supplied - error with secure boot policy \(PCR7\) measurements: unexpected EV_EFI_ACTION event "DMA Protection Disabled" whilst measuring config `) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 3) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 3) - var hse *HostSecurityError - c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrInsufficientDMAProtection), testutil.IsTrue) + var hse *HostSecurityError + c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrInsufficientDMAProtection), testutil.IsTrue) - var bme *BootManagerCodePCRError - c.Check(errors.As(errs[1], &bme), testutil.IsTrue) + var bme *BootManagerCodePCRError + c.Check(errors.As(errs[1], &bme), testutil.IsTrue) - var sbpe *SecureBootPolicyPCRError - c.Check(errors.As(errs[2], &sbpe), testutil.IsTrue) + var sbpe *SecureBootPolicyPCRError + c.Check(errors.As(errs[2], &sbpe), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksBadInsufficientDMAProtectionAndNoKernelIOMMU(c *C) { - s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) - - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } - - _, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, ErrorMatches, `3 errors detected: + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + s.RequireAlgorithm(c, tpm2.AlgorithmSHA384) + + _, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + }) + c.Assert(err, ErrorMatches, `3 errors detected: - error with system security: the platform firmware indicates that DMA protections are insufficient - error with system security: no kernel IOMMU support was detected - error with secure boot policy \(PCR7\) measurements: unexpected EV_EFI_ACTION event "DMA Protection Disabled" whilst measuring config `) - var ce CompoundError - c.Assert(err, Implements, &ce) - ce = err.(CompoundError) - errs := ce.Unwrap() - c.Assert(errs, HasLen, 3) + var ce CompoundError + c.Assert(err, Implements, &ce) + ce = err.(CompoundError) + errs := ce.Unwrap() + c.Assert(errs, HasLen, 3) - var hse *HostSecurityError - c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrInsufficientDMAProtection), testutil.IsTrue) + var hse *HostSecurityError + c.Assert(errors.As(errs[0], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrInsufficientDMAProtection), testutil.IsTrue) - c.Assert(errors.As(errs[1], &hse), testutil.IsTrue) - c.Check(errors.Is(hse, ErrNoKernelIOMMU), testutil.IsTrue) + c.Assert(errors.As(errs[1], &hse), testutil.IsTrue) + c.Check(errors.Is(hse, ErrNoKernelIOMMU), testutil.IsTrue) - var sbpe *SecureBootPolicyPCRError - c.Check(errors.As(errs[2], &sbpe), testutil.IsTrue) + var sbpe *SecureBootPolicyPCRError + c.Check(errors.As(errs[2], &sbpe), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksAllowInsufficientDMAProtection(c *C) { - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusBase, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), - } + required := runChecksHostCapabilityNoKernelIOMMU + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ + Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + DMAProtection: efitest.DMAProtectionDisabled, + })), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde}))))), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitInsufficientDMAProtection, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 5) - warnings, err := s.testRunChecks(c, &testRunChecksParams{ - env: efitest.NewMockHostEnvironmentWithOpts( - efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), - efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), - efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{ - Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - DMAProtection: efitest.DMAProtectionDisabled, - })), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), - ), - tpmPropertyModifiers: map[tpm2.Property]uint32{ - tpm2.PropertyNVCountersMax: 0, - tpm2.PropertyPSFamilyIndicator: 1, - tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), - }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitInsufficientDMAProtection, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, - }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 5) - - warning := warnings[0] - c.Check(warning, ErrorMatches, `the platform firmware indicates that DMA protections are insufficient`) - c.Check(errors.Is(warning, ErrInsufficientDMAProtection), testutil.IsTrue) - - warning = warnings[1] - c.Check(warning, ErrorMatches, `no kernel IOMMU support was detected`) - c.Check(errors.Is(warning, ErrNoKernelIOMMU), testutil.IsTrue) - - warning = warnings[2] - c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[3] - c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[4] - c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + warning := warnings[0] + c.Check(warning, ErrorMatches, `the platform firmware indicates that DMA protections are insufficient`) + c.Check(errors.Is(warning, ErrInsufficientDMAProtection), testutil.IsTrue) + + warning = warnings[1] + c.Check(warning, ErrorMatches, `no kernel IOMMU support was detected`) + c.Check(errors.Is(warning, ErrNoKernelIOMMU), testutil.IsTrue) + + warning = warnings[2] + c.Check(warning, ErrorMatches, `error with platform config \(PCR1\) measurements: generating profiles for PCR 1 is not supported yet, see https://github.com/canonical/secboot/issues/322`) + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[3] + c.Check(warning, ErrorMatches, `error with drivers and apps config \(PCR3\) measurements: generating profiles for PCR 3 is not supported yet, see https://github.com/canonical/secboot/issues/341`) + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[4] + c.Check(warning, ErrorMatches, `error with boot manager config \(PCR5\) measurements: generating profiles for PCR 5 is not supported yet, see https://github.com/canonical/secboot/issues/323`) + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) + } } func (s *runChecksSuite) TestRunChecksAllowNoHardwareRootOfTrust(c *C) { // Test that PermitNoHardwareRootOfTrust converts related errors to warnings - meiAttrs := map[string][]byte{ - "fw_ver": []byte(`0:16.1.27.2176 -0:16.1.27.2176 -0:16.0.15.1624 -`), - "fw_status": fwStatusManufacturingMode, - } - devices := []internal_efi.SysfsDevice{ - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar0", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/virtual/iommu/dmar1", nil, "iommu", nil, nil), - efitest.NewMockSysfsDevice("/sys/devices/pci0000:00/0000:00:16.0/mei/mei0", map[string]string{"DEVNAME": "mei0"}, "mei", meiAttrs, efitest.NewMockSysfsDevice( - "/sys/devices/pci0000:00:16:0", map[string]string{"DRIVER": "mei_me"}, "pci", nil, nil, - )), + required := runChecksHostCapabilityInsufficientHWRootOfTrust + for _, fixture := range runChecksHostFixturesFor(c, required) { + c.Logf("running with host fixture %q", fixture.name) + fixture.mockRuntimeGOARCH(s) + warnings, err := s.testRunChecks(c, &testRunChecksParams{ + env: fixture.newEnvironment( + efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), + efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), + efitest.WithMockVars(efitest.MockVars{ + {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, + {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, + {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + ), + tpmPropertyModifiers: map[tpm2.Property]uint32{ + tpm2.PropertyNVCountersMax: 0, + tpm2.PropertyPSFamilyIndicator: 1, + tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), + }, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoHardwareRootOfTrust, + loadedImages: efiImagesDefault(), + expectedPcrAlg: tpm2.HashAlgorithmSHA256, + expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, + expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport | fixture.additionalExpectedFlags, + }) + c.Assert(err, IsNil) + c.Assert(warnings, HasLen, 4) + + warning := warnings[0] + c.Check(warning, ErrorMatches, "encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode") + var nohwrot *NoHardwareRootOfTrustError + c.Check(errors.As(warning, &nohwrot), testutil.IsTrue) + + // Do not check the error messages below, as it is verified in another test + warning = warnings[1] + var pce *PlatformConfigPCRError + c.Check(errors.As(warning, &pce), testutil.IsTrue) + + warning = warnings[2] + var dce *DriversAndAppsConfigPCRError + c.Check(errors.As(warning, &dce), testutil.IsTrue) + + warning = warnings[3] + var bmce *BootManagerConfigPCRError + c.Check(errors.As(warning, &bmce), testutil.IsTrue) } +} - warnings, err := s.testRunChecks(c, &testRunChecksParams{ +func (s *runChecksSuite) TestRunChecksBadHostSecurityUnsupportedArchitecture(c *C) { + s.AddCleanup(MockRuntimeGOARCH("ppc64le")) + + _, err := s.testRunChecks(c, &testRunChecksParams{ env: efitest.NewMockHostEnvironmentWithOpts( efitest.WithVirtMode(internal_efi.VirtModeNone, internal_efi.DetectVirtModeAll), efitest.WithTPMDevice(newTpmDevice(tpm2_testutil.NewTransportBackedDevice(s.Transport, false, 1), nil, tpm2_device.ErrNoPPI)), efitest.WithLog(efitest.NewLog(c, &efitest.LogOptions{Algorithms: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}})), - efitest.WithAMD64Environment("GenuineIntel", 0x6, []uint64{cpuid.SDBG, cpuid.SMX}, 4, map[uint32]uint64{0xc80: 0x40000000, 0x13a: (3 << 1)}), - efitest.WithSysfsDevices(devices...), - efitest.WithMockVars(efitest.MockVars{ - {Name: "AuditMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "DeployedMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeNonVolatile | efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x1}}, - {Name: "SetupMode", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x0}}, - {Name: "OsIndicationsSupported", GUID: efi.GlobalVariable}: &efitest.VarEntry{Attrs: efi.AttributeBootserviceAccess | efi.AttributeRuntimeAccess, Payload: []byte{0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - }.SetSecureBoot(true).SetPK(c, efitest.NewSignatureListX509(c, snakeoilCert, efi.MakeGUID(0x03f66fa4, 0x5eee, 0x479c, 0xa408, [...]uint8{0xc4, 0xdc, 0x0a, 0x33, 0xfc, 0xde})))), + efitest.WithMockVars(efitest.MockVars{}.SetSecureBoot(false)), ), tpmPropertyModifiers: map[tpm2.Property]uint32{ tpm2.PropertyNVCountersMax: 0, tpm2.PropertyPSFamilyIndicator: 1, tpm2.PropertyManufacturer: uint32(tpm2.TPMManufacturerINTC), }, - enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, - flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport | PermitNoHardwareRootOfTrust, - loadedImages: efiImagesDefault(), - expectedPcrAlg: tpm2.HashAlgorithmSHA256, - expectedUsedSecureBootCAs: []*X509CertificateID{NewX509CertificateID(testutil.ParseCertificate(c, msUefiCACert))}, - expectedFlags: NoPlatformConfigProfileSupport | NoDriversAndAppsConfigProfileSupport | NoBootManagerConfigProfileSupport, + enabledBanks: []tpm2.HashAlgorithmId{tpm2.HashAlgorithmSHA256}, + flags: PermitNoPlatformConfigProfileSupport | PermitNoDriversAndAppsConfigProfileSupport | PermitNoBootManagerConfigProfileSupport, }) - c.Assert(err, IsNil) - c.Assert(warnings, HasLen, 4) - - warning := warnings[0] - c.Check(warning, ErrorMatches, "encountered an error when checking Intel BootGuard configuration: no hardware root-of-trust properly configured: system is in manufacturing mode") - var nohwrot *NoHardwareRootOfTrustError - c.Check(errors.As(warning, &nohwrot), testutil.IsTrue) - - // Do not check the error messages below, as it is verified in another test - warning = warnings[1] - var pce *PlatformConfigPCRError - c.Check(errors.As(warning, &pce), testutil.IsTrue) - - warning = warnings[2] - var dce *DriversAndAppsConfigPCRError - c.Check(errors.As(warning, &dce), testutil.IsTrue) - - warning = warnings[3] - var bmce *BootManagerConfigPCRError - c.Check(errors.As(warning, &bmce), testutil.IsTrue) + c.Check(err, ErrorMatches, `error with system security: unsupported platform: checking host security is not implemented on ppc64le`) + var hse *HostSecurityError + c.Check(errors.As(err, &hse), testutil.IsTrue) + var upe *UnsupportedPlatformError + c.Check(errors.As(err, &upe), testutil.IsTrue) } diff --git a/efi/preinstall/util_amd64.go b/efi/preinstall/cpu_vendor.go similarity index 96% rename from efi/preinstall/util_amd64.go rename to efi/preinstall/cpu_vendor.go index c8532f84..8da28d82 100644 --- a/efi/preinstall/util_amd64.go +++ b/efi/preinstall/cpu_vendor.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/util_amd64_test.go b/efi/preinstall/cpu_vendor_test.go similarity index 97% rename from efi/preinstall/util_amd64_test.go rename to efi/preinstall/cpu_vendor_test.go index 3b15a95e..5b8d1eaf 100644 --- a/efi/preinstall/util_amd64_test.go +++ b/efi/preinstall/cpu_vendor_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as diff --git a/efi/preinstall/export_amd64_test.go b/efi/preinstall/export_amd64_test.go deleted file mode 100644 index 03de4c17..00000000 --- a/efi/preinstall/export_amd64_test.go +++ /dev/null @@ -1,54 +0,0 @@ -//go:build amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package preinstall - -type ( - CpuVendor = cpuVendor - HfstsRegisters = hfstsRegisters - HfstsRegistersCsme11 = hfstsRegistersCsme11 - HfstsRegistersCsme18 = hfstsRegistersCsme18 - MeVersion = meVersion -) - -const ( - CpuVendorIntel = cpuVendorIntel - CpuVendorAMD = cpuVendorAMD - MeFamilyUnknown = meFamilyUnknown - MeFamilySps = meFamilySps - MeFamilyTxe = meFamilyTxe - MeFamilyMe = meFamilyMe - MeFamilyCsme = meFamilyCsme -) - -var ( - CalculateIntelMEFamily = calculateIntelMEFamily - CheckHostSecurityAMDPSP = checkHostSecurityAMDPSP - CheckHostSecurityIntelBootGuard = checkHostSecurityIntelBootGuard - CheckHostSecurityIntelBootGuardCSME11 = checkHostSecurityIntelBootGuardCSME11 - CheckHostSecurityIntelBootGuardCSME18 = checkHostSecurityIntelBootGuardCSME18 - CheckHostSecurityIntelBootGuardMSR = checkHostSecurityIntelBootGuardMSR - CheckHostSecurityIntelCPUDebuggingLocked = checkHostSecurityIntelCPUDebuggingLocked - DetermineCPUVendor = determineCPUVendor - IsTPMDiscreteFromIntelBootGuard = isTPMDiscreteFromIntelBootGuard - ReadIntelHFSTSRegistersFromMEISysfs = readIntelHFSTSRegistersFromMEISysfs - ReadIntelMEVersionFromMEISysfs = readIntelMEVersionFromMEISysfs -) diff --git a/efi/preinstall/export_test.go b/efi/preinstall/export_test.go index 753f468e..7c3273a9 100644 --- a/efi/preinstall/export_test.go +++ b/efi/preinstall/export_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -37,8 +37,13 @@ type ( BootManagerCodeResult = bootManagerCodeResult CheckFirmwareLogFlags = checkFirmwareLogFlags CheckTPM2DeviceFlags = checkTPM2DeviceFlags + CpuVendor = cpuVendor DetectVirtResult = detectVirtResult + HfstsRegisters = hfstsRegisters + HfstsRegistersCsme11 = hfstsRegistersCsme11 + HfstsRegistersCsme18 = hfstsRegistersCsme18 JoinError = joinError + MeVersion = meVersion PcrResults = pcrResults SecureBootPolicyResult = secureBootPolicyResult SecureBootPolicyResultFlags = secureBootPolicyResultFlags @@ -49,6 +54,8 @@ const ( AuthorityTrustDrivers = authorityTrustDrivers CheckFirmwareLogPermitWeakPCRBanks = checkFirmwareLogPermitWeakPCRBanks CheckTPM2DevicePostInstall = checkTPM2DevicePostInstall + CpuVendorAMD = cpuVendorAMD + CpuVendorIntel = cpuVendorIntel DetectVirtNone = detectVirtNone DetectVirtVM = detectVirtVM DiscreteTPMDetected = discreteTPMDetected @@ -56,6 +63,12 @@ const ( DtpmPartialResetAttackMitigationPreferred = dtpmPartialResetAttackMitigationPreferred DtpmPartialResetAttackMitigationUnavailable = dtpmPartialResetAttackMitigationUnavailable InsufficientDMAProtectionDetected = insufficientDMAProtectionDetected + MeFamilyCsme = meFamilyCsme + MeFamilyMe = meFamilyMe + MeFamilySps = meFamilySps + MeFamilyTxe = meFamilyTxe + MeFamilyUnknown = meFamilyUnknown + PlatformFirmwareIntegrityNone = platformFirmwareIntegrityNone PlatformFirmwareIntegrityMeasured = platformFirmwareIntegrityMeasured PlatformFirmwareIntegrityVerified = platformFirmwareIntegrityVerified SecureBootIncludesWeakAlg = secureBootIncludesWeakAlg @@ -65,7 +78,14 @@ const ( ) var ( + CalculateIntelMEFamily = calculateIntelMEFamily CheckBootManagerCodeMeasurements = checkBootManagerCodeMeasurements + CheckHostSecurityAMDPSP = checkHostSecurityAMDPSP + CheckHostSecurityIntelBootGuard = checkHostSecurityIntelBootGuard + CheckHostSecurityIntelBootGuardCSME11 = checkHostSecurityIntelBootGuardCSME11 + CheckHostSecurityIntelBootGuardCSME18 = checkHostSecurityIntelBootGuardCSME18 + CheckHostSecurityIntelBootGuardMSR = checkHostSecurityIntelBootGuardMSR + CheckHostSecurityIntelCPUDebuggingLocked = checkHostSecurityIntelCPUDebuggingLocked CheckDiscreteTPMPartialResetAttackMitigationStatus = checkDiscreteTPMPartialResetAttackMitigationStatus CheckDriversAndAppsMeasurements = checkDriversAndAppsMeasurements CheckFirmwareLogAndChoosePCRBank = checkFirmwareLogAndChoosePCRBank @@ -76,16 +96,20 @@ var ( CheckSystemIsEFI = checkSystemIsEFI CheckTPM2ForRequiredPCClientFeatures = checkTPM2ForRequiredPCClientFeatures ClearTPM = clearTPM + DetermineCPUVendor = determineCPUVendor DetectVirtualization = detectVirtualization ErrInvalidLockoutAuthValueSupplied = errInvalidLockoutAuthValueSupplied InsertActionProceed = insertActionProceed IsLaunchedFromLoadOption = isLaunchedFromLoadOption IsPPIActionAvailable = isPPIActionAvailable IsTPMDiscrete = isTPMDiscrete + IsTPMDiscreteFromIntelBootGuard = isTPMDiscreteFromIntelBootGuard JoinErrors = joinErrors MatchLaunchToLoadOption = matchLaunchToLoadOption NewX509CertificateID = newX509CertificateID OpenAndCheckTPM2Device = openAndCheckTPM2Device + ReadIntelHFSTSRegistersFromMEISysfs = readIntelHFSTSRegistersFromMEISysfs + ReadIntelMEVersionFromMEISysfs = readIntelMEVersionFromMEISysfs ReadOrderedLoadOptionVariables = readOrderedLoadOptionVariables RestrictedTPMLocalitiesIntel = restrictedTPMLocalitiesIntel RunPPIAction = runPPIAction @@ -158,3 +182,9 @@ func NewPCRBankResults(alg tpm2.HashAlgorithmId, sl uint8, pcrs [8]PcrResults) * pcrs: pcrs, } } + +func MockRuntimeGOARCH(arch string) (restore func()) { + orig := runtimeGOARCH + runtimeGOARCH = arch + return func() { runtimeGOARCH = orig } +} diff --git a/efi/preinstall/intel_util.go b/efi/preinstall/intel_util.go index f044d1b9..6306fe73 100644 --- a/efi/preinstall/intel_util.go +++ b/efi/preinstall/intel_util.go @@ -1,5 +1,3 @@ -//go:build amd64 - // -*- Mode: Go; indent-tabs-mode: t -*- /* diff --git a/internal/cpuid/cpuid_amd64.go b/internal/cpuid/cpuid_amd64.go new file mode 100644 index 00000000..c278ddda --- /dev/null +++ b/internal/cpuid/cpuid_amd64.go @@ -0,0 +1,47 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2026 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// Package cpuid is a deliberately thin, architecture-gated wrapper around +// github.com/canonical/cpuid, which does not compile on non-x86 architectures. +// Confining that dependency here keeps every consumer architecture-neutral, so +// that consumers are compiled and unit tested on every architecture rather than +// being gated by build constraints. +// +// On amd64 the functions delegate to the upstream package. On every other +// architecture they return zero values, because CPUID is x86-only. +package cpuid + +import ( + upstream_cpuid "github.com/canonical/cpuid" +) + +// VendorIdentificator returns the CPU vendor identificator string, e.g. "GenuineIntel". +func VendorIdentificator() string { + return upstream_cpuid.VendorIdentificatorString +} + +// Family returns the CPU display family ID. +func Family() uint32 { + return upstream_cpuid.DisplayFamily +} + +// HasFeature returns whether the supplied CPUID feature bit is set. +func HasFeature(feature uint64) bool { + return upstream_cpuid.HasFeature(feature) +} diff --git a/internal/cpuid/cpuid_amd64_test.go b/internal/cpuid/cpuid_amd64_test.go new file mode 100644 index 00000000..95412d2b --- /dev/null +++ b/internal/cpuid/cpuid_amd64_test.go @@ -0,0 +1,52 @@ +// -*- Mode: Go; indent-tabs-mode: t -*- + +/* + * Copyright (C) 2026 Canonical Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// This file contains drift-guard tests comparing the architecture-neutral +// CPUIDFeature* constants declared in internal/efi against their upstream +// cpuid equivalents. This package is the only place permitted to import +// github.com/canonical/cpuid, so it is the only place that can compare our +// constants against upstream's bit positions. + +package cpuid_test + +import ( + "testing" + + upstream_cpuid "github.com/canonical/cpuid" + internal_efi "github.com/snapcore/secboot/internal/efi" + . "gopkg.in/check.v1" +) + +func Test(t *testing.T) { TestingT(t) } + +type cpuidSuite struct{} + +var _ = Suite(&cpuidSuite{}) + +func (s *cpuidSuite) TestCPUIDFeatureSMXMatchesCpuidPackage(c *C) { + // Drift guard: CPUIDFeatureSMX must equal cpuid.SMX. If the cpuid + // package ever changes its bit positions this test will catch it. + c.Check(internal_efi.CPUIDFeatureSMX, Equals, upstream_cpuid.SMX) +} + +func (s *cpuidSuite) TestCPUIDFeatureSDBGMatchesCpuidPackage(c *C) { + // Drift guard: CPUIDFeatureSDBG must equal cpuid.SDBG. If the cpuid + // package ever changes its bit positions this test will catch it. + c.Check(internal_efi.CPUIDFeatureSDBG, Equals, upstream_cpuid.SDBG) +} diff --git a/efi/preinstall/check_tpm_null.go b/internal/cpuid/cpuid_null.go similarity index 52% rename from efi/preinstall/check_tpm_null.go rename to internal/cpuid/cpuid_null.go index c30ae75b..2f529731 100644 --- a/efi/preinstall/check_tpm_null.go +++ b/internal/cpuid/cpuid_null.go @@ -3,7 +3,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 @@ -19,15 +19,22 @@ * */ -package preinstall +package cpuid -import ( - "fmt" - "runtime" +// VendorIdentificator returns the CPU vendor identificator string. +// CPUID is x86-only; this stub always returns "" on this architecture. +func VendorIdentificator() string { + return "" +} - internal_efi "github.com/snapcore/secboot/internal/efi" -) +// Family returns the CPU display family ID. +// CPUID is x86-only; this stub always returns 0 on this architecture. +func Family() uint32 { + return 0 +} -func isTPMDiscrete(env internal_efi.HostEnvironment) (bool, error) { - return false, &UnsupportedPlatformError{fmt.Errorf("checking for TPM discreteness is not implemented on %s", runtime.GOARCH)} +// HasFeature returns whether the supplied CPUID feature bit is set. +// CPUID is x86-only; this stub always returns false on this architecture. +func HasFeature(feature uint64) bool { + return false } diff --git a/internal/efi/default_env.go b/internal/efi/default_env.go index 20e851fc..cbbc55fd 100644 --- a/internal/efi/default_env.go +++ b/internal/efi/default_env.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2021 Canonical Ltd + * Copyright (C) 2021-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -22,24 +22,35 @@ package efi import ( "bytes" "context" + "encoding/binary" + "errors" "fmt" "io" "os" "os/exec" "path/filepath" + "runtime" + "strconv" + "syscall" efi "github.com/canonical/go-efilib" "github.com/canonical/tcglog-parser" "github.com/pilebones/go-udev/crawler" "github.com/pilebones/go-udev/netlink" + internal_cpuid "github.com/snapcore/secboot/internal/cpuid" "github.com/snapcore/secboot/internal/tpm2_device" ) var ( crawlerExistingDevices = crawler.ExistingDevices + cpuidFamily = internal_cpuid.Family + cpuidHasFeature = internal_cpuid.HasFeature + cpuidVendorIdentificator = internal_cpuid.VendorIdentificator + devcpuPath = "/dev/cpu" osOpen = os.Open osReadFile = os.ReadFile osReadlink = os.Readlink + runtimeGOARCH = runtime.GOARCH tpm2_deviceDefaultDevice = tpm2_device.DefaultDevice eventLogPath = "/sys/kernel/security/tpm0/binary_bios_measurements" // Path of the TCG event log for the default TPM, in binary form @@ -240,3 +251,88 @@ func (defaultEnvImpl) EnumerateDevices(matcher netlink.Matcher) ([]SysfsDevice, // DefaultEnv corresponds to the environment associated with the host // machine. var DefaultEnv = defaultEnvImpl{} + +type defaultEnvAMD64Impl struct{} + +// CPUVendorIdentificator implements [HostEnvironmentAMD64.CPUVendorIdentificator]. +func (defaultEnvAMD64Impl) CPUVendorIdentificator() string { + return cpuidVendorIdentificator() +} + +// CPUFamily implements [HostEnvironmentAMD64.CPUFamily]. +func (defaultEnvAMD64Impl) CPUFamily() uint32 { + return cpuidFamily() +} + +// HasCPUIDFeature implements [HostEnvironmentAMD64.HasCPUIDFeature]. +func (defaultEnvAMD64Impl) HasCPUIDFeature(feature uint64) bool { + return cpuidHasFeature(feature) +} + +// ReadMSRs implements [HostEnvironmentAMD64.ReadMSRs]. +func (defaultEnvAMD64Impl) ReadMSRs(msr uint32) (map[uint32]uint64, error) { + dir, err := os.Open(devcpuPath) + switch { + case os.IsNotExist(err): + return nil, ErrNoKernelMSRSupport + case err != nil: + return nil, err + } + defer dir.Close() + + entries, err := dir.ReadDir(-1) + if err != nil { + return nil, err + } + + out := make(map[uint32]uint64) + + for _, entry := range entries { + cpuNo, err := strconv.ParseUint(entry.Name(), 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid CPU number for name %s: %w", entry.Name(), err) + } + + val, err := func(name string) (uint64, error) { + f, err := os.Open(filepath.Join(dir.Name(), name, "msr")) + switch { + case os.IsNotExist(err): + return 0, ErrNoKernelMSRSupport + case errors.Is(err, syscall.EIO): + return 0, ErrNoMSRSupport + case err != nil: + return 0, err + } + defer f.Close() + + var data [8]byte + _, err = f.ReadAt(data[:], int64(msr)) + switch { + case errors.Is(err, syscall.EIO): // I think the kernel returns -EIO if the MSR is not supported, but this is poorly documented. + return 0, ErrNoMSRSupport + case err != nil: + return 0, fmt.Errorf("cannot read from MSR device: %w", err) + } + + return binary.LittleEndian.Uint64(data[:]), nil + }(entry.Name()) + if err != nil { + return nil, fmt.Errorf("cannot read value for CPU %s: %w", entry.Name(), err) + } + + out[uint32(cpuNo)] = val + } + + return out, nil +} + +// AMD64 implements [HostEnvironment.AMD64]. +// +// The architecture is checked at runtime (rather than by build constraint) so +// that this implementation is compiled and unit tested on every architecture. +func (defaultEnvImpl) AMD64() (HostEnvironmentAMD64, error) { + if runtimeGOARCH != "amd64" { + return nil, ErrNotAMD64Host + } + return defaultEnvAMD64Impl{}, nil +} diff --git a/internal/efi/default_env_amd64.go b/internal/efi/default_env_amd64.go deleted file mode 100644 index b9b13917..00000000 --- a/internal/efi/default_env_amd64.go +++ /dev/null @@ -1,116 +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 efi - -import ( - "encoding/binary" - "errors" - "fmt" - "os" - "path/filepath" - "strconv" - "syscall" - - "github.com/canonical/cpuid" -) - -var ( - cpuidHasFeature = cpuid.HasFeature - devcpuPath = "/dev/cpu" -) - -type defaultEnvAMD64Impl struct{} - -// CPUVendorIdentificator implements [HostEnvironmentAMD64.CPUVendorIdentificator]. -func (defaultEnvAMD64Impl) CPUVendorIdentificator() string { - return cpuid.VendorIdentificatorString -} - -// CPUFamily implements [HostEnvironmentAMD64.CPUFamily]. -func (defaultEnvAMD64Impl) CPUFamily() uint32 { - return cpuid.DisplayFamily -} - -// HasCPUIDFeature implements [HostEnvironmentAMD64.HasCPUIDFeature]. -func (defaultEnvAMD64Impl) HasCPUIDFeature(feature uint64) bool { - return cpuidHasFeature(feature) -} - -// ReadMSR implements [HostEnvironmentAMD64.ReadMSRs]. -func (defaultEnvAMD64Impl) ReadMSRs(msr uint32) (map[uint32]uint64, error) { - dir, err := os.Open(devcpuPath) - switch { - case os.IsNotExist(err): - return nil, ErrNoKernelMSRSupport - case err != nil: - return nil, err - } - defer dir.Close() - - entries, err := dir.ReadDir(-1) - if err != nil { - return nil, err - } - - out := make(map[uint32]uint64) - - for _, entry := range entries { - cpuNo, err := strconv.ParseUint(entry.Name(), 10, 32) - if err != nil { - return nil, fmt.Errorf("invalid CPU number for name %s: %w", entry.Name(), err) - } - - val, err := func(name string) (uint64, error) { - f, err := os.Open(filepath.Join(dir.Name(), name, "msr")) - switch { - case os.IsNotExist(err): - return 0, ErrNoKernelMSRSupport - case errors.Is(err, syscall.EIO): - return 0, ErrNoMSRSupport - case err != nil: - return 0, err - } - defer f.Close() - - var data [8]byte - _, err = f.ReadAt(data[:], int64(msr)) - switch { - case errors.Is(err, syscall.EIO): // I think the kernel returns -EIO if the MSR is not supported, but this is poorly documented. - return 0, ErrNoMSRSupport - case err != nil: - return 0, fmt.Errorf("cannot read from MSR device: %w", err) - } - - return binary.LittleEndian.Uint64(data[:]), nil - }(entry.Name()) - if err != nil { - return nil, fmt.Errorf("cannot read value for CPU %s: %w", entry.Name(), err) - } - - out[uint32(cpuNo)] = val - } - - return out, nil -} - -// AMD64 implements [HostEnvironment.AMD64]. -func (defaultEnvImpl) AMD64() (HostEnvironmentAMD64, error) { - return defaultEnvAMD64Impl{}, nil -} diff --git a/internal/efi/default_env_amd64_test.go b/internal/efi/default_env_amd64_test.go deleted file mode 100644 index abec67f1..00000000 --- a/internal/efi/default_env_amd64_test.go +++ /dev/null @@ -1,139 +0,0 @@ -//go:build amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2021-2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package efi_test - -import ( - "encoding/binary" - "os" - "path/filepath" - - "github.com/canonical/cpuid" - . "github.com/snapcore/secboot/internal/efi" - "github.com/snapcore/secboot/internal/testutil" - . "gopkg.in/check.v1" -) - -type defaultEnvAMD64Suite struct{} - -var _ = Suite(&defaultEnvAMD64Suite{}) - -func (s *defaultEnvAMD64Suite) TestCPUVendorIdentificatorIntel(c *C) { - orig := cpuid.VendorIdentificatorString - cpuid.VendorIdentificatorString = "GenuineIntel" - defer func() { cpuid.VendorIdentificatorString = orig }() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.CPUVendorIdentificator(), Equals, "GenuineIntel") -} - -func (s *defaultEnvAMD64Suite) TestCPUVendorIdentificatorAMD(c *C) { - orig := cpuid.VendorIdentificatorString - cpuid.VendorIdentificatorString = "AuthenticAMD" - defer func() { cpuid.VendorIdentificatorString = orig }() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.CPUVendorIdentificator(), Equals, "AuthenticAMD") -} - -func (s *defaultEnvAMD64Suite) TestCPUFamily1(c *C) { - orig := cpuid.DisplayFamily - cpuid.DisplayFamily = 0x12 - defer func() { cpuid.DisplayFamily = orig }() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.CPUFamily(), Equals, uint32(0x12)) -} - -func (s *defaultEnvAMD64Suite) TestCPUFamily2(c *C) { - orig := cpuid.DisplayFamily - cpuid.DisplayFamily = 0x17 - defer func() { cpuid.DisplayFamily = orig }() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.CPUFamily(), Equals, uint32(0x17)) -} - -func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSDBGTrue(c *C) { - restore := MockCPUIDHasFeature(func(feature uint64) bool { - c.Check(feature, Equals, cpuid.SDBG) - return true - }) - defer restore() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.HasCPUIDFeature(cpuid.SDBG), testutil.IsTrue) -} - -func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSDBGFalse(c *C) { - restore := MockCPUIDHasFeature(func(feature uint64) bool { - c.Check(feature, Equals, cpuid.SDBG) - return false - }) - defer restore() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.HasCPUIDFeature(cpuid.SDBG), testutil.IsFalse) -} - -func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSSE3True(c *C) { - restore := MockCPUIDHasFeature(func(feature uint64) bool { - c.Check(feature, Equals, cpuid.SSE3) - return true - }) - defer restore() - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - c.Check(amd64.HasCPUIDFeature(cpuid.SSE3), testutil.IsTrue) -} - -func (s *defaultEnvAMD64Suite) TestReadMSR(c *C) { - dir := c.MkDir() - restore := MockDevcpuPath(dir) - defer restore() - - c.Assert(os.Mkdir(filepath.Join(dir, "0"), 0755), IsNil) - c.Assert(os.Mkdir(filepath.Join(dir, "1"), 0755), IsNil) - - data := make([]byte, 0xc80) - var data8 [8]byte - binary.LittleEndian.PutUint64(data8[:], 0x40000000) - data = append(data, data8[:]...) - - c.Assert(os.WriteFile(filepath.Join(dir, "0/msr"), data, 0644), IsNil) - c.Assert(os.WriteFile(filepath.Join(dir, "1/msr"), data, 0644), IsNil) - - amd64, err := DefaultEnv.AMD64() - c.Assert(err, IsNil) - vals, err := amd64.ReadMSRs(0xc80) - c.Assert(err, IsNil) - c.Check(vals, DeepEquals, map[uint32]uint64{ - 0: 0x40000000, - 1: 0x40000000, - }) -} diff --git a/internal/efi/default_env_not_amd64_test.go b/internal/efi/default_env_not_amd64_test.go deleted file mode 100644 index 316544c5..00000000 --- a/internal/efi/default_env_not_amd64_test.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build !amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2021-2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package efi_test - -import ( - . "github.com/snapcore/secboot/internal/efi" - . "gopkg.in/check.v1" -) - -type defaultEnvAMD64Suite struct{} - -var _ = Suite(&defaultEnvAMD64Suite{}) - -func (s *defaultEnvAMD64Suite) TestNotAMD64Host(c *C) { - _, err := DefaultEnv.AMD64() - c.Check(err, Equals, ErrNotAMD64Host) -} diff --git a/internal/efi/default_env_null.go b/internal/efi/default_env_null.go deleted file mode 100644 index dbea4dc4..00000000 --- a/internal/efi/default_env_null.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package efi - -// AMD64 implements [HostEnvironment.AMD64]. -func (defaultEnvImpl) AMD64() (HostEnvironmentAMD64, error) { - return nil, ErrNotAMD64Host -} diff --git a/internal/efi/default_env_test.go b/internal/efi/default_env_test.go index 70f7e69e..e6b2dd67 100644 --- a/internal/efi/default_env_test.go +++ b/internal/efi/default_env_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2021-2024 Canonical Ltd + * Copyright (C) 2021-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -21,6 +21,7 @@ package efi_test import ( "context" + "encoding/binary" "errors" "io" "os" @@ -638,3 +639,129 @@ func (s *defaultEnvSuite) TestSysfsDeviceParentNoParent(c *C) { c.Check(err, IsNil) c.Check(parent, IsNil) } + +type defaultEnvAMD64Suite struct { + restoreGOARCH func() +} + +var _ = Suite(&defaultEnvAMD64Suite{}) + +func (s *defaultEnvAMD64Suite) SetUpTest(c *C) { + s.restoreGOARCH = MockRuntimeGOARCH("amd64") +} + +func (s *defaultEnvAMD64Suite) TearDownTest(c *C) { + s.restoreGOARCH() + s.restoreGOARCH = nil +} + +func (s *defaultEnvAMD64Suite) TestCPUVendorIdentificatorIntel(c *C) { + restore := MockCPUIDVendorIdentificator(func() string { return "GenuineIntel" }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.CPUVendorIdentificator(), Equals, "GenuineIntel") +} + +func (s *defaultEnvAMD64Suite) TestCPUVendorIdentificatorAMD(c *C) { + restore := MockCPUIDVendorIdentificator(func() string { return "AuthenticAMD" }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.CPUVendorIdentificator(), Equals, "AuthenticAMD") +} + +func (s *defaultEnvAMD64Suite) TestCPUFamily1(c *C) { + restore := MockCPUIDFamily(func() uint32 { return 0x12 }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.CPUFamily(), Equals, uint32(0x12)) +} + +func (s *defaultEnvAMD64Suite) TestCPUFamily2(c *C) { + restore := MockCPUIDFamily(func() uint32 { return 0x17 }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.CPUFamily(), Equals, uint32(0x17)) +} + +func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSDBGTrue(c *C) { + restore := MockCPUIDHasFeature(func(feature uint64) bool { + c.Check(feature, Equals, CPUIDFeatureSDBG) + return true + }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.HasCPUIDFeature(CPUIDFeatureSDBG), testutil.IsTrue) +} + +func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureSDBGFalse(c *C) { + restore := MockCPUIDHasFeature(func(feature uint64) bool { + c.Check(feature, Equals, CPUIDFeatureSDBG) + return false + }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.HasCPUIDFeature(CPUIDFeatureSDBG), testutil.IsFalse) +} + +func (s *defaultEnvAMD64Suite) TestCPUIDHasFeatureArbitraryBitPassedThrough(c *C) { + // Verify that an arbitrary feature bit is forwarded unchanged to the + // underlying hook (architecture-neutral replacement for SSE3-specific test). + const arbitraryFeature = uint64(1) << 0 // leaf 1, ECX bit 0 + restore := MockCPUIDHasFeature(func(feature uint64) bool { + c.Check(feature, Equals, arbitraryFeature) + return true + }) + defer restore() + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + c.Check(amd64.HasCPUIDFeature(arbitraryFeature), testutil.IsTrue) +} + +func (s *defaultEnvAMD64Suite) TestReadMSR(c *C) { + dir := c.MkDir() + restore := MockDevcpuPath(dir) + defer restore() + + c.Assert(os.Mkdir(filepath.Join(dir, "0"), 0755), IsNil) + c.Assert(os.Mkdir(filepath.Join(dir, "1"), 0755), IsNil) + + data := make([]byte, 0xc80) + var data8 [8]byte + binary.LittleEndian.PutUint64(data8[:], 0x40000000) + data = append(data, data8[:]...) + + c.Assert(os.WriteFile(filepath.Join(dir, "0/msr"), data, 0644), IsNil) + c.Assert(os.WriteFile(filepath.Join(dir, "1/msr"), data, 0644), IsNil) + + amd64, err := DefaultEnv.AMD64() + c.Assert(err, IsNil) + vals, err := amd64.ReadMSRs(0xc80) + c.Assert(err, IsNil) + c.Check(vals, DeepEquals, map[uint32]uint64{ + 0: 0x40000000, + 1: 0x40000000, + }) +} + +func (s *defaultEnvAMD64Suite) TestNotAMD64Host(c *C) { + // Override the arch pinned by SetUpTest to simulate a non-amd64 host. + // This now runs on every architecture including amd64 itself. + restore := MockRuntimeGOARCH("arm64") + defer restore() + + _, err := DefaultEnv.AMD64() + c.Check(err, Equals, ErrNotAMD64Host) +} diff --git a/internal/efi/env.go b/internal/efi/env.go index c0a0b3ae..15ff4889 100644 --- a/internal/efi/env.go +++ b/internal/efi/env.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2024 Canonical Ltd + * Copyright (C) 2024-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -65,6 +65,14 @@ type SysfsDevice interface { AttributeReader(attr string) (io.ReadCloser, error) } +// CPUIDFeatureSMX is the CPUID feature flag for Safer Mode Extensions (Intel TXT), +// from leaf 1, ECX bit 6. Use with [HostEnvironmentAMD64.HasCPUIDFeature]. +const CPUIDFeatureSMX = uint64(1) << 6 + +// CPUIDFeatureSDBG is the CPUID feature flag for the Silicon Debug interface, +// from leaf 1, ECX bit 11. Use with [HostEnvironmentAMD64.HasCPUIDFeature]. +const CPUIDFeatureSDBG = uint64(1) << 11 + // HostEnvironmentAMD64 is an interface that abstracts out a host environment specific // to AMD64 platforms. type HostEnvironmentAMD64 interface { @@ -74,8 +82,10 @@ type HostEnvironmentAMD64 interface { // CPUFamily returns the CPU family ID. CPUFamily() uint32 - // HasCPUIDFeature returns if feature from FeatureNames map in the - // github.com/intel-go/cpuid package is available. + // HasCPUIDFeature returns if the given CPUID feature is available. Callers + // should use the CPUIDFeature* constants declared in this package, because + // github.com/canonical/cpuid only builds on x86 and callers of this interface + // are architecture independent. HasCPUIDFeature(feature uint64) bool // ReadMSRs reads the value of the specified MSR for all CPUs, diff --git a/internal/efi/export_amd64_test.go b/internal/efi/export_amd64_test.go deleted file mode 100644 index d75b464d..00000000 --- a/internal/efi/export_amd64_test.go +++ /dev/null @@ -1,38 +0,0 @@ -//go:build amd64 - -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2024 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package efi - -func MockDevcpuPath(path string) (restore func()) { - orig := devcpuPath - devcpuPath = path - return func() { - devcpuPath = orig - } -} - -func MockCPUIDHasFeature(fn func(uint64) bool) (restore func()) { - orig := cpuidHasFeature - cpuidHasFeature = fn - return func() { - cpuidHasFeature = orig - } -} diff --git a/internal/efi/export_test.go b/internal/efi/export_test.go index e2828882..e9635503 100644 --- a/internal/efi/export_test.go +++ b/internal/efi/export_test.go @@ -1,7 +1,7 @@ // -*- Mode: Go; indent-tabs-mode: t -*- /* - * Copyright (C) 2019-2024 Canonical Ltd + * Copyright (C) 2019-2026 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -74,3 +74,43 @@ func MockOsReadlink(fn func(string) (string, error)) (restore func()) { osReadlink = orig } } + +func MockCPUIDVendorIdentificator(fn func() string) (restore func()) { + orig := cpuidVendorIdentificator + cpuidVendorIdentificator = fn + return func() { + cpuidVendorIdentificator = orig + } +} + +func MockCPUIDFamily(fn func() uint32) (restore func()) { + orig := cpuidFamily + cpuidFamily = fn + return func() { + cpuidFamily = orig + } +} + +func MockCPUIDHasFeature(fn func(uint64) bool) (restore func()) { + orig := cpuidHasFeature + cpuidHasFeature = fn + return func() { + cpuidHasFeature = orig + } +} + +func MockDevcpuPath(path string) (restore func()) { + orig := devcpuPath + devcpuPath = path + return func() { + devcpuPath = orig + } +} + +func MockRuntimeGOARCH(arch string) (restore func()) { + orig := runtimeGOARCH + runtimeGOARCH = arch + return func() { + runtimeGOARCH = orig + } +}