Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e25b821
efi, efi/preinstall: Allow opt-in to secure boot being in user mode
chrisccoulson Feb 12, 2026
3973cb2
tpm2: Update go-tpm2 version to v1.15.0
chrisccoulson Feb 26, 2026
86574c8
Merge pull request #511 from chrisccoulson/update-go-tpm2-to-1.15.0
chrisccoulson Mar 2, 2026
b03116f
tpm2: Add initial Connection.ResetDictionaryAttackLock APIs
chrisccoulson Feb 26, 2026
07123b0
tpm2: Add a comment to the use of Policy.Execute
chrisccoulson Mar 9, 2026
9e91580
efi/preinstall: relax checkSecureBootPolicyForDegradedFirmwareSettings
chrisccoulson Mar 9, 2026
fc91a56
efi/preinstall: refine the checks for manufacturing mode on Intel
chrisccoulson Mar 6, 2026
e55d961
efi/preinstall: Don't require Platform Secure Boot on AMD
chrisccoulson Mar 6, 2026
6f023d2
Merge pull request #512 from chrisccoulson/tpm2-add-initial-da-reset-api
chrisccoulson Mar 10, 2026
23fd31c
Merge pull request #508 from chrisccoulson/preinstall-allow-user-mode…
chrisccoulson Mar 10, 2026
6eb9edc
Merge branch 'master' into preinstall-relax-amd-checks
chrisccoulson Mar 10, 2026
5798c18
Merge pull request #525 from chrisccoulson/preinstall-improve-csme-ma…
chrisccoulson Mar 10, 2026
30faaae
Merge pull request #526 from chrisccoulson/fr-12830
chrisccoulson Mar 10, 2026
15396a4
Merge branch 'master' into preinstall-relax-amd-checks
chrisccoulson Mar 10, 2026
357a0e7
Merge pull request #524 from chrisccoulson/preinstall-relax-amd-checks
chrisccoulson Mar 10, 2026
c23d39f
efi/preinstall: Permit pre-OS image verification events to be measure…
chrisccoulson Jul 15, 2025
bca2fdc
efi/preinstall: Add a comment
chrisccoulson Mar 17, 2026
20066c4
efi/preinstall: Add an additional test case
chrisccoulson Mar 17, 2026
b39f826
Merge pull request #527 from chrisccoulson/preinstall-relax-pcr7-rules
chrisccoulson Mar 17, 2026
cdcb649
efi,efi/preinstall Permit unknown vendor event types in PCR7 (#528)
chrisccoulson Mar 20, 2026
26dce57
efi/preinstall: fix checkHostSecurity null implementation signiture u…
ernestl Mar 20, 2026
f92f7e0
efi/preinstall: Permit pre-OS application launches from SPI flash in …
chrisccoulson Mar 26, 2026
d54cad9
Relax recovery key parsing
chrisccoulson Mar 26, 2026
cb514b9
Merge pull request #531 from chrisccoulson/relax-recovery-key-parsing
chrisccoulson Mar 27, 2026
8fe54af
Merge pull request #530 from chrisccoulson/preinstall-fix-pcr4-tests-…
chrisccoulson Mar 27, 2026
39dc044
efi/preinstall,tpm2: Don't fail due to lack of TPM_CAP_AUTH_POLICIES
chrisccoulson Apr 7, 2026
821844b
efi/preinstall: Fall back to checking the BootGuard status MSR in HAP…
chrisccoulson Apr 8, 2026
2b0a173
Merge pull request #534 from chrisccoulson/preinstall-fix-issue-408
chrisccoulson Apr 9, 2026
7bdbc7d
efi/preinstall: update copyright
chrisccoulson Apr 9, 2026
7557d93
Merge pull request #535 from chrisccoulson/preinstall-support-btgstat…
chrisccoulson Apr 9, 2026
3f8b98c
efi/preinstall: Stop relying on BootCurrent (#536)
chrisccoulson Apr 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions crypt.go
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOT APPLICABLE

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (
"io"
"os"
"strconv"
"strings"
"unicode"

"golang.org/x/sys/unix"
"golang.org/x/xerrors"
Expand Down Expand Up @@ -95,10 +97,11 @@ func ParseRecoveryKey(s string) (out RecoveryKey, err error) {

// Move to the next 5 digits
s = s[5:]
// Permit each set of 5 digits to be separated by an optional '-', but don't allow the formatted key to end or begin with one.
if len(s) > 1 && s[0] == '-' {
s = s[1:]
}

// Permit each set of 5 digits to be separated by an arbitrary number of spaces or '-' characters.
s = strings.TrimLeftFunc(s, func(c rune) bool {
return unicode.IsSpace(c) || c == '-'
})
}

if len(s) > 0 {
Expand Down
22 changes: 14 additions & 8 deletions crypt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,20 @@ func (s *cryptSuite) TestParseRecoveryKey3(c *C) {
})
}

func (s *cryptSuite) TestParseRecoveryKey4(c *C) {
s.testParseRecoveryKey(c, &testParseRecoveryKeyData{
formatted: "61665 00531 54469 09783 47273 19035 40077 28287",
expected: testutil.DecodeHexString(c, "e1f01302c5d43726a9b85b4a8d9c7f6e"),
})
}

func (s *cryptSuite) TestParseRecoveryKey5(c *C) {
s.testParseRecoveryKey(c, &testParseRecoveryKeyData{
formatted: "61665 00531-54469 09783- 4727319035 -40077 28287 ",
expected: testutil.DecodeHexString(c, "e1f01302c5d43726a9b85b4a8d9c7f6e"),
})
}

type testParseRecoveryKeyErrorHandlingData struct {
formatted string
errChecker Checker
Expand Down Expand Up @@ -725,14 +739,6 @@ func (s *cryptSuite) TestParseRecoveryKeyErrorHandling4(c *C) {
})
}

func (s *cryptSuite) TestParseRecoveryKeyErrorHandling5(c *C) {
s.testParseRecoveryKeyErrorHandling(c, &testParseRecoveryKeyErrorHandlingData{
formatted: "00000-00000-00000-00000-00000-00000-00000-00000-",
errChecker: ErrorMatches,
errCheckerArgs: []interface{}{"incorrectly formatted: too many characters"},
})
}

type testRecoveryKeyStringifyData struct {
key []byte
expected string
Expand Down
80 changes: 57 additions & 23 deletions efi/fw_load_handler.go
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RESEALING RELATED

Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,12 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error
e := events[0]
events = events[1:]

if e.PCRIndex == internal_efi.SecureBootPolicyPCR && e.EventType == tcglog.EventTypeEFIVariableDriverConfig {
if e.PCRIndex != internal_efi.SecureBootPolicyPCR {
// we don't care about this event.
continue
}

if e.EventType == tcglog.EventTypeEFIVariableDriverConfig {
// This is the first secure boot configuration measurement. In most
// circumstances, this will be the first measurement to PCR7. Only
// in the case where the first event is a EV_EFI_ACTION "DMA Protection
Expand All @@ -159,7 +164,7 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error
}

switch {
case e.PCRIndex == internal_efi.SecureBootPolicyPCR && e.EventType == tcglog.EventTypeEFIAction &&
case e.EventType == tcglog.EventTypeEFIAction &&
(bytes.Equal(e.Data.Bytes(), []byte(dmaProtectionDisabled)) || bytes.Equal(e.Data.Bytes(), []byte(dmaProtectionDisabledNul))) &&
allowInsufficientDMAProtection:
// This is a EV_EFI_ACTION "DMA Protection Disabled" measurement and is
Expand All @@ -175,10 +180,10 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error
ctx.ExtendPCR(internal_efi.SecureBootPolicyPCR, e.Digests[ctx.PCRAlg()])
}
allowInsufficientDMAProtection = false // Only allow this event to appear once
case e.PCRIndex == internal_efi.SecureBootPolicyPCR && e.EventType != tcglog.EventTypeEFIVariableDriverConfig:
return fmt.Errorf("unexpected event type (%v) found in log, before config", e.EventType)
case internal_efi.IsVendorEventType(e.EventType):
ctx.ExtendPCR(internal_efi.SecureBootPolicyPCR, e.Digests[ctx.PCRAlg()])
default:
// we don't care about this event.
return fmt.Errorf("unexpected event type (%v) found in log, before config", e.EventType)
}
}

Expand All @@ -199,6 +204,28 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error

// TODO: Support optional dbt/dbr database

// Include the user mode related measurements if the system is in user mode, it is
// permitted with the WithSecureBootUserMode option and they are being included in this
// branch.
includeUserMode := boolParamOrFalse(ctx.Params(), includeSecureBootUserModeParamKey)
switch deployedMode, _, err := ctx.Vars().ReadVar("DeployedMode", efi.GlobalVariable); {
case errors.Is(err, efi.ErrVarNotExist):
// pre-2.5 UEFI system
case err != nil:
return fmt.Errorf("cannot read DeployedMode variable: %w", err)
case len(deployedMode) != 1:
return fmt.Errorf("invalid DeployedMode value %#x", deployedMode)
case deployedMode[0] == 0 && includeUserMode:
// System is in user mode, the WithSecureBootUserMode option was supplied and
// we are including the user mode related measurements in this branch.
ctx.MeasureVariable(internal_efi.SecureBootPolicyPCR, efi.GlobalVariable, "AuditMode", []byte{0})
ctx.MeasureVariable(internal_efi.SecureBootPolicyPCR, efi.GlobalVariable, "DeployedMode", []byte{0})
default:
// Do nothing for the deployed mode case, or where the system is in user mode
// but where the WithSecureBootUserMode option is not supplied or we are creating
// a branch that allows for deployed mode to be enabled.
}

// We don't measure a EV_SEPARATOR here yet because we need to preserve the
// device-specific measurement ordering - see the notes above about when the
// verification of third-party pre-OS code is measured. We don't know whether
Expand Down Expand Up @@ -256,24 +283,6 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error
// once we've encountered the first EV_EFI_VARIABLE_AUTHORITY event and
// we'll likely generate an invalid profile if we do. The preinstall
// checks will catch this.

// Except...
// Backward compliance: On Ubuntu Core not using preinstall checks,
// the firmware might be UEFI 2.5 compliant but not be in deployed mode.
// In that case we should still expect those measurements due to the mode.
if data, ok := e.Data.(*tcglog.EFIVariableData); ok {
if (data.VariableName == efi.GlobalVariable && data.UnicodeName == "AuditMode") {
if bytes.Equal(data.VariableData, []byte{0}) {
ctx.MeasureVariable(internal_efi.SecureBootPolicyPCR, efi.GlobalVariable, "AuditMode", data.VariableData)
}
}
if (data.VariableName == efi.GlobalVariable && data.UnicodeName == "DeployedMode") {
if bytes.Equal(data.VariableData, []byte{0}) {
ctx.MeasureVariable(internal_efi.SecureBootPolicyPCR, efi.GlobalVariable, "DeployedMode", data.VariableData)
}
}
}

case e.PCRIndex == internal_efi.SecureBootPolicyPCR && e.EventType == tcglog.EventTypeEFIAction &&
(bytes.Equal(e.Data.Bytes(), []byte(dmaProtectionDisabled)) || bytes.Equal(e.Data.Bytes(), []byte(dmaProtectionDisabledNul))) &&
allowInsufficientDMAProtection:
Expand All @@ -293,6 +302,8 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error
ctx.ExtendPCR(internal_efi.SecureBootPolicyPCR, e.Digests[ctx.PCRAlg()])
}
allowInsufficientDMAProtection = false // Only allow this event to appear once
case e.PCRIndex == internal_efi.SecureBootPolicyPCR && internal_efi.IsVendorEventType(e.EventType):
ctx.ExtendPCR(internal_efi.SecureBootPolicyPCR, e.Digests[ctx.PCRAlg()])
case e.PCRIndex == internal_efi.SecureBootPolicyPCR:
return fmt.Errorf("unexpected event type (%v) found in log", e.EventType)
default:
Expand All @@ -311,6 +322,29 @@ func (h *fwLoadHandler) measureSecureBootPolicyPreOS(ctx pcrBranchContext) error
if !measuredSecureBootSeparator {
return errors.New("missing separator in log")
}

// Retain any other vendor defined events that occur before the first EV_EFI_VARIABLE_AUTHORITY
// event.
for len(events) > 0 {
e := events[0]
events = events[1:]

if e.PCRIndex != internal_efi.SecureBootPolicyPCR {
continue
}

if e.EventType == tcglog.EventTypeEFIVariableAuthority {
break
}

switch {
case internal_efi.IsVendorEventType(e.EventType):
ctx.ExtendPCR(internal_efi.SecureBootPolicyPCR, e.Digests[ctx.PCRAlg()])
default:
return fmt.Errorf("unexpected event type (%v) found in log", e.EventType)
}
}

return nil
}

Expand Down
Loading
Loading